Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions qiskit/circuit/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import copy
from itertools import zip_longest
import math
from typing import List, Type

import numpy
Expand Down Expand Up @@ -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
Comment on lines +633 to +641
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess specifically this is stdlib-gate parameters, but that's fine.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's why I made it private, I can add a comment or docstring for it. Or were you propoposing I rename it _compare_stdlib_gate_parameters()?

3 changes: 3 additions & 0 deletions qiskit/circuit/library/standard_gates/dcx.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,6 @@ def _define(self):
qc._append(instr, qargs, cargs)

self.definition = qc

def __eq__(self, other):
return isinstance(other, DCXGate)
3 changes: 3 additions & 0 deletions qiskit/circuit/library/standard_gates/ecr.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If someone were to extend ECRGate via inheritance, this definition of __eq__ would be wrong for that subclass. Is it worth instead defining this once for SingletonGate as:

def __eq__(self, other):
    return isinstance(other, type(self))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wouldn't actually be correct for singleton gates, where the singleton instance is a separate part of the inheritance tree to the non-singleton versions.

I'm not super convinced that __eq__ should attempt to drive additional logic within subclasses; we can't really know what additional information a subclass might add on, nor what should really cause them to be considered equal. It largely seems to me that subclasses should almost always be responsible for overriding __eq__.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I forgot about that nuance with the class hierarchy. It seems to me like __eq__ should behave the same for all SingletonGates. If there is more state to compare, then I'd think it's no longer a SingletonGate from a traiting perspective.

7 changes: 7 additions & 0 deletions qiskit/circuit/library/standard_gates/global_phase.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
6 changes: 6 additions & 0 deletions qiskit/circuit/library/standard_gates/h.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment. Perhaps a shared implementation is possible for all SingletonControlledGate instances?

3 changes: 3 additions & 0 deletions qiskit/circuit/library/standard_gates/i.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
3 changes: 3 additions & 0 deletions qiskit/circuit/library/standard_gates/iswap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
10 changes: 10 additions & 0 deletions qiskit/circuit/library/standard_gates/p.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/r.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
10 changes: 10 additions & 0 deletions qiskit/circuit/library/standard_gates/rx.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/rxx.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
10 changes: 10 additions & 0 deletions qiskit/circuit/library/standard_gates/ry.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/ryy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
10 changes: 10 additions & 0 deletions qiskit/circuit/library/standard_gates/rz.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/rzx.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/rzz.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 12 additions & 0 deletions qiskit/circuit/library/standard_gates/s.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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
6 changes: 6 additions & 0 deletions qiskit/circuit/library/standard_gates/swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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
9 changes: 9 additions & 0 deletions qiskit/circuit/library/standard_gates/sx.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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
6 changes: 6 additions & 0 deletions qiskit/circuit/library/standard_gates/t.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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)
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/u.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading