Skip to content

Commit 4349397

Browse files
haimeng-zhangmtreinish
authored andcommitted
Fix InverseCancellation to run in classical blocks (#13454)
* Fix an issue that `InverseCancellation` does not run in classical blocks (#13437) * Add test functions for pass running in classical blocks. * Reformat test function file * Add a release note (cherry picked from commit 6025b7c)
1 parent e86d9b6 commit 4349397

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

qiskit/transpiler/passes/optimization/inverse_cancellation.py

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from qiskit.dagcircuit import DAGCircuit
2020
from qiskit.transpiler.basepasses import TransformationPass
2121
from qiskit.transpiler.exceptions import TranspilerError
22+
from qiskit.transpiler.passes.utils import control_flow
2223

2324
from qiskit._accelerate.inverse_cancellation import inverse_cancellation
2425

@@ -74,6 +75,7 @@ def __init__(self, gates_to_cancel: List[Union[Gate, Tuple[Gate, Gate]]]):
7475

7576
super().__init__()
7677

78+
@control_flow.trivial_recurse
7779
def run(self, dag: DAGCircuit):
7880
"""Run the InverseCancellation pass on `dag`.
7981
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fixes:
2+
- |
3+
The transpilation pass :class`.InverseCancellation` now runs inside of flow controlled blocks. Previously, it ignores the pairs of gates in classical blocks that can be cancelled. Refer to `#13437 <https://github.com/Qiskit/qiskit/issues/13437>` for more details.

test/python/transpiler/test_inverse_cancellation.py

+54
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from qiskit.transpiler.exceptions import TranspilerError
2222
from qiskit.transpiler.passes import InverseCancellation
2323
from qiskit.transpiler import PassManager
24+
from qiskit.circuit import Clbit, Qubit
2425
from qiskit.circuit.library import (
2526
RXGate,
2627
HGate,
@@ -398,6 +399,59 @@ def test_backwards_pair(self):
398399
new_circ = inverse_pass(qc)
399400
self.assertEqual(new_circ, QuantumCircuit(1))
400401

402+
def test_if_else(self):
403+
"""Test that the pass recurses in a simple if-else."""
404+
pass_ = InverseCancellation([CXGate()])
405+
406+
inner_test = QuantumCircuit(4, 1)
407+
inner_test.cx(0, 1)
408+
inner_test.cx(0, 1)
409+
inner_test.cx(2, 3)
410+
411+
inner_expected = QuantumCircuit(4, 1)
412+
inner_expected.cx(2, 3)
413+
414+
test = QuantumCircuit(4, 1)
415+
test.h(0)
416+
test.measure(0, 0)
417+
test.if_else((0, True), inner_test.copy(), inner_test.copy(), range(4), [0])
418+
419+
expected = QuantumCircuit(4, 1)
420+
expected.h(0)
421+
expected.measure(0, 0)
422+
expected.if_else((0, True), inner_expected, inner_expected, range(4), [0])
423+
424+
self.assertEqual(pass_(test), expected)
425+
426+
def test_nested_control_flow(self):
427+
"""Test that collection recurses into nested control flow."""
428+
pass_ = InverseCancellation([CXGate()])
429+
qubits = [Qubit() for _ in [None] * 4]
430+
clbit = Clbit()
431+
432+
inner_test = QuantumCircuit(qubits, [clbit])
433+
inner_test.cx(0, 1)
434+
inner_test.cx(0, 1)
435+
inner_test.cx(2, 3)
436+
437+
inner_expected = QuantumCircuit(qubits, [clbit])
438+
inner_expected.cx(2, 3)
439+
440+
true_body = QuantumCircuit(qubits, [clbit])
441+
true_body.while_loop((clbit, True), inner_test.copy(), [0, 1, 2, 3], [0])
442+
443+
test = QuantumCircuit(qubits, [clbit])
444+
test.for_loop(range(2), None, inner_test.copy(), [0, 1, 2, 3], [0])
445+
test.if_else((clbit, True), true_body, None, [0, 1, 2, 3], [0])
446+
447+
expected_if_body = QuantumCircuit(qubits, [clbit])
448+
expected_if_body.while_loop((clbit, True), inner_expected, [0, 1, 2, 3], [0])
449+
expected = QuantumCircuit(qubits, [clbit])
450+
expected.for_loop(range(2), None, inner_expected, [0, 1, 2, 3], [0])
451+
expected.if_else((clbit, True), expected_if_body, None, [0, 1, 2, 3], [0])
452+
453+
self.assertEqual(pass_(test), expected)
454+
401455

402456
if __name__ == "__main__":
403457
unittest.main()

0 commit comments

Comments
 (0)