Source code for pennylane.ops.qubit

# Copyright 2018 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This module contains the available built-in discrete-variable
quantum operations supported by PennyLane, as well as their conventions.
"""
import numpy as np

from pennylane.operation import All, Any, Observable, Operation


[docs]class Hadamard(Observable, Operation): r"""Hadamard(wires) The Hadamard operator .. math:: H = \frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1\\ 1 & -1\end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wire the operation acts on """ num_params = 0 num_wires = 1 par_domain = None
[docs]class PauliX(Observable, Operation): r"""PauliX(wires) The Pauli X operator .. math:: \sigma_x = \begin{bmatrix} 0 & 1 \\ 1 & 0\end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wire the operation acts on """ num_params = 0 num_wires = 1 par_domain = None
[docs]class PauliY(Observable, Operation): r"""PauliY(wires) The Pauli Y operator .. math:: \sigma_y = \begin{bmatrix} 0 & -i \\ i & 0\end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wire the operation acts on """ num_params = 0 num_wires = 1 par_domain = None
[docs]class PauliZ(Observable, Operation): r"""PauliZ(wires) The Pauli Z operator .. math:: \sigma_z = \begin{bmatrix} 1 & 0 \\ 0 & -1\end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wire the operation acts on """ num_params = 0 num_wires = 1 par_domain = None
[docs]class S(Operation): r"""S(wires) The single-qubit phase gate .. math:: S = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wire the operation acts on """ num_params = 0 num_wires = 1 par_domain = None
[docs]class T(Operation): r"""T(wires) The single-qubit T gate .. math:: T = \begin{bmatrix} 1 & 0 \\ 0 & e^{\frac{i\pi}{4}} \end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wire the operation acts on """ num_params = 0 num_wires = 1 par_domain = None
[docs]class CNOT(Operation): r"""CNOT(wires) The controlled-NOT operator .. math:: CNOT = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0 \end{bmatrix}. .. note:: The first wire provided corresponds to the **control qubit**. **Details:** * Number of wires: 2 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wires the operation acts on """ num_params = 0 num_wires = 2 par_domain = None
[docs]class CZ(Operation): r"""CZ(wires) The controlled-Z operator .. math:: CZ = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & -1 \end{bmatrix}. .. note:: The first wire provided corresponds to the **control qubit**. **Details:** * Number of wires: 2 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wires the operation acts on """ num_params = 0 num_wires = 2 par_domain = None
[docs]class SWAP(Operation): r"""SWAP(wires) The swap operator .. math:: SWAP = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}. **Details:** * Number of wires: 2 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wires the operation acts on """ num_params = 0 num_wires = 2 par_domain = None
[docs]class CSWAP(Operation): r"""CSWAP(wires) The controlled-swap operator .. math:: CSWAP = \begin{bmatrix} 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{bmatrix}. .. note:: The first wire provided corresponds to the **control qubit**. **Details:** * Number of wires: 3 * Number of parameters: 0 Args: wires (Sequence[int] or int): the wires the operation acts on """ num_params = 0 num_wires = 3 par_domain = None
[docs]class RX(Operation): r"""RX(phi, wires) The single qubit X rotation .. math:: R_x(\phi) = e^{-i\phi\sigma_x/2} = \begin{bmatrix} \cos(\phi/2) & -i\sin(\phi/2) \\ -i\sin(\phi/2) & \cos(\phi/2) \end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 1 * Gradient recipe: :math:`\frac{d}{d\phi}f(R_x(\phi)) = \frac{1}{2}\left[f(R_x(\phi+\pi/2)) - f(R_x(\phi-\pi/2))\right]` where :math:`f` is an expectation value depending on :math:`R_x(\phi)`. Args: phi (float): rotation angle :math:`\phi` wires (Sequence[int] or int): the wire the operation acts on """ num_params = 1 num_wires = 1 par_domain = "R" grad_method = "A" generator = [PauliX, -1/2]
[docs]class RY(Operation): r"""RY(phi, wires) The single qubit Y rotation .. math:: R_y(\phi) = e^{-i\phi\sigma_y/2} = \begin{bmatrix} \cos(\phi/2) & -\sin(\phi/2) \\ \sin(\phi/2) & \cos(\phi/2) \end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 1 * Gradient recipe: :math:`\frac{d}{d\phi}f(R_y(\phi)) = \frac{1}{2}\left[f(R_y(\phi+\pi/2)) - f(R_y(\phi-\pi/2))\right]` where :math:`f` is an expectation value depending on :math:`R_y(\phi)`. Args: phi (float): rotation angle :math:`\phi` wires (Sequence[int] or int): the wire the operation acts on """ num_params = 1 num_wires = 1 par_domain = "R" grad_method = "A" generator = [PauliY, -1/2]
[docs]class RZ(Operation): r"""RZ(phi, wires) The single qubit Z rotation .. math:: R_z(\phi) = e^{-i\phi\sigma_z/2} = \begin{bmatrix} e^{-i\phi/2} & 0 \\ 0 & e^{i\phi/2} \end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 1 * Gradient recipe: :math:`\frac{d}{d\phi}f(R_z(\phi)) = \frac{1}{2}\left[f(R_z(\phi+\pi/2)) - f(R_z(\phi-\pi/2))\right]` where :math:`f` is an expectation value depending on :math:`R_z(\phi)`. Args: phi (float): rotation angle :math:`\phi` wires (Sequence[int] or int): the wire the operation acts on """ num_params = 1 num_wires = 1 par_domain = "R" grad_method = "A" generator = [PauliZ, -1/2]
[docs]class PhaseShift(Operation): r"""PhaseShift(phi, wires) Arbitrary single qubit local phase shift .. math:: R_\phi(\phi) = e^{i\phi/2}R_z(\phi) = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\phi} \end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 1 * Gradient recipe: :math:`\frac{d}{d\phi}f(R_\phi(\phi)) = \frac{1}{2}\left[f(R_\phi(\phi+\pi/2)) - f(R_\phi(\phi-\pi/2))\right]` where :math:`f` is an expectation value depending on :math:`R_{\phi}(\phi)`. Args: phi (float): rotation angle :math:`\phi` wires (Sequence[int] or int): the wire the operation acts on """ num_params = 1 num_wires = 1 par_domain = "R" grad_method = "A" generator = [np.array([[0, 0], [0, 1]]), 1]
[docs]class Rot(Operation): r"""Rot(phi, theta, omega, wires) Arbitrary single qubit rotation .. math:: R(\phi,\theta,\omega) = RZ(\omega)RY(\theta)RZ(\phi)= \begin{bmatrix} e^{-i(\phi+\omega)/2}\cos(\theta/2) & -e^{i(\phi-\omega)/2}\sin(\theta/2) \\ e^{-i(\phi-\omega)/2}\sin(\theta/2) & e^{i(\phi+\omega)/2}\cos(\theta/2) \end{bmatrix}. **Details:** * Number of wires: 1 * Number of parameters: 3 * Gradient recipe: :math:`\frac{d}{d\phi}f(R(\phi, \theta, \omega)) = \frac{1}{2}\left[f(R(\phi+\pi/2, \theta, \omega)) - f(R(\phi-\pi/2, \theta, \omega))\right]` where :math:`f` is an expectation value depending on :math:`R(\phi, \theta, \omega)`. This gradient recipe applies for each angle argument :math:`\{\phi, \theta, \omega\}`. Args: phi (float): rotation angle :math:`\phi` theta (float): rotation angle :math:`\theta` omega (float): rotation angle :math:`\omega` wires (Sequence[int] or int): the wire the operation acts on """ num_params = 3 num_wires = 1 par_domain = "R" grad_method = "A"
[docs]class CRX(Operation): r"""CRX(phi, wires) The controlled-RX operator .. math:: CR_x(\phi) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & \cos(\phi/2) & -i\sin(\phi/2)\\ 0 & 0 & -i\sin(\phi/2) & \cos(\phi/2) \end{bmatrix}. .. note:: The first wire provided corresponds to the **control qubit**. **Details:** * Number of wires: 2 * Number of parameters: 1 * Gradient recipe: :math:`\frac{d}{d\phi}f(CR_x(\phi)) = \frac{1}{2}\left[f(CR_x(\phi+\pi/2)) - f(CR_x(\phi-\pi/2))\right]` where :math:`f` is an expectation value depending on :math:`CR_x(\phi)`. Args: phi (float): rotation angle :math:`\phi` wires (Sequence[int] or int): the wire the operation acts on """ num_params = 1 num_wires = 2 par_domain = "R" grad_method = "A" generator = [np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]), -1/2]
[docs]class CRY(Operation): r"""CRY(phi, wires) The controlled-RY operator .. math:: CR_y(\phi) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & \cos(\phi/2) & -\sin(\phi/2)\\ 0 & 0 & \sin(\phi/2) & \cos(\phi/2) \end{bmatrix}. .. note:: The first wire provided corresponds to the **control qubit**. **Details:** * Number of wires: 2 * Number of parameters: 1 * Gradient recipe: :math:`\frac{d}{d\phi}f(CR_y(\phi)) = \frac{1}{2}\left[f(CR_y(\phi+\pi/2)) - f(CR_y(\phi-\pi/2))\right]` where :math:`f` is an expectation value depending on :math:`CR_y(\phi)`. Args: phi (float): rotation angle :math:`\phi` wires (Sequence[int] or int): the wire the operation acts on """ num_params = 1 num_wires = 2 par_domain = "R" grad_method = "A" generator = [np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0]]), -1/2]
[docs]class CRZ(Operation): r"""CRZ(phi, wires) The controlled-RZ operator .. math:: CR_z(\phi) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & e^{-i\phi/2} & 0\\ 0 & 0 & 0 & e^{i\phi/2} \end{bmatrix}. .. note:: The first wire provided corresponds to the **control qubit**. **Details:** * Number of wires: 2 * Number of parameters: 1 * Gradient recipe: :math:`\frac{d}{d\phi}f(CR_z(\phi)) = \frac{1}{2}\left[f(CR_z(\phi+\pi/2)) - f(CR_z(\phi-\pi/2))\right]` where :math:`f` is an expectation value depending on :math:`CR_z(\phi)`. Args: phi (float): rotation angle :math:`\phi` wires (Sequence[int] or int): the wire the operation acts on """ num_params = 1 num_wires = 2 par_domain = "R" grad_method = "A" generator = [np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]]), -1/2]
[docs]class CRot(Operation): r"""CRot(phi, theta, omega, wires) The controlled-Rot operator .. math:: CR(\phi, \theta, \omega) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & e^{-i(\phi+\omega)/2}\cos(\theta/2) & -e^{i(\phi-\omega)/2}\sin(\theta/2)\\ 0 & 0 & e^{-i(\phi-\omega)/2}\sin(\theta/2) & e^{i(\phi+\omega)/2}\cos(\theta/2) \end{bmatrix}. .. note:: The first wire provided corresponds to the **control qubit**. **Details:** * Number of wires: 2 * Number of parameters: 3 * Gradient recipe: :math:`\frac{d}{d\phi}f(CR(\phi, \theta, \omega)) = \frac{1}{2}\left[f(CR(\phi+\pi/2, \theta, \omega)) - f(CR(\phi-\pi/2, \theta, \omega))\right]` where :math:`f` is an expectation value depending on :math:`CR(\phi, \theta, \omega)`. This gradient recipe applies for each angle argument :math:`\{\phi, \theta, \omega\}`. Args: phi (float): rotation angle :math:`\phi` theta (float): rotation angle :math:`\theta` omega (float): rotation angle :math:`\omega` wires (Sequence[int] or int): the wire the operation acts on """ num_params = 3 num_wires = 2 par_domain = "R" grad_method = "A"
# ============================================================================= # Arbitrary operations # =============================================================================
[docs]class QubitUnitary(Operation): r"""QubitUnitary(U, wires) Apply an arbitrary fixed unitary matrix. **Details:** * Number of wires: The operation can act on any number of wires. * Number of parameters: 1 * Gradient recipe: None Args: U (array[complex]): square unitary matrix wires (Sequence[int] or int): the wire(s) the operation acts on """ num_params = 1 num_wires = Any par_domain = "A" grad_method = None
# ============================================================================= # State preparation # =============================================================================
[docs]class BasisState(Operation): r"""BasisState(n, wires) Prepares a single computational basis state. **Details:** * Number of wires: All (applied to the entire system) * Number of parameters: 1 * Gradient recipe: None (integer parameters not supported) Args: n (array): prepares the basis state :math:`\ket{n}`, where ``n`` is an array of integers from the set :math:`\{0, 1\}`, i.e., if ``n = np.array([0, 1, 0])``, prepares the state :math:`|010\rangle`. wires (Sequence[int] or int): the wire(s) the operation acts on """ num_params = 1 num_wires = Any par_domain = "A" grad_method = None
[docs]class QubitStateVector(Operation): r"""QubitStateVector(state, wires) Prepare subsystems using the given ket vector in the computational basis. **Details:** * Number of wires: All (applied to the entire system) * Number of parameters: 1 * Gradient recipe: None Args: state (array[complex]): a state vector of size 2**len(wires) wires (Sequence[int] or int): the wire(s) the operation acts on """ num_params = 1 num_wires = All par_domain = "A" grad_method = None
# ============================================================================= # Observables # =============================================================================
[docs]class Hermitian(Observable): r"""Hermitian(A, wires) An arbitrary Hermitian observable. For a Hermitian matrix :math:`A`, the expectation command returns the value .. math:: \braket{A} = \braketT{\psi}{\cdots \otimes I\otimes A\otimes I\cdots}{\psi} where :math:`A` acts on the requested wires. If acting on :math:`N` wires, then the matrix :math:`A` must be of size :math:`2^N\times 2^N`. **Details:** * Number of wires: Any * Number of parameters: 1 * Gradient recipe: None Args: A (array): square hermitian matrix wires (Sequence[int] or int): the wire(s) the operation acts on """ num_wires = Any num_params = 1 par_domain = "A" grad_method = "F"
ops = { "Hadamard", "PauliX", "PauliY", "PauliZ", "S", "T", "CNOT", "CZ", "SWAP", "CSWAP", "RX", "RY", "RZ", "PhaseShift", "Rot", "CRX", "CRY", "CRZ", "CRot", "BasisState", "QubitStateVector", "QubitUnitary", } obs = {"Hadamard", "PauliX", "PauliY", "PauliZ", "Hermitian"} __all__ = list(ops | obs)