diff --git a/docs/changelog.rst b/docs/changelog.rst index ce059b0f..443ac46d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -13,6 +13,7 @@ Unreleased * Add conversion of controlled unitary gates from qiskit to tket. * Initialize `TketAutoPass` with a `BackendV2`. * Update `TketBackend` to derive from `BackendV2`. +* Fix to allow `AerBackend` to work with multi-controlled Z gates. 0.55.0 (July 2024) ------------------ diff --git a/pytket/extensions/qiskit/qiskit_convert.py b/pytket/extensions/qiskit/qiskit_convert.py index 79559051..e77119c0 100644 --- a/pytket/extensions/qiskit/qiskit_convert.py +++ b/pytket/extensions/qiskit/qiskit_convert.py @@ -758,7 +758,9 @@ def append_tk_command_to_qiskit( if optype == OpType.CnY: return qcirc.append(qiskit_gates.YGate().control(len(qargs) - 1), qargs) if optype == OpType.CnZ: - return qcirc.append(qiskit_gates.ZGate().control(len(qargs) - 1), qargs) + new_gate = qiskit_gates.ZGate().control(len(qargs) - 1) + new_gate.name = "mcz" + return qcirc.append(new_gate, qargs) if optype == OpType.CnRy: # might as well do a bit more checking assert len(op.params) == 1 diff --git a/tests/backend_test.py b/tests/backend_test.py index ea30ece0..ed2617a9 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -1498,3 +1498,17 @@ def test_noisy_density_matrix_simulation() -> None: assert noisy_dm.shape == (8, 8) # Check purity to verify mixed state assert np.trace(noisy_dm**2).real < 0.99 + + +def test_mc_gate_on_aer() -> None: + """Test for cm gates support in aer simulators + https://github.com/CQCL/pytket-qiskit/issues/368""" + b = AerBackend() + c = Circuit(3, 3) + c.X(0).X(1) + c.H(2) + c.add_gate(OpType.CnZ, [0, 1, 2]) + c.H(2) + c.measure_all() + r = b.run_circuit(c, n_shots=10) + assert r.get_counts() == Counter({(1, 1, 1): 10}) diff --git a/tests/qiskit_convert_test.py b/tests/qiskit_convert_test.py index 4e1a22b1..d7d9ad4d 100644 --- a/tests/qiskit_convert_test.py +++ b/tests/qiskit_convert_test.py @@ -828,7 +828,7 @@ def test_multicontrolled_gate_conversion() -> None: assert my_tkc.n_gates_of_type(OpType.CnRy) == 2 my_new_qc = tk_to_qiskit(my_tkc) qiskit_ops = my_new_qc.count_ops() - assert qiskit_ops["c3y"] and qiskit_ops["c3z"] and qiskit_ops["c3ry"] == 2 + assert qiskit_ops["c3y"] and qiskit_ops["mcz"] and qiskit_ops["c3ry"] == 2 tcirc = qiskit_to_tk(my_new_qc) unitary_after = tcirc.get_unitary() assert compare_unitaries(unitary_before, unitary_after) @@ -1034,7 +1034,7 @@ def test_ccz_conversion() -> None: assert tkc_ccz.n_gates_of_type(OpType.CnZ) == tkc_ccz.n_gates == 2 # bidirectional CnZ conversion already supported qc_ccz2 = tk_to_qiskit(tkc_ccz) - assert qc_ccz2.count_ops()["ccz"] == 2 + assert qc_ccz2.count_ops()["mcz"] == 2 tkc_ccz2 = qiskit_to_tk(qc_ccz2) assert compare_unitaries(tkc_ccz.get_unitary(), tkc_ccz2.get_unitary())