From 8cfeb0d8b592b01ca25df0f71dabb4f07de3fc39 Mon Sep 17 00:00:00 2001 From: Edwin Navarro Date: Thu, 21 Jan 2021 03:01:46 -0800 Subject: [PATCH 1/2] Create explicit C3XGate/C4XGate in MCXGrayCode (#5601) * Make MCX a C3X or C4X if MCXGrayCode and 3 or 4 controls * Update test * Place all explicit in MCXGrayCode Co-authored-by: Julien Gacon (cherry picked from commit 3b59319fd9b9f4bff3f6d40b024aa1dde8be4ff0) --- qiskit/circuit/library/standard_gates/x.py | 25 ++++++++++++++++--- ...ate_explicit_c3x_c4x-d4475c0bb70fae49.yaml | 8 ++++++ test/python/circuit/test_controlled_gate.py | 8 ++++++ 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml diff --git a/qiskit/circuit/library/standard_gates/x.py b/qiskit/circuit/library/standard_gates/x.py index 7641a9930378..56bdeed76734 100644 --- a/qiskit/circuit/library/standard_gates/x.py +++ b/qiskit/circuit/library/standard_gates/x.py @@ -723,11 +723,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 @@ -806,6 +806,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..a5c1440678c4 --- /dev/null +++ b/releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + 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 1b961674d98e..fb6368793930 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.""" From 56708325e45ced9ae6e2c6990b3ecef6c7cba286 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Mon, 25 Jan 2021 09:47:37 -0500 Subject: [PATCH 2/2] Update releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml --- .../notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml b/releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml index a5c1440678c4..c748b419f7f9 100644 --- a/releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml +++ b/releasenotes/notes/mcx_create_explicit_c3x_c4x-d4475c0bb70fae49.yaml @@ -1,5 +1,5 @@ --- -features: +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``