Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
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.

12 changes: 12 additions & 0 deletions qiskit/circuit/library/standard_gates/global_phase.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@

"""Global Phase Gate"""

import math
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 +64,12 @@ 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):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return True
except TypeError:
return self.params[0] == other.params[0]
Comment thread
mtreinish marked this conversation as resolved.
Outdated
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)
19 changes: 19 additions & 0 deletions qiskit/circuit/library/standard_gates/p.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"""Phase Gate."""

from __future__ import annotations
import math
from cmath import exp
import numpy
from qiskit.circuit.controlledgate import ControlledGate
Expand Down Expand Up @@ -133,6 +134,15 @@ def power(self, exponent: float):
(theta,) = self.params
return PhaseGate(exponent * theta)

def __eq__(self, other):
if isinstance(other, PhaseGate):
try:
if math.isclose(self.params[0], other.params[0], abs_tol=1e-10, rel_tol=0):
return True
except TypeError:
return self.params[0] == other.params[0]
return False


class CPhaseGate(ControlledGate):
r"""Controlled-Phase gate.
Expand Down Expand Up @@ -263,6 +273,15 @@ def power(self, exponent: float):
(theta,) = self.params
return CPhaseGate(exponent * theta)

def __eq__(self, other):
if isinstance(other, CPhaseGate):
try:
if math.isclose(self.params[0], other.params[0]):
return self.ctrl_state == other.ctrl_state
except TypeError:
return self.params[0] == other.params[0] and self.ctrl_state == other.ctrl_state
return False


class MCPhaseGate(ControlledGate):
r"""Multi-controlled-Phase gate.
Expand Down
11 changes: 11 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,14 @@ 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):
try:
if math.isclose(
self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10
) and math.isclose(self.params[1], other.params[1], rel_tol=0, abs_tol=1e-10):
return True
except TypeError:
return self.params[0] == other.params[0] and self.params[1] == other.params[1]
return False
18 changes: 18 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,15 @@ def power(self, exponent: float):
(theta,) = self.params
return RXGate(exponent * theta)

def __eq__(self, other):
if isinstance(other, RXGate):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return True
except TypeError:
return self.params[0] == other.params[0]
return False


class CRXGate(ControlledGate):
r"""Controlled-RX gate.
Expand Down Expand Up @@ -244,3 +253,12 @@ 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):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return self.ctrl_state == other.ctrl_state
except TypeError:
return self.params[0] == other.params[0] and self.ctrl_state == other.ctrl_state
return False
9 changes: 9 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,12 @@ 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):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return True
except TypeError:
return self.params[0] == other.params[0]
return False
18 changes: 18 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,15 @@ def power(self, exponent: float):
(theta,) = self.params
return RYGate(exponent * theta)

def __eq__(self, other):
if isinstance(other, RYGate):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return True
except TypeError:
return self.params[0] == other.params[0]
return False


class CRYGate(ControlledGate):
r"""Controlled-RY gate.
Expand Down Expand Up @@ -239,3 +248,12 @@ 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):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return self.ctrl_state == other.ctrl_state
except TypeError:
return self.params[0] == other.params[0] and self.ctrl_state == other.ctrl_state
return False
9 changes: 9 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,12 @@ 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):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return True
except TypeError:
return self.params[0] == other.params[0]
return False
18 changes: 18 additions & 0 deletions qiskit/circuit/library/standard_gates/rz.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# that they have been altered from the originals.

"""Rotation around the Z axis."""
import math
from cmath import exp
from typing import Optional, Union
from qiskit.circuit.gate import Gate
Expand Down Expand Up @@ -124,6 +125,14 @@ def power(self, exponent: float):
(theta,) = self.params
return RZGate(exponent * theta)

def __eq__(self, other):
if isinstance(other, RZGate):
try:
return math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10)
except TypeError:
return self.params[0] == other.params[0]
return False


class CRZGate(ControlledGate):
r"""Controlled-RZ gate.
Expand Down Expand Up @@ -259,3 +268,12 @@ 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):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return self.ctrl_state == other.ctrl_state
except TypeError:
return self.params[0] == other.params[0] and self.ctrl_state == other.ctrl_state
return False
9 changes: 9 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,12 @@ 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):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return True
except TypeError:
return self.params[0] == other.params[0]
return False
10 changes: 10 additions & 0 deletions qiskit/circuit/library/standard_gates/rzz.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# that they have been altered from the originals.

"""Two-qubit ZZ-rotation gate."""
import math
from cmath import exp
from typing import Optional
from qiskit.circuit.gate import Gate
Expand Down Expand Up @@ -139,3 +140,12 @@ 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):
try:
if math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10):
return True
except TypeError:
return self.params[0] == other.params[0]
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)
Comment thread
mtreinish marked this conversation as resolved.
Outdated
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)
16 changes: 16 additions & 0 deletions qiskit/circuit/library/standard_gates/u.py
Comment thread
jakelishman marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,22 @@ def __array__(self, dtype=complex):
dtype=dtype,
)

def __eq__(self, other):
if isinstance(other, UGate):
try:
return (
math.isclose(self.params[0], other.params[0], rel_tol=0, abs_tol=1e-10)
and math.isclose(self.params[1], other.params[1], rel_tol=0, abs_tol=1e-10)
and math.isclose(self.params[2], other.params[2], rel_tol=0, abs_tol=1e-10)
)
except TypeError:
return (
self.params[0] == other.params[0]
and self.params[1] == other.params[1]
and self.params[2] == other.params[2]
)
return False


class _CUGateParams(list):
# This awful class is to let `CUGate.params` have its keys settable (as
Expand Down
Loading