Skip to content

Commit

Permalink
Merge pull request #7 from notmgsk/6-non-adjacent-2q-gates
Browse files Browse the repository at this point in the history
Fix: lift non-adjacent 2Q gates
  • Loading branch information
notmgsk authored Jul 12, 2021
2 parents f529826 + ae39bec commit b064816
Showing 1 changed file with 60 additions and 18 deletions.
78 changes: 60 additions & 18 deletions src/gates/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pub mod standard;

use itertools::Itertools;
use ndarray::{Array, Array2};
use num::complex::Complex64;

Expand Down Expand Up @@ -49,17 +48,7 @@ impl QGate {
match self.qubits.len().cmp(&2) {
std::cmp::Ordering::Less => self.lift_adjacent(self.qubits[0], n_qubits),
std::cmp::Ordering::Equal => {
let start = *self
.qubits
.iter()
.sorted()
.rev()
.collect_vec()
.last()
.unwrap()
.to_owned();

let (permutation, _) =
let (permutation, _, start) =
juxtaposing_permutation_matrix(self.qubits[0], self.qubits[1], n_qubits);
let permutation_dag = conj(permutation.clone().reversed_axes());
let lifted = self.lift_adjacent(start, n_qubits);
Expand All @@ -84,25 +73,29 @@ fn conj(arr: Array2<Complex64>) -> Array2<Complex64> {

/// Creates a permutation matrix that moves the Hilbert space for qubit `i` into
/// a position adjacent to that of qubit `j`.
fn juxtaposing_permutation_matrix(j: u64, k: u64, n_qubits: u64) -> (Array2<Complex64>, Vec<u64>) {
fn juxtaposing_permutation_matrix(
j: u64,
k: u64,
n_qubits: u64,
) -> (Array2<Complex64>, Vec<u64>, u64) {
let mut permutation = Array::eye(2u64.pow(n_qubits as u32) as usize);
let mut new_q_map = (0..n_qubits).collect();

match j.cmp(&k) {
std::cmp::Ordering::Equal => (permutation, new_q_map),
std::cmp::Ordering::Equal => (permutation, new_q_map, j),
std::cmp::Ordering::Less => {
for i in j..k {
permutation = swap(0, 1).lift_adjacent(i, n_qubits).dot(&permutation);
new_q_map.swap(i as usize, (i + 1) as usize)
}
(permutation, new_q_map)
(permutation, new_q_map, k - 1)
}
std::cmp::Ordering::Greater => {
for i in j..k {
for i in (k + 1..j).rev() {
permutation = swap(0, 1).lift_adjacent(i - 1, n_qubits).dot(&permutation);
new_q_map.swap((i - 1) as usize, i as usize)
}
(permutation, new_q_map)
(permutation, new_q_map, j - 1)
}
}
}
Expand Down Expand Up @@ -159,6 +152,55 @@ mod tests {
#[test]
fn lift_2q() {
let gate = super::cnot(0, 1);
println!("{:#}", gate.lift(3));
assert_eq!(
gate.lift(2),
arr2(&[
[C1, C0, C0, C0],
[C0, C0, C0, C1],
[C0, C0, C1, C0],
[C0, C1, C0, C0],
])
);

let gate = super::cnot(1, 0);
assert_eq!(
gate.lift(2),
arr2(&[
[C1, C0, C0, C0],
[C0, C1, C0, C0],
[C0, C0, C0, C1],
[C0, C0, C1, C0],
])
);

let gate = super::cnot(0, 2);
assert_eq!(
gate.lift(3),
arr2(&[
[C1, C0, C0, C0, C0, C0, C0, C0],
[C0, C0, C0, C0, C0, C1, C0, C0],
[C0, C0, C1, C0, C0, C0, C0, C0],
[C0, C0, C0, C0, C0, C0, C0, C1],
[C0, C0, C0, C0, C1, C0, C0, C0],
[C0, C1, C0, C0, C0, C0, C0, C0],
[C0, C0, C0, C0, C0, C0, C1, C0],
[C0, C0, C0, C1, C0, C0, C0, C0],
])
);

let gate = super::cnot(2, 0);
assert_eq!(
gate.lift(3),
arr2(&[
[C1, C0, C0, C0, C0, C0, C0, C0],
[C0, C1, C0, C0, C0, C0, C0, C0],
[C0, C0, C1, C0, C0, C0, C0, C0],
[C0, C0, C0, C1, C0, C0, C0, C0],
[C0, C0, C0, C0, C0, C1, C0, C0],
[C0, C0, C0, C0, C1, C0, C0, C0],
[C0, C0, C0, C0, C0, C0, C0, C1],
[C0, C0, C0, C0, C0, C0, C1, C0],
])
);
}
}

0 comments on commit b064816

Please sign in to comment.