From c31a896f3f2a62207b699fe2a1a083b0f17399f1 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Tue, 25 Feb 2020 22:19:55 +0100 Subject: [PATCH 1/2] remove mct, mcu1 and mcr[x,y,z], they moved to Terra --- .../algorithms/single_sample/grover/grover.py | 1 - .../algorithms/single_sample/shor/shor.py | 1 - .../aqua/circuits/boolean_logical_circuits.py | 4 +- qiskit/aqua/circuits/gates/__init__.py | 18 - .../circuits/gates/boolean_logical_gates.py | 1 - .../gates/multi_control_rotation_gates.py | 228 ------------- .../gates/multi_control_toffoli_gate.py | 322 ------------------ .../circuits/gates/multi_control_u1_gate.py | 103 ------ .../circuits/gates/relative_phase_toffoli.py | 135 -------- qiskit/aqua/circuits/polynomial_rotation.py | 1 - .../components/reciprocals/long_division.py | 1 - .../components/reciprocals/lookup_rotation.py | 6 +- 12 files changed, 5 insertions(+), 816 deletions(-) delete mode 100644 qiskit/aqua/circuits/gates/multi_control_rotation_gates.py delete mode 100644 qiskit/aqua/circuits/gates/multi_control_toffoli_gate.py delete mode 100644 qiskit/aqua/circuits/gates/multi_control_u1_gate.py delete mode 100644 qiskit/aqua/circuits/gates/relative_phase_toffoli.py diff --git a/qiskit/aqua/algorithms/single_sample/grover/grover.py b/qiskit/aqua/algorithms/single_sample/grover/grover.py index b4be0ea2e8..7e92eb6bfe 100644 --- a/qiskit/aqua/algorithms/single_sample/grover/grover.py +++ b/qiskit/aqua/algorithms/single_sample/grover/grover.py @@ -30,7 +30,6 @@ from qiskit.aqua.components.initial_states import Custom from qiskit.aqua.components.oracles import Oracle from qiskit.aqua.components.initial_states import InitialState -from qiskit.aqua.circuits.gates import mct # pylint: disable=unused-import logger = logging.getLogger(__name__) diff --git a/qiskit/aqua/algorithms/single_sample/shor/shor.py b/qiskit/aqua/algorithms/single_sample/shor/shor.py index 68d0153f7c..2b240b55af 100644 --- a/qiskit/aqua/algorithms/single_sample/shor/shor.py +++ b/qiskit/aqua/algorithms/single_sample/shor/shor.py @@ -29,7 +29,6 @@ from qiskit.aqua.utils import get_subsystem_density_matrix from qiskit.aqua.algorithms import QuantumAlgorithm from qiskit.aqua.circuits import FourierTransformCircuits as ftc -from qiskit.aqua.circuits.gates import mcu1 # pylint: disable=unused-import from qiskit.aqua.utils import summarize_circuits from qiskit.aqua.utils.validation import validate_min diff --git a/qiskit/aqua/circuits/boolean_logical_circuits.py b/qiskit/aqua/circuits/boolean_logical_circuits.py index cfc6bddfa8..5ddbcde2a1 100644 --- a/qiskit/aqua/circuits/boolean_logical_circuits.py +++ b/qiskit/aqua/circuits/boolean_logical_circuits.py @@ -22,7 +22,6 @@ from qiskit.qasm import pi from qiskit.aqua import AquaError -from .gates import mct # pylint: disable=unused-import logger = logging.getLogger(__name__) @@ -261,6 +260,7 @@ class CNF(BooleanLogicNormalForm): """ Class for constructing circuits for Conjunctive Normal Forms """ + def construct_circuit( self, circuit=None, @@ -367,6 +367,7 @@ class DNF(BooleanLogicNormalForm): """ Class for constructing circuits for Disjunctive Normal Forms """ + def construct_circuit( self, circuit=None, @@ -480,6 +481,7 @@ class ESOP(BooleanLogicNormalForm): """ Class for constructing circuits for Exclusive Sum of Products """ + def construct_circuit( self, circuit=None, diff --git a/qiskit/aqua/circuits/gates/__init__.py b/qiskit/aqua/circuits/gates/__init__.py index 24316d8462..a95836c1e4 100644 --- a/qiskit/aqua/circuits/gates/__init__.py +++ b/qiskit/aqua/circuits/gates/__init__.py @@ -29,35 +29,17 @@ :toctree: ../stubs/ :nosignatures: - mcu1 - mcrx - mcry - mcrz - mct mcmt logical_and logical_or - rccx - rcccx """ -from .multi_control_u1_gate import mcu1 -from .multi_control_rotation_gates import mcrx, mcry, mcrz -from .multi_control_toffoli_gate import mct from .multi_control_multi_target_gate import mcmt from .boolean_logical_gates import logical_and, logical_or -from .relative_phase_toffoli import rccx, rcccx __all__ = [ - 'mcu1', - 'mcrx', - 'mcry', - 'mcrz', - 'mct', 'mcmt', 'logical_and', 'logical_or', - 'rccx', - 'rcccx' ] diff --git a/qiskit/aqua/circuits/gates/boolean_logical_gates.py b/qiskit/aqua/circuits/gates/boolean_logical_gates.py index 7a606e4baf..a5a37ee492 100644 --- a/qiskit/aqua/circuits/gates/boolean_logical_gates.py +++ b/qiskit/aqua/circuits/gates/boolean_logical_gates.py @@ -22,7 +22,6 @@ from qiskit.qasm import pi from qiskit.aqua import AquaError -from .multi_control_toffoli_gate import mct # pylint: disable=unused-import logger = logging.getLogger(__name__) diff --git a/qiskit/aqua/circuits/gates/multi_control_rotation_gates.py b/qiskit/aqua/circuits/gates/multi_control_rotation_gates.py deleted file mode 100644 index 2db906edca..0000000000 --- a/qiskit/aqua/circuits/gates/multi_control_rotation_gates.py +++ /dev/null @@ -1,228 +0,0 @@ -# -*- coding: utf-8 -*- - -# This code is part of Qiskit. -# -# (C) Copyright IBM 2018, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. -""" -Multiple-Control U3 gate. Not using ancillary qubits. -""" - -import logging -from math import pi -from sympy.combinatorics.graycode import GrayCode - -from qiskit.circuit import QuantumCircuit, QuantumRegister, Qubit - -from qiskit.aqua.utils.controlled_circuit import apply_cu3 - -from qiskit.aqua import AquaError - -logger = logging.getLogger(__name__) - - -def _apply_mcu3_graycode(circuit, theta, phi, lam, ctls, tgt, use_basis_gates): - """Apply multi-controlled u3 gate from ctls to tgt using graycode - pattern with single-step angles theta, phi, lam.""" - - n = len(ctls) - - gray_code = list(GrayCode(n).generate_gray()) - last_pattern = None - - for pattern in gray_code: - if '1' not in pattern: - continue - if last_pattern is None: - last_pattern = pattern - # find left most set bit - lm_pos = list(pattern).index('1') - - # find changed bit - comp = [i != j for i, j in zip(pattern, last_pattern)] - if True in comp: - pos = comp.index(True) - else: - pos = None - if pos is not None: - if pos != lm_pos: - circuit.cx(ctls[pos], ctls[lm_pos]) - else: - indices = [i for i, x in enumerate(pattern) if x == '1'] - for idx in indices[1:]: - circuit.cx(ctls[idx], ctls[lm_pos]) - # check parity and undo rotation - if pattern.count('1') % 2 == 0: - # inverse CU3: u3(theta, phi, lamb)^dagger = u3(-theta, -lam, -phi) - apply_cu3(circuit, -theta, -lam, -phi, ctls[lm_pos], tgt, - use_basis_gates=use_basis_gates) - else: - apply_cu3(circuit, theta, phi, lam, ctls[lm_pos], tgt, - use_basis_gates=use_basis_gates) - last_pattern = pattern - - -def mcrx(self, theta, q_controls, q_target, use_basis_gates=False): - """ - Apply Multiple-Controlled X rotation gate - - Args: - self (QuantumCircuit): The QuantumCircuit object to apply the mcrx gate on. - theta (float): angle theta - q_controls (list[Qubit]): The list of control qubits - q_target (Qubit): The target qubit - use_basis_gates (bool): use basis gates - Raises: - AquaError: invalid input - """ - - # check controls - if isinstance(q_controls, QuantumRegister): - control_qubits = list(q_controls) - elif isinstance(q_controls, list): - control_qubits = q_controls - else: - raise AquaError( - 'The mcrx gate needs a list of qubits or a quantum register for controls.') - - # check target - if isinstance(q_target, Qubit): - target_qubit = q_target - else: - raise AquaError('The mcrx gate needs a single qubit as target.') - - all_qubits = control_qubits + [target_qubit] - - self._check_qargs(all_qubits) - self._check_dups(all_qubits) - - n_c = len(control_qubits) - if n_c == 1: # cu3 - apply_cu3(self, theta, -pi/2, pi/2, control_qubits[0], - target_qubit, use_basis_gates=use_basis_gates) - else: - theta_step = theta * (1 / (2 ** (n_c - 1))) - _apply_mcu3_graycode(self, theta_step, -pi/2, pi/2, control_qubits, - target_qubit, use_basis_gates=use_basis_gates) - - -def mcry(self, theta, q_controls, q_target, q_ancillae, mode='basic', - use_basis_gates=False): - """ - Apply Multiple-Controlled Y rotation gate - - Args: - self (QuantumCircuit): The QuantumCircuit object to apply the mcry gate on. - theta (float): angle theta - q_controls (list[Qubit]): The list of control qubits - q_target (Qubit): The target qubit - q_ancillae (Union(QuantumRegister,tuple(QuantumRegister, int))): - The list of ancillary qubits. - mode (str): The implementation mode to use - use_basis_gates (bool): use basis gates - Raises: - AquaError: invalid input - """ - - # check controls - if isinstance(q_controls, QuantumRegister): - control_qubits = list(q_controls) - elif isinstance(q_controls, list): - control_qubits = q_controls - else: - raise AquaError('The mcry gate needs a list of qubits or a quantum register for controls.') - - # check target - if isinstance(q_target, Qubit): - target_qubit = q_target - else: - raise AquaError('The mcry gate needs a single qubit as target.') - - # check ancilla - if q_ancillae is None: - ancillary_qubits = [] - elif isinstance(q_ancillae, QuantumRegister): - ancillary_qubits = list(q_ancillae) - elif isinstance(q_ancillae, list): - ancillary_qubits = q_ancillae - else: - raise AquaError('The mcry gate needs None or a list ' - 'of qubits or a quantum register for ancilla.') - - all_qubits = control_qubits + [target_qubit] + ancillary_qubits - - self._check_qargs(all_qubits) - self._check_dups(all_qubits) - - if mode == 'basic': - self.u3(theta / 2, 0, 0, q_target) - self.mct(q_controls, q_target, q_ancillae) - self.u3(-theta / 2, 0, 0, q_target) - self.mct(q_controls, q_target, q_ancillae) - elif mode == 'noancilla': - n_c = len(control_qubits) - if n_c == 1: # cu3 - apply_cu3(self, theta, 0, 0, control_qubits[0], - target_qubit, use_basis_gates=use_basis_gates) - else: - theta_step = theta * (1 / (2 ** (n_c - 1))) - _apply_mcu3_graycode(self, theta_step, 0, 0, control_qubits, - target_qubit, use_basis_gates=use_basis_gates) - else: - raise AquaError('Unrecognized mode for building MCRY circuit: {}.'.format(mode)) - - -def mcrz(self, lam, q_controls, q_target, use_basis_gates=False): - """ - Apply Multiple-Controlled Z rotation gate - - Args: - self (QuantumCircuit): The QuantumCircuit object to apply the mcrz gate on. - lam (float): angle lam - q_controls (list[Qubit]): The list of control qubits - q_target (Qubit): The target qubit - use_basis_gates (bool): use basis gates - Raises: - AquaError: invalid input - """ - - # check controls - if isinstance(q_controls, QuantumRegister): - control_qubits = list(q_controls) - elif isinstance(q_controls, list): - control_qubits = q_controls - else: - raise AquaError( - 'The mcrz gate needs a list of qubits or a quantum register for controls.') - - # check target - if isinstance(q_target, Qubit): - target_qubit = q_target - else: - raise AquaError('The mcrz gate needs a single qubit as target.') - - all_qubits = control_qubits + [target_qubit] - - self._check_qargs(all_qubits) - self._check_dups(all_qubits) - - n_c = len(control_qubits) - if n_c == 1: # cu3 - apply_cu3(self, 0, 0, lam, control_qubits[0], - target_qubit, use_basis_gates=use_basis_gates) - else: - lam_step = lam * (1 / (2 ** (n_c - 1))) - _apply_mcu3_graycode(self, 0, 0, lam_step, control_qubits, - target_qubit, use_basis_gates=use_basis_gates) - - -QuantumCircuit.mcrx = mcrx -QuantumCircuit.mcry = mcry -QuantumCircuit.mcrz = mcrz diff --git a/qiskit/aqua/circuits/gates/multi_control_toffoli_gate.py b/qiskit/aqua/circuits/gates/multi_control_toffoli_gate.py deleted file mode 100644 index 83555e2a3c..0000000000 --- a/qiskit/aqua/circuits/gates/multi_control_toffoli_gate.py +++ /dev/null @@ -1,322 +0,0 @@ -# -*- coding: utf-8 -*- - -# This code is part of Qiskit. -# -# (C) Copyright IBM 2018, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -""" -Multiple-Control Toffoli Gate. -""" - -import logging -from math import pi, ceil - -from qiskit.circuit import QuantumCircuit, QuantumRegister, Qubit - -from qiskit.aqua import AquaError -from .relative_phase_toffoli import rccx # pylint: disable=unused-import - -logger = logging.getLogger(__name__) - -# pylint: disable=invalid-name - - -def _mct_v_chain(qc, control_qubits, target_qubit, ancillary_qubits, dirty_ancilla=False): - """ - Create new MCT circuit by chaining Toffoli gates into a V shape. - - The dirty_ancilla mode is from https://arxiv.org/abs/quant-ph/9503016 Lemma 7.2 - - All intermediate Toffoli gates are implemented up to a relative phase, - see https://arxiv.org/abs/1508.03273 - - An additional saving of 4 CNOTs is achieved - by using the Toffoli implementation from Section IV.B of https://arxiv.org/abs/1508.03273 - """ - - if len(ancillary_qubits) < len(control_qubits) - 2: - raise AquaError('Insufficient number of ancillary qubits.') - - if dirty_ancilla: - anci_idx = len(control_qubits) - 3 - - qc.u2(0, pi, target_qubit) - qc.cx(target_qubit, ancillary_qubits[anci_idx]) - qc.u1(-pi/4, ancillary_qubits[anci_idx]) - qc.cx(control_qubits[len(control_qubits) - 1], ancillary_qubits[anci_idx]) - qc.u1(pi/4, ancillary_qubits[anci_idx]) - qc.cx(target_qubit, ancillary_qubits[anci_idx]) - qc.u1(-pi/4, ancillary_qubits[anci_idx]) - qc.cx(control_qubits[len(control_qubits) - 1], ancillary_qubits[anci_idx]) - qc.u1(pi/4, ancillary_qubits[anci_idx]) - - for idx in reversed(range(2, len(control_qubits) - 1)): - qc.rccx(control_qubits[idx], ancillary_qubits[anci_idx - 1], ancillary_qubits[anci_idx]) - anci_idx -= 1 - - anci_idx = 0 - qc.rccx(control_qubits[0], control_qubits[1], ancillary_qubits[anci_idx]) - for idx in range(2, len(control_qubits) - 1): - qc.rccx(control_qubits[idx], ancillary_qubits[anci_idx], ancillary_qubits[anci_idx + 1]) - anci_idx += 1 - - if dirty_ancilla: - qc.u1(-pi/4, ancillary_qubits[anci_idx]) - qc.cx(control_qubits[len(control_qubits) - 1], ancillary_qubits[anci_idx]) - qc.u1(pi/4, ancillary_qubits[anci_idx]) - qc.cx(target_qubit, ancillary_qubits[anci_idx]) - qc.u1(-pi/4, ancillary_qubits[anci_idx]) - qc.cx(control_qubits[len(control_qubits) - 1], ancillary_qubits[anci_idx]) - qc.u1(pi/4, ancillary_qubits[anci_idx]) - qc.cx(target_qubit, ancillary_qubits[anci_idx]) - qc.u2(0, pi, target_qubit) - else: - qc.ccx(control_qubits[len(control_qubits) - 1], ancillary_qubits[anci_idx], target_qubit) - - for idx in reversed(range(2, len(control_qubits) - 1)): - qc.rccx(control_qubits[idx], ancillary_qubits[anci_idx - 1], ancillary_qubits[anci_idx]) - anci_idx -= 1 - qc.rccx(control_qubits[0], control_qubits[1], ancillary_qubits[anci_idx]) - - if dirty_ancilla: - anci_idx = 0 - for idx in range(2, len(control_qubits) - 1): - qc.rccx(control_qubits[idx], ancillary_qubits[anci_idx], ancillary_qubits[anci_idx + 1]) - anci_idx += 1 - - -def _cccx(qc, qrs, angle=pi / 4): - """ - A 3-qubit controlled-NOT. - - Implementation based on Page 17 of Barenco et al. - - Args: - qc (QuantumCircuit): quantum circuit - qrs (list[QuantumRegister]): The last qubit is the target, the rest are controls - - angle (float): default pi/4 when x is the NOT gate, set to pi/8 for square root of NOT - """ - assert len(qrs) == 4, "There must be exactly 4 qubits of quantum registers for cccx" - - # controlled-V - qc.h(qrs[3]) - qc.cu1(-angle, qrs[0], qrs[3]) - qc.h(qrs[3]) - # ------------ - - qc.cx(qrs[0], qrs[1]) - - # controlled-Vdag - qc.h(qrs[3]) - qc.cu1(angle, qrs[1], qrs[3]) - qc.h(qrs[3]) - # --------------- - - qc.cx(qrs[0], qrs[1]) - - # controlled-V - qc.h(qrs[3]) - qc.cu1(-angle, qrs[1], qrs[3]) - qc.h(qrs[3]) - # ------------ - - qc.cx(qrs[1], qrs[2]) - - # controlled-Vdag - qc.h(qrs[3]) - qc.cu1(angle, qrs[2], qrs[3]) - qc.h(qrs[3]) - # --------------- - - qc.cx(qrs[0], qrs[2]) - - # controlled-V - qc.h(qrs[3]) - qc.cu1(-angle, qrs[2], qrs[3]) - qc.h(qrs[3]) - # ------------ - - qc.cx(qrs[1], qrs[2]) - - # controlled-Vdag - qc.h(qrs[3]) - qc.cu1(angle, qrs[2], qrs[3]) - qc.h(qrs[3]) - # --------------- - - qc.cx(qrs[0], qrs[2]) - - # controlled-V - qc.h(qrs[3]) - qc.cu1(-angle, qrs[2], qrs[3]) - qc.h(qrs[3]) - - -def _ccccx(qc, qrs): - """ - a 4-qubit controlled-NOT. - - An implementation based on Page 21 (Lemma 7.5) of Barenco et al. - - Args: - qc (QuantumCircuit): quantum circuit - qrs (list[QuantumRegister]): The last qubit is the target, the rest are controls - """ - assert len(qrs) == 5, "There must be exactly 5 qubits for ccccx" - - # controlled-V - qc.h(qrs[4]) - qc.cu1(-pi / 2, qrs[3], qrs[4]) - qc.h(qrs[4]) - # ------------ - - _cccx(qc, qrs[:4]) - - # controlled-Vdag - qc.h(qrs[4]) - qc.cu1(pi / 2, qrs[3], qrs[4]) - qc.h(qrs[4]) - # ------------ - - _cccx(qc, qrs[:4]) - _cccx(qc, [qrs[0], qrs[1], qrs[2], qrs[4]], angle=pi / 8) - - -def _multicx(qc, qrs, qancilla=None): - """ - Construct a circuit for multi-qubit controlled not - - Args: - qc (QuantumCircuit): quantum circuit - qrs (list[QuantumRegister]): list of quantum registers of at least length 1 - qancilla (QuantumRegister): a quantum register. can be None if len(qrs) <= 5 - - Returns: - qc: a circuit appended with multi-qubit cnot - """ - if not qrs: - pass - elif len(qrs) == 1: - qc.x(qrs[0]) - elif len(qrs) == 2: - qc.cx(qrs[0], qrs[1]) - elif len(qrs) == 3: - qc.ccx(qrs[0], qrs[1], qrs[2]) - else: - _multicx_recursion(qc, qrs, qancilla) - - -def _multicx_recursion(qc, qrs, qancilla=None): - if len(qrs) == 4: - _cccx(qc, qrs) - elif len(qrs) == 5: - _ccccx(qc, qrs) - else: # qrs[0], qrs[n-2] is the controls, qrs[n-1] is the target, and qancilla as working qubit - assert qancilla is not None, \ - "There must be an ancilla qubit not necessarily initialized to zero" - n = len(qrs) - m1 = ceil(n / 2) - _multicx_recursion(qc, [*qrs[:m1], qancilla], qrs[m1]) - _multicx_recursion(qc, [*qrs[m1:n - 1], qancilla, qrs[n - 1]], qrs[m1 - 1]) - _multicx_recursion(qc, [*qrs[:m1], qancilla], qrs[m1]) - _multicx_recursion(qc, [*qrs[m1:n - 1], qancilla, qrs[n - 1]], qrs[m1 - 1]) - - -def _multicx_noancilla(qc, qrs): - """ - Construct a circuit for multi-qubit controlled not without ancillary qubits - - Args: - qc (QuantumCircuit): quantum circuit - qrs (list): list of quantum registers of at least length 1 - - Returns: - QuantumCircuit: a circuit appended with multi-qubit cnot - """ - if not qrs: - pass - elif len(qrs) == 1: - qc.x(qrs[0]) - elif len(qrs) == 2: - qc.cx(qrs[0], qrs[1]) - else: - # qrs[0], qrs[n-2] is the controls, qrs[n-1] is the target - ctls = qrs[:-1] - tgt = qrs[-1] - qc.h(tgt) - qc.mcu1(pi, ctls, tgt) - qc.h(tgt) - - -def mct(self, q_controls, q_target, q_ancilla, mode='basic'): - """ - Apply Multiple-Control Toffoli operation - - Args: - self (QuantumCircuit): The QuantumCircuit object to apply the mct gate on. - q_controls (Union(QuantumRegister, list[Qubit])): The list of control qubits - q_target (Qubit): The target qubit - q_ancilla (Union(QuantumRegister, list[Qubit])): The list of ancillary qubits - mode (str): The implementation mode to use - Raises: - AquaError: invalid input - """ - - if len(q_controls) == 1: # cx - self.cx(q_controls[0], q_target) - elif len(q_controls) == 2: # ccx - self.ccx(q_controls[0], q_controls[1], q_target) - else: - # check controls - if isinstance(q_controls, QuantumRegister): - control_qubits = list(q_controls) - elif isinstance(q_controls, list): - control_qubits = q_controls - else: - raise AquaError('MCT needs a list of qubits or a quantum register for controls.') - - # check target - if isinstance(q_target, Qubit): - target_qubit = q_target - else: - raise AquaError('MCT needs a single qubit as target.') - - # check ancilla - if q_ancilla is None: - ancillary_qubits = [] - elif isinstance(q_ancilla, QuantumRegister): - ancillary_qubits = list(q_ancilla) - elif isinstance(q_ancilla, list): - ancillary_qubits = q_ancilla - else: - raise AquaError('MCT needs None or a list of qubits or a quantum register for ancilla.') - - all_qubits = control_qubits + [target_qubit] + ancillary_qubits - - self._check_qargs(all_qubits) - self._check_dups(all_qubits) - - if mode == 'basic': - _mct_v_chain(self, control_qubits, target_qubit, ancillary_qubits, dirty_ancilla=False) - elif mode == 'basic-dirty-ancilla': - _mct_v_chain(self, control_qubits, target_qubit, ancillary_qubits, dirty_ancilla=True) - elif mode == 'advanced': - _multicx(self, - [*control_qubits, target_qubit], - ancillary_qubits[0] if ancillary_qubits else None) - elif mode == 'noancilla': - _multicx_noancilla(self, [*control_qubits, target_qubit]) - else: - raise AquaError('Unrecognized mode for building MCT circuit: {}.'.format(mode)) - - -QuantumCircuit.mct = mct diff --git a/qiskit/aqua/circuits/gates/multi_control_u1_gate.py b/qiskit/aqua/circuits/gates/multi_control_u1_gate.py deleted file mode 100644 index c2c46cb267..0000000000 --- a/qiskit/aqua/circuits/gates/multi_control_u1_gate.py +++ /dev/null @@ -1,103 +0,0 @@ -# -*- coding: utf-8 -*- - -# This code is part of Qiskit. -# -# (C) Copyright IBM 2018, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. -""" -Multiple-Control U1 gate. Not using ancillary qubits. -""" - -import logging -from numpy import angle - -from sympy.combinatorics.graycode import GrayCode -from qiskit.circuit import QuantumCircuit, QuantumRegister, Qubit # pylint: disable=unused-import - - -from qiskit.aqua.utils.controlled_circuit import apply_cu1 - -logger = logging.getLogger(__name__) - - -def _apply_mcu1(circuit, lam, ctls, tgt, global_phase=0): - """Apply multi-controlled u1 gate from ctls to tgt with angle theta.""" - - n = len(ctls) - - gray_code = list(GrayCode(n).generate_gray()) - last_pattern = None - - lam_angle = lam*(1/(2**(n-1))) - gp_angle = angle(global_phase)*(1/(2**(n-1))) - - for pattern in gray_code: - if '1' not in pattern: - continue - if last_pattern is None: - last_pattern = pattern - # find left most set bit - lm_pos = list(pattern).index('1') - - # find changed bit - comp = [i != j for i, j in zip(pattern, last_pattern)] - if True in comp: - pos = comp.index(True) - else: - pos = None - if pos is not None: - if pos != lm_pos: - circuit.cx(ctls[pos], ctls[lm_pos]) - else: - indices = [i for i, x in enumerate(pattern) if x == '1'] - for idx in indices[1:]: - circuit.cx(ctls[idx], ctls[lm_pos]) - # check parity - if pattern.count('1') % 2 == 0: - # inverse - apply_cu1(circuit, -lam_angle, ctls[lm_pos], tgt) - if global_phase: - circuit.u1(-gp_angle, ctls[lm_pos]) - else: - apply_cu1(circuit, lam_angle, ctls[lm_pos], tgt) - if global_phase: - circuit.u1(gp_angle, ctls[lm_pos]) - last_pattern = pattern - - -def mcu1(self, lam, control_qubits, target_qubit): - """ - Apply Multiple-Controlled U1 gate - - Args: - self (QuantumCircuit): The QuantumCircuit object to apply the mcu1 gate on. - lam (float): angle lambda - control_qubits (list[Qubit]): The list of control qubits - target_qubit (Qubit): The target qubit - """ - if isinstance(target_qubit, QuantumRegister) and len(target_qubit) == 1: - target_qubit = target_qubit[0] - temp = [] - - self._check_qargs(control_qubits) - temp += control_qubits - - self._check_qargs([target_qubit]) - temp.append(target_qubit) - - self._check_dups(temp) - n_c = len(control_qubits) - if n_c == 1: # cu1 - apply_cu1(self, lam, control_qubits[0], target_qubit) - else: - _apply_mcu1(self, lam, control_qubits, target_qubit) - - -QuantumCircuit.mcu1 = mcu1 diff --git a/qiskit/aqua/circuits/gates/relative_phase_toffoli.py b/qiskit/aqua/circuits/gates/relative_phase_toffoli.py deleted file mode 100644 index ac4b57ab2b..0000000000 --- a/qiskit/aqua/circuits/gates/relative_phase_toffoli.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- - -# This code is part of Qiskit. -# -# (C) Copyright IBM 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -""" -Relative Phase Toffoli Gates. -""" - -from qiskit.circuit import QuantumCircuit, Qubit -from qiskit.qasm import pi - -from qiskit.aqua import AquaError - -# pylint: disable=invalid-name - - -def _apply_rccx(circ, a, b, c): - circ.u2(0, pi, c) # h - circ.u1(pi / 4, c) # t - circ.cx(b, c) - circ.u1(-pi / 4, c) # tdg - circ.cx(a, c) - circ.u1(pi / 4, c) # t - circ.cx(b, c) - circ.u1(-pi / 4, c) # tdg - circ.u2(0, pi, c) # h - - -def _apply_rcccx(circ, a, b, c, d): - circ.u2(0, pi, d) # h - circ.u1(pi / 4, d) # t - circ.cx(c, d) - circ.u1(-pi / 4, d) # tdg - circ.u2(0, pi, d) # h - circ.cx(a, d) - circ.u1(pi / 4, d) # t - circ.cx(b, d) - circ.u1(-pi / 4, d) # tdg - circ.cx(a, d) - circ.u1(pi / 4, d) # t - circ.cx(b, d) - circ.u1(-pi / 4, d) # tdg - circ.u2(0, pi, d) # h - circ.u1(pi / 4, d) # t - circ.cx(c, d) - circ.u1(-pi / 4, d) # tdg - circ.u2(0, pi, d) # h - - -def rccx(self, q_control_1, q_control_2, q_target): - """ - Apply 2-Control Relative-Phase Toffoli gate from q_control_1 and q_control_2 to q_target. - - The implementation is based on https://arxiv.org/pdf/1508.03273.pdf Figure 3 - - Args: - self (QuantumCircuit): The QuantumCircuit object to apply the rccx gate on. - q_control_1 (Qubit): The 1st control qubit. - q_control_2 (Qubit): The 2nd control qubit. - q_target (Qubit): The target qubit. - Raises: - AquaError: invalid input - - """ - if not isinstance(q_control_1, Qubit): - raise AquaError('A qubit is expected for the first control.') - if not self.has_register(q_control_1.register): - raise AquaError('The first control qubit is expected to be part of the circuit.') - - if not isinstance(q_control_2, Qubit): - raise AquaError('A qubit is expected for the second control.') - if not self.has_register(q_control_2.register): - raise AquaError('The second control qubit is expected to be part of the circuit.') - - if not isinstance(q_target, Qubit): - raise AquaError('A qubit is expected for the target.') - if not self.has_register(q_target.register): - raise AquaError('The target qubit is expected to be part of the circuit.') - self._check_dups([q_control_1, q_control_2, q_target]) - _apply_rccx(self, q_control_1, q_control_2, q_target) - - -def rcccx(self, q_control_1, q_control_2, q_control_3, q_target): - """ - Apply 3-Control Relative-Phase Toffoli gate from q_control_1, - q_control_2, and q_control_3 to q_target. - - The implementation is based on https://arxiv.org/pdf/1508.03273.pdf Figure 4 - - Args: - self (QuantumCircuit): The QuantumCircuit object to apply the rcccx gate on. - q_control_1 (Qubit): The 1st control qubit. - q_control_2 (Qubit): The 2nd control qubit. - q_control_3 (Qubit): The 3rd control qubit. - q_target (Qubit): The target qubit. - Raises: - AquaError: invalid input - - """ - if not isinstance(q_control_1, Qubit): - raise AquaError('A qubit is expected for the first control.') - if not self.has_register(q_control_1.register): - raise AquaError('The first control qubit is expected to be part of the circuit.') - - if not isinstance(q_control_2, Qubit): - raise AquaError('A qubit is expected for the second control.') - if not self.has_register(q_control_2.register): - raise AquaError('The second control qubit is expected to be part of the circuit.') - - if not isinstance(q_control_3, Qubit): - raise AquaError('A qubit is expected for the third control.') - if not self.has_register(q_control_3.register): - raise AquaError('The third control qubit is expected to be part of the circuit.') - - if not isinstance(q_target, Qubit): - raise AquaError('A qubit is expected for the target.') - if not self.has_register(q_target.register): - raise AquaError('The target qubit is expected to be part of the circuit.') - - self._check_dups([q_control_1, q_control_2, q_control_3, q_target]) - _apply_rcccx(self, q_control_1, q_control_2, q_control_3, q_target) - - -QuantumCircuit.rccx = rccx -QuantumCircuit.rcccx = rcccx diff --git a/qiskit/aqua/circuits/polynomial_rotation.py b/qiskit/aqua/circuits/polynomial_rotation.py index 8f55c1af3b..3e4294dada 100644 --- a/qiskit/aqua/circuits/polynomial_rotation.py +++ b/qiskit/aqua/circuits/polynomial_rotation.py @@ -21,7 +21,6 @@ import numpy as np from qiskit.aqua.utils import CircuitFactory -from qiskit.aqua.circuits.gates import mcrx, mcry, mcrz # pylint: disable=unused-import # pylint: disable=invalid-name diff --git a/qiskit/aqua/components/reciprocals/long_division.py b/qiskit/aqua/components/reciprocals/long_division.py index bc169efaf2..6503993500 100644 --- a/qiskit/aqua/components/reciprocals/long_division.py +++ b/qiskit/aqua/components/reciprocals/long_division.py @@ -23,7 +23,6 @@ import numpy as np from qiskit import QuantumRegister, QuantumCircuit from qiskit.aqua.components.reciprocals import Reciprocal -from qiskit.aqua.circuits.gates import mct # pylint: disable=unused-import # pylint: disable=invalid-name diff --git a/qiskit/aqua/components/reciprocals/lookup_rotation.py b/qiskit/aqua/components/reciprocals/lookup_rotation.py index 13efb0808e..ae154e5cb0 100644 --- a/qiskit/aqua/components/reciprocals/lookup_rotation.py +++ b/qiskit/aqua/components/reciprocals/lookup_rotation.py @@ -21,7 +21,6 @@ from qiskit import QuantumRegister, QuantumCircuit from qiskit.aqua.components.reciprocals import Reciprocal -from qiskit.aqua.circuits.gates import mct # pylint: disable=unused-import from qiskit.aqua.utils.validation import validate_range logger = logging.getLogger(__name__) @@ -274,7 +273,6 @@ def _set_bit_pattern(self, pattern, tgt, offset): qc.x(self._ev[int(c + offset)]) def construct_circuit(self, mode, inreg): # pylint: disable=arguments-differ - """Construct the Lookup Rotation circuit. Args: @@ -304,12 +302,12 @@ def construct_circuit(self, mode, inreg): # pylint: disable=arguments-differ if self._pat_length is None: if self._reg_size <= 6: self._pat_length = self._reg_size - \ - (2 if self._negative_evals else 1) + (2 if self._negative_evals else 1) else: self._pat_length = 5 if self._reg_size <= self._pat_length: self._pat_length = self._reg_size - \ - (2 if self._negative_evals else 1) + (2 if self._negative_evals else 1) if self._subpat_length is None: self._subpat_length = int(np.ceil(self._pat_length/2)) m = self._subpat_length From 74a720e5c6a98a03612167f2a94cf35bfabe3542 Mon Sep 17 00:00:00 2001 From: Julien Gacon Date: Wed, 26 Feb 2020 12:00:51 +0100 Subject: [PATCH 2/2] Update copyright year of boolean_logic_gates --- qiskit/aqua/circuits/gates/boolean_logical_gates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/aqua/circuits/gates/boolean_logical_gates.py b/qiskit/aqua/circuits/gates/boolean_logical_gates.py index a5a37ee492..e21969b505 100644 --- a/qiskit/aqua/circuits/gates/boolean_logical_gates.py +++ b/qiskit/aqua/circuits/gates/boolean_logical_gates.py @@ -2,7 +2,7 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019. +# (C) Copyright IBM 2019, 2020. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory