diff --git a/qiskit/extensions/__init__.py b/qiskit/extensions/__init__.py index d13fd4d39e06..392fbbcb12e9 100644 --- a/qiskit/extensions/__init__.py +++ b/qiskit/extensions/__init__.py @@ -45,6 +45,7 @@ RYGate RZGate RZZGate + RZXGate SGate SdgGate SwapGate diff --git a/qiskit/extensions/standard/__init__.py b/qiskit/extensions/standard/__init__.py index 4408bc4d12d7..b8292ee57535 100644 --- a/qiskit/extensions/standard/__init__.py +++ b/qiskit/extensions/standard/__init__.py @@ -27,6 +27,7 @@ from .ryy import RYYGate from .rz import RZGate, CRZGate from .rzz import RZZGate +from .rzx import RZXGate from .s import SGate, SdgGate from .swap import SwapGate, CSwapGate from .iswap import iSwapGate diff --git a/qiskit/extensions/standard/dcx.py b/qiskit/extensions/standard/dcx.py index 3e8e6664c81c..a1cc9e97e740 100644 --- a/qiskit/extensions/standard/dcx.py +++ b/qiskit/extensions/standard/dcx.py @@ -40,7 +40,7 @@ class DCXGate(Gate): .. math:: - DCX = + DCX\ q_0, q_1 = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ @@ -50,6 +50,7 @@ class DCXGate(Gate): """ def __init__(self): + """Create new DCX gate.""" super().__init__('dcx', 2, []) def _define(self): @@ -72,27 +73,7 @@ def to_matrix(self): def dcx(self, qubit1, qubit2): - """Apply DCX gate to a pair specified qubits (qubit1, qubit2). - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(2) - circuit.dcx(0, 1) - print(circuit) - print(circuit.decompose()) - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.dcx import DCXGate - DCXGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.DCXGate`. """ return self.append(DCXGate(), [qubit1, qubit2], []) diff --git a/qiskit/extensions/standard/h.py b/qiskit/extensions/standard/h.py index 3f9f883cdece..6ed16ce6d222 100644 --- a/qiskit/extensions/standard/h.py +++ b/qiskit/extensions/standard/h.py @@ -28,10 +28,33 @@ # pylint: disable=cyclic-import class HGate(Gate): - """Hadamard gate.""" + r"""Single-qubit Hadamard gate. + + This gate is a \pi rotation about the X+Z axis, and has the effect of + changing computation basis from :math:`|0\rangle,|1\rangle` to + :math:`|+\rangle,|-\rangle` and vice-versa. + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ H ├ + └───┘ + + **Matrix Representation:** + + .. math:: + + H = \frac{1}{\sqrt{2}} + \begin{pmatrix} + 1 & 1 \\ + 1 & -1 + \end{pmatrix} + """ def __init__(self, label=None): - """Create new Hadamard gate.""" + """Create new H gate.""" super().__init__('h', 1, [], label=label) def _define(self): @@ -49,7 +72,9 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (multi-)controlled-H gate. + + One control qubit returns a CH gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -67,7 +92,7 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate.""" + r"""Return inverted H gate (itself).""" return HGate() # self-inverse def to_matrix(self): @@ -78,43 +103,62 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def h(self, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument - r"""Apply Hadamard (H) gate. + """Apply :class:`~qiskit.extensions.standard.HGate`.""" + return self.append(HGate(), [qubit], []) - Applied to a specified qubit ``qubit``. - An H gate implements a rotation of :math:`\pi` about the axis - :math:`\frac{(x + z)}{\sqrt{2}}` on the Bloch sphere. This gate is - canonically used to rotate the qubit state from :math:`|0\rangle` to - :math:`|+\rangle` or :math:`|1\rangle` to :math:`|-\rangle`. +QuantumCircuit.h = h - Examples: - Circuit Representation: +class CHGate(ControlledGate): + r"""Controlled-Hadamard gate. - .. jupyter-execute:: + Applies a Hadamard on the target qubit if the control is + in the :math:`|1\rangle` state. - from qiskit import QuantumCircuit + **Circuit symbol:** - circuit = QuantumCircuit(1) - circuit.h(0) - circuit.draw() + .. parsed-literal:: - Matrix Representation: + ┌───┐ + q_0: ┤ H ├ + └─┬─┘ + q_1: ──■── - .. jupyter-execute:: + **Matrix Representation:** - from qiskit.extensions.standard.h import HGate - HGate().to_matrix() + .. math:: - """ - return self.append(HGate(), [qubit], []) + CH\ q_1, q_0 = + |0\rangle\langle 0| \otimes I + |1\rangle\langle 1| \otimes H = + \frac{1}{\sqrt{2}} + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & 1 & 1 \\ + 0 & 0 & 1 & -1 + \end{pmatrix} + .. note:: -QuantumCircuit.h = h + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which is how we present the gate above as well, resulting in textbook + matrices. Instead, if we use q_0 as control, the matrix will be: + .. math:: -class CHGate(ControlledGate): - """The controlled-H gate.""" + CH\ q_0, q_1 = + I \otimes |0\rangle\langle 0| + H \otimes |1\rangle\langle 1| = + \frac{1}{\sqrt{2}} + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 1 \\ + 0 & 0 & 1 & 0 \\ + 0 & 1 & 0 & -1 + \end{pmatrix} + """ def __init__(self): """Create new CH gate.""" @@ -150,7 +194,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverted CH gate (itself).""" return CHGate() # self-inverse def to_matrix(self): @@ -165,32 +209,7 @@ def to_matrix(self): @deprecate_arguments({'ctl': 'control_qubit', 'tgt': 'target_qubit'}) def ch(self, control_qubit, target_qubit, # pylint: disable=invalid-name *, ctl=None, tgt=None): # pylint: disable=unused-argument - """Apply cH gate - - From a specified control ``control_qubit`` to target ``target_qubit`` qubit. - This gate is canonically used to rotate the qubit state from :math:`|0\\rangle` to - :math:`|+\\rangle` and :math:`|1\\rangle to :math:`|−\\rangle` when the control qubit is - in state :math:`|1\\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(2) - circuit.ch(0,1) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.h import CHGate - CHGate().to_matrix() - """ + """Apply :class:`~qiskit.extensions.standard.CHGate`.""" return self.append(CHGate(), [control_qubit, target_qubit], []) diff --git a/qiskit/extensions/standard/i.py b/qiskit/extensions/standard/i.py index d4e93fdca3dc..0188f61952da 100644 --- a/qiskit/extensions/standard/i.py +++ b/qiskit/extensions/standard/i.py @@ -33,10 +33,26 @@ def __instancecheck__(mcs, inst): class IGate(Gate, metaclass=IMeta): - """Identity gate. + r"""Identity gate. Identity gate corresponds to a single-qubit gate wait cycle, and should not be optimized or unrolled (it is an opaque gate). + + **Matrix Representation:** + + .. math:: + + I = \begin{pmatrix} + 1 & 0 \\ + 0 & 1 + \end{pmatrix} + + **Circuit symbol:** + + .. parsed-literal:: + ┌───┐ + q_0: ┤ I ├ + └───┘ """ def __init__(self, label=None): @@ -66,32 +82,7 @@ def __init__(self): @deprecate_arguments({'q': 'qubit'}) def i(self, qubit, *, q=None): # pylint: disable=unused-argument - """Apply Identity to to a specified qubit ``qubit``. - - The Identity gate ensures that nothing is applied to a qubit for one unit - of gate time. It leaves the quantum states :math:`|0\\rangle` and - :math:`|1\\rangle` unchanged. The Identity gate should not be optimized or - unrolled (it is an opaque gate). - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(1) - circuit.id(0) # or circuit.i(0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.i import IGate - IGate().to_matrix() - """ + """Apply :class:`~qiskit.extensions.standard.IGate`.""" return self.append(IGate(), [qubit], []) diff --git a/qiskit/extensions/standard/iswap.py b/qiskit/extensions/standard/iswap.py index 7e1c3daf29ae..2391f420f2e3 100644 --- a/qiskit/extensions/standard/iswap.py +++ b/qiskit/extensions/standard/iswap.py @@ -25,11 +25,21 @@ class iSwapGate(Gate): r"""iSWAP gate. - A 2-qubit XY interaction that is equivalent to a SWAP up to a diagonal. + A 2-qubit XX+YY interaction. This is a Clifford and symmetric gate. Its action is to swap two qubit states and phase the :math:`|01\rangle` and :math:`|10\rangle` amplitudes by i. + **Circuit Symbol:** + + .. parsed-literal:: + + q_0: ─⨂─ + │ + q_1: ─⨂─ + + **Reference Implementation:** + .. parsed-literal:: ┌───┐┌───┐ ┌───┐ @@ -38,16 +48,25 @@ class iSwapGate(Gate): q_1: ┤ S ├─────┤ X ├──■──┤ H ├ └───┘ └───┘ └───┘ + **Matrix Representation:** + .. math:: - iSWAP = + iSWAP = R_{XX+YY}(-\frac{\pi}{2}) + = exp(i \frac{\pi}{4} (X{\otimes}X+Y{\otimes}Y)) = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & i & 0 \\ 0 & i & 0 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} - = \begin{pmatrix} + + This gate is equivalent to a SWAP up to a diagonal. + + .. math:: + + iSWAP = + \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ @@ -62,6 +81,7 @@ class iSwapGate(Gate): """ def __init__(self): + """Create new iSwap gate.""" super().__init__('iswap', 2, []) def _define(self): @@ -97,25 +117,7 @@ def to_matrix(self): def iswap(self, qubit1, qubit2): - """Apply iSWAP gate to a pair specified qubits (qubit1, qubit2). - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(2) - circuit.iswap(0,1) - circuit.draw() - - .. jupyter-execute:: - - from qiskit.extensions.standard.iswap import iSwapGate - from qiskit.quantum_info import Operator - Operator(iSwapGate()).data + """Apply :class:`~qiskit.extensions.standard.iSwapGate`. """ return self.append(iSwapGate(), [qubit1, qubit2], []) diff --git a/qiskit/extensions/standard/ms.py b/qiskit/extensions/standard/ms.py index 8c626dfc75b3..850841e8e807 100644 --- a/qiskit/extensions/standard/ms.py +++ b/qiskit/extensions/standard/ms.py @@ -16,12 +16,6 @@ """ Global Mølmer–Sørensen gate. - -The Mølmer–Sørensen gate is native to ion-trap systems. The global MS can be -applied to multiple ions to entangle multiple qubits simultaneously. - -In the two-qubit case, this is equivalent to an XX(theta) interaction, -and is thus reduced to the RXXGate. """ @@ -31,7 +25,14 @@ class MSGate(Gate): - """Global Molmer-Sorensen gate.""" + """Global Mølmer–Sørensen gate. + + The Mølmer–Sørensen gate is native to ion-trap systems. The global MS can be + applied to multiple ions to entangle multiple qubits simultaneously. + + In the two-qubit case, this is equivalent to an XX(theta) interaction, + and is thus reduced to the RXXGate. + """ def __init__(self, n_qubits, theta): """Create new MS gate.""" @@ -52,7 +53,7 @@ def _define(self): def ms(self, theta, qubits): - """Apply MS to q1 and q2.""" + """Apply :class:`~qiskit.extensions.standard.MSGate`.""" return self.append(MSGate(len(qubits), theta), qubits) diff --git a/qiskit/extensions/standard/rx.py b/qiskit/extensions/standard/rx.py index 801bc27eef75..78797659a5c7 100644 --- a/qiskit/extensions/standard/rx.py +++ b/qiskit/extensions/standard/rx.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -Rotation around the x-axis. +Rotation around the X axis. """ import math import numpy @@ -26,10 +26,31 @@ class RXGate(Gate): - """The rotation around the x-axis.""" + r"""Single-qubit rotation about the X axis. + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───────┐ + q_0: ┤ Rx(ϴ) ├ + └───────┘ + + **Matrix Representation:** + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + RX(\theta) = exp(-i \th X) = + \begin{pmatrix} + \cos{\th} & -i\sin{\th} \\ + -i\sin{\th} & \cos{\th} + \end{pmatrix} + """ def __init__(self, theta): - """Create new rx single qubit gate.""" + """Create new RX gate.""" super().__init__('rx', 1, [theta]) def _define(self): @@ -47,7 +68,7 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (mutli-)controlled-RX gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -65,9 +86,9 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate. + r"""Return inverted RX gate. - rx(theta)^dagger = rx(-theta) + :math:`RX(\lambda)^{\dagger} = RX(-\lambda)` """ return RXGate(-self.params[0]) @@ -81,31 +102,7 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def rx(self, theta, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument - """Apply Rx gate with angle theta to a specified qubit (qubit). - An Rx gate implements a theta radian rotation of the qubit state vector about the - x axis of the Bloch sphere. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit.circuit import QuantumCircuit, Parameter - - theta = Parameter('θ') - circuit = QuantumCircuit(1) - circuit.rx(theta,0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - import numpy - from qiskit.extensions.standard.rx import RXGate - RXGate(numpy.pi/2).to_matrix() - """ + """Apply :class:`~qiskit.extensions.standard.RXGate`.""" return self.append(RXGate(theta), [qubit], []) @@ -123,10 +120,55 @@ def __instancecheck__(mcs, inst): class CRXGate(ControlledGate, metaclass=CRXMeta): - """The controlled-rx gate.""" + r"""Controlled-RX gate. + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───────┐ + q_0: ┤ Rx(ϴ) ├ + └───┬───┘ + q_1: ────■──── + + **Matrix representation:** + + .. math:: + \newcommand{\th}{\frac{\theta}{2}} + + CRX(\theta)\ q_1, q_0 = + |0\rangle\langle0| \otimes I + |1\rangle\langle1| \otimes RX(\theta) = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & \cos{\th} & -i\sin{\th} \\ + 0 & 0 & -i\sin{\th} & \cos{\th} + \end{pmatrix} + + .. note:: + + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which is how we present the gate above as well, resulting in textbook + matrices. Instead, if we use q_0 as control, the matrix will be: + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + CRX(\lambda)\ q_0, q_1 = + I \otimes |0\rangle\langle 0| + RX(\theta) \otimes |1\rangle\langle 1| = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & \cos{\th} & 0 & -i\sin{\th} \\ + 0 & 0 & 1 & 0 \\ + 0 & -i\sin{\th} & 0 & \cos{\th} + \end{pmatrix} + """ def __init__(self, theta): - """Create new crx gate.""" + """Create new CRX gate.""" super().__init__('crx', 2, [theta], num_ctrl_qubits=1) self.base_gate = RXGate(theta) @@ -157,7 +199,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse RX gate (i.e. with the negative rotation angle).""" return CRXGate(-self.params[0]) @@ -177,7 +219,7 @@ def __init__(self, theta): 'tgt': 'target_qubit'}) def crx(self, theta, control_qubit, target_qubit, *, ctl=None, tgt=None): # pylint: disable=unused-argument - """Apply crx from ctl to tgt with angle theta.""" + """Apply :class:`~qiskit.extensions.standard.CRXGate`.""" return self.append(CRXGate(theta), [control_qubit, target_qubit], []) diff --git a/qiskit/extensions/standard/rxx.py b/qiskit/extensions/standard/rxx.py index 1a36c666e325..c928d1035e06 100644 --- a/qiskit/extensions/standard/rxx.py +++ b/qiskit/extensions/standard/rxx.py @@ -21,20 +21,63 @@ class RXXGate(Gate): - """Two-qubit XX-rotation gate. + r"""A parameteric 2-qubit :math:`X \otimes X` interaction (rotation about XX). - This gate corresponds to the rotation U(θ) = exp(-1j * θ * X⊗X / 2) - up to the phase exp(-1j * θ/2). + This gate is symmetric, and is maximally entangling at :math:`\theta = \pi/2`. + + **Circuit Symbol:** + + .. parsed-literal:: + + ┌─────────┐ + q_0: ┤1 ├ + │ Rxx(ϴ) │ + q_1: ┤0 ├ + └─────────┘ + + **Matrix Representation:** + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + R_{XX}(\theta) = exp(-i \frac{\theta}{2} X{\otimes}X) = + \begin{pmatrix} + \cos(\th) & 0 & 0 & -i\sin(\th) \\ + 0 & \cos(\th) & -i\sin(\th) & 0 \\ + 0 & -i\sin(\th) & \cos(\th) & 0 \\ + -i\sin(\th) & 0 & 0 & \cos(\th)} + \end{pmatrix} + + **Examples:** + + .. math:: + + R_{XX}(\theta = 0) = I + + .. math:: + + R_{XX}(\theta = \pi) = i X \otimes X + + .. math:: + + R_{XX}(\theta = \frac{\pi}{2}) = \frac{1}{\sqrt{2}} + \begin{pmatrix} + 1 & 0 & 0 & -i \\ + 0 & 1 & -i & 0 \\ + 0 & -i & 1 & 0 \\ + -i & 0 & 0 & 1 + \end{pmatrix} """ def __init__(self, theta): - """Create new rxx gate.""" + """Create new RXX gate.""" super().__init__('rxx', 2, [theta]) def _define(self): """Calculate a subcircuit that implements this unitary.""" from qiskit.extensions.standard.x import CXGate - from qiskit.extensions.standard.u1 import U1Gate + from qiskit.extensions.standard.rz import RZGate from qiskit.extensions.standard.h import HGate definition = [] q = QuantumRegister(2, 'q') @@ -43,7 +86,7 @@ def _define(self): (HGate(), [q[0]], []), (HGate(), [q[1]], []), (CXGate(), [q[0], q[1]], []), - (U1Gate(theta), [q[1]], []), + (RZGate(theta), [q[1]], []), (CXGate(), [q[0], q[1]], []), (HGate(), [q[1]], []), (HGate(), [q[0]], []), @@ -53,24 +96,25 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse RXX gate (i.e. with the negative rotation angle).""" return RXXGate(-self.params[0]) - # NOTE: we should use the following as the canonical matrix - # definition but we don't include it yet since it differs from - # the circuit decomposition matrix by a global phase + # TODO: this is the correct matrix and is equal to the definition above, + # however the control mechanism cannot distinguish U1 and RZ yet. # def to_matrix(self): - # """Return a Numpy.array for the RXX gate.""" - # theta = float(self.params[0]) - # return np.array([ - # [np.cos(theta / 2), 0, 0, -1j * np.sin(theta / 2)], - # [0, np.cos(theta / 2), -1j * np.sin(theta / 2), 0], - # [0, -1j * np.sin(theta / 2), np.cos(theta / 2), 0], - # [-1j * np.sin(theta / 2), 0, 0, np.cos(theta / 2)]], dtype=complex) + # """Return a Numpy.array for the RXX gate.""" + # theta = float(self.params[0]) + # cos = np.cos(theta / 2) + # sin = np.sin(theta / 2) + # return np.array([ + # [cos, 0, 0, -1j * sin], + # [0, cos, -1j * sin, 0], + # [0, -1j * sin, cos, 0], + # [-1j * sin, 0, 0, cos]], dtype=complex) def rxx(self, theta, qubit1, qubit2): - """Apply RXX to circuit.""" + """Apply :class:`~qiskit.extensions.standard.RXXGate`.""" return self.append(RXXGate(theta), [qubit1, qubit2], []) diff --git a/qiskit/extensions/standard/ry.py b/qiskit/extensions/standard/ry.py index a76668f132f1..b60b2d737f86 100644 --- a/qiskit/extensions/standard/ry.py +++ b/qiskit/extensions/standard/ry.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -Rotation around the y-axis. +Rotation around the Y axis. """ import math import numpy @@ -26,10 +26,31 @@ class RYGate(Gate): - """The rotation around the y-axis.""" + r"""Single-qubit rotation about the Y axis. + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───────┐ + q_0: ┤ Ry(ϴ) ├ + └───────┘ + + **Matrix Representation:** + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + RX(\theta) = exp(-i \th Y) = + \begin{pmatrix} + \cos{\th} & -\sin{\th} \\ + \sin{\th} & \cos{\th} + \end{pmatrix} + """ def __init__(self, theta): - """Create new RY single qubit gate.""" + """Create new RY gate.""" super().__init__('ry', 1, [theta]) def _define(self): @@ -47,7 +68,7 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (mutli-)controlled-RY gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -65,9 +86,9 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate. + r"""Return inverted RY gate. - ry(theta)^dagger = ry(-theta) + :math:`RY(\lambda){\dagger} = RY(-\lambda)` """ return RYGate(-self.params[0]) @@ -81,31 +102,7 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def ry(self, theta, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument - """Apply Ry gate with angle theta to a specified qubit (qubit). - An Ry gate implements a theta radian rotation of the qubit state vector about the - y axis of the Bloch sphere. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit.circuit import QuantumCircuit, Parameter - - theta = Parameter('θ') - circuit = QuantumCircuit(1) - circuit.ry(theta,0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - import numpy - from qiskit.extensions.standard.ry import RYGate - RYGate(numpy.pi/2).to_matrix() - """ + """Apply :class:`~qiskit.extensions.standard.RYGate`.""" return self.append(RYGate(theta), [qubit], []) @@ -123,10 +120,57 @@ def __instancecheck__(mcs, inst): class CRYGate(ControlledGate, metaclass=CRYMeta): - """The controlled-ry gate.""" + r"""Controlled-RY gate. + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───────┐ + q_0: ┤ Ry(ϴ) ├ + └───┬───┘ + q_1: ────■──── + + + **Matrix representation:** + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + CRY(\theta)\ q_1, q_0 = + |0\rangle\langle 0| \otimes I + |1\rangle\langle 1| \otimes RY(\theta) = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & \cos{\th} & -\sin{\th} \\ + 0 & 0 & \sin{\th} & \cos{\th} + \end{pmatrix} + + .. note:: + + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which is how we present the gate above as well, resulting in textbook + matrices. Instead, if we use q_0 as control, the matrix will be: + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + CRY(\theta)\ q_0, q_1 = + I \otimes |0\rangle\langle 0| + RY(\theta) \otimes |1\rangle\langle 1| = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & \cos{\th} & 0 & -\sin{\th} \\ + 0 & 0 & 1 & 0 \\ + 0 & \sin{\th} & 0 & \cos{\th} + \end{pmatrix} + """ def __init__(self, theta): - """Create new cry gate.""" + """Create new CRY gate.""" super().__init__('cry', 2, [theta], num_ctrl_qubits=1) self.base_gate = RYGate(theta) @@ -153,7 +197,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse RY gate (i.e. with the negative rotation angle).""" return CRYGate(-self.params[0]) @@ -173,7 +217,7 @@ def __init__(self, theta): 'tgt': 'target_qubit'}) def cry(self, theta, control_qubit, target_qubit, *, ctl=None, tgt=None): # pylint: disable=unused-argument - """Apply cry from ctl to tgt with angle theta.""" + """Apply :class:`~qiskit.extensions.standard.CRYGate`.""" return self.append(CRYGate(theta), [control_qubit, target_qubit], []) diff --git a/qiskit/extensions/standard/ryy.py b/qiskit/extensions/standard/ryy.py index f8acdf9e208a..e756ca592e1b 100644 --- a/qiskit/extensions/standard/ryy.py +++ b/qiskit/extensions/standard/ryy.py @@ -22,14 +22,57 @@ class RYYGate(Gate): - r"""Two-qubit YY-rotation gate. + r"""A parameteric 2-qubit :math:`Y \otimes Y` interaction (rotation about YY). - This gate corresponds to the rotation :math:`U(\theta) = e^{-i\theta / 2 Y \otimes Y)`, - multiplied by the phase :math:`e^{i \theta / 2}`. + This gate is symmetric, and is maximally entangling at :math:`\theta = \pi/2`. + + **Circuit Symbol:** + + .. parsed-literal:: + + ┌─────────┐ + q_0: ┤1 ├ + │ Ryy(ϴ) │ + q_1: ┤0 ├ + └─────────┘ + + **Matrix Representation:** + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + R_{YY}(\theta) = exp(-i.\frac{\theta}{2}.Y{\otimes}Y) = + \begin{pmatrix} + \cos(\th) & 0 & 0 & i\sin(\th) \\ + 0 & \cos(\th) & -i\sin(\th) & 0 \\ + 0 & -i\sin(\th) & \cos(\th) & 0 \\ + i\sin(\th) & 0 & 0 & \cos(\th)} + \end{pmatrix} + + **Examples:** + + .. math:: + + R_{YY}(\theta = 0) = I + + .. math:: + + R_{YY}(\theta = \pi) = i Y \otimes Y + + .. math:: + + R_{YY}(\theta = \frac{\pi}{2}) = \frac{1}{\sqrt{2}} + \begin{pmatrix} + 1 & 0 & 0 & i \\ + 0 & 1 & -i & 0 \\ + 0 & -i & 1 & 0 \\ + i & 0 & 0 & 1 + \end{pmatrix} """ def __init__(self, theta): - """Create new ryy gate.""" + """Create new RYY gate.""" super().__init__('ryy', 2, [theta]) def _define(self): @@ -55,24 +98,27 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse RYY gate (i.e. with the negative rotation angle).""" return RYYGate(-self.params[0]) - def to_matrix(self): - """Return a numpy.arry for the RYY gate.""" - theta = self.params[0] - return np.exp(0.5j * theta) * np.array([ - [np.cos(theta / 2), 0, 0, 1j * np.sin(theta / 2)], - [0, np.cos(theta / 2), -1j * np.sin(theta / 2), 0], - [0, -1j * np.sin(theta / 2), np.cos(theta / 2), 0], - [1j * np.sin(theta / 2), 0, 0, np.cos(theta / 2)] - ], dtype=complex) + # TODO: this is the correct matrix and is equal to the definition above, + # however the control mechanism cannot distinguish U1 and RZ yet. + # def to_matrix(self): + # """Return a numpy.arry for the RYY gate.""" + # theta = self.params[0] + # cos = np.cos(theta / 2) + # sin = np.sin(theta / 2) + # return np.array([ + # [cos, 0, 0, 1j * sin], + # [0, cos, -1j * sin, 0], + # [0, -1j * sin, cos, 0], + # [1j * sin, 0, 0, cos] + # ], dtype=complex) def ryy(self, theta, qubit1, qubit2): - """Apply RYY to circuit.""" + """Apply :class:`~qiskit.extensions.standard.RYYGate`.""" return self.append(RYYGate(theta), [qubit1, qubit2], []) -# Add to QuantumCircuit class QuantumCircuit.ryy = ryy diff --git a/qiskit/extensions/standard/rz.py b/qiskit/extensions/standard/rz.py index 0b595605c541..b8470ef52b3b 100644 --- a/qiskit/extensions/standard/rz.py +++ b/qiskit/extensions/standard/rz.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -Rotation around the z-axis. +Rotation around the Z axis. """ from qiskit.circuit import Gate from qiskit.circuit import ControlledGate @@ -23,10 +23,43 @@ class RZGate(Gate): - """The rotation around the z-axis.""" + r"""Single-qubit rotation about the Z axis. + This is a diagonal gate. It can be implemented virtually in hardware + via framechanges (i.e. at zero error and duration). + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───────┐ + q_0: ┤ Rz(λ) ├ + └───────┘ + + **Matrix Representation:** + + .. math:: + + RZ(\lambda) = exp(-i\frac{\lambda}{2}Z) = + \begin{pmatrix} + e^{-i\frac{\lambda}{2}} & 0 \\ + 0 & e^{i\frac{\lambda}{2}} + \end{pmatrix} + + .. seealso:: + + :class:`~qiskit.extensions.standard.U1Gate` + This gate is equivalent to U1 up to a phase factor. + + .. math:: + + U1(\lambda) = e^{i{\lambda}/2}RZ(\lambda) + + Reference for virtual Z gate implementation: + `1612.00858 `_ + """ def __init__(self, phi): - """Create new RZ single qubit gate.""" + """Create new RZ gate.""" super().__init__('rz', 1, [phi]) def _define(self): @@ -44,7 +77,7 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (mutli-)controlled-RZ gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -62,34 +95,24 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate. + r"""Return inverted RZ gate - rz(phi)^dagger = rz(-phi) + :math:`RZ(\lambda){\dagger} = RZ(-\lambda)` """ return RZGate(-self.params[0]) + # TODO: this is the correct matrix however the control mechanism + # cannot distinguish U1 and RZ yet. + # def to_matrix(self): + # """Return a numpy.array for the RZ gate.""" + # lam = float(self.params[0]) + # return np.array([[np.exp(-1j * lam / 2), 0], + # [0, np.exp(1j * lam / 2)]], dtype=complex) + @deprecate_arguments({'q': 'qubit'}) def rz(self, phi, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument - """Apply Rz gate with angle :math:`\\phi` - - The gate is applied to a specified qubit `qubit`. - An Rz gate implemements a phi radian rotation of the qubit state vector - about the z axis of the Bloch sphere. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit.circuit import QuantumCircuit, Parameter - - phi = Parameter('φ') - circuit = QuantumCircuit(1) - circuit.rz(phi,0) - circuit.draw() - """ + """Apply :class:`~qiskit.extensions.standard.RZGate`.""" return self.append(RZGate(phi), [qubit], []) @@ -107,10 +130,62 @@ def __instancecheck__(mcs, inst): class CRZGate(ControlledGate, metaclass=CRZMeta): - """The controlled-rz gate.""" + r"""Controlled-RZ gate. + + This is a diagonal but non-symmetric gate that induces a + phase on the state of the target qubit, depending on the control state. + **Circuit symbol:** + + .. parsed-literal:: + + ┌───────┐ + q_0: ┤ Rz(λ) ├ + └───┬───┘ + q_1: ────■──── + + + **Matrix representation:** + + .. math:: + + CRZ(\lambda)\ q_1, q_0 = + |0\rangle\langle 0| \otimes I + |1\rangle\langle 1| \otimes RZ(\lambda) = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & e^{-i\frac{\lambda}{2}} & 0 \\ + 0 & 0 & 0 & e^{i\frac{\lambda}{2}} + \end{pmatrix} + + .. note:: + + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which is how we present the gate above as well, resulting in textbook + matrices. Instead, if we use q_0 as control, the matrix will be: + + .. math:: + + CRZ(\lambda)\ q_0, q_1 = + I \otimes |0\rangle\langle 0| + RZ(\lambda) \otimes |1\rangle\langle 1| = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & e^{-i\frac{\lambda}{2}} & 0 & 0 \\ + 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & e^{i\frac{\lambda}{2}} + \end{pmatrix} + + .. seealso:: + + :class:`~qiskit.extensions.standard.CU1Gate`: + Due to the global phase difference in the matrix definitions + of U1 and RZ, CU1 and CRZ are different gates with a relative + phase difference. + """ def __init__(self, theta): - """Create new crz gate.""" + """Create new CRZ gate.""" super().__init__('crz', 2, [theta], num_ctrl_qubits=1) self.base_gate = RZGate(theta) @@ -136,7 +211,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse RZ gate (i.e. with the negative rotation angle).""" return CRZGate(-self.params[0]) @@ -155,26 +230,7 @@ def __init__(self, theta): @deprecate_arguments({'ctl': 'control_qubit', 'tgt': 'target_qubit'}) def crz(self, theta, control_qubit, target_qubit, *, ctl=None, tgt=None): # pylint: disable=unused-argument - """Apply cRz gate - - Applied from a specified control ``control_qubit`` to target ``target_qubit`` qubit - with angle :math:`\\theta`. A cRz gate implements a :math:`\\theta` radian rotation - of the qubit state vector about the z axis of the Bloch sphere when the control - qubit is in state :math:`|1\\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit.circuit import QuantumCircuit, Parameter - - theta = Parameter('θ') - circuit = QuantumCircuit(2) - circuit.crz(theta,0,1) - circuit.draw() - """ + """Apply :class:`~qiskit.extensions.standard.CRZGate`.""" return self.append(CRZGate(theta), [control_qubit, target_qubit], []) diff --git a/qiskit/extensions/standard/rzx.py b/qiskit/extensions/standard/rzx.py new file mode 100644 index 000000000000..f617db53c8e4 --- /dev/null +++ b/qiskit/extensions/standard/rzx.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2020. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +""" +Two-qubit ZX-rotation gate. +""" +from qiskit.circuit import Gate +from qiskit.circuit import QuantumCircuit +from qiskit.circuit import QuantumRegister + + +class RZXGate(Gate): + r"""A parameteric 2-qubit :math:`Z \otimes X` interaction (rotation about ZX). + + This gate is maximally entangling at :math:`\theta = \pi/2`. + + The cross-resonance gate (CR) for superconducting qubits implements + a ZX interaction (however other terms are also present in an experiment). + + **Circuit Symbol:** + + .. parsed-literal:: + + ┌─────────┐ + q_0: ┤1 ├ + │ Rzx(θ) │ + q_1: ┤0 ├ + └─────────┘ + + **Matrix Representation:** + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + R_{ZX}(\theta)\ q_1, q_0 = exp(-i \frac{\theta}{2} Z{\otimes}X) = + \begin{pmatrix} + \cos(\th) & -i\sin(\th) & 0 & 0 \\ + -i\sin(\th) & \cos(\th) & 0 & 0 \\ + 0 & 0 & \cos(\th) & i\sin(\th) \\ + 0 & 0 & i\sin(\th) & \cos(\th) + \end{pmatrix} + + This is a direct sum of RX rotations, so this gate is equivalent to a + uniformly controlled (multiplexed) RX gate: + + .. math:: + + R_{ZX}(\theta)\ q_1, q_0 = + \begin{pmatrix} + RX(\theta) & 0 \\ + 0 & RX(-\theta) + \end{pmatrix} + + .. note:: + + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In the above example we apply the gate + on (q_1, q_0) which results in the ZX tensor order. Instead, if we + apply it on (q_0, q_1), the matrix will be: + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + R_{ZX}(\theta)\ q_0, q_1 = exp(-i \frac{\theta}{2} X{\otimes}Z) = + \begin{pmatrix} + \cos(\th) & 0 & -i\sin(\th) & 0 \\ + 0 & \cos(\th) & 0 & i\sin(\th) \\ + -i\sin(\th) & 0 & \cos(\th) & 0 \\ + 0 & i\sin(\th) & 0 & \cos(\th) + \end{pmatrix} + + **Examples:** + + .. math:: + + R_{ZX}(\theta = 0) = I + + .. math:: + + R_{ZX}(\theta = 2\pi) = -I + + .. math:: + + R_{ZX}(\theta = \pi) = -i Z \otimes X + + .. math:: + + RZX(\theta = \frac{\pi}{2}) = \frac{1}{\sqrt{2}} + \begin{pmatrix} + 1 & -i & 0 & 0 \\ + -i & 1 & 0 & 0 \\ + 0 & 0 & 1 & i \\ + 0 & 0 & i & 1 + \end{pmatrix} + """ + + def __init__(self, theta): + """Create new RZX gate.""" + super().__init__('rzx', 2, [theta]) + + def _define(self): + """ + gate rzx(theta) a, b { h b; cx a, b; u1(theta) b; cx a, b; h b;} + """ + from qiskit.extensions.standard.u1 import U1Gate + from qiskit.extensions.standard.h import HGate + from qiskit.extensions.standard.x import CXGate + q = QuantumRegister(2, 'q') + self.definition = [ + (HGate(), [q[1]], []), + (CXGate(), [q[0], q[1]], []), + (U1Gate(self.params[0]), [q[1]], []), + (CXGate(), [q[0], q[1]], []), + (HGate(), [q[1]], []) + ] + + def inverse(self): + """Return inverse RZX gate (i.e. with the negative rotation angle).""" + return RZXGate(-self.params[0]) + + # TODO: this is the correct definition but has a global phase with respect + # to the decomposition above. Restore after allowing phase on circuits. + # def to_matrix(self): + # """Return a numpy.array for the RZX gate.""" + # theta = self.params[0] + # return np.array([[np.cos(theta/2), 0, -1j*np.sin(theta/2), 0], + # [0, np.cos(theta/2), 0, 1j*np.sin(theta/2)], + # [-1j*np.sin(theta/2), 0, np.cos(theta/2), 0], + # [0, 1j*np.sin(theta/2), 0, np.cos(theta/2)]], + # dtype=complex) + + +def rzx(self, theta, qubit1, qubit2): + """Apply :class:`~qiskit.extensions.standard.RZXGate`.""" + return self.append(RZXGate(theta), [qubit1, qubit2], []) + + +# Add to QuantumCircuit class +QuantumCircuit.rzx = rzx diff --git a/qiskit/extensions/standard/rzz.py b/qiskit/extensions/standard/rzz.py index 00f7e322754a..0464941ae079 100644 --- a/qiskit/extensions/standard/rzz.py +++ b/qiskit/extensions/standard/rzz.py @@ -21,23 +21,81 @@ class RZZGate(Gate): - """The two-qubit ZZ-rotation gate.""" + r"""A parameteric 2-qubit :math:`Z \otimes Z` interaction (rotation about ZZ). + + This gate is symmetric, and is maximally entangling at :math:`\theta = \pi/2`. + + **Circuit Symbol:** + + .. parsed-literal:: + + q_0: ───■──── + │zz(θ) + q_1: ───■──── + + **Matrix Representation:** + + .. math:: + + R_{ZZ}(\theta) = exp(-i \frac{\theta}{2} Z{\otimes}Z) = + \begin{pmatrix} + e^{-i\frac{\theta}{2}} & 0 & 0 & 0 \\ + 0 & e^{i\frac{\theta}{2}} & 0 & 0 \\ + 0 & 0 & e^{i\frac{\theta}{2}} & 0 \\ + 0 & 0 & 0 & e^{-i\frac{\theta}{2}} + \end{pmatrix} + + This is a direct sum of RZ rotations, so this gate is equivalent to a + uniformly controlled (multiplexed) RZ gate: + + .. math:: + + R_{ZZ}(\theta) = + \begin{pmatrix} + RZ(\theta) & 0 \\ + 0 & RZ(-\theta) + \end{pmatrix} + + **Examples:** + + .. math:: + + R_{ZZ}(\theta = 0) = I + + .. math:: + + R_{ZZ}(\theta = 2\pi) = -I + + .. math:: + + R_{ZZ}(\theta = \pi) = - Z \otimes Z + + .. math:: + + R_{ZZ}(\theta = \frac{\pi}{2}) = \frac{1}{\sqrt{2}} + \begin{pmatrix} + 1-i & 0 & 0 & 0 \\ + 0 & 1+i & 0 & 0 \\ + 0 & 0 & 1+i & 0 \\ + 0 & 0 & 0 & 1-i + \end{pmatrix} + """ def __init__(self, theta): - """Create new rzz gate.""" + """Create new RZZ gate.""" super().__init__('rzz', 2, [theta]) def _define(self): """ - gate rzz(theta) a, b { cx a, b; u1(theta) b; cx a, b; } + gate rzz(theta) a, b { cx a, b; rz(theta) b; cx a, b; } """ - from qiskit.extensions.standard.u1 import U1Gate + from qiskit.extensions.standard.rz import RZGate from qiskit.extensions.standard.x import CXGate definition = [] q = QuantumRegister(2, 'q') rule = [ (CXGate(), [q[0], q[1]], []), - (U1Gate(self.params[0]), [q[1]], []), + (RZGate(self.params[0]), [q[1]], []), (CXGate(), [q[0], q[1]], []) ] for inst in rule: @@ -45,14 +103,23 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse RZZ gate (i.e. with the negative rotation angle).""" return RZZGate(-self.params[0]) + # TODO: this is the correct matrix and is equal to the definition above, + # however the control mechanism cannot distinguish U1 and RZ yet. + # def to_matrix(self): + # """Return a numpy.array for the RZZ gate.""" + # theta = float(self.params[0]) + # return np.array([[np.exp(-1j*theta/2), 0, 0, 0], + # [0, np.exp(1j*theta/2), 0, 0], + # [0, 0, np.exp(1j*theta/2), 0], + # [0, 0, 0, np.exp(-1j*theta/2)]], dtype=complex) + def rzz(self, theta, qubit1, qubit2): - """Apply RZZ to circuit.""" + """Apply :class:`~qiskit.extensions.standard.RZZGate`.""" return self.append(RZZGate(theta), [qubit1, qubit2], []) -# Add to QuantumCircuit class QuantumCircuit.rzz = rzz diff --git a/qiskit/extensions/standard/s.py b/qiskit/extensions/standard/s.py index 7dc61269fe37..44cf2c088a74 100644 --- a/qiskit/extensions/standard/s.py +++ b/qiskit/extensions/standard/s.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -The S gate (Clifford phase gate) and its inverse. +S and Sdg gate. """ import numpy from qiskit.circuit import Gate @@ -24,8 +24,31 @@ class SGate(Gate): - """The S gate, also called Clifford phase gate.""" + r"""Single qubit S gate (Z**0.5). + It induces a :math:`\pi/2` phase, and is sometimes called the P gate (phase). + + This is a Clifford gate and a square-root of Pauli-Z. + + **Matrix Representation:** + + .. math:: + + S = \begin{pmatrix} + 1 & 0 \\ + 0 & i + \end{pmatrix} + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ S ├ + └───┘ + + Equivalent to a :math:`\pi/2` radian rotation about the Z axis. + """ def __init__(self, label=None): """Create a new S gate.""" super().__init__('s', 1, [], label=label) @@ -45,7 +68,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse of S (SdgGate).""" return SdgGate() def to_matrix(self): @@ -55,7 +78,31 @@ def to_matrix(self): class SdgGate(Gate): - """Sdg=diag(1,-i) Clifford adjoint phase gate.""" + r"""Single qubit S-adjoint gate (~Z**0.5). + + It induces a :math:`-\pi/2` phase. + + This is a Clifford gate and a square-root of Pauli-Z. + + **Matrix Representation:** + + .. math:: + + Sdg = \begin{pmatrix} + 1 & 0 \\ + 0 & -i + \end{pmatrix} + + **Circuit symbol:** + + .. parsed-literal:: + + ┌─────┐ + q_0: ┤ Sdg ├ + └─────┘ + + Equivalent to a :math:`\pi/2` radian rotation about the Z axis. + """ def __init__(self, label=None): """Create a new Sdg gate.""" @@ -76,7 +123,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse of Sdg (SGate).""" return SGate() def to_matrix(self): @@ -87,56 +134,14 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def s(self, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument - """Apply S gate to a specified qubit (qubit). - An S gate implements a pi/2 rotation of the qubit state vector about the - z axis of the Bloch sphere. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(1) - circuit.s(0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.s import SGate - SGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.SGate`. """ return self.append(SGate(), [qubit], []) @deprecate_arguments({'q': 'qubit'}) def sdg(self, qubit, *, q=None): # pylint: disable=unused-argument - """Apply Sdg gate to a specified qubit (qubit). - An Sdg gate implements a -pi/2 rotation of the qubit state vector about the - z axis of the Bloch sphere. It is the inverse of S gate. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(1) - circuit.sdg(0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.s import SdgGate - SdgGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.SdgGate`. """ return self.append(SdgGate(), [qubit], []) diff --git a/qiskit/extensions/standard/swap.py b/qiskit/extensions/standard/swap.py index 94d8a1a6e706..1a437abd8821 100644 --- a/qiskit/extensions/standard/swap.py +++ b/qiskit/extensions/standard/swap.py @@ -24,7 +24,36 @@ class SwapGate(Gate): - """SWAP gate.""" + r"""The SWAP gate. + + This is a symmetric and Clifford gate. + + **Circuit symbol:** + + .. parsed-literal:: + + q_0: ─X─ + │ + q_1: ─X─ + + **Matrix Representation:** + + .. math:: + + SWAP = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 1 + \end{pmatrix} + + The gate is equivalent to a state swap and is a classical logic gate. + + .. math:: + + |a, b\rangle \rightarrow |b, a\rangle + """ def __init__(self): """Create new SWAP gate.""" @@ -47,7 +76,9 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (multi-)controlled-SWAP gate. + + One control returns a CSWAP (Fredkin) gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -65,7 +96,7 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate.""" + """Return inverse Swap gate (itself).""" return SwapGate() # self-inverse def to_matrix(self): @@ -77,27 +108,7 @@ def to_matrix(self): def swap(self, qubit1, qubit2): - """Apply SWAP gate to a pair specified qubits (qubit1, qubit2). - The SWAP gate canonically swaps the states of two qubits. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(2) - circuit.swap(0,1) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.swap import SwapGate - SwapGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.SwapGate`. """ return self.append(SwapGate(), [qubit1, qubit2], []) @@ -116,7 +127,70 @@ def __instancecheck__(mcs, inst): class CSwapGate(ControlledGate, metaclass=CSwapMeta): - """The controlled-swap gate, also called Fredkin gate.""" + r"""Controlled-X gate. + + **Circuit symbol:** + + .. parsed-literal:: + + + q_0: ─X─ + │ + q_1: ─X─ + │ + q_2: ─■─ + + + **Matrix representation:** + + .. math:: + + CSWAP\ q_2, q_1, q_0 = + |0 \rangle \langle 0| \otimes I \otimes I + + |1 \rangle \langle 1| \otimes SWAP = + \begin{pmatrix} + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ + \end{pmatrix} + + .. note:: + + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which is how we present the gate above as well, resulting in textbook + matrices. Instead, if we use q_0 as control, the matrix will be: + + .. math:: + + CSWAP\ q_0, q_1, q_2 = + |0 \rangle \langle 0| \otimes I \otimes I + + |1 \rangle \langle 1| \otimes SWAP = + \begin{pmatrix} + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ + \end{pmatrix} + + In the computational basis, this gate swaps the states of + the two target qubits if the control qubit is in the + :math:`|1\rangle` state. + + .. math:: + |0, b, c\rangle \rightarrow |0, b, c\rangle + |1, b, c\rangle \rightarrow |1, c, b\rangle + """ def __init__(self): """Create new CSWAP gate.""" @@ -145,7 +219,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse CSwap gate (itself).""" return CSwapGate() # self-inverse def to_matrix(self): @@ -177,31 +251,7 @@ def __init__(self): 'tgt2': 'target_qubit2'}) def cswap(self, control_qubit, target_qubit1, target_qubit2, *, ctl=None, tgt1=None, tgt2=None): # pylint: disable=unused-argument - """Apply Fredkin (CSWAP) gate - - From a specified control ``control_qubit`` to target1 ``target_qubit1`` and - target2 ``target_qubit2`` qubits. The CSWAP gate is canonically - used to swap the qubit states of target1 and target2 when the control qubit - is in state :math:`|1\\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(3) - circuit.cswap(0,1,2) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.swap import CSwapGate - CSwapGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.CSwapGate`. """ return self.append(CSwapGate(), [control_qubit, target_qubit1, target_qubit2], []) diff --git a/qiskit/extensions/standard/t.py b/qiskit/extensions/standard/t.py index ff49cb7ddcae..29c2d2621d36 100644 --- a/qiskit/extensions/standard/t.py +++ b/qiskit/extensions/standard/t.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -T=sqrt(S) phase gate or its inverse. +T and Tdg gate. """ import numpy from qiskit.circuit import Gate @@ -24,7 +24,32 @@ class TGate(Gate): - """T Gate: pi/4 rotation around Z axis.""" + r"""Single qubit T gate (Z**0.25). + + It induces a :math:`\pi/4` phase, and is sometimes called the pi/8 gate + (because of how the RZ(\pi/4) matrix looks like). + + This is a non-Clifford gate and a fourth-root of Pauli-Z. + + **Matrix Representation:** + + .. math:: + + T = \begin{pmatrix} + 1 & 0 \\ + 0 & 1+i + \end{pmatrix} + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ T ├ + └───┘ + + Equivalent to a :math:`\pi/4` radian rotation about the Z axis. + """ def __init__(self, label=None): """Create new T gate.""" @@ -45,7 +70,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse T gate (i.e. Tdg).""" return TdgGate() def to_matrix(self): @@ -55,7 +80,31 @@ def to_matrix(self): class TdgGate(Gate): - """Tdg Gate: -pi/4 rotation around Z axis.""" + r"""Single qubit T-adjoint gate (~Z**0.25). + + It induces a :math:`-\pi/4` phase. + + This is a non-Clifford gate and a fourth-root of Pauli-Z. + + **Matrix Representation:** + + .. math:: + + Tdg = \begin{pmatrix} + 1 & 0 \\ + 0 & 1-i + \end{pmatrix} + + **Circuit symbol:** + + .. parsed-literal:: + + ┌─────┐ + q_0: ┤ Tdg ├ + └─────┘ + + Equivalent to a :math:`\pi/2` radian rotation about the Z axis. + """ def __init__(self, label=None): """Create a new Tdg gate.""" @@ -76,7 +125,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverse Tdg gate (i.e. T).""" return TGate() def to_matrix(self): @@ -87,56 +136,14 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def t(self, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument - """Apply T gate to a specified qubit (qubit). - A T gate implements a pi/4 rotation of a qubit state vector about the - z axis of the Bloch sphere. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(1) - circuit.t(0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.t import TGate - TGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.TGate`. """ return self.append(TGate(), [qubit], []) @deprecate_arguments({'q': 'qubit'}) def tdg(self, qubit, *, q=None): # pylint: disable=unused-argument - """Apply Tdg gate to a specified qubit (qubit). - A Tdg gate implements a -pi/4 rotation of a qubit state vector about the - z axis of the Bloch sphere. It is the inverse of T-gate. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(1) - circuit.tdg(0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.t import TdgGate - TdgGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.TdgGate`. """ return self.append(TdgGate(), [qubit], []) diff --git a/qiskit/extensions/standard/u1.py b/qiskit/extensions/standard/u1.py index 1ade6b1ca905..b6df08f8bf3c 100644 --- a/qiskit/extensions/standard/u1.py +++ b/qiskit/extensions/standard/u1.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -Diagonal single qubit gate. +U1 Gate. """ import numpy from qiskit.circuit import ControlledGate @@ -25,10 +25,62 @@ # pylint: disable=cyclic-import class U1Gate(Gate): - """Diagonal single-qubit gate.""" + r"""Single-qubit rotation about the Z axis. + + This is a diagonal gate. It can be implemented virtually in hardware + via framechanges (i.e. at zero error and duration). + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───────┐ + q_0: ┤ U1(λ) ├ + └───────┘ + + **Matrix Representation:** + + .. math:: + + U1(\lambda) = + \begin{pmatrix} + 1 & 0 \\ + 0 & e^{i\lambda} + \end{pmatrix} + + **Examples:** + + .. math:: + + U1(\lambda = \pi) = Z + + .. math:: + + U1(\lambda = \pi/2) = S + + .. math:: + + U1(\lambda = \pi/4) = T + + .. seealso:: + + :class:`~qiskit.extensions.standard.RZGate`: + This gate is equivalent to RZ up to a phase factor. + + .. math:: + + U1(\lambda) = e^{i{\lambda}/2} RZ(\lambda) + + :class:`~qiskit.extensions.standard.U3Gate`: + U3 is a generalization of U2 that covers all single-qubit rotations, + using two X90 pulses. + + Reference for virtual Z gate implementation: + `1612.00858 `_ + """ def __init__(self, theta, label=None): - """Create new diagonal single-qubit gate.""" + """Create new U1 gate.""" super().__init__('u1', 1, [theta], label=label) def _define(self): @@ -43,7 +95,7 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (mutli-)controlled-U1 gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -61,7 +113,7 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate.""" + r"""Return inverted U1 gate (:math:`U1(\lambda){\dagger} = U1(-\lambda)`)""" return U1Gate(-self.params[0]) def to_matrix(self): @@ -73,33 +125,7 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def u1(self, theta, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument - """Apply U1 gate with angle theta - - Applied to a specified qubit ``qubit``. - :math:`u1(\\lambda) := diag(1, ei\\lambda) ∼ U(0, 0, \\lambda) = Rz(\\lambda)` - where :math:`~` is equivalence up to a global phase. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit.circuit import QuantumCircuit, Parameter - - theta = Parameter('θ') - circuit = QuantumCircuit(1) - circuit.u1(theta,0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - import numpy - from qiskit.extensions.standard.u1 import U1Gate - U1Gate(numpy.pi/2).to_matrix() - """ + """Apply :class:`~qiskit.extensions.standard.U1Gate`.""" return self.append(U1Gate(theta), [qubit], []) @@ -117,10 +143,44 @@ def __instancecheck__(mcs, inst): class CU1Gate(ControlledGate, metaclass=CU1Meta): - """The controlled-u1 gate.""" + r"""Controlled-U1 gate. + + This is a diagonal and symmetric gate that induces a + phase on the state of the target qubit, depending on the control state. + + **Circuit symbol:** + + .. parsed-literal:: + + + q_0: ─■── + │λ + q_1: ─■── + + + **Matrix representation:** + + .. math:: + + CU1 = + |0\rangle\langle 0| \otimes I + |1\rangle\langle 1| \otimes U1 = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & e^{i\lambda} + \end{pmatrix} + + .. seealso:: + + :class:`~qiskit.extensions.standard.CRZGate`: + Due to the global phase difference in the matrix definitions + of U1 and RZ, CU1 and CRZ are different gates with a relative + phase difference. + """ def __init__(self, theta): - """Create new cu1 gate.""" + """Create new CU1 gate.""" super().__init__('cu1', 2, [theta], num_ctrl_qubits=1) self.base_gate = U1Gate(theta) @@ -147,7 +207,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + r"""Return inverted CU1 gate (:math:`CU1(\lambda){\dagger} = CU1(-\lambda)`)""" return CU1Gate(-self.params[0]) @@ -167,26 +227,7 @@ def __init__(self, theta): 'tgt': 'target_qubit'}) def cu1(self, theta, control_qubit, target_qubit, *, ctl=None, tgt=None): # pylint: disable=unused-argument - r"""Apply cU1 gate - - Applied from a specified control ``control_qubit`` to target - ``target_qubit`` qubit with angle theta. A cU1 gate implements a - :math:`\theta` radian rotation of the qubit state vector about the z axis - of the Bloch sphere when the control qubit is in state :math:`|1\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit.circuit import QuantumCircuit, Parameter - - theta = Parameter('θ') - circuit = QuantumCircuit(2) - circuit.cu1(theta,0,1) - circuit.draw() - """ + """Apply :class:`~qiskit.extensions.standard.CU1Gate`.""" return self.append(CU1Gate(theta), [control_qubit, target_qubit], []) diff --git a/qiskit/extensions/standard/u2.py b/qiskit/extensions/standard/u2.py index f73c0bae41c8..f6d19715ba09 100644 --- a/qiskit/extensions/standard/u2.py +++ b/qiskit/extensions/standard/u2.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -One-pulse single-qubit gate. +U2 Gate. """ import numpy from qiskit.circuit import Gate @@ -24,10 +24,46 @@ class U2Gate(Gate): - """One-pulse single-qubit gate.""" + r"""Single-qubit rotation about the X+Z axis. + + Implemented using one X90 pulse on IBM Quantum systems: + + .. math:: + U2(\phi, \lambda) = RZ(\phi+\pi/2).RX(\frac{\pi}{2}).RZ(\lambda-\pi/2) + + **Circuit symbol:** + + .. parsed-literal:: + + ┌─────────┐ + q_0: ┤ U2(φ,λ) ├ + └─────────┘ + + **Matrix Representation:** + + .. math:: + + U2(\phi, \lambda) = \frac{1}{\sqrt{2}} + \begin{pmatrix} + 1 & e^{-i\lambda} \\ + e^{i\phi} & e^{i(\phi+\lambda)} + \end{pmatrix} + + **Examples:** + + .. math:: + + U2(\pi, 0) = H + + .. seealso:: + + :class:`~qiskit.extensions.standard.U3Gate`: + U3 is a generalization of U2 that covers all single-qubit rotations, + using two X90 pulses. + """ def __init__(self, phi, lam, label=None): - """Create new one-pulse single-qubit gate.""" + """Create new U2 gate.""" super().__init__('u2', 1, [phi, lam], label=label) def _define(self): @@ -40,9 +76,9 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate. + r"""Return inverted U2 gate. - u2(phi,lamb)^dagger = u2(-lamb-pi,-phi+pi) + :math:`U2(\phi, \lambda)^{\dagger} =U2(-\lambda-\pi, -\phi+\pi)`) """ return U2Gate(-self.params[1] - pi, -self.params[0] + pi) @@ -65,31 +101,7 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def u2(self, phi, lam, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument - """Apply U2 gate with angle phi and lam to a specified qubit (qubit). - u2(φ,λ) := U(π/2,φ,λ) = Rz(φ + π/2)Rx(π/2)Rz(λ − π/2) - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit.circuit import QuantumCircuit, Parameter - - phi = Parameter('φ') - lam = Parameter('λ') - circuit = QuantumCircuit(1) - circuit.u2(phi,lam,0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - import numpy - from qiskit.extensions.standard.u2 import U2Gate - U2Gate(numpy.pi/2,numpy.pi/2).to_matrix() - """ + """Apply :class:`~qiskit.extensions.standard.U2Gate`.""" return self.append(U2Gate(phi, lam), [qubit], []) diff --git a/qiskit/extensions/standard/u3.py b/qiskit/extensions/standard/u3.py index c1c32798064c..08cfe31ea6ba 100644 --- a/qiskit/extensions/standard/u3.py +++ b/qiskit/extensions/standard/u3.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -Two-pulse single-qubit gate. +U3 Gate, three-parameter single-qubit gate. """ import numpy @@ -26,21 +26,57 @@ # pylint: disable=cyclic-import class U3Gate(Gate): - """Two-pulse single-qubit gate.""" + r"""Generic single-qubit rotation gate with 3 Euler angles. + + Implemented using two X90 pulses on IBM Quantum systems: + + .. math:: + U2(\phi, \lambda) = RZ(\phi+\pi/2) RX(\frac{\pi}{2}) RZ(\lambda-\pi/2) + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───────────┐ + q_0: ┤ U3(ϴ,φ,λ) ├ + └───────────┘ + + **Matrix Representation:** + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + U3(\theta, \phi, \lambda) = + \begin{pmatrix} + \cos(\th) & e^{-i\lambda}\sin(\th) \\ + e^{i\phi}\sin(\th) & e^{i(\phi+\lambda)\cos(\th)} + \end{pmatrix} + + **Examples:** + + .. math:: + + U3(\theta, -\frac{\pi}{2}, \frac{pi}{2}) = RX(\theta) + + .. math:: + + U3(\theta, 0, 0) = RY(\theta) + """ def __init__(self, theta, phi, lam, label=None): - """Create new two-pulse single qubit gate.""" + """Create new U3 gate.""" super().__init__('u3', 1, [theta, phi, lam], label=label) def inverse(self): - """Invert this gate. + r"""Return inverted U3 gate. - u3(theta, phi, lamb)^dagger = u3(-theta, -lam, -phi) + :math:`U3(\theta,\phi,\lambda)^{\dagger} =U3(-\theta,-\phi,-\lambda)`) """ return U3Gate(-self.params[0], -self.params[2], -self.params[1]) def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (mutli-)controlled-U3 gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -75,32 +111,7 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def u3(self, theta, phi, lam, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument - """Apply U3 gate with angle theta, phi, and lam to a specified qubit (qubit). - u3(θ, φ, λ) := U(θ, φ, λ) = Rz(φ + 3π)Rx(π/2)Rz(θ + π)Rx(π/2)Rz(λ) - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit.circuit import QuantumCircuit, Parameter - - theta = Parameter('theta') - phi = Parameter('φ') - lam = Parameter('λ') - circuit = QuantumCircuit(1) - circuit.u3(theta,phi,lam,0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - import numpy - from qiskit.extensions.standard.u3 import U3Gate - U3Gate(numpy.pi/2,numpy.pi/2,numpy.pi/2).to_matrix() - """ + """Apply :class:`~qiskit.extensions.standard.U3Gate`.""" return self.append(U3Gate(theta, phi, lam), [qubit], []) @@ -118,10 +129,61 @@ def __instancecheck__(mcs, inst): class CU3Gate(ControlledGate, metaclass=CU3Meta): - """The controlled-u3 gate.""" + r"""Controlled-U3 gate (3-parameter two-qubit gate). + + This is a controlled version of the U3 gate (generic single qubit rotation). + It is restricted to 3 parameters, and so cannot cover generic two-qubit + controlled gates). + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───────────┐ + q_0: ┤ U3(ϴ,φ,λ) ├ + └─────┬─────┘ + q_1: ──────■────── + + + **Matrix representation:** + + .. math:: + + \newcommand{\th}{\frac{\theta}{2}} + + CU3(\theta, \phi, \lambda)\ q_1, q_0= + |0\rangle\langle 0| \otimes I + |1\rangle\langle 1| \otimes U3(\theta,\phi,\lambda) = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & \cos(\th) & e^{-i\lambda}\sin(\th) \\ + 0 & 0 & e^{i\phi}\sin(\th) & e^{i(\phi+\lambda)\cos(\th)} + \end{pmatrix} + + + .. note:: + + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which is how we present the gate above as well, resulting in textbook + matrices. Instead, if we use q_0 as control, the matrix will be: + + .. math:: + + CU3(\theta, \phi, \lambda)\ q_0, q_1 = + I \otimes |0\rangle\langle 0| + + U3(\theta,\phi,\lambda) \otimes |1\rangle\langle 1| = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & \cos(\th) & 0 & e^{-i\lambda}\sin(\th) \\ + 0 & 0 & 1 & 0 \\ + 0 & e^{i\phi}\sin(\th) & 0 & e^{i(\phi+\lambda)\cos(\th)} + \end{pmatrix} + """ def __init__(self, theta, phi, lam): - """Create new cu3 gate.""" + """Create new CU3 gate.""" super().__init__('cu3', 2, [theta, phi, lam], num_ctrl_qubits=1) self.base_gate = U3Gate(theta, phi, lam) @@ -153,7 +215,10 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + r"""Return inverted CU3 gate. + + :math:`CU3(\theta,\phi,\lambda)^{\dagger} =CU3(-\theta,-\phi,-\lambda)`) + """ return CU3Gate(-self.params[0], -self.params[2], -self.params[1]) @@ -173,28 +238,7 @@ def __init__(self, theta, phi, lam): 'tgt': 'target_qubit'}) def cu3(self, theta, phi, lam, control_qubit, target_qubit, *, ctl=None, tgt=None): # pylint: disable=unused-argument - """Apply cU3 gate - - Applied from a specified control ``control_qubit`` to target - ``target_qubit`` qubit with angle ``theta``, ``phi``, and ``lam``. - A cU3 gate implements a ``U3(theta,phi,lam)`` on the target qubit when the - control qubit is in state :math:`|1\\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit.circuit import QuantumCircuit, Parameter - - theta = Parameter('θ') - phi = Parameter('φ') - lam = Parameter('λ') - circuit = QuantumCircuit(2) - circuit.cu3(theta,phi,lam,0,1) - circuit.draw() - """ + """Apply :class:`~qiskit.extensions.standard.U3Gate`.""" return self.append(CU3Gate(theta, phi, lam), [control_qubit, target_qubit], []) diff --git a/qiskit/extensions/standard/x.py b/qiskit/extensions/standard/x.py index c5cd3dc57b1a..10bb860bd52c 100644 --- a/qiskit/extensions/standard/x.py +++ b/qiskit/extensions/standard/x.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -Pauli X (bit-flip) gate. +X, CX and CCX gates. """ import numpy from qiskit.circuit import ControlledGate @@ -28,7 +28,47 @@ class XGate(Gate): - """Pauli X (bit-flip) gate.""" + r"""The single-qubit Pauli-X gate (:math:`\sigma_x`). + + **Matrix Representation:** + + .. math:: + + X = \begin{pmatrix} + 0 & 1 \\ + 1 & 0 + \end{pmatrix} + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ X ├ + └───┘ + + Equivalent to a :math:`\pi` radian rotation about the X axis. + + .. note:: + + A global phase difference exists between the definitions of + :math:`RX(\pi)` and :math:`X`. + + .. math:: + + RX(\pi) = \begin{pmatrix} + 0 & -i \\ + -i & 0 + \end{pmatrix} + = -i X + + The gate is equivalent to a classical bit flip. + + .. math:: + + |0\rangle \rightarrow |1\rangle \\ + |1\rangle \rightarrow |0\rangle + """ def __init__(self, label=None): """Create new X gate.""" @@ -36,9 +76,7 @@ def __init__(self, label=None): def _define(self): """ - gate x a { - u3(pi,0,pi) a; - } + gate x a { u3(pi,0,pi) a; } """ from qiskit.extensions.standard.u3 import U3Gate definition = [] @@ -51,7 +89,9 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (mutli-)controlled-X gate. + + One control returns a CX gate. Two controls returns a CCX gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -71,7 +111,7 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate.""" + r"""Return inverted X gate (itself)""" return XGate() # self-inverse def to_matrix(self): @@ -82,31 +122,7 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def x(self, qubit, *, q=None): # pylint: disable=unused-argument - """Apply X gate to a specified qubit (qubit). - - An X gate implements a :math:`\\pi` rotation of the qubit state vector about - the x axis of the Bloch sphere. This gate is canonically used to implement - a bit flip on the qubit state from :math:`|0\\rangle` to :math:`|1\\rangle`, - or vice versa. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(1) - circuit.x(0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.x import XGate - XGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.XGate`. """ return self.append(XGate(), [qubit], []) @@ -125,15 +141,65 @@ def __instancecheck__(mcs, inst): class CXGate(ControlledGate, metaclass=CXMeta): - """The controlled-X gate.""" + r"""Controlled-X gate. + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ X ├ + └─┬─┘ + q_1: ──■── + + + **Matrix representation:** + + .. math:: + + CX\ q_1, q_0 = + |0\rangle\langle0| \otimes I + |1\rangle\langle1| \otimes X = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 1 \\ + 0 & 0 & 1 & 0 + \end{pmatrix} + + .. note:: + + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which is how we present the gate above as well, resulting in textbook + matrices. Instead, if we use q_0 as control, the matrix will be: + + .. math:: + + CX\ q_0, q_1 = + I \otimes |0\rangle\langle 0| + Y \otimes |1\rangle\langle 1| = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 \\ + 0 & 0 & 1 & 0 \\ + 0 & 1 & 0 & 0 + \end{pmatrix} + + In the computational basis, this gate flips the target qubit + if the control qubit is in the :math:`|1\rangle` state. + In this sense it is similar to a classical XOR gate. + + .. math:: + `|a, b\rangle \rightarrow |a, a \oplus b\rangle` + """ def __init__(self): - """Create new cx gate.""" + """Create new CX gate.""" super().__init__('cx', 2, [], num_ctrl_qubits=1) self.base_gate = XGate() def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a controlled-X gate with more control lines. Args: num_ctrl_qubits (int): number of control qubits. @@ -151,7 +217,7 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate.""" + """Return inverted CX gate (itself).""" return CXGate() # self-inverse def to_matrix(self): @@ -178,33 +244,7 @@ def __init__(self): 'tgt': 'target_qubit'}) def cx(self, control_qubit, target_qubit, # pylint: disable=invalid-name *, ctl=None, tgt=None): # pylint: disable=unused-argument - """Apply CX gate - - From a specified control ``control_qubit`` to target ``target_qubit`` qubit. - A CX gate implements a :math:`\\pi` rotation of the qubit state vector about - the x axis of the Bloch sphere when the control qubit is in state :math:`|1\\rangle` - This gate is canonically used to implement a bit flip on the qubit state from - :math:`|0\\rangle` to :math:`|1\\rangle`, or vice versa when the control qubit is in - :math:`|1\\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(2) - circuit.cx(0,1) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.x import CXGate - CXGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.CXGate`. """ return self.append(CXGate(), [control_qubit, target_qubit], []) @@ -225,7 +265,60 @@ def __instancecheck__(mcs, inst): class CCXGate(ControlledGate, metaclass=CCXMeta): - """The double-controlled-not gate, also called Toffoli gate.""" + r"""CCX gate, also known as Toffoli gate. + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ X ├ + └─┬─┘ + q_1: ──■── + │ + q_2: ──■── + + + **Matrix representation:** + + .. math:: + + CCX\ q_2, q_1, q_0 = + I \otimes I \otimes |0\rangle\langle 0| + CX \otimes |1\rangle\langle 1| = + \begin{pmatrix} + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\\ + 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 + \end{pmatrix} + + .. note:: + + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which is how we present the gate above as well, resulting in textbook + matrices. Instead, if we use q_0 and q_1 as control, the matrix will be: + + .. math:: + + CCX q_0, q_1, q_2 = + |0\rangle\langle 0| \otimes I \otimes I + |1\rangle\langle 1| \otimes CX = + \begin{pmatrix} + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ + 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\\ + 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\ + 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0\\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 + \end{pmatrix} + """ def __init__(self): """Create new CCX gate.""" @@ -265,7 +358,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return an inverted CCX gate (also a CCX).""" return CCXGate() # self-inverse def to_matrix(self): @@ -297,30 +390,7 @@ def __init__(self): 'tgt': 'target_qubit'}) def ccx(self, control_qubit1, control_qubit2, target_qubit, *, ctl1=None, ctl2=None, tgt=None): # pylint: disable=unused-argument - """Apply Toffoli (ccX) gate - - From two specified controls ``(control_qubit1 and control_qubit2)`` to target ``target_qubit`` - qubit. This gate is canonically used to rotate the qubit state from :math:`|0\\rangle` to - :math:`|1\\rangle`, or vice versa when both the control qubits are in state :math:`|1\\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(3) - circuit.ccx(0,1,2) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.x import CCXGate - CCXGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.CCXGate` (Toffoli). """ return self.append(CCXGate(), diff --git a/qiskit/extensions/standard/y.py b/qiskit/extensions/standard/y.py index 30eeb7473d0c..84871ea34621 100644 --- a/qiskit/extensions/standard/y.py +++ b/qiskit/extensions/standard/y.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -Pauli Y (bit-phase-flip) gate. +Y and CY gates. """ import numpy from qiskit.circuit import Gate @@ -25,7 +25,47 @@ class YGate(Gate): - """Pauli Y (bit-phase-flip) gate.""" + r"""The single-qubit Pauli-Y gate (:math:`\sigma_y`). + + **Matrix Representation:** + + .. math:: + + Y = \begin{pmatrix} + 0 & -i \\ + i & 0 + \end{pmatrix} + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ Y ├ + └───┘ + + Equivalent to a :math:`\pi` radian rotation about the Y axis. + + .. note:: + + A global phase difference exists between the definitions of + :math:`RY(\pi)` and :math:`Y`. + + .. math:: + + RY(\pi) = \begin{pmatrix} + 0 & -1 \\ + 1 & 0 + \end{pmatrix} + = -i Y + + The gate is equivalent to a bit and phase flip. + + .. math:: + + |0\rangle \rightarrow i|1\rangle \\ + |1\rangle \rightarrow -i|0\rangle + """ def __init__(self, label=None): """Create new Y gate.""" @@ -43,7 +83,9 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (mutli-)controlled-Y gate. + + One control returns a CY gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -61,7 +103,7 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate.""" + r"""Return inverted Y gate (:math:`Y{\dagger} = Y`)""" return YGate() # self-inverse def to_matrix(self): @@ -72,32 +114,7 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def y(self, qubit, *, q=None): # pylint: disable=unused-argument - """Apply Y gate to a specified qubit (qubit). - - A Y gate implements a :math:`\\pi` rotation of the qubit state vector about - the y axis of the Bloch sphere. This gate is canonically used to implement - a bit flip and phase flip on the qubit state from :math:`|0\\rangle` to - :math:`i|1\\rangle`, or from :math:`|1\\rangle` to :math:`-i|0\\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(1) - circuit.y(0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.y import YGate - YGate().to_matrix() - """ + """Apply :class:`~qiskit.extensions.standard.YGate`.""" return self.append(YGate(), [qubit], []) @@ -115,10 +132,53 @@ def __instancecheck__(mcs, inst): class CYGate(ControlledGate, metaclass=CYMeta): - """The controlled-Y gate.""" + r"""Controlled-Y gate. + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ Y ├ + └─┬─┘ + q_1: ──■── + + + **Matrix representation:** + + .. math:: + + CY\ q_1, q_0 = + |0\rangle\langle 0| \otimes I + |1\rangle\langle 1| \otimes Y = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & -i \\ + 0 & 0 & i & 0 + \end{pmatrix} + + .. note:: + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which is how we present the gate above as well, resulting in textbook + matrices. Instead, if we use q_0 as control, the matrix will be: + + .. math:: + + CY\ q_0, q_1 = + I \otimes |0\rangle\langle 0| + Y \otimes |1\rangle\langle 1| = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & -i \\ + 0 & 0 & 1 & 0 \\ + 0 & i & 0 & 0 + \end{pmatrix} + + """ def __init__(self): - """Create a new CY gate.""" + """Create new CY gate.""" super().__init__('cy', 2, [], num_ctrl_qubits=1) self.base_gate = YGate() @@ -141,7 +201,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverted CY gate (itself)""" return CYGate() # self-inverse def to_matrix(self): @@ -168,27 +228,7 @@ def __init__(self): 'tgt': 'target_qubit'}) def cy(self, control_qubit, target_qubit, # pylint: disable=invalid-name *, ctl=None, tgt=None): # pylint: disable=unused-argument - """Apply cY gate - - Applied from a specified control ``control_qubit`` to target ``target_qubit`` qubit. - A cY gate implements a pi rotation of the qubit state vector about the y axis - of the Bloch sphere when the control qubit is in state :math:`|1\\rangle`. - This gate is canonically used to implement a bit flip and phase flip on the qubit state - from :math:`|0\\rangle` to :math:`i|1\\rangle`, or from :math:`|1\\rangle` to - :math:`-i|0\\rangle` when the control qubit is in state :math:`|1\\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(2) - circuit.cy(0,1) - circuit.draw() - """ + """Apply :class:`~qiskit.extensions.standard.CYGate`.""" return self.append(CYGate(), [control_qubit, target_qubit], []) diff --git a/qiskit/extensions/standard/z.py b/qiskit/extensions/standard/z.py index a5b4c329d9d1..56b4d73fae3a 100644 --- a/qiskit/extensions/standard/z.py +++ b/qiskit/extensions/standard/z.py @@ -13,7 +13,7 @@ # that they have been altered from the originals. """ -Pauli Z (phase-flip) gate. +Z and CZ gates. """ import numpy from qiskit.circuit import Gate @@ -25,7 +25,47 @@ class ZGate(Gate): - """Pauli Z (phase-flip) gate.""" + r"""The single-qubit Pauli-Z gate (:math:`\sigma_z`). + + **Matrix Representation:** + + .. math:: + + Z = \begin{pmatrix} + 1 & 0 \\ + 0 & -1 + \end{pmatrix} + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ Z ├ + └───┘ + + Equivalent to a :math:`\pi` radian rotation about the Z axis. + + .. note:: + + A global phase difference exists between the definitions of + :math:`RZ(\pi)` and :math:`Z`. + + .. math:: + + RZ(\pi) = \begin{pmatrix} + -1 & 0 \\ + 0 & 1 + \end{pmatrix} + = -Z + + The gate is equivalent to a phase flip. + + .. math:: + + |0\rangle \rightarrow |0\rangle \\ + |1\rangle \rightarrow -|1\rangle + """ def __init__(self, label=None): """Create new Z gate.""" @@ -43,7 +83,9 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Controlled version of this gate. + """Return a (mutli-)controlled-Z gate. + + One control returns a CZ gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -61,7 +103,7 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): ctrl_state=ctrl_state) def inverse(self): - """Invert this gate.""" + r"""Return inverted Z gate (itself).""" return ZGate() # self-inverse def to_matrix(self): @@ -72,31 +114,7 @@ def to_matrix(self): @deprecate_arguments({'q': 'qubit'}) def z(self, qubit, *, q=None): # pylint: disable=unused-argument - """Apply Z gate to a specified qubit (qubit). - - A Z gate implements a :math:`\\pi` rotation of the qubit state vector about - the z axis of the Bloch sphere. This gate is canonically used to implement - a phase flip on the qubit state from :math:`|+\\rangle` to :math:`|-\\rangle`, - or vice versa. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - - circuit = QuantumCircuit(1) - circuit.z(0) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.z import ZGate - ZGate().to_matrix() + """Apply :class:`~qiskit.extensions.standard.ZGate`. """ return self.append(ZGate(), [qubit], []) @@ -115,7 +133,33 @@ def __instancecheck__(mcs, inst): class CZGate(ControlledGate, metaclass=CZMeta): - """The controlled-Z gate.""" + r"""Controlled-Z gate. + + **Circuit symbol:** + + .. parsed-literal:: + + ┌───┐ + q_0: ┤ Z ├ + └─┬─┘ + q_1: ──■── + + **Matrix representation:** + + .. math:: + + CZ\ q_1, q_0 = + |0\rangle\langle 0| \otimes I + |1\rangle\langle 1| \otimes Z = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & -1 + \end{pmatrix} + + In the computational basis, this gate flips the phase of + the target qubit if the control qubit is in the :math:`|1\rangle` state. + """ def __init__(self, label=None): """Create new CZ gate.""" @@ -140,7 +184,7 @@ def _define(self): self.definition = definition def inverse(self): - """Invert this gate.""" + """Return inverted CZ gate (itself).""" return CZGate() # self-inverse def to_matrix(self): @@ -167,35 +211,7 @@ def __init__(self): 'tgt': 'target_qubit'}) def cz(self, control_qubit, target_qubit, # pylint: disable=invalid-name *, ctl=None, tgt=None): # pylint: disable=unused-argument - """Apply cZ gate - - From a specified control ``control_qubit`` to target ``target_qubit`` qubit. - A cZ gate implements a :math:`\\pi` rotation of the qubit state vector about - the z axis of the Bloch sphere when the control qubit is in state :math:`|1\\rangle`. - This gate is canonically used to implement a phase flip on the qubit state from - :math:`|+\\rangle` to :math:`|-\\rangle`, or vice versa when the control qubit is in - state :math:`|1\\rangle`. - - Examples: - - Circuit Representation: - - .. jupyter-execute:: - - from qiskit import QuantumCircuit - import numpy - - circuit = QuantumCircuit(2) - circuit.cz(0,1) - circuit.draw() - - Matrix Representation: - - .. jupyter-execute:: - - from qiskit.extensions.standard.z import CZGate - CZGate().to_matrix() - """ + """Apply :class:`~qiskit.extensions.standard.CZGate`.""" return self.append(CZGate(), [control_qubit, target_qubit], []) diff --git a/releasenotes/notes/gate-documentation-5a376c8a471a13e1.yaml b/releasenotes/notes/gate-documentation-5a376c8a471a13e1.yaml new file mode 100644 index 000000000000..a44668617f6f --- /dev/null +++ b/releasenotes/notes/gate-documentation-5a376c8a471a13e1.yaml @@ -0,0 +1,7 @@ +--- +prelude: > + This release has vastly improved documentation across Qiskit. This + includes documentation for the circuit, pulse and quantum_info modules. + The documentation can be navigated at + `qiskit.org `_. + diff --git a/test/python/circuit/test_gate_definitions.py b/test/python/circuit/test_gate_definitions.py index 5b6da673b39d..728d67ac8cfd 100644 --- a/test/python/circuit/test_gate_definitions.py +++ b/test/python/circuit/test_gate_definitions.py @@ -19,10 +19,9 @@ from ddt import ddt, data -from qiskit import QuantumCircuit, BasicAer, execute +from qiskit import QuantumCircuit from qiskit.quantum_info import Operator from qiskit.test import QiskitTestCase -from qiskit.quantum_info.operators.predicates import matrix_equal from qiskit.circuit import ParameterVector @@ -30,7 +29,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 + ZGate, CZGate, RYYGate ) from qiskit.extensions.standard.equivalence_library import StandardEquivalenceLibrary as std_eqlib @@ -112,20 +111,6 @@ def test_cx_definition(self): decomposed_circ = circ.decompose() self.assertTrue(Operator(circ).equiv(Operator(decomposed_circ))) - def test_ryy_matrix_representation(self): - """Test the matrix representation of the RYY gate. - """ - from qiskit.extensions.standard.ryy import RYYGate - theta = 0.991283 - expected = RYYGate(theta).to_matrix() - - circuit = QuantumCircuit(2) - circuit.ryy(theta, 0, 1) - backend = BasicAer.get_backend('unitary_simulator') - simulated = execute(circuit, backend).result().get_unitary() - - self.assertTrue(matrix_equal(expected, simulated)) - @ddt class TestStandardEquivalenceLibrary(QiskitTestCase): @@ -135,7 +120,7 @@ class TestStandardEquivalenceLibrary(QiskitTestCase): 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 + ZGate, CZGate, RYYGate ) def test_definition_parameters(self, gate_class): """Verify decompositions from standard equivalence library match definitions."""