From 36e0472c3cdb4f530581b85993eedae335735156 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Thu, 9 Apr 2020 11:38:32 -0400 Subject: [PATCH] Revert "Moving up some parameter checks in the class hierarchy (#3668)" This change has some unforseen backwards compatibility implications and is causing downstream projects like qiskit-aer to fail CI now. Given the pending release and this not being critical, this commit reverts this commit and we can revisit it after the 0.13.0 release. This reverts commit 5afe87ce1e5279ca716fdf5a3c478f2e27a6519f. --- qiskit/circuit/gate.py | 9 ------ qiskit/circuit/instruction.py | 28 +++++++++++++++---- qiskit/converters/ast_to_dag.py | 13 +++++++-- .../quantum_initializer/diagonal.py | 7 ----- .../quantum_initializer/initializer.py | 9 ------ .../quantum_initializer/isometry.py | 9 ------ .../quantum_initializer/mcg_up_to_diagonal.py | 9 ------ qiskit/extensions/quantum_initializer/squ.py | 9 ------ qiskit/extensions/quantum_initializer/uc.py | 9 ------ qiskit/extensions/standard/barrier.py | 5 ---- qiskit/extensions/unitary.py | 11 ++------ .../circuit/test_extensions_standard.py | 7 +---- .../visualization/test_circuit_text_drawer.py | 2 -- 13 files changed, 36 insertions(+), 91 deletions(-) diff --git a/qiskit/circuit/gate.py b/qiskit/circuit/gate.py index 4b2c3c81cd58..53f1f5842251 100644 --- a/qiskit/circuit/gate.py +++ b/qiskit/circuit/gate.py @@ -17,7 +17,6 @@ import numpy as np from scipy.linalg import schur -from qiskit.circuit.parameter import ParameterExpression from qiskit.circuit.exceptions import CircuitError from .instruction import Instruction @@ -220,11 +219,3 @@ def broadcast_arguments(self, qargs, cargs): return Gate._broadcast_3_or_more_args(qargs) else: raise CircuitError('This gate cannot handle %i arguments' % len(qargs)) - - def validate_parameter(self, parameter): - """Gate parameters should be int, float, or ParameterExpression""" - if isinstance(parameter, (int, float, np.number, ParameterExpression)): - return parameter - else: - raise CircuitError("invalid param type {0} for gate {1}".format(type(parameter), - self.name)) diff --git a/qiskit/circuit/instruction.py b/qiskit/circuit/instruction.py index f8d8dd9b79a8..ebfce5510a15 100644 --- a/qiskit/circuit/instruction.py +++ b/qiskit/circuit/instruction.py @@ -137,11 +137,29 @@ def params(self): def params(self, parameters): self._params = [] for single_param in parameters: - self._params.append(self.validate_parameter(single_param)) - - def validate_parameter(self, parameter): - """Instruction parameters has no validation or normalization.""" - return parameter + # example: u2(pi/2, sin(pi/4)) + if isinstance(single_param, (ParameterExpression)): + self._params.append(single_param) + # example: u3(0.1, 0.2, 0.3) + elif isinstance(single_param, (int, float)): + self._params.append(single_param) + # example: Initialize([complex(0,1), complex(0,0)]) + elif isinstance(single_param, complex): + self._params.append(single_param) + # example: snapshot('label') + elif isinstance(single_param, str): + self._params.append(single_param) + # example: Aer expectation_value_snapshot [complex, 'X'] + elif isinstance(single_param, list): + self._params.append(single_param) + # example: numpy.array([[1, 0], [0, 1]]) + elif isinstance(single_param, numpy.ndarray): + self._params.append(single_param) + elif isinstance(single_param, numpy.number): + self._params.append(single_param.item()) + else: + raise CircuitError("invalid param type {0} in instruction " + "{1}".format(type(single_param), self.name)) def is_parameterized(self): """Return True .IFF. instruction is parameterized else False""" diff --git a/qiskit/converters/ast_to_dag.py b/qiskit/converters/ast_to_dag.py index fc31c15a147b..d04724409633 100644 --- a/qiskit/converters/ast_to_dag.py +++ b/qiskit/converters/ast_to_dag.py @@ -23,6 +23,7 @@ from qiskit.circuit import QuantumRegister, ClassicalRegister, Gate from qiskit.qasm.node.real import Real +from qiskit.circuit.instruction import Instruction from qiskit.circuit.measure import Measure from qiskit.circuit.reset import Reset from qiskit.extensions.standard.barrier import Barrier @@ -401,9 +402,15 @@ def _create_op(self, name, params): if name in self.standard_extension: op = self.standard_extension[name](*params) elif name in self.gates: - op = Gate(name=name, num_qubits=self.gates[name]['n_bits'], params=params) - if not self.gates[name]['opaque']: - # call a custom gate (otherwise, opaque) + if self.gates[name]['opaque']: + # call an opaque gate + op = Gate(name=name, num_qubits=self.gates[name]['n_bits'], params=params) + else: + # call a custom gate + op = Instruction(name=name, + num_qubits=self.gates[name]['n_bits'], + num_clbits=0, + params=params) op.definition = self._gate_definition_to_qiskit_definition(self.gates[name], params=params) else: diff --git a/qiskit/extensions/quantum_initializer/diagonal.py b/qiskit/extensions/quantum_initializer/diagonal.py index f3a2c7c27d47..1083ffd36946 100644 --- a/qiskit/extensions/quantum_initializer/diagonal.py +++ b/qiskit/extensions/quantum_initializer/diagonal.py @@ -79,13 +79,6 @@ def _define(self): diag_circuit.append(gate, q[:]) self.definition = diag_circuit.data - def validate_parameter(self, parameter): - """Diagonal Gate parameter can be complex in addition to the Gate parameter types.""" - if isinstance(parameter, complex): - return parameter - else: - return super().validate_parameter(parameter) - def _dec_diag(self): """ Call to create a circuit implementing the diagonal gate. diff --git a/qiskit/extensions/quantum_initializer/initializer.py b/qiskit/extensions/quantum_initializer/initializer.py index b3d86b36f695..d0ae22dab026 100644 --- a/qiskit/extensions/quantum_initializer/initializer.py +++ b/qiskit/extensions/quantum_initializer/initializer.py @@ -23,7 +23,6 @@ from qiskit.circuit import QuantumCircuit from qiskit.circuit import QuantumRegister from qiskit.circuit import Instruction -from qiskit.circuit.exceptions import CircuitError from qiskit.extensions.standard.x import CXGate from qiskit.extensions.standard.ry import RYGate from qiskit.extensions.standard.rz import RZGate @@ -247,14 +246,6 @@ def broadcast_arguments(self, qargs, cargs): (2**self.num_qubits, self.num_qubits, len(flat_qargs))) yield flat_qargs, [] - def validate_parameter(self, parameter): - """Initialize instruction parameter can be int, float, and complex.""" - if isinstance(parameter, (int, float, complex)): - return parameter - else: - raise CircuitError("invalid param type {0} for instruction " - "{1}".format(type(parameter), self.name)) - def initialize(self, params, qubits): """Apply initialize to circuit.""" diff --git a/qiskit/extensions/quantum_initializer/isometry.py b/qiskit/extensions/quantum_initializer/isometry.py index 9c5203580c41..106976cd2100 100644 --- a/qiskit/extensions/quantum_initializer/isometry.py +++ b/qiskit/extensions/quantum_initializer/isometry.py @@ -28,7 +28,6 @@ from qiskit import QuantumRegister from qiskit.circuit import Instruction from qiskit.circuit import QuantumCircuit -from qiskit.circuit.exceptions import CircuitError from qiskit.exceptions import QiskitError from qiskit.quantum_info.operators.predicates import is_isometry from qiskit.extensions.quantum_initializer.uc import UCGate @@ -258,14 +257,6 @@ def _define_qubit_role(self, q): q_ancillas_dirty = q[n + self.num_ancillas_zero:] return q_input, q_ancillas_for_output, q_ancillas_zero, q_ancillas_dirty - def validate_parameter(self, parameter): - """Isometry parameter has to be an ndarray.""" - if isinstance(parameter, np.ndarray): - return parameter - else: - raise CircuitError("invalid param type {0} for gate " - "{1}".format(type(parameter), self.name)) - # Find special unitary matrix that maps [c0,c1] to [r,0] or [0,r] if basis_state=0 or # basis_state=1 respectively diff --git a/qiskit/extensions/quantum_initializer/mcg_up_to_diagonal.py b/qiskit/extensions/quantum_initializer/mcg_up_to_diagonal.py index f0f3c38d8ab7..01f71829eacf 100644 --- a/qiskit/extensions/quantum_initializer/mcg_up_to_diagonal.py +++ b/qiskit/extensions/quantum_initializer/mcg_up_to_diagonal.py @@ -29,7 +29,6 @@ from qiskit.circuit.quantumcircuit import QuantumRegister, QuantumCircuit from qiskit.quantum_info.operators.predicates import is_isometry from qiskit.exceptions import QiskitError -from qiskit.circuit.exceptions import CircuitError from qiskit.extensions.quantum_initializer.uc import UCGate _EPS = 1e-10 # global variable used to chop very small numbers to zero @@ -117,11 +116,3 @@ def _define_qubit_role(self, q): q_ancillas_zero = q[self.num_controls + 1:self.num_controls + 1 + self.num_ancillas_zero] q_ancillas_dirty = q[self.num_controls + 1 + self.num_ancillas_zero:] return q_target, q_controls, q_ancillas_zero, q_ancillas_dirty - - def validate_parameter(self, parameter): - """Multi controlled single-qubit unitary gate parameter has to be an ndarray.""" - if isinstance(parameter, np.ndarray): - return parameter - else: - raise CircuitError("invalid param type {0} in gate " - "{1}".format(type(parameter), self.name)) diff --git a/qiskit/extensions/quantum_initializer/squ.py b/qiskit/extensions/quantum_initializer/squ.py index eb9b4eb780be..0cb3cf76c576 100644 --- a/qiskit/extensions/quantum_initializer/squ.py +++ b/qiskit/extensions/quantum_initializer/squ.py @@ -29,7 +29,6 @@ from qiskit.circuit import Gate from qiskit.circuit.quantumcircuit import QuantumRegister, QuantumCircuit, Qubit -from qiskit.circuit.exceptions import CircuitError from qiskit.quantum_info.operators.predicates import is_unitary_matrix from qiskit.exceptions import QiskitError @@ -133,14 +132,6 @@ def _zyz_dec(self): # Therefore, we have to take the inverse of the angles at the end. return -a, -b, -c, d - def validate_parameter(self, parameter): - """Single-qubit unitary gate parameter has to be an ndarray.""" - if isinstance(parameter, np.ndarray): - return parameter - else: - raise CircuitError("invalid param type {0} in gate " - "{1}".format(type(parameter), self.name)) - def squ(self, u, qubit, mode="ZYZ", up_to_diagonal=False): """ Decompose an arbitrary 2*2 unitary into three rotation gates :math:`U=R_zR_yR_z`. diff --git a/qiskit/extensions/quantum_initializer/uc.py b/qiskit/extensions/quantum_initializer/uc.py index 9c398b228c1a..f58afc3643be 100644 --- a/qiskit/extensions/quantum_initializer/uc.py +++ b/qiskit/extensions/quantum_initializer/uc.py @@ -46,7 +46,6 @@ from qiskit.quantum_info.operators.predicates import is_unitary_matrix from qiskit.circuit.quantumregister import QuantumRegister from qiskit.circuit.quantumcircuit import QuantumCircuit -from qiskit.circuit.exceptions import CircuitError from qiskit.exceptions import QiskitError from qiskit.quantum_info.synthesis import OneQubitEulerDecomposer @@ -264,14 +263,6 @@ def _ct(m): def _rz(alpha): return np.array([[np.exp(1j * alpha / 2), 0], [0, np.exp(-1j * alpha / 2)]]) - def validate_parameter(self, parameter): - """Uniformly controlled gate parameter has to be an ndarray.""" - if isinstance(parameter, np.ndarray): - return parameter - else: - raise CircuitError("invalid param type {0} in gate " - "{1}".format(type(parameter), self.name)) - def uc(self, gate_list, q_controls, q_target, up_to_diagonal=False): """Attach a uniformly controlled gates (also called multiplexed gates) to a circuit. diff --git a/qiskit/extensions/standard/barrier.py b/qiskit/extensions/standard/barrier.py index d05dea0ae770..e031504c9f59 100644 --- a/qiskit/extensions/standard/barrier.py +++ b/qiskit/extensions/standard/barrier.py @@ -19,7 +19,6 @@ from qiskit.circuit.quantumregister import QuantumRegister from qiskit.circuit import Instruction from qiskit.exceptions import QiskitError -from qiskit.circuit.exceptions import CircuitError class Barrier(Instruction): @@ -39,10 +38,6 @@ def broadcast_arguments(self, qargs, cargs): def c_if(self, classical, val): raise QiskitError('Barriers are compiler directives and cannot be conditional.') - def validate_parameter(self, parameter): - """Barrier paramenter""" - raise CircuitError("Barrier has no parameters: {0} was provided".format(type(parameter))) - def barrier(self, *qargs): """Apply barrier to circuit. diff --git a/qiskit/extensions/unitary.py b/qiskit/extensions/unitary.py index 729cf4ee9138..91805bed4075 100644 --- a/qiskit/extensions/unitary.py +++ b/qiskit/extensions/unitary.py @@ -23,7 +23,6 @@ from qiskit.circuit import QuantumCircuit from qiskit.circuit import QuantumRegister from qiskit.exceptions import QiskitError -from qiskit.circuit.exceptions import CircuitError from qiskit.extensions.standard import U3Gate from qiskit.quantum_info.operators.predicates import matrix_equal from qiskit.quantum_info.operators.predicates import is_unitary_matrix @@ -182,14 +181,6 @@ def qasm(self): return self._qasm_definition + self._qasmif(self._qasm_name) - def validate_parameter(self, parameter): - """Unitary gate parameter has to be an ndarray.""" - if isinstance(parameter, numpy.ndarray): - return parameter - else: - raise CircuitError("invalid param type {0} in gate " - "{1}".format(type(parameter), self.name)) - def _compute_control_matrix(base_mat, num_ctrl_qubits, ctrl_state=None): r""" @@ -228,6 +219,8 @@ def _compute_control_matrix(base_mat, num_ctrl_qubits, ctrl_state=None): raise QiskitError('Invalid control state value specified.') else: raise QiskitError('Invalid control state type specified.') + full_mat_dim = ctrl_dim * base_mat.shape[0] + full_mat = numpy.zeros((full_mat_dim, full_mat_dim), dtype=base_mat.dtype) ctrl_proj = numpy.diag(numpy.roll(ctrl_grnd, ctrl_state)) full_mat = (numpy.kron(numpy.eye(2**num_target), numpy.eye(ctrl_dim) - ctrl_proj) diff --git a/test/python/circuit/test_extensions_standard.py b/test/python/circuit/test_extensions_standard.py index 0ea45f07b124..b38228470204 100644 --- a/test/python/circuit/test_extensions_standard.py +++ b/test/python/circuit/test_extensions_standard.py @@ -32,7 +32,7 @@ HGate, CHGate, IGate, RGate, RXGate, CRXGate, RYGate, CRYGate, RZGate, CRZGate, SGate, SdgGate, CSwapGate, TGate, TdgGate, U1Gate, CU1Gate, U2Gate, U3Gate, CU3Gate, XGate, CXGate, CCXGate, YGate, CYGate, - ZGate, CZGate, Barrier + ZGate, CZGate ) @@ -66,11 +66,6 @@ def test_barrier_invalid(self): self.assertRaises(CircuitError, qc.barrier, (self.qr, 'a')) self.assertRaises(CircuitError, qc.barrier, .0) - def test_barrier_parameters(self): - barrier = Barrier(2) - with self.assertRaises(CircuitError): - barrier.params = [0, 1] - def test_conditional_barrier_invalid(self): qc = self.circuit barrier = qc.barrier(self.qr) diff --git a/test/python/visualization/test_circuit_text_drawer.py b/test/python/visualization/test_circuit_text_drawer.py index 3a00cc86373c..01f9f01eb8e1 100644 --- a/test/python/visualization/test_circuit_text_drawer.py +++ b/test/python/visualization/test_circuit_text_drawer.py @@ -921,7 +921,6 @@ def test_kraus(self): self.assertEqual(str(_text_circuit_drawer(qc)), expected) - @unittest.skip("Add back when Multiplexer is implemented in terms of UCGate") def test_multiplexer(self): """ Test Multiplexer. See https://github.com/Qiskit/qiskit-terra/pull/2238#issuecomment-487630014""" @@ -1476,7 +1475,6 @@ def test_conditional_reset(self): self.assertEqual(str(_text_circuit_drawer(circuit)), expected) - @unittest.skip("Add back when Multiplexer is implemented in terms of UCGate") def test_conditional_multiplexer(self): """ Test Multiplexer.""" cx_multiplexer = Gate('multiplexer', 2, [numpy.eye(2), numpy.array([[0, 1], [1, 0]])])