Skip to content

Commit

Permalink
Fix phase for rotations by 0.0
Browse files Browse the repository at this point in the history
This follows up on the fix from #173, which inadvertantly introduced a global phase on Rx/Ry rotations by 0.0 (and odd increments of Pi). This avoids the problem by checking the other part of the matrix to determine if the phase is required rather than applying it unconditionally.
  • Loading branch information
swernli committed Jun 14, 2024
1 parent b331b6b commit 9b6bf8b
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 21 deletions.
53 changes: 32 additions & 21 deletions sparsesim/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -974,29 +974,40 @@ impl QuantumSim {
} else {
self.mcx(ctls, target);
}
// Rx/Ry are different from X/Y by a global phase of -i, so apply that here for mathematical correctness.
// Rx/Ry are different from X/Y by a global phase of -i, so apply that here when indicated by m01,
// for mathematical correctness.
let (_, ctls) = self.resolve_and_check_qubits(target, ctls);
self.state =
self.state
.drain()
.fold(SparseState::default(), |mut accum, (index, value)| {
if ctls.iter().all(|c| index.bit(*c)) {
accum.insert(index, value * -Complex64::i());
}
accum
});
let factor = m01
* if sign_flip {
Complex64::i()
} else {
Complex64::one()
};
if factor != Complex64::one() {
self.state =
self.state
.drain()
.fold(SparseState::default(), |mut accum, (index, value)| {
if ctls.iter().all(|c| index.bit(*c)) {
accum.insert(index, value * factor);
}
accum
});
}
} else if m01.is_nearly_zero() {
// This is just identity, so we can effectively no-op and just add a phase of -1.
let (_, ctls) = self.resolve_and_check_qubits(target, ctls);
self.state =
self.state
.drain()
.fold(SparseState::default(), |mut accum, (index, value)| {
if ctls.iter().all(|c| index.bit(*c)) {
accum.insert(index, value * -Complex64::one());
}
accum
});
// This is just identity, so we can effectively no-op, and just add a phase of -1 as indicated by m00.
if m00 == -Complex64::one() {
let (_, ctls) = self.resolve_and_check_qubits(target, ctls);
self.state =
self.state
.drain()
.fold(SparseState::default(), |mut accum, (index, value)| {
if ctls.iter().all(|c| index.bit(*c)) {
accum.insert(index, value * -Complex64::one());
}
accum
});
}
} else {
let (target, ctls) = self.resolve_and_check_qubits(target, ctls);
let mut new_state = SparseState::default();
Expand Down
78 changes: 78 additions & 0 deletions sparsesim/src/matrix_testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,45 @@ mod tests {
);
}

#[test]
fn test_rx_zero() {
assert_operation_equal_referenced(
|sim, qs| {
sim.rx(0.0, qs[0]);
},
|sim, qs| {
sim.apply(&adjoint(&rx(0.0)), &[qs[0]], None);
},
1,
);
}

#[test]
fn test_rx_3pi() {
assert_operation_equal_referenced(
|sim, qs| {
sim.rx(3.0 * PI, qs[0]);
},
|sim, qs| {
sim.apply(&adjoint(&rx(3.0 * PI)), &[qs[0]], None);
},
1,
);
}

#[test]
fn test_rx_4pi() {
assert_operation_equal_referenced(
|sim, qs| {
sim.rx(4.0 * PI, qs[0]);
},
|sim, qs| {
sim.apply(&adjoint(&rx(4.0 * PI)), &[qs[0]], None);
},
1,
);
}

#[test]
fn test_ry() {
assert_operation_equal_referenced(
Expand Down Expand Up @@ -642,6 +681,45 @@ mod tests {
);
}

#[test]
fn test_ry_zero() {
assert_operation_equal_referenced(
|sim, qs| {
sim.ry(0.0, qs[0]);
},
|sim, qs| {
sim.apply(&adjoint(&ry(0.0)), &[qs[0]], None);
},
1,
);
}

#[test]
fn test_ry_3pi() {
assert_operation_equal_referenced(
|sim, qs| {
sim.ry(3.0 * PI, qs[0]);
},
|sim, qs| {
sim.apply(&adjoint(&ry(3.0 * PI)), &[qs[0]], None);
},
1,
);
}

#[test]
fn test_ry_4pi() {
assert_operation_equal_referenced(
|sim, qs| {
sim.ry(4.0 * PI, qs[0]);
},
|sim, qs| {
sim.apply(&adjoint(&ry(4.0 * PI)), &[qs[0]], None);
},
1,
);
}

#[test]
fn test_mcri() {
assert_operation_equal_referenced(
Expand Down

0 comments on commit 9b6bf8b

Please sign in to comment.