Skip to content

Commit

Permalink
Deprecation of MCMT in favor of MCMTGate (backport #13584) (#13810)
Browse files Browse the repository at this point in the history
* Deprecation of MCMT in favor of MCMTGate (#13584)

* remove pending deprecations in mcmt

* reno

* testing a regression

(cherry picked from commit 28a33d7)

# Conflicts:
#	test/python/circuit/library/test_mcmt.py

* Fix conflict

---------

Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
  • Loading branch information
3 people authored Feb 14, 2025
1 parent f0f90ac commit 4f4de71
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 15 deletions.
11 changes: 5 additions & 6 deletions qiskit/circuit/library/generalized_gates/mcmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class MCMT(QuantumCircuit):
:class:`~qiskit.circuit.library.MCMTVChain`.
"""

@deprecate_func(since="1.3", additional_msg="Use MCMTGate instead.", pending=True)
@deprecate_func(since="1.4", additional_msg="Use MCMTGate instead.")
def __init__(
self,
gate: Gate | Callable[[QuantumCircuit, circuit.Qubit, circuit.Qubit], circuit.Instruction],
Expand All @@ -76,15 +76,15 @@ def __init__(
warnings.warn(
"Passing a callable to MCMT is pending deprecation since Qiskit 1.3. Pass a "
"gate instance or the gate name instead, e.g. pass 'h' instead of QuantumCircuit.h.",
category=PendingDeprecationWarning,
category=DeprecationWarning,
stacklevel=2,
)
gate = gate.__name__
elif isinstance(gate, QuantumCircuit):
warnings.warn(
"Passing a QuantumCircuit is pending deprecation since Qiskit 1.3. Pass a gate "
"or turn the circuit into a gate using the ``to_gate`` method, instead.",
category=PendingDeprecationWarning,
category=DeprecationWarning,
stacklevel=2,
)
gate = gate.to_gate()
Expand Down Expand Up @@ -157,9 +157,8 @@ class MCMTVChain(MCMT):
"""

@deprecate_func(
since="1.3",
since="1.4",
additional_msg="Use MCMTGate with the V-chain synthesis plugin instead.",
pending=True,
)
def __init__(
self,
Expand Down Expand Up @@ -276,7 +275,7 @@ def _identify_base_gate(gate):
warnings.warn(
"Passing a controlled gate to MCMT is pending deprecation since Qiskit 1.3. Pass a "
"single-qubit gate instance or the gate name instead, e.g. pass 'h' instead of 'ch'.",
category=PendingDeprecationWarning,
category=DeprecationWarning,
stacklevel=2,
)
base_gate = gate.base_gate
Expand Down
8 changes: 8 additions & 0 deletions releasenotes/notes/followup_13150-5bd0c77248601e1a.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
deprecations_circuits:
- |
The Multiple-Control-Multiple-Target in :class:`~qiskit.circuit.library.generalized_gates.MCMT` is now deprecated
and replaced by :class:`.MCMTGate`, which is a proper :class:`.Gate` subclass. Using
a gate instead of a circuit allows the compiler to reason about the object at a higher
level of abstraction and allows for multiple synthesis plugins.
25 changes: 16 additions & 9 deletions test/python/circuit/library/test_mcmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ class TestMCMT(QiskitTestCase):
def test_mcmt_as_normal_control(self, mcmt_class):
"""Test that the MCMT can act as normal control gate."""
qc = QuantumCircuit(2)
mcmt = mcmt_class(gate=CHGate(), num_ctrl_qubits=1, num_target_qubits=1)
with self.assertWarns(DeprecationWarning):
mcmt = mcmt_class(gate=CHGate(), num_ctrl_qubits=1, num_target_qubits=1)
qc = qc.compose(mcmt, [0, 1])

ref = QuantumCircuit(2)
Expand All @@ -65,20 +66,23 @@ def test_mcmt_as_normal_control(self, mcmt_class):
def test_missing_qubits(self):
"""Test that an error is raised if qubits are missing."""
with self.subTest(msg="no control qubits"):
with self.assertRaises(AttributeError):
_ = MCMT(XGate(), num_ctrl_qubits=0, num_target_qubits=1)
with self.assertWarns(DeprecationWarning):
with self.assertRaises(AttributeError):
_ = MCMT(XGate(), num_ctrl_qubits=0, num_target_qubits=1)

with self.subTest(msg="no target qubits"):
with self.assertRaises(AttributeError):
_ = MCMT(ZGate(), num_ctrl_qubits=4, num_target_qubits=0)
with self.assertWarns(DeprecationWarning):
with self.assertRaises(AttributeError):
_ = MCMT(ZGate(), num_ctrl_qubits=4, num_target_qubits=0)

def test_different_gate_types(self):
"""Test the different supported input types for the target gate."""
x_circ = QuantumCircuit(1)
x_circ.x(0)
for input_gate in [x_circ, QuantumCircuit.cx, QuantumCircuit.x, "cx", "x", CXGate()]:
with self.subTest(input_gate=input_gate):
mcmt = MCMT(input_gate, 2, 2)
with self.assertWarns(DeprecationWarning):
mcmt = MCMT(input_gate, 2, 2)
if isinstance(input_gate, QuantumCircuit):
self.assertEqual(mcmt.gate.definition[0].operation, XGate())
self.assertEqual(len(mcmt.gate.definition), 1)
Expand All @@ -89,13 +93,15 @@ def test_mcmt_v_chain_ancilla_test(self):
"""Test too few and too many ancillas for the MCMT V-chain mode."""
with self.subTest(msg="insufficient number of auxiliary qubits on gate"):
qc = QuantumCircuit(5)
mcmt = MCMTVChain(ZGate(), 3, 1)
with self.assertWarns(DeprecationWarning):
mcmt = MCMTVChain(ZGate(), 3, 1)
with self.assertRaises(QiskitError):
qc.append(mcmt, range(5))

with self.subTest(msg="too many auxiliary qubits on gate"):
qc = QuantumCircuit(9)
mcmt = MCMTVChain(ZGate(), 3, 1)
with self.assertWarns(DeprecationWarning):
mcmt = MCMTVChain(ZGate(), 3, 1)
with self.assertRaises(QiskitError):
qc.append(mcmt, range(9))

Expand Down Expand Up @@ -135,7 +141,8 @@ def test_mcmt_v_chain_simulation(self, cgate, num_controls, num_targets):
for i in subset:
qc.x(controls[i])

mcmt = MCMTVChain(cgate, num_controls, num_targets)
with self.assertWarns(DeprecationWarning):
mcmt = MCMTVChain(cgate, num_controls, num_targets)
qc.compose(mcmt, qubits, inplace=True)

for i in subset:
Expand Down

0 comments on commit 4f4de71

Please sign in to comment.