Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add efficient gate power methods #9318

Merged
merged 8 commits into from
Jan 10, 2023
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
4 changes: 4 additions & 0 deletions qiskit/circuit/library/standard_gates/i.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,7 @@ def inverse(self):
def __array__(self, dtype=None):
"""Return a numpy.array for the identity gate."""
return numpy.array([[1, 0], [0, 1]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
return IGate()
9 changes: 9 additions & 0 deletions qiskit/circuit/library/standard_gates/iswap.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@
"""iSWAP gate."""

from typing import Optional

import numpy as np

from qiskit.circuit.gate import Gate
from qiskit.circuit.quantumregister import QuantumRegister

from .xx_plus_yy import XXPlusYYGate


class iSwapGate(Gate):
r"""iSWAP gate.
Expand Down Expand Up @@ -96,6 +100,7 @@ def _define(self):
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit

from .h import HGate
from .s import SGate
from .x import CXGate
Expand All @@ -118,3 +123,7 @@ def _define(self):
def __array__(self, dtype=None):
"""Return a numpy.array for the iSWAP gate."""
return np.array([[1, 0, 0, 0], [0, 0, 1j, 0], [0, 1j, 0, 0], [0, 0, 0, 1]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
return XXPlusYYGate(-np.pi * exponent)
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 @@ -125,6 +125,11 @@ def __array__(self, dtype=None):
lam = float(self.params[0])
return numpy.array([[1, 0], [0, exp(1j * lam)]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
(theta,) = self.params
return PhaseGate(exponent * theta)


class CPhaseGate(ControlledGate):
r"""Controlled-Phase gate.
Expand Down Expand Up @@ -244,6 +249,11 @@ def __array__(self, dtype=None):
)
return numpy.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, eith, 0], [0, 0, 0, 1]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
(theta,) = self.params
return CPhaseGate(exponent * theta)


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 @@ -88,3 +88,8 @@ def __array__(self, dtype=None):
exp_m = exp(-1j * phi)
exp_p = exp(1j * phi)
return numpy.array([[cos, -1j * exp_m * sin], [-1j * exp_p * sin, cos]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
theta, phi = self.params
return RGate(exponent * theta, phi)
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/rx.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ def __array__(self, dtype=None):
sin = math.sin(self.params[0] / 2)
return numpy.array([[cos, -1j * sin], [-1j * sin, cos]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
(theta,) = self.params
return RXGate(exponent * theta)


class CRXGate(ControlledGate):
r"""Controlled-RX gate.
Expand Down
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 @@ -119,3 +119,8 @@ def __array__(self, dtype=None):
[[cos, 0, 0, -isin], [0, cos, -isin, 0], [0, -isin, cos, 0], [-isin, 0, 0, cos]],
dtype=dtype,
)

def power(self, exponent: float):
"""Raise gate to a power."""
(theta,) = self.params
return RXXGate(exponent * theta)
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/ry.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ def __array__(self, dtype=None):
sin = math.sin(self.params[0] / 2)
return numpy.array([[cos, -sin], [sin, cos]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
(theta,) = self.params
return RYGate(exponent * theta)


class CRYGate(ControlledGate):
r"""Controlled-RY gate.
Expand Down
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 @@ -119,3 +119,8 @@ def __array__(self, dtype=None):
[[cos, 0, 0, isin], [0, cos, -isin, 0], [0, -isin, cos, 0], [isin, 0, 0, cos]],
dtype=dtype,
)

def power(self, exponent: float):
"""Raise gate to a power."""
(theta,) = self.params
return RYYGate(exponent * theta)
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/rz.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ def __array__(self, dtype=None):
ilam2 = 0.5j * float(self.params[0])
return np.array([[exp(-ilam2), 0], [0, exp(ilam2)]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
(theta,) = self.params
return RZGate(exponent * theta)


class CRZGate(ControlledGate):
r"""Controlled-RZ gate.
Expand Down
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 @@ -165,3 +165,8 @@ def __array__(self, dtype=None):
[[cos, 0, -isin, 0], [0, cos, 0, isin], [-isin, 0, cos, 0], [0, isin, 0, cos]],
dtype=dtype,
)

def power(self, exponent: float):
"""Raise gate to a power."""
(theta,) = self.params
return RZXGate(exponent * theta)
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 @@ -132,3 +132,8 @@ def __array__(self, dtype=None):
],
dtype=dtype,
)

def power(self, exponent: float):
"""Raise gate to a power."""
(theta,) = self.params
return RZZGate(exponent * theta)
29 changes: 22 additions & 7 deletions qiskit/circuit/library/standard_gates/s.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
"""The S, Sdg, CS and CSdg gates."""

from typing import Optional, Union

import numpy
from qiskit.qasm import pi

from qiskit.circuit.controlledgate import ControlledGate
from qiskit.circuit.gate import Gate
from qiskit.circuit.library.standard_gates.p import CPhaseGate, PhaseGate
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.qasm import pi


class SGate(Gate):
Expand Down Expand Up @@ -60,6 +63,7 @@ def _define(self):
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit

from .u1 import U1Gate

q = QuantumRegister(1, "q")
Expand All @@ -78,6 +82,10 @@ def __array__(self, dtype=None):
"""Return a numpy.array for the S gate."""
return numpy.array([[1, 0], [0, 1j]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
return PhaseGate(0.5 * numpy.pi * exponent)


class SdgGate(Gate):
r"""Single qubit S-adjoint gate (~Z**0.5).
Expand Down Expand Up @@ -119,6 +127,7 @@ def _define(self):
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit

from .u1 import U1Gate

q = QuantumRegister(1, "q")
Expand All @@ -137,6 +146,10 @@ def __array__(self, dtype=None):
"""Return a numpy.array for the Sdg gate."""
return numpy.array([[1, 0], [0, -1j]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
return PhaseGate(-0.5 * numpy.pi * exponent)


class CSGate(ControlledGate):
r"""Controlled-S gate.
Expand Down Expand Up @@ -194,9 +207,6 @@ def _define(self):
"""
gate cs a,b { h b; cp(pi/2) a,b; h b; }
"""
# pylint: disable=cyclic-import
from .p import CPhaseGate

self.definition = CPhaseGate(theta=pi / 2).definition

def inverse(self):
Expand All @@ -210,6 +220,10 @@ def __array__(self, dtype=None):
return numpy.asarray(mat, dtype=dtype)
return mat

def power(self, exponent: float):
"""Raise gate to a power."""
return CPhaseGate(0.5 * numpy.pi * exponent)


class CSdgGate(ControlledGate):
r"""Controlled-S^\dagger gate.
Expand Down Expand Up @@ -273,9 +287,6 @@ def _define(self):
"""
gate csdg a,b { h b; cp(-pi/2) a,b; h b; }
"""
# pylint: disable=cyclic-import
from .p import CPhaseGate

self.definition = CPhaseGate(theta=-pi / 2).definition

def inverse(self):
Expand All @@ -288,3 +299,7 @@ def __array__(self, dtype=None):
if dtype is not None:
return numpy.asarray(mat, dtype=dtype)
return mat

def power(self, exponent: float):
"""Raise gate to a power."""
return CPhaseGate(-0.5 * numpy.pi * exponent)
15 changes: 14 additions & 1 deletion qiskit/circuit/library/standard_gates/t.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
"""T and Tdg gate."""
import math
from typing import Optional

import numpy
from qiskit.qasm import pi

from qiskit.circuit.gate import Gate
from qiskit.circuit.library.standard_gates.p import PhaseGate
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.qasm import pi


class TGate(Gate):
Expand Down Expand Up @@ -60,6 +63,7 @@ def _define(self):
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit

from .u1 import U1Gate

q = QuantumRegister(1, "q")
Expand All @@ -78,6 +82,10 @@ def __array__(self, dtype=None):
"""Return a numpy.array for the T gate."""
return numpy.array([[1, 0], [0, (1 + 1j) / numpy.sqrt(2)]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
return PhaseGate(0.25 * numpy.pi * exponent)


class TdgGate(Gate):
r"""Single qubit T-adjoint gate (~Z**0.25).
Expand Down Expand Up @@ -119,6 +127,7 @@ def _define(self):
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit

from .u1 import U1Gate

q = QuantumRegister(1, "q")
Expand All @@ -136,3 +145,7 @@ def inverse(self):
def __array__(self, dtype=None):
"""Return a numpy.array for the inverse T gate."""
return numpy.array([[1, 0], [0, (1 - 1j) / math.sqrt(2)]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
return PhaseGate(-0.25 * numpy.pi * exponent)
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/xx_minus_yy.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,8 @@ def __array__(self, dtype=complex):
],
dtype=dtype,
)

def power(self, exponent: float):
"""Raise gate to a power."""
theta, beta = self.params
return XXMinusYYGate(exponent * theta, beta)
5 changes: 5 additions & 0 deletions qiskit/circuit/library/standard_gates/xx_plus_yy.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,8 @@ def __array__(self, dtype=complex):
],
dtype=dtype,
)

def power(self, exponent: float):
"""Raise gate to a power."""
theta, beta = self.params
return XXPlusYYGate(exponent * theta, beta)
15 changes: 13 additions & 2 deletions qiskit/circuit/library/standard_gates/z.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@
"""Z, CZ and CCZ gates."""

from typing import Optional, Union

import numpy
from qiskit.qasm import pi

from qiskit.circuit._utils import _compute_control_matrix
from qiskit.circuit.controlledgate import ControlledGate
from qiskit.circuit.gate import Gate
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit._utils import _compute_control_matrix
from qiskit.qasm import pi

from .p import PhaseGate


class ZGate(Gate):
Expand Down Expand Up @@ -74,6 +78,7 @@ def __init__(self, label: Optional[str] = None):
def _define(self):
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit

from .u1 import U1Gate

q = QuantumRegister(1, "q")
Expand Down Expand Up @@ -117,6 +122,10 @@ def __array__(self, dtype=None):
"""Return a numpy.array for the Z gate."""
return numpy.array([[1, 0], [0, -1]], dtype=dtype)

def power(self, exponent: float):
"""Raise gate to a power."""
return PhaseGate(numpy.pi * exponent)


class CZGate(ControlledGate):
r"""Controlled-Z gate.
Expand Down Expand Up @@ -163,6 +172,7 @@ def _define(self):
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit

from .h import HGate
from .x import CXGate

Expand Down Expand Up @@ -241,6 +251,7 @@ def _define(self):
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit

from .h import HGate
from .x import CCXGate

Expand Down
25 changes: 25 additions & 0 deletions releasenotes/notes/efficient-gate-power-effa21e3ee4581ee.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
features:
- |
Overrides some gate power methods to make them more efficient and less lossy:
- Powering a :class:`~.CPhaseGate` gives a :class:`~.CPhaseGate`.
- Powering a :class:`~.CSGate` gives a :class:`~.CPhaseGate`.
- Powering a :class:`~.CSdgGate` gives a :class:`~.CPhaseGate`.
- Powering an :class:`~.IGate` gives an :class:`~.IGate`.
- Powering a :class:`~.PhaseGate` gives a :class:`~.PhaseGate`.
- Powering an :class:`~.RGate` gives an :class:`~.RGate`.
- Powering an :class:`~.RXGate` gives an :class:`~.RXGate`.
- Powering an :class:`~.RXXGate` gives an :class:`~.RXXGate`.
- Powering an :class:`~.RYGate` gives an :class:`~.RYGate`.
- Powering an :class:`~.RYYGate` gives an :class:`~.RYYGate`.
- Powering an :class:`~.RZGate` gives an :class:`~.RZGate`.
- Powering an :class:`~.RZXGate` gives an :class:`~.RZXGate`.
- Powering an :class:`~.RZZGate` gives an :class:`~.RZZGate`.
- Powering a :class:`~.SdgGate` gives a :class:`~.PhaseGate`.
- Powering an :class:`~.SGate` gives a :class:`~.PhaseGate`.
- Powering a :class:`~.TdgGate` gives a :class:`~.PhaseGate`.
- Powering a :class:`~.TGate` gives a :class:`~.PhaseGate`.
- Powering an :class:`~.XXMinusYYGate` gives an :class:`~.XXMinusYYGate`.
- Powering an :class:`~.XXPlusYYGate` gives an :class:`~.XXPlusYYGate`.
- Powering a :class:`~.ZGate` gives a :class:`~.PhaseGate`.
- Powering an :class:`~.iSwapGate` gives an :class:`~.XXPlusYYGate`.
Loading