Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions crates/transpiler/src/passes/inverse_cancellation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ fn std_inverse_pairs(dag: &mut DAGCircuit) {
{
continue;
}
let pair_symmetric_2q = matches!([gate_0, gate_1], [StandardGate::CS, StandardGate::CSdg]);
let filter = |inst: &PackedInstruction| -> bool {
match inst.op.view() {
OperationRef::StandardGate(gate) => gate == gate_0 || gate == gate_1,
Expand All @@ -264,12 +265,17 @@ fn std_inverse_pairs(dag: &mut DAGCircuit) {
let NodeType::Operation(next_inst) = &dag[nodes[i + 1]] else {
unreachable!("Not an op node");
};
if inst.qubits == next_inst.qubits
&& (inst.op.try_standard_gate() == Some(gate_0)
&& next_inst.op.try_standard_gate() == Some(gate_1))
|| (inst.op.try_standard_gate() == Some(gate_1)
&& next_inst.op.try_standard_gate() == Some(gate_0))
{
let inst_gate = inst.op.try_standard_gate();
let next_gate = next_inst.op.try_standard_gate();
let pair_match = (inst_gate == Some(gate_0) && next_gate == Some(gate_1))
|| (inst_gate == Some(gate_1) && next_gate == Some(gate_0));
let qargs_match = inst.qubits == next_inst.qubits
|| (pair_symmetric_2q && {
let a = dag.get_qargs(inst.qubits);
let b = dag.get_qargs(next_inst.qubits);
a.len() == 2 && b.len() == 2 && a[0] == b[1] && a[1] == b[0]
});
if pair_match && qargs_match {
dag.remove_op_node(nodes[i]);
dag.remove_op_node(nodes[i + 1]);
i += 2;
Expand Down
6 changes: 6 additions & 0 deletions releasenotes/notes/fix-inverse-cancellation-qubits-15855.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
Fixed :class:`.InverseCancellation` so the default :class:`.CSGate` and
:class:`.CSdgGate` inverse pair is cancelled consistently when the two
gates act on the same qubits in opposite order.
10 changes: 10 additions & 0 deletions test/python/transpiler/test_inverse_cancellation.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,16 @@ def test_some_inverse_pairs(self, gates_to_cancel):
self.assertNotIn("t", new_circ.count_ops())
self.assertNotIn("tdg", new_circ.count_ops())

def test_cs_csdg_cancel_with_reversed_qargs_in_both_orders(self):
"""CS/CSdg are symmetric in qubit order, so both inverse orders cancel."""
for first, second in (("csdg", "cs"), ("cs", "csdg")):
with self.subTest(first=first, second=second):
qc = QuantumCircuit(2)
getattr(qc, first)(0, 1)
getattr(qc, second)(1, 0)
new_circ = InverseCancellation()(qc)
self.assertEqual(new_circ, QuantumCircuit(2))

@ddt.data([HGate(), CXGate(), CZGate(), (TGate(), TdgGate())], None)
def test_some_inverse_and_cancelled(self, gates_to_cancel):
"""Test when there are some but not all pairs to cancel."""
Expand Down
Loading