Source code for qutip.core.gates

# Required for Sphinx to follow autodoc_type_aliases
from __future__ import annotations

from itertools import product
from functools import partial, reduce
from operator import mul

import numpy as np
import scipy.sparse as sp
from . import Qobj, qeye, sigmax, fock_dm, qdiags, qeye_like
from .dimensions import Dimensions
from .. import settings
from . import data as _data
from ..typing import LayerType


__all__ = [
    "rx",
    "ry",
    "rz",
    "sqrtnot",
    "snot",
    "phasegate",
    "qrot",
    "cy_gate",
    "cz_gate",
    "s_gate",
    "t_gate",
    "cs_gate",
    "ct_gate",
    "cphase",
    "cnot",
    "csign",
    "berkeley",
    "swapalpha",
    "swap",
    "iswap",
    "sqrtswap",
    "sqrtiswap",
    "fredkin",
    "molmer_sorensen",
    "toffoli",
    "hadamard_transform",
    "qubit_clifford_group",
    "globalphase",
]


_DIMS_2_QB = Dimensions([[2, 2], [2, 2]])
_DIMS_3_QB = Dimensions([[2, 2, 2], [2, 2, 2]])


[docs] def cy_gate(*, dtype: LayerType = None) -> Qobj: """Controlled Y gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : :class:`.Qobj` Quantum object for operator describing the rotation. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0]], dims=_DIMS_2_QB, isherm=True, isunitary=True, ).to(dtype)
[docs] def cz_gate(*, dtype: LayerType = None) -> Qobj: """Controlled Z gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : :class:`.Qobj` Quantum object for operator describing the rotation. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return qdiags([1, 1, 1, -1], dims=_DIMS_2_QB, dtype=dtype)
[docs] def s_gate(*, dtype: LayerType = None) -> Qobj: """Single-qubit rotation also called Phase gate or the Z90 gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : :class:`.Qobj` Quantum object for operator describing a 90 degree rotation around the z-axis. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return qdiags([1, 1j], dtype=dtype)
[docs] def cs_gate(*, dtype: LayerType = None) -> Qobj: """Controlled S gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : :class:`.Qobj` Quantum object for operator describing the rotation. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return qdiags([1, 1, 1, 1j], dims=_DIMS_2_QB, dtype=dtype)
[docs] def t_gate(*, dtype: LayerType = None) -> Qobj: """Single-qubit rotation related to the S gate by the relationship S=T*T. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : :class:`.Qobj` Quantum object for operator describing a phase shift of pi/4. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return qdiags([1, np.exp(1j * np.pi / 4)], dtype=dtype)
[docs] def ct_gate(*, dtype: LayerType = None) -> Qobj: """Controlled T gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : :class:`.Qobj` Quantum object for operator describing the rotation. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return qdiags( [1, 1, 1, np.exp(1j * np.pi / 4)], dims=_DIMS_2_QB, dtype=dtype, )
[docs] def rx(phi: float, *, dtype: LayerType = None) -> Qobj: """Single-qubit rotation for operator sigmax with angle phi. Parameters ---------- phi : float Rotation angle dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : qobj Quantum object for operator describing the rotation. """ dtype = dtype or settings.core["default_dtype"] or _data.Dense return Qobj( [ [np.cos(phi / 2), -1j * np.sin(phi / 2)], [-1j * np.sin(phi / 2), np.cos(phi / 2)], ], isherm=(phi % (2 * np.pi) <= settings.core["atol"]), isunitary=True, ).to(dtype)
[docs] def ry(phi: float, *, dtype: LayerType = None) -> Qobj: """Single-qubit rotation for operator sigmay with angle phi. Parameters ---------- phi : float Rotation angle dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : qobj Quantum object for operator describing the rotation. """ dtype = dtype or settings.core["default_dtype"] or _data.Dense return Qobj( [ [np.cos(phi / 2), -np.sin(phi / 2)], [np.sin(phi / 2), np.cos(phi / 2)], ], isherm=(phi % (2 * np.pi) <= settings.core["atol"]), isunitary=True, ).to(dtype)
[docs] def rz(phi: float, *, dtype: LayerType = None) -> Qobj: """Single-qubit rotation for operator sigmaz with angle phi. Parameters ---------- phi : float Rotation angle dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : qobj Quantum object for operator describing the rotation. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return qdiags([np.exp(-1j * phi / 2), np.exp(1j * phi / 2)], dtype=dtype)
[docs] def sqrtnot(*, dtype: LayerType = None) -> Qobj: """Single-qubit square root NOT gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- result : qobj Quantum object for operator describing the square root NOT gate. """ dtype = dtype or settings.core["default_dtype"] or _data.Dense return Qobj( [[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]], isherm=False, isunitary=True, ).to(dtype)
[docs] def snot(*, dtype: LayerType = None) -> Qobj: """Quantum object representing the SNOT (Hadamard) gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- snot_gate : qobj Quantum object representation of SNOT gate. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( [[np.sqrt(0.5), np.sqrt(0.5)], [np.sqrt(0.5), -np.sqrt(0.5)]], isherm=True, isunitary=True, ).to(dtype)
[docs] def phasegate(theta: float, *, dtype: LayerType = None) -> Qobj: """ Returns quantum object representing the phase shift gate. Parameters ---------- theta : float Phase rotation angle. dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- phase_gate : qobj Quantum object representation of phase shift gate. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return qdiags([1, np.exp(1.0j * theta)], dtype=dtype)
[docs] def qrot(theta: float, phi: float, *, dtype: LayerType = None) -> Qobj: """ Single qubit rotation driving by Rabi oscillation with 0 detune. Parameters ---------- phi : float The inital phase of the rabi pulse. theta : float The duration of the rabi pulse. dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- qrot_gate : :class:`.Qobj` Quantum object representation of physical qubit rotation under a rabi pulse. """ dtype = dtype or settings.core["default_dtype"] or _data.Dense return Qobj( [ [np.cos(theta / 2), -1j * np.exp(-1j * phi) * np.sin(theta / 2)], [-1j * np.exp(1j * phi) * np.sin(theta / 2), np.cos(theta / 2)], ], isherm=(theta % (2 * np.pi) <= settings.core["atol"]), isunitary=True, ).to(dtype)
# # 2 Qubit Gates #
[docs] def cphase(theta: float, *, dtype: LayerType = None) -> Qobj: """ Returns quantum object representing the controlled phase shift gate. Parameters ---------- theta : float Phase rotation angle. dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- U : qobj Quantum object representation of controlled phase gate. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return qdiags( [1, 1, 1, np.exp(1.0j * theta)], dims=_DIMS_2_QB, dtype=dtype )
[docs] def cnot(*, dtype: LayerType = None) -> Qobj: """ Quantum object representing the CNOT gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- cnot_gate : qobj Quantum object representation of CNOT gate """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], dims=_DIMS_2_QB, isherm=True, isunitary=True, ).to(dtype)
[docs] def csign(*, dtype: LayerType = None) -> Qobj: """ Quantum object representing the CSIGN gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- csign_gate : qobj Quantum object representation of CSIGN gate """ return cz_gate(dtype=dtype)
[docs] def berkeley(*, dtype: LayerType = None) -> Qobj: """ Quantum object representing the Berkeley gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- berkeley_gate : qobj Quantum object representation of Berkeley gate """ dtype = dtype or settings.core["default_dtype"] or _data.Dense return Qobj( [ [np.cos(np.pi / 8), 0, 0, 1.0j * np.sin(np.pi / 8)], [0, np.cos(3 * np.pi / 8), 1.0j * np.sin(3 * np.pi / 8), 0], [0, 1.0j * np.sin(3 * np.pi / 8), np.cos(3 * np.pi / 8), 0], [1.0j * np.sin(np.pi / 8), 0, 0, np.cos(np.pi / 8)], ], dims=_DIMS_2_QB, isherm=False, isunitary=True, ).to(dtype)
[docs] def swapalpha(alpha: float, *, dtype: LayerType = None) -> Qobj: """ Quantum object representing the SWAPalpha gate. Parameters ---------- alpha : float Angle of the SWAPalpha gate. dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- swapalpha_gate : qobj Quantum object representation of SWAPalpha gate """ dtype = dtype or settings.core["default_dtype"] or _data.CSR phase = np.exp(1.0j * np.pi * alpha) return Qobj( [ [1, 0, 0, 0], [0, 0.5 * (1 + phase), 0.5 * (1 - phase), 0], [0, 0.5 * (1 - phase), 0.5 * (1 + phase), 0], [0, 0, 0, 1], ], dims=_DIMS_2_QB, isherm=(np.abs(phase.imag) <= settings.core["atol"]), isunitary=True, ).to(dtype)
[docs] def swap(*, dtype: LayerType = None) -> Qobj: """Quantum object representing the SWAP gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- swap_gate : qobj Quantum object representation of SWAP gate """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dims=_DIMS_2_QB, isherm=True, isunitary=True, ).to(dtype)
[docs] def iswap(*, dtype: LayerType = None) -> Qobj: """Quantum object representing the iSWAP gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- iswap_gate : qobj Quantum object representation of iSWAP gate """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( [[1, 0, 0, 0], [0, 0, 1j, 0], [0, 1j, 0, 0], [0, 0, 0, 1]], dims=_DIMS_2_QB, isherm=False, isunitary=True, ).to(dtype)
[docs] def sqrtswap(*, dtype: LayerType = None) -> Qobj: """Quantum object representing the square root SWAP gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- sqrtswap_gate : qobj Quantum object representation of square root SWAP gate """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( np.array( [ [1, 0, 0, 0], [0, 0.5 + 0.5j, 0.5 - 0.5j, 0], [0, 0.5 - 0.5j, 0.5 + 0.5j, 0], [0, 0, 0, 1], ] ), dims=_DIMS_2_QB, isherm=False, isunitary=True, ).to(dtype)
[docs] def sqrtiswap(*, dtype: LayerType = None) -> Qobj: """Quantum object representing the square root iSWAP gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- sqrtiswap_gate : qobj Quantum object representation of square root iSWAP gate """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( np.array( [ [1, 0, 0, 0], [0, 1 / np.sqrt(2), 1j / np.sqrt(2), 0], [0, 1j / np.sqrt(2), 1 / np.sqrt(2), 0], [0, 0, 0, 1], ] ), dims=_DIMS_2_QB, isherm=False, isunitary=True, ).to(dtype)
[docs] def molmer_sorensen(theta: float, *, dtype: LayerType = None) -> Qobj: """ Quantum object of a Mølmer–Sørensen gate. Parameters ---------- theta: float The duration of the interaction pulse. target: int The indices of the target qubits. dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- molmer_sorensen_gate: :class:`.Qobj` Quantum object representation of the Mølmer–Sørensen gate. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( [ [np.cos(theta / 2.0), 0, 0, -1.0j * np.sin(theta / 2.0)], [0, np.cos(theta / 2.0), -1.0j * np.sin(theta / 2.0), 0], [0, -1.0j * np.sin(theta / 2.0), np.cos(theta / 2.0), 0], [-1.0j * np.sin(theta / 2.0), 0, 0, np.cos(theta / 2.0)], ], dims=_DIMS_2_QB, isherm=(theta % (2 * np.pi) <= settings.core["atol"]), isunitary=True, ).to(dtype)
# # 3 Qubit Gates #
[docs] def fredkin(*, dtype: LayerType = None) -> Qobj: """Quantum object representing the Fredkin gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- fredkin_gate : qobj Quantum object representation of Fredkin gate. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( [ [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], ], dims=_DIMS_3_QB, isherm=True, isunitary=True, ).to(dtype)
[docs] def toffoli(*, dtype: LayerType = None) -> Qobj: """Quantum object representing the Toffoli gate. Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- toff_gate : qobj Quantum object representation of Toffoli gate. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return Qobj( [ [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], ], dims=_DIMS_3_QB, isherm=True, isunitary=True, ).to(dtype)
# # Miscellaneous Gates #
[docs] def globalphase(theta: float, N: int = 1, *, dtype: LayerType = None) -> Qobj: """ Returns quantum object representing the global phase shift gate. Parameters ---------- theta : float Phase rotation angle. N : int: Number of qubits dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- phase_gate : qobj Quantum object representation of global phase shift gate. """ dtype = dtype or settings.core["default_dtype"] or _data.CSR return qeye([2] * N, dtype=dtype) * np.exp(1.0j * theta)
# # Operation on Gates # def _hamming_distance(x): """ Calculate the bit-wise Hamming distance of x from 0: That is, the number 1s in the integer x. """ tot = 0 while x: tot += 1 x &= x - 1 return tot
[docs] def hadamard_transform(N: int = 1, *, dtype: LayerType = None) -> Qobj: """Quantum object representing the N-qubit Hadamard gate. Parameters ---------- N : int: Number of qubits dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- q : qobj Quantum object representation of the N-qubit Hadamard gate. """ dtype = dtype or settings.core["default_dtype"] or _data.Dense data = 2 ** (-N / 2) * np.array( [ [(-1) ** _hamming_distance(i & j) for i in range(2**N)] for j in range(2**N) ] ) return Qobj(data, dims=[[2] * N, [2] * N], isherm=True, isunitary=True).to( dtype )
def _powers(op, N): """ Generator that yields powers of an operator `op`, through to `N`. """ acc = qeye_like(op) yield acc for _ in range(N - 1): acc *= op yield acc
[docs] def qubit_clifford_group(*, dtype: LayerType = None) -> list[Qobj]: """ Generates the Clifford group on a single qubit, using the presentation of the group given by Ross and Selinger (http://www.mathstat.dal.ca/~selinger/newsynth/). Parameters ---------- dtype : str or type, [keyword only] [optional] Storage representation. Any data-layer known to `qutip.data.to` is accepted. Returns ------- op : list of Qobj Clifford operators, represented as Qobj instances. """ dtype = dtype or settings.core["default_dtype"] or _data.Dense # The Ross-Selinger presentation of the single-qubit Clifford # group expresses each element in the form C_{ijk} = E^i X^j S^k # for gates E, X and S, and for i in range(3), j in range(2) and # k in range(4). # # We start by defining these gates. E is defined in terms of H, # \omega and S, so we define \omega and H first. w = np.exp(1j * 2 * np.pi / 8) H = snot() X = sigmax() S = phasegate(np.pi / 2) E = H @ (S**3) * w**3 # partial(reduce, mul) returns a function that takes products # of its argument, by analogy to sum. Note that by analogy, # sum can be written as partial(reduce, add). # product(...) yields the Cartesian product of its arguments. # Here, each element is a tuple (E**i, X**j, S**k) such that # partial(reduce, mul) acting on the tuple yields E**i * X**j * S**k. gates = [ op.to(dtype) for op in map( partial(reduce, mul), product(_powers(E, 3), _powers(X, 2), _powers(S, 4)), ) ] for gate in gates: gate.isherm gate._isunitary = True return gates