diff --git a/qiskit/circuit/instruction.py b/qiskit/circuit/instruction.py index b1278b4c0e22..55a640a832a5 100644 --- a/qiskit/circuit/instruction.py +++ b/qiskit/circuit/instruction.py @@ -35,6 +35,7 @@ import copy from itertools import zip_longest +import math from typing import List, Type import numpy @@ -628,3 +629,13 @@ def num_clbits(self): def num_clbits(self, num_clbits): """Set num_clbits.""" self._num_clbits = num_clbits + + def _compare_parameters(self, other): + for x, y in zip(self.params, other.params): + try: + if not math.isclose(x, y, rel_tol=0, abs_tol=1e-10): + return False + except TypeError: + if x != y: + return False + return True diff --git a/qiskit/circuit/library/standard_gates/dcx.py b/qiskit/circuit/library/standard_gates/dcx.py index e917b6874d57..6455bea2779e 100644 --- a/qiskit/circuit/library/standard_gates/dcx.py +++ b/qiskit/circuit/library/standard_gates/dcx.py @@ -69,3 +69,6 @@ def _define(self): qc._append(instr, qargs, cargs) self.definition = qc + + def __eq__(self, other): + return isinstance(other, DCXGate) diff --git a/qiskit/circuit/library/standard_gates/ecr.py b/qiskit/circuit/library/standard_gates/ecr.py index 1b38f7ad08e7..939f96f9e5b2 100644 --- a/qiskit/circuit/library/standard_gates/ecr.py +++ b/qiskit/circuit/library/standard_gates/ecr.py @@ -112,3 +112,6 @@ def _define(self): def inverse(self): """Return inverse ECR gate (itself).""" return ECRGate() # self-inverse + + def __eq__(self, other): + return isinstance(other, ECRGate) diff --git a/qiskit/circuit/library/standard_gates/global_phase.py b/qiskit/circuit/library/standard_gates/global_phase.py index 55625f6f3e44..7cda9c49ffbc 100644 --- a/qiskit/circuit/library/standard_gates/global_phase.py +++ b/qiskit/circuit/library/standard_gates/global_phase.py @@ -13,7 +13,9 @@ """Global Phase Gate""" from typing import Optional + import numpy + from qiskit.circuit.gate import Gate from qiskit.circuit.quantumregister import QuantumRegister from qiskit.circuit.quantumcircuit import QuantumCircuit @@ -61,3 +63,8 @@ def __array__(self, dtype=complex): """Return a numpy.array for the global_phase gate.""" theta = self.params[0] return numpy.array([[numpy.exp(1j * theta)]], dtype=dtype) + + def __eq__(self, other): + if isinstance(other, GlobalPhaseGate): + return self._compare_parameters(other) + return False diff --git a/qiskit/circuit/library/standard_gates/h.py b/qiskit/circuit/library/standard_gates/h.py index b738548cd444..ab58194b0c04 100644 --- a/qiskit/circuit/library/standard_gates/h.py +++ b/qiskit/circuit/library/standard_gates/h.py @@ -101,6 +101,9 @@ def inverse(self): r"""Return inverted H gate (itself).""" return HGate() # self-inverse + def __eq__(self, other): + return isinstance(other, HGate) + @with_controlled_gate_array(_H_ARRAY, num_ctrl_qubits=1) class CHGate(SingletonControlledGate): @@ -222,3 +225,6 @@ def _define(self): def inverse(self): """Return inverted CH gate (itself).""" return CHGate(ctrl_state=self.ctrl_state) # self-inverse + + def __eq__(self, other): + return isinstance(other, CHGate) and self.ctrl_state == other.ctrl_state diff --git a/qiskit/circuit/library/standard_gates/i.py b/qiskit/circuit/library/standard_gates/i.py index ec7009f37ff5..720e9de20f1a 100644 --- a/qiskit/circuit/library/standard_gates/i.py +++ b/qiskit/circuit/library/standard_gates/i.py @@ -58,3 +58,6 @@ def inverse(self): def power(self, exponent: float): """Raise gate to a power.""" return IGate() + + def __eq__(self, other): + return isinstance(other, IGate) diff --git a/qiskit/circuit/library/standard_gates/iswap.py b/qiskit/circuit/library/standard_gates/iswap.py index 7b3168ce0c57..d871f6b8c3de 100644 --- a/qiskit/circuit/library/standard_gates/iswap.py +++ b/qiskit/circuit/library/standard_gates/iswap.py @@ -127,3 +127,6 @@ def _define(self): def power(self, exponent: float): """Raise gate to a power.""" return XXPlusYYGate(-np.pi * exponent) + + def __eq__(self, other): + return isinstance(other, iSwapGate) diff --git a/qiskit/circuit/library/standard_gates/p.py b/qiskit/circuit/library/standard_gates/p.py index cc6cb5a464f8..7a354fa4f4ab 100644 --- a/qiskit/circuit/library/standard_gates/p.py +++ b/qiskit/circuit/library/standard_gates/p.py @@ -133,6 +133,11 @@ def power(self, exponent: float): (theta,) = self.params return PhaseGate(exponent * theta) + def __eq__(self, other): + if isinstance(other, PhaseGate): + return self._compare_parameters(other) + return False + class CPhaseGate(ControlledGate): r"""Controlled-Phase gate. @@ -263,6 +268,11 @@ def power(self, exponent: float): (theta,) = self.params return CPhaseGate(exponent * theta) + def __eq__(self, other): + if isinstance(other, CPhaseGate): + return self._compare_parameters(other) and self.ctrl_state == other.ctrl_state + return False + class MCPhaseGate(ControlledGate): r"""Multi-controlled-Phase gate. diff --git a/qiskit/circuit/library/standard_gates/r.py b/qiskit/circuit/library/standard_gates/r.py index cfc74d1b2cbf..e7772f043aef 100644 --- a/qiskit/circuit/library/standard_gates/r.py +++ b/qiskit/circuit/library/standard_gates/r.py @@ -99,3 +99,8 @@ def power(self, exponent: float): """Raise gate to a power.""" theta, phi = self.params return RGate(exponent * theta, phi) + + def __eq__(self, other): + if isinstance(other, RGate): + return self._compare_parameters(other) + return False diff --git a/qiskit/circuit/library/standard_gates/rx.py b/qiskit/circuit/library/standard_gates/rx.py index 5084834888b4..69b8fe8fa328 100644 --- a/qiskit/circuit/library/standard_gates/rx.py +++ b/qiskit/circuit/library/standard_gates/rx.py @@ -113,6 +113,11 @@ def power(self, exponent: float): (theta,) = self.params return RXGate(exponent * theta) + def __eq__(self, other): + if isinstance(other, RXGate): + return self._compare_parameters(other) + return False + class CRXGate(ControlledGate): r"""Controlled-RX gate. @@ -244,3 +249,8 @@ def __array__(self, dtype=None): return numpy.array( [[cos, 0, -isin, 0], [0, 1, 0, 0], [-isin, 0, cos, 0], [0, 0, 0, 1]], dtype=dtype ) + + def __eq__(self, other): + if isinstance(other, CRXGate): + return self._compare_parameters(other) and self.ctrl_state == other.ctrl_state + return False diff --git a/qiskit/circuit/library/standard_gates/rxx.py b/qiskit/circuit/library/standard_gates/rxx.py index 361c6b8a40d0..b9635f293f23 100644 --- a/qiskit/circuit/library/standard_gates/rxx.py +++ b/qiskit/circuit/library/standard_gates/rxx.py @@ -126,3 +126,8 @@ def power(self, exponent: float): """Raise gate to a power.""" (theta,) = self.params return RXXGate(exponent * theta) + + def __eq__(self, other): + if isinstance(other, RXXGate): + return self._compare_parameters(other) + return False diff --git a/qiskit/circuit/library/standard_gates/ry.py b/qiskit/circuit/library/standard_gates/ry.py index e0270e4f04c9..6fed9206dcb7 100644 --- a/qiskit/circuit/library/standard_gates/ry.py +++ b/qiskit/circuit/library/standard_gates/ry.py @@ -112,6 +112,11 @@ def power(self, exponent: float): (theta,) = self.params return RYGate(exponent * theta) + def __eq__(self, other): + if isinstance(other, RYGate): + return self._compare_parameters(other) + return False + class CRYGate(ControlledGate): r"""Controlled-RY gate. @@ -239,3 +244,8 @@ def __array__(self, dtype=None): return numpy.array( [[cos, 0, -sin, 0], [0, 1, 0, 0], [sin, 0, cos, 0], [0, 0, 0, 1]], dtype=dtype ) + + def __eq__(self, other): + if isinstance(other, CRYGate): + return self._compare_parameters(other) and self.ctrl_state == other.ctrl_state + return False diff --git a/qiskit/circuit/library/standard_gates/ryy.py b/qiskit/circuit/library/standard_gates/ryy.py index 40d638aac3cc..bc654d1af437 100644 --- a/qiskit/circuit/library/standard_gates/ryy.py +++ b/qiskit/circuit/library/standard_gates/ryy.py @@ -126,3 +126,8 @@ def power(self, exponent: float): """Raise gate to a power.""" (theta,) = self.params return RYYGate(exponent * theta) + + def __eq__(self, other): + if isinstance(other, RYYGate): + return self._compare_parameters(other) + return False diff --git a/qiskit/circuit/library/standard_gates/rz.py b/qiskit/circuit/library/standard_gates/rz.py index 33b7146b44f1..b96fe6183869 100644 --- a/qiskit/circuit/library/standard_gates/rz.py +++ b/qiskit/circuit/library/standard_gates/rz.py @@ -124,6 +124,11 @@ def power(self, exponent: float): (theta,) = self.params return RZGate(exponent * theta) + def __eq__(self, other): + if isinstance(other, RZGate): + return self._compare_parameters(other) + return False + class CRZGate(ControlledGate): r"""Controlled-RZ gate. @@ -259,3 +264,8 @@ def __array__(self, dtype=None): [[exp(-arg), 0, 0, 0], [0, 1, 0, 0], [0, 0, exp(arg), 0], [0, 0, 0, 1]], dtype=dtype, ) + + def __eq__(self, other): + if isinstance(other, CRZGate): + return self._compare_parameters(other) and self.ctrl_state == other.ctrl_state + return False diff --git a/qiskit/circuit/library/standard_gates/rzx.py b/qiskit/circuit/library/standard_gates/rzx.py index 7963d60f9274..bd76d8f0af39 100644 --- a/qiskit/circuit/library/standard_gates/rzx.py +++ b/qiskit/circuit/library/standard_gates/rzx.py @@ -172,3 +172,8 @@ def power(self, exponent: float): """Raise gate to a power.""" (theta,) = self.params return RZXGate(exponent * theta) + + def __eq__(self, other): + if isinstance(other, RZXGate): + return self._compare_parameters(other) + return False diff --git a/qiskit/circuit/library/standard_gates/rzz.py b/qiskit/circuit/library/standard_gates/rzz.py index a9b2b01e8afe..d15f5cb70d7a 100644 --- a/qiskit/circuit/library/standard_gates/rzz.py +++ b/qiskit/circuit/library/standard_gates/rzz.py @@ -139,3 +139,8 @@ def power(self, exponent: float): """Raise gate to a power.""" (theta,) = self.params return RZZGate(exponent * theta) + + def __eq__(self, other): + if isinstance(other, RZZGate): + return self._compare_parameters(other) + return False diff --git a/qiskit/circuit/library/standard_gates/s.py b/qiskit/circuit/library/standard_gates/s.py index 1a35dc8fdcc7..e31ca8de894e 100644 --- a/qiskit/circuit/library/standard_gates/s.py +++ b/qiskit/circuit/library/standard_gates/s.py @@ -90,6 +90,9 @@ def power(self, exponent: float): return PhaseGate(0.5 * numpy.pi * exponent) + def __eq__(self, other): + return isinstance(other, SGate) + @with_gate_array(_SDG_ARRAY) class SdgGate(SingletonGate): @@ -155,6 +158,9 @@ def power(self, exponent: float): return PhaseGate(-0.5 * numpy.pi * exponent) + def __eq__(self, other): + return isinstance(other, SdgGate) + @with_controlled_gate_array(_S_ARRAY, num_ctrl_qubits=1) class CSGate(SingletonControlledGate): @@ -229,6 +235,9 @@ def power(self, exponent: float): return CPhaseGate(0.5 * numpy.pi * exponent) + def __eq__(self, other): + return isinstance(other, CSGate) and self.ctrl_state == other.ctrl_state + @with_controlled_gate_array(_SDG_ARRAY, num_ctrl_qubits=1) class CSdgGate(SingletonControlledGate): @@ -301,3 +310,6 @@ def power(self, exponent: float): from .p import CPhaseGate return CPhaseGate(-0.5 * numpy.pi * exponent) + + def __eq__(self, other): + return isinstance(other, CSdgGate) and self.ctrl_state == other.ctrl_state diff --git a/qiskit/circuit/library/standard_gates/swap.py b/qiskit/circuit/library/standard_gates/swap.py index 551e760c6932..2a7ccd16d41f 100644 --- a/qiskit/circuit/library/standard_gates/swap.py +++ b/qiskit/circuit/library/standard_gates/swap.py @@ -112,6 +112,9 @@ def inverse(self): """Return inverse Swap gate (itself).""" return SwapGate() # self-inverse + def __eq__(self, other): + return isinstance(other, SwapGate) + @with_controlled_gate_array(_SWAP_ARRAY, num_ctrl_qubits=1) class CSwapGate(SingletonControlledGate): @@ -244,3 +247,6 @@ def _define(self): def inverse(self): """Return inverse CSwap gate (itself).""" return CSwapGate(ctrl_state=self.ctrl_state) # self-inverse + + def __eq__(self, other): + return isinstance(other, CSwapGate) and self.ctrl_state == other.ctrl_state diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index 1c8344c6fa59..88a8119e59b2 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -112,6 +112,9 @@ def control( return gate return super().control(num_ctrl_qubits=num_ctrl_qubits, label=label, ctrl_state=ctrl_state) + def __eq__(self, other): + return isinstance(other, SXGate) + @with_gate_array(_SXDG_ARRAY) class SXdgGate(SingletonGate): @@ -169,6 +172,9 @@ def inverse(self): """Return inverse SXdg gate (i.e. SX).""" return SXGate() + def __eq__(self, other): + return isinstance(other, SXdgGate) + @with_controlled_gate_array(_SX_ARRAY, num_ctrl_qubits=1) class CSXGate(SingletonControlledGate): @@ -266,3 +272,6 @@ def _define(self): for operation, qubits, clbits in rules: qc._append(operation, qubits, clbits) self.definition = qc + + def __eq__(self, other): + return isinstance(other, CSXGate) and self.ctrl_state == other.ctrl_state diff --git a/qiskit/circuit/library/standard_gates/t.py b/qiskit/circuit/library/standard_gates/t.py index eaa912456d7c..c1e83f0871a5 100644 --- a/qiskit/circuit/library/standard_gates/t.py +++ b/qiskit/circuit/library/standard_gates/t.py @@ -86,6 +86,9 @@ def power(self, exponent: float): """Raise gate to a power.""" return PhaseGate(0.25 * numpy.pi * exponent) + def __eq__(self, other): + return isinstance(other, TGate) + @with_gate_array([[1, 0], [0, (1 - 1j) / math.sqrt(2)]]) class TdgGate(SingletonGate): @@ -148,3 +151,6 @@ def inverse(self): def power(self, exponent: float): """Raise gate to a power.""" return PhaseGate(-0.25 * numpy.pi * exponent) + + def __eq__(self, other): + return isinstance(other, TdgGate) diff --git a/qiskit/circuit/library/standard_gates/u.py b/qiskit/circuit/library/standard_gates/u.py index 23a9fc7861ce..30f6ff7f735b 100644 --- a/qiskit/circuit/library/standard_gates/u.py +++ b/qiskit/circuit/library/standard_gates/u.py @@ -130,6 +130,11 @@ def __array__(self, dtype=complex): dtype=dtype, ) + def __eq__(self, other): + if isinstance(other, UGate): + return self._compare_parameters(other) + return False + class _CUGateParams(list): # This awful class is to let `CUGate.params` have its keys settable (as diff --git a/qiskit/circuit/library/standard_gates/x.py b/qiskit/circuit/library/standard_gates/x.py index 7effa675c83c..4ea9712c3dd7 100644 --- a/qiskit/circuit/library/standard_gates/x.py +++ b/qiskit/circuit/library/standard_gates/x.py @@ -123,6 +123,9 @@ def inverse(self): r"""Return inverted X gate (itself).""" return XGate() # self-inverse + def __eq__(self, other): + return isinstance(other, XGate) + @with_controlled_gate_array(_X_ARRAY, num_ctrl_qubits=1) class CXGate(SingletonControlledGate): @@ -244,6 +247,9 @@ def inverse(self): """Return inverted CX gate (itself).""" return CXGate(ctrl_state=self.ctrl_state) # self-inverse + def __eq__(self, other): + return isinstance(other, CXGate) and self.ctrl_state == other.ctrl_state + @with_controlled_gate_array(_X_ARRAY, num_ctrl_qubits=2, cached_states=(3,)) class CCXGate(SingletonControlledGate): @@ -414,6 +420,9 @@ def inverse(self): """Return an inverted CCX gate (also a CCX).""" return CCXGate(ctrl_state=self.ctrl_state) # self-inverse + def __eq__(self, other): + return isinstance(other, CCXGate) and self.ctrl_state == other.ctrl_state + @with_gate_array( [ @@ -486,6 +495,9 @@ def _define(self): self.definition = qc + def __eq__(self, other): + return isinstance(other, RCCXGate) + class C3SXGate(SingletonControlledGate): """The 3-qubit controlled sqrt-X gate. @@ -589,6 +601,9 @@ def _define(self): self.definition = qc + def __eq__(self, other): + return isinstance(other, C3SXGate) and self.ctrl_state == other.ctrl_state + @with_controlled_gate_array(_X_ARRAY, num_ctrl_qubits=3, cached_states=(7,)) class C3XGate(SingletonControlledGate): @@ -724,6 +739,9 @@ def inverse(self): """Invert this gate. The C4X is its own inverse.""" return C3XGate(ctrl_state=self.ctrl_state) + def __eq__(self, other): + return isinstance(other, C3XGate) and self.ctrl_state == other.ctrl_state + @with_gate_array( [ @@ -820,6 +838,9 @@ def _define(self): self.definition = qc + def __eq__(self, other): + return isinstance(other, RC3XGate) + @with_controlled_gate_array(_X_ARRAY, num_ctrl_qubits=4, cached_states=(15,)) class C4XGate(SingletonControlledGate): @@ -940,6 +961,9 @@ def inverse(self): """Invert this gate. The C4X is its own inverse.""" return C4XGate(ctrl_state=self.ctrl_state) + def __eq__(self, other): + return isinstance(other, C4XGate) and self.ctrl_state == other.ctrl_state + class MCXGate(ControlledGate): """The general, multi-controlled X gate. diff --git a/qiskit/circuit/library/standard_gates/xx_minus_yy.py b/qiskit/circuit/library/standard_gates/xx_minus_yy.py index 4b9597169c30..127c57cee039 100644 --- a/qiskit/circuit/library/standard_gates/xx_minus_yy.py +++ b/qiskit/circuit/library/standard_gates/xx_minus_yy.py @@ -177,3 +177,8 @@ def power(self, exponent: float): """Raise gate to a power.""" theta, beta = self.params return XXMinusYYGate(exponent * theta, beta) + + def __eq__(self, other): + if isinstance(other, XXMinusYYGate): + return self._compare_parameters(other) + return False diff --git a/qiskit/circuit/library/standard_gates/xx_plus_yy.py b/qiskit/circuit/library/standard_gates/xx_plus_yy.py index 599d870e0ec1..8b76c21ea375 100644 --- a/qiskit/circuit/library/standard_gates/xx_plus_yy.py +++ b/qiskit/circuit/library/standard_gates/xx_plus_yy.py @@ -178,3 +178,8 @@ def power(self, exponent: float): """Raise gate to a power.""" theta, beta = self.params return XXPlusYYGate(exponent * theta, beta) + + def __eq__(self, other): + if isinstance(other, XXPlusYYGate): + return self._compare_parameters(other) + return False diff --git a/qiskit/circuit/library/standard_gates/y.py b/qiskit/circuit/library/standard_gates/y.py index 1789fed72e10..b57e29b5ed1f 100644 --- a/qiskit/circuit/library/standard_gates/y.py +++ b/qiskit/circuit/library/standard_gates/y.py @@ -117,6 +117,9 @@ def inverse(self): r"""Return inverted Y gate (:math:`Y^{\dagger} = Y`)""" return YGate() # self-inverse + def __eq__(self, other): + return isinstance(other, YGate) + @with_controlled_gate_array(_Y_ARRAY, num_ctrl_qubits=1) class CYGate(SingletonControlledGate): @@ -219,3 +222,6 @@ def _define(self): def inverse(self): """Return inverted CY gate (itself).""" return CYGate(ctrl_state=self.ctrl_state) # self-inverse + + def __eq__(self, other): + return isinstance(other, CYGate) and self.ctrl_state == other.ctrl_state diff --git a/qiskit/circuit/library/standard_gates/z.py b/qiskit/circuit/library/standard_gates/z.py index 1df875a81099..e79cfdd6e874 100644 --- a/qiskit/circuit/library/standard_gates/z.py +++ b/qiskit/circuit/library/standard_gates/z.py @@ -125,6 +125,9 @@ def power(self, exponent: float): """Raise gate to a power.""" return PhaseGate(numpy.pi * exponent) + def __eq__(self, other): + return isinstance(other, ZGate) + @with_controlled_gate_array(_Z_ARRAY, num_ctrl_qubits=1) class CZGate(SingletonControlledGate): @@ -206,6 +209,9 @@ def inverse(self): """Return inverted CZ gate (itself).""" return CZGate(ctrl_state=self.ctrl_state) # self-inverse + def __eq__(self, other): + return isinstance(other, CZGate) and self.ctrl_state == other.ctrl_state + @with_controlled_gate_array(_Z_ARRAY, num_ctrl_qubits=2, cached_states=(3,)) class CCZGate(SingletonControlledGate): @@ -292,3 +298,6 @@ def _define(self): def inverse(self): """Return inverted CCZ gate (itself).""" return CCZGate(ctrl_state=self.ctrl_state) # self-inverse + + def __eq__(self, other): + return isinstance(other, CCZGate) and self.ctrl_state == other.ctrl_state