diff --git a/qiskit/transpiler/passes/utils/gate_direction.py b/qiskit/transpiler/passes/utils/gate_direction.py index 90e66821a268..3c331441d83e 100644 --- a/qiskit/transpiler/passes/utils/gate_direction.py +++ b/qiskit/transpiler/passes/utils/gate_direction.py @@ -20,7 +20,7 @@ from qiskit.circuit import QuantumRegister from qiskit.dagcircuit import DAGCircuit -from qiskit.circuit.library.standard_gates import RYGate, HGate, CXGate, ECRGate, RZXGate +from qiskit.circuit.library.standard_gates import RYGate, HGate, CXGate, CZGate, ECRGate, RZXGate class GateDirection(TransformationPass): @@ -78,6 +78,11 @@ def __init__(self, coupling_map, target=None): self._ecr_dag.apply_operation_back(HGate(), [qr[0]], []) self._ecr_dag.apply_operation_back(HGate(), [qr[1]], []) + self._cz_dag = DAGCircuit() + qr = QuantumRegister(2) + self._cz_dag.add_qreg(qr) + self._cz_dag.apply_operation_back(CZGate(), [qr[1], qr[0]], []) + @staticmethod def _rzx_dag(parameter): _rzx_dag = DAGCircuit() @@ -138,6 +143,8 @@ def run(self, dag): if (physical_q0, physical_q1) not in cmap_edges: if node.name == "cx": dag.substitute_node_with_dag(node, self._cx_dag) + elif node.name == "cz": + dag.substitute_node_with_dag(node, self._cz_dag) elif node.name == "ecr": dag.substitute_node_with_dag(node, self._ecr_dag) elif node.name == "rzx": @@ -169,6 +176,16 @@ def run(self, dag): "The circuit requires a connection between physical " "qubits %s and %s for cx" % (physical_q0, physical_q1) ) + elif node.name == "cz": + if (physical_q0, physical_q1) in self.target["cz"]: + continue + if (physical_q1, physical_q0) in self.target["cz"]: + dag.substitute_node_with_dag(node, self._cz_dag) + else: + raise TranspilerError( + "The circuit requires a connection between physical " + "qubits %s and %s for cz" % (physical_q0, physical_q1) + ) elif node.name == "ecr": if (physical_q0, physical_q1) in self.target["ecr"]: continue diff --git a/releasenotes/notes/fix-flipping-cz-gate-fd08305ca12d9a79.yaml b/releasenotes/notes/fix-flipping-cz-gate-fd08305ca12d9a79.yaml new file mode 100644 index 000000000000..4c27b40a2255 --- /dev/null +++ b/releasenotes/notes/fix-flipping-cz-gate-fd08305ca12d9a79.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fix a problem in the `GateDirection` transpiler pass for the CZ gate. The CZ is symmetric, so flipping the qubit arguments is allowed to match the directed coupling map. + diff --git a/test/python/transpiler/test_gate_direction.py b/test/python/transpiler/test_gate_direction.py index 0960c840ddad..59fa04a517a2 100644 --- a/test/python/transpiler/test_gate_direction.py +++ b/test/python/transpiler/test_gate_direction.py @@ -15,6 +15,7 @@ from math import pi from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit +from qiskit.compiler import transpile from qiskit.transpiler import TranspilerError from qiskit.transpiler import CouplingMap from qiskit.transpiler.passes import GateDirection @@ -245,6 +246,21 @@ def test_preserves_conditions(self): self.assertEqual(circuit_to_dag(expected), after) + def test_regression_gh_8387(self): + """Regression test for flipping of CZ gate""" + qc = QuantumCircuit(3) + qc.cz(1, 0) + qc.barrier() + qc.cz(2, 0) + + coupling_map = CouplingMap([[0, 1], [1, 2]]) + _ = transpile( + qc, + basis_gates=["cz", "cx", "u3", "u2", "u1"], + coupling_map=coupling_map, + optimization_level=2, + ) + if __name__ == "__main__": unittest.main()