Source code for braket.ir.jaqcd.instructions

# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file 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.

from enum import Enum

from braket.ir.jaqcd.shared_models import (
    Angle,
    CompilerDirective,
    DampingProbability,
    DampingSingleProbability,
    DoubleControl,
    DoubleTarget,
    MultiProbability,
    MultiTarget,
    SingleControl,
    SingleProbability,
    SingleProbability_34,
    SingleProbability_1516,
    SingleTarget,
    TripleProbability,
    TwoDimensionalMatrix,
    TwoDimensionalMatrixList,
)

"""
Instructions that can be supplied to the braket.ir.jaqcd.Program.

To add a new instruction:
    - Implement a class in this module.
      - Class must contain a property, "type", that is an enum of the class implemented in the
        next step.
      - Implement a subclass, "Type", within this class that extends [str, enum].
        All enum values must be unique across all instructions, otherwise de-serialization
        will have undeterministic behaviors. These enums will be used to determine what type
        the instruction is, i.e. what class to use for deserializing.
      - NOTE: Due to how multiple inhertiance works in Python it is easiest to define a
        type enum class within each instruction, instead of calling the relevant parent
        constructors to initialize it correctly.
    - Inherit any classes from braket.ir.jaqcd.shared_models.
    - Write up docstrings to define the instruction, properties, and examples.
"""


[docs] class H(SingleTarget): """ Hadamard gate. Attributes: type (str): The instruction type. default = "h". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> H(target=1) """
[docs] class Type(str, Enum): h = "h"
type = Type.h
[docs] class I(SingleTarget): # noqa: E742, E261 """ Identity gate. Attributes: type (str): The instruction type. default = "i". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> I(target=1) """
[docs] class Type(str, Enum): i = "i"
type = Type.i
[docs] class X(SingleTarget): """ Pauli-X gate. Attributes: type (str): The instruction type. default = "x". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> X(target=0) """
[docs] class Type(str, Enum): x = "x"
type = Type.x
[docs] class Y(SingleTarget): """ Pauli-Y gate. Attributes: type (str): The instruction type. default = "y". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> Y(target=0) """
[docs] class Type(str, Enum): y = "y"
type = Type.y
[docs] class Z(SingleTarget): """ Pauli-Z gate. Attributes: type (str): The instruction type. default = "z". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> Z(target=0) """
[docs] class Type(str, Enum): z = "z"
type = Type.z
[docs] class Rx(SingleTarget, Angle): """ X-axis rotation gate. Attributes: type (str): The instruction type. default = "rx". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. Examples: >>> Rx(target=0, angle=0.15) """
[docs] class Type(str, Enum): rx = "rx"
type = Type.rx
[docs] class Ry(SingleTarget, Angle): """ Y-axis rotation gate. Attributes: type (str): The instruction type. default = "ry". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. Examples: >>> Ry(target=0, angle=0.15) """
[docs] class Type(str, Enum): ry = "ry"
type = Type.ry
[docs] class Rz(SingleTarget, Angle): """ Z-axis rotation gate. Attributes: type (str): The instruction type. default = "rz". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. Examples: >>> Rz(target=0, angle=0.15) """
[docs] class Type(str, Enum): rz = "rz"
type = Type.rz
[docs] class S(SingleTarget): """ S gate. Applies a 90 degree rotation around the Z-axis. Attributes: type (str): The instruction type. default = "s". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> S(target=0) """
[docs] class Type(str, Enum): s = "s"
type = Type.s
[docs] class T(SingleTarget): """ T gate. Applies a 45 degree rotation around the Z-axis. Attributes: type (str): The instruction type. default = "t". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> T(target=0) """
[docs] class Type(str, Enum): t = "t"
type = Type.t
[docs] class Si(SingleTarget): """ Si gate. Conjugate transpose of S gate. Attributes: type (str): The instruction type. default = "si". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> Si(target=0) """
[docs] class Type(str, Enum): si = "si"
type = Type.si
[docs] class Ti(SingleTarget): """ Ti gate. Conjugate transpose of T gate. Attributes: type (str): The instruction type. default = "ti". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> Ti(target=0) """
[docs] class Type(str, Enum): ti = "ti"
type = Type.ti
[docs] class Swap(DoubleTarget): """ Swap gate. Swaps the state of the two qubits. Attributes: type (str): The instruction type. default = "swap". (type) is optional. This should be unique among all instruction types. targets (List[int]): The target qubits. This is a list with two items and all items are int >= 0. Examples: >>> Swap(targets=[0, 1]) """
[docs] class Type(str, Enum): swap = "swap"
type = Type.swap
[docs] class CSwap(SingleControl, DoubleTarget): """ Controlled swap gate. Attributes: type (str): The instruction type. default = "cswap". (type) is optional. This should be unique among all instruction types. control (int): The control qubit. This is an int >= 0. targets (List[int]): The target qubits. This is a list with two items and all items are int >= 0. Examples: >>> Swap(control=0, targets=[1, 2]) """
[docs] class Type(str, Enum): cswap = "cswap"
type = Type.cswap
[docs] class ISwap(DoubleTarget): """ ISwap gate. Swaps the state of two qubits, applying a -i phase to q1 when it is in the 1 state and a -i phase to q2 when it is in the 0 state. This is equivalent to XY(pi) Attributes: type (str): The instruction type. default = "iswap". (type) is optional. This should be unique among all instruction types. targets (List[int]): The target qubits. This is a list with two items and all items are int >= 0. Examples: >>> ISwap(targets=[0, 1]) """
[docs] class Type(str, Enum): iswap = "iswap"
type = Type.iswap
[docs] class PSwap(DoubleTarget, Angle): """ Parameterized swap gate that takes in the angle of the phase to apply to the swapped gates. Attributes: type (str): The instruction type. default = "pswap". (type) is optional. This should be unique among all instruction types. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. targets (List[int]): The target qubits. This is a list with two items and all items are int >= 0. Examples: >>> PSwap(targets=[0, 1], angle=0.15) """
[docs] class Type(str, Enum): pswap = "pswap"
type = Type.pswap
[docs] class XY(DoubleTarget, Angle): """ Rotates between \\|01> and \\|10> by the given angle. Attributes: type (str): The instruction type. default = "xy". (type) is optional. This should be unique among all instruction types. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. targets (List[int]): The target qubits. This is a list with two items and all items are int >= 0. Examples: >>> XY(targets=[0, 1], angle=0.15) """
[docs] class Type(str, Enum): xy = "xy"
type = Type.xy
[docs] class PhaseShift(SingleTarget, Angle): """ Phase shift gate. Shifts the phase between \\|0> and \\|1> by a given angle. Attributes: type (str): The instruction type. default = "phaseshift". (type) is optional. This should be unique among all instruction types. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. target (int): The target qubit. This is an int >= 0. Examples: >>> PhaseShift(target=1, angle=0.15) """
[docs] class Type(str, Enum): phaseshift = "phaseshift"
type = Type.phaseshift
[docs] class CPhaseShift(SingleTarget, SingleControl, Angle): """ Controlled phase shift gate. Attributes: type (str): The instruction type. default = "cphaseshift". (type) is optional. This should be unique among all instruction types. control (int): The control qubit. This is an int >= 0. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. target (int): The target qubit. This is an int >= 0. Examples: >>> CPhaseShift(control=0, target=1, angle=0.15) """
[docs] class Type(str, Enum): cphaseshift = "cphaseshift"
type = Type.cphaseshift
[docs] class CPhaseShift00(SingleTarget, SingleControl, Angle): """ Controlled phase shift gate that phases the \\|00> state. Attributes: type (str): The instruction type. default = "cphaseshift00". (type) is optional. This should be unique among all instruction types. control (int): The control qubit. This is an int >= 0. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. target (int): The target qubit. This is an int >= 0. Examples: >>> CPhaseShift00(control=0, target=1, angle=0.15) """
[docs] class Type(str, Enum): cphaseshift00 = "cphaseshift00"
type = Type.cphaseshift00
[docs] class CPhaseShift01(SingleTarget, SingleControl, Angle): """ Controlled phase shift gate that phases the \\|01> state. Attributes: type (str): The instruction type. default = "cphaseshift01". (type) is optional. This should be unique among all instruction types. control (int): The control qubit. This is an int >= 0. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. target (int): The target qubit. This is an int >= 0. Examples: >>> CPhaseShift01(control=0, target=1, angle=0.15) """
[docs] class Type(str, Enum): cphaseshift01 = "cphaseshift01"
type = Type.cphaseshift01
[docs] class CPhaseShift10(SingleTarget, SingleControl, Angle): """ Controlled phase shift gate that phases the \\|10> state. Attributes: type (str): The instruction type. default = "cphaseshift10". (type) is optional. This should be unique among all instruction types. control (int): The control qubit. This is an int >= 0. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. target (int): The target qubit. This is an int >= 0. Examples: >>> CPhaseShift10(control=0, target=1, angle=0.15) """
[docs] class Type(str, Enum): cphaseshift10 = "cphaseshift10"
type = Type.cphaseshift10
[docs] class CNot(SingleTarget, SingleControl): """ Controlled not gate. Also known as the CX gate. Attributes: type (str): The instruction type. default = "cnot". (type) is optional. This should be unique among all instruction types. control (int): The control qubit. This is an int >= 0. target (int): The target qubit. This is an int >= 0. Examples: >>> CNot(control=0, target=1) """
[docs] class Type(str, Enum): cnot = "cnot"
type = Type.cnot
[docs] class CCNot(SingleTarget, DoubleControl): """ Doubly-controlled NOT gate. Also known as the Toffoli gate. Attributes: type (str): The instruction type. default = "ccnot". (type) is optional. This should be unique among all instruction types. controls (int): The control qubits. This is a list with two items and all items are int >= 0. target (int): The target qubit. This is an int >= 0. Examples: >>> CCNot(control=[0,1], target=1) """
[docs] class Type(str, Enum): ccnot = "ccnot"
type = Type.ccnot
[docs] class CV(SingleTarget, SingleControl): """ Controlled sqrt(NOT) gate. Also known as the CV gate. Attributes: type (str): The instruction type. default = "cv". (type) is optional. This should be unique among all instruction types. control (int): The control qubit. This is an int >= 0. target (int): The target qubit. This is an int >= 0. Examples: >>> CV(control=0, target=1) """
[docs] class Type(str, Enum): cv = "cv"
type = Type.cv
[docs] class CY(SingleTarget, SingleControl): """ Controlled Y-gate. Attributes: type (str): The instruction type. default = "cy". (type) is optional. This should be unique among all instruction types. control (int): The control qubit target (int): The target qubit. This is an int >= 0. Examples: >>> CY(control=0, target=1) """
[docs] class Type(str, Enum): cy = "cy"
type = Type.cy
[docs] class CZ(SingleTarget, SingleControl): """ Controlled Z-gate. Attributes: type (str): The instruction type. default = "cz". (type) is optional. This should be unique among all instruction types. control (int): The control qubit. This is an int >= 0. target (int): The target qubit. This is an int >= 0. Examples: >>> CZ(control=0, target=1) """
[docs] class Type(str, Enum): cz = "cz"
type = Type.cz
[docs] class ECR(DoubleTarget): """ An echoed RZX(pi/2) gate. Attributes: type (str): The instruction type. default = "ecr". (type) is optional. This should be unique among all instruction types. targets (List[int]): The target qubits. This is a list with two items and all items are int >= 0. Examples: >>> ECR(targets=[0, 1]) """
[docs] class Type(str, Enum): ecr = "ecr"
type = Type.ecr
[docs] class XX(DoubleTarget, Angle): """ The Ising (XX) gate. Attributes: type (str): The instruction type. default = "xx". (type) is optional. This should be unique among all instruction types. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. targets (List[int]): The target qubits. This is a list with two items and all items are int >= 0. Examples: >>> XX(targets=[0, 1], angle=0.15) """
[docs] class Type(str, Enum): xx = "xx"
type = Type.xx
[docs] class YY(DoubleTarget, Angle): """ The Ising (YY) gate. Attributes: type (str): The instruction type. default = "yy". (type) is optional. This should be unique among all instruction types. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. targets (List[int]): The target qubits. This is a list with two items and all items are int >= 0. Examples: >>> YY(targets=[0, 1], angle=0.15) """
[docs] class Type(str, Enum): yy = "yy"
type = Type.yy
[docs] class ZZ(DoubleTarget, Angle): """ The Ising (ZZ) gate. Attributes: type (str): The instruction type. default = "zz". (type) is optional. This should be unique among all instruction types. angle (float): The angle in radians. inf, -inf, and NaN are not allowable inputs. targets (List[int]): The target qubits. This is a list with two items and all items are int >= 0. Examples: >>> ZZ(targets=[0, 1], angle=0.15) """
[docs] class Type(str, Enum): zz = "zz"
type = Type.zz
[docs] class V(SingleTarget): """ Square root of NOT gate. Attributes: type (str): The instruction type. default = "v". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> V(target=0) """
[docs] class Type(str, Enum): v = "v"
type = Type.v
[docs] class Vi(SingleTarget): """ Conjugate transpose of square root of NOT gate. Attributes: type (str): The instruction type. default = "vi". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> Vi(target=0) """
[docs] class Type(str, Enum): vi = "vi"
type = Type.vi
[docs] class Unitary(TwoDimensionalMatrix, MultiTarget): """ Arbitrary unitary matrix gate Attributes: type (str): The instruction type. default = "unitary". (type) is optional. This should be unique among all instruction types. targets (List[int]): The target qubits. This is a list with ints and all ints >= 0. matrix (List[List[List[float]]]): The unitary matrix specifying the behavior of the gate. Examples: >>> Unitary(targets=[0], matrix=[[[0, 0], [1, 0]],[[1, 0], [0, 1]]]) """
[docs] class Type(str, Enum): unitary = "unitary"
type = Type.unitary
[docs] class BitFlip(SingleTarget, SingleProbability): """ Bit Flip noise channel. Attributes: type (str): The instruction type. default = "bit_flip". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> BitFlip(target=1, probability=0.1) """
[docs] class Type(str, Enum): bit_flip = "bit_flip"
type = Type.bit_flip
[docs] class PhaseFlip(SingleTarget, SingleProbability): """ Phase Flip noise channel. Attributes: type (str): The instruction type. default = "phase_flip". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> PhaseFlip(target=1, probability=0.1) """
[docs] class Type(str, Enum): phase_flip = "phase_flip"
type = Type.phase_flip
[docs] class PauliChannel(SingleTarget, TripleProbability): """ A single qubit Pauli noise channel. Attributes: type (str): The instruction type. default = "pauli_channel". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> PauliChannel(target=1, probX=0.1, probY=0.2, probZ=0.3) """
[docs] class Type(str, Enum): pauli_channel = "pauli_channel"
type = Type.pauli_channel
[docs] class MultiQubitPauliChannel(MultiTarget, MultiProbability): """ Multi-qubit Pauli noise channel. Attributes: type (str): The instruction type. default = "multi_qubit_pauli_channel". (type) is optional. This should be unique among all instruction types. target (int): The target qubit(s). This is list of intergers >= 0. The length of the list must match the length of the Pauli strings provided. Examples: >>> MultiQubitPauliChannel(target=1, probabilities={"X": 0.1}) >>> MultiQubitPauliChannel(target=[0,1], probabilities={"XY": 0.1}) >>> MultiQubitPauliChannel(target=[0,1,2], probabilities={"XYZ": 0.1}) """
[docs] class Type(str, Enum): multi_qubit_pauli_channel = "multi_qubit_pauli_channel"
type = Type.multi_qubit_pauli_channel
[docs] class Depolarizing(SingleTarget, SingleProbability_34): """ Depolarizing noise channel. Attributes: type (str): The instruction type. default = "depolarizing". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> Depolarizing(target=1, probability=0.1) """
[docs] class Type(str, Enum): depolarizing = "depolarizing"
type = Type.depolarizing
[docs] class TwoQubitDepolarizing(DoubleTarget, SingleProbability_1516): """ Two-Qubit Depolarizing noise channel. Attributes: type (str): The instruction type. default = "two_qubit_depolarizing". (type) is optional. This should be unique among all instruction types. target (int): The target qubits. This is an int >= 0. Examples: >>> TwoQubitDepolarizing(target1=0, target2=1, probability=0.1) """
[docs] class Type(str, Enum): two_qubit_depolarizing = "two_qubit_depolarizing"
type = Type.two_qubit_depolarizing
[docs] class TwoQubitDephasing(DoubleTarget, SingleProbability_34): """ Two-Qubit Dephasing noise channel. Attributes: type (str): The instruction type. default = "two_qubit_dephasing". (type) is optional. This should be unique among all instruction types. target (int): The target qubits. This is an int >= 0. Examples: >>> TwoQubitDephasing(target1=0, target2=1, probability=0.1) """
[docs] class Type(str, Enum): two_qubit_dephasing = "two_qubit_dephasing"
type = Type.two_qubit_dephasing
[docs] class AmplitudeDamping(SingleTarget, DampingProbability): """ Amplitude Damping noise channel. Attributes: type (str): The instruction type. default = "amplitude_damping". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> AmplitudeDamping(target=1, gamma=0.1) """
[docs] class Type(str, Enum): amplitude_damping = "amplitude_damping"
type = Type.amplitude_damping
[docs] class GeneralizedAmplitudeDamping(SingleTarget, DampingProbability, DampingSingleProbability): """ Generalized Amplitude Damping noise channel. Attributes: type (str): The instruction type. default = "generalized_amplitude_damping". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> GeneralizedAmplitudeDamping(target=1, gamma=0.1, probability=0.9) """
[docs] class Type(str, Enum): generalized_amplitude_damping = "generalized_amplitude_damping"
type = Type.generalized_amplitude_damping
[docs] class PhaseDamping(SingleTarget, DampingProbability): """ Phase Damping noise channel. Attributes: type (str): The instruction type. default = "phase_damping". (type) is optional. This should be unique among all instruction types. target (int): The target qubit. This is an int >= 0. Examples: >>> PhaseDamping(target=1, gamma=0.1) """
[docs] class Type(str, Enum): phase_damping = "phase_damping"
type = Type.phase_damping
[docs] class Kraus(TwoDimensionalMatrixList, MultiTarget): """ Arbitrary quantum channel defined by the input matrices. Attributes: type (str): The instruction type. default = "kraus". (type) is optional. This should be unique among all instruction types. targets (List[int]): The target qubits. This is a list with ints and all ints >= 0. matrices (List[List[List[List[float]]]]): A list of matrices specifying the quantum channel. A complex number is represented as a list of 2 real numbers. So each matrix has type List[List[List[float]]]. Examples: >>> matrix1 = [[[1/sqrt(2), 0],[0, 0]],[[0, 0],[1/sqrt(2), 0]]] >>> matrix2 = [[[0, 0],[1/sqrt(2), 0]],[[1/sqrt(2), 0],[0, 0]]] >>> matrices = [matrix1, matrix2] >>> Kraus(targets=[0], matrices=matrices) """
[docs] class Type(str, Enum): kraus = "kraus"
type = Type.kraus
[docs] class StartVerbatimBox(CompilerDirective): """ StartVerbatimBox is a compiler instruction to start a portion of code that will preserve the instruction within StartVerbatimBox and EndVerbatimBox from being modified in any way by the compiler. Attributes: type (str): The instruction type. default = "start_verbatim_box". (type) is optional. This should be unique among all instruction types. Examples: >>> StartVerbatimBox() """
[docs] class Type(str, Enum): start_verbatim_box = "start_verbatim_box"
type = Type.start_verbatim_box directive: str = "StartVerbatimBox"
[docs] class EndVerbatimBox(CompilerDirective): """ EndVerbatimBox is a compiler instruction to mark the end of a portion of code that preserves the instruction within StartVerbatimBox and EndVerbatimBox from being modified in any way by the compiler. Attributes: type (str): The instruction type. default = "end_verbatim_box". (type) is optional. This should be unique among all instruction types. Examples: >>> EndVerbatimBox() """
[docs] class Type(str, Enum): end_verbatim_box = "end_verbatim_box"
type = Type.end_verbatim_box directive: str = "EndVerbatimBox"