diff --git a/qiskit/circuit/library/standard_gates/x.py b/qiskit/circuit/library/standard_gates/x.py index 1711d113d045..a813226e355f 100644 --- a/qiskit/circuit/library/standard_gates/x.py +++ b/qiskit/circuit/library/standard_gates/x.py @@ -826,11 +826,11 @@ class MCXGate(ControlledGate): def __new__(cls, num_ctrl_qubits=None, label=None, ctrl_state=None): """Create a new MCX instance. - Depending on the number of controls, this creates an explicit CX, CCX, C3X or C4X - instance or a generic MCX gate. + Depending on the number of controls and which mode of the MCX, this creates an + explicit CX, CCX, C3X or C4X instance or a generic MCX gate. """ - # these gates will always be implemented for all modes of the MCX if the number of control - # qubits matches this + # The CXGate and CCXGate will be implemented for all modes of the MCX, and + # the C3XGate and C4XGate will be implemented in the MCXGrayCode class. explicit = { 1: CXGate, 2: CCXGate @@ -909,6 +909,23 @@ class MCXGrayCode(MCXGate): This delegates the implementation to the MCU1 gate, since :math:`X = H \cdot U1(\pi) \cdot H`. """ + def __new__(cls, num_ctrl_qubits=None, label=None, ctrl_state=None): + """Create a new MCXGrayCode instance + """ + # if 1 to 4 control qubits, create explicit gates + explicit = { + 1: CXGate, + 2: CCXGate, + 3: C3XGate, + 4: C4XGate + } + if num_ctrl_qubits in explicit.keys(): + gate_class = explicit[num_ctrl_qubits] + gate = gate_class.__new__(gate_class, label=label, ctrl_state=ctrl_state) + # if __new__ does not return the same type as cls, init is not called + gate.__init__(label=label, ctrl_state=ctrl_state) + return gate + return super().__new__(cls) def __init__(self, num_ctrl_qubits, label=None, ctrl_state=None): super().__init__(num_ctrl_qubits, label=label, ctrl_state=ctrl_state, _name='mcx_gray') diff --git a/releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml b/releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml new file mode 100644 index 000000000000..c748b419f7f9 --- /dev/null +++ b/releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml @@ -0,0 +1,8 @@ +--- +upgrade: + - | + The class :class:`~qiskit.library.standard_gates.x.MCXGrayCode` will now create + a ``C3XGate`` if ``num_ctrl_qubits`` is 3 and a ``C4XGate`` if ``num_ctrl_qubits`` + is 4. This is in addition to the previous functionality where for any of the + modes of the :class:'qiskit.library.standard_gates.x.MCXGate`, if ``num_ctrl_bits`` + is 1, a ``CXGate`` is created, and if 2, a ``CCXGate`` is created. diff --git a/test/python/circuit/test_controlled_gate.py b/test/python/circuit/test_controlled_gate.py index 2f6421c743d3..d687fed7478a 100644 --- a/test/python/circuit/test_controlled_gate.py +++ b/test/python/circuit/test_controlled_gate.py @@ -569,6 +569,14 @@ def test_mcx_gates_yield_explicit_gates(self, num_ctrl_qubits): explicit = {1: CXGate, 2: CCXGate} self.assertEqual(cls, explicit[num_ctrl_qubits]) + @data(1, 2, 3, 4) + def test_mcxgraycode_gates_yield_explicit_gates(self, num_ctrl_qubits): + """Test creating an mcx gate calls MCXGrayCode and yeilds explicit definition.""" + qc = QuantumCircuit(num_ctrl_qubits+1) + qc.mcx(list(range(num_ctrl_qubits)), [num_ctrl_qubits]) + explicit = {1: CXGate, 2: CCXGate, 3: C3XGate, 4: C4XGate} + self.assertEqual(type(qc[0][0]), explicit[num_ctrl_qubits]) + @data(3, 4, 5, 8) def test_mcx_gates(self, num_ctrl_qubits): """Test the mcx gates."""