Source code for shor.gates
import math
from typing import Iterable, Union
import numpy as np
from shor.errors import CircuitError
from shor.layers import _Layer
from shor.utils.collections import flatten
QbitOrIterable = Union[int, Iterable]
class _Gate(_Layer):
"""Abstract base quantum gate class
A quantum gate operates on qbits only, and represents a pure (unitary) quantum operation.
input_length = valid length of input qbits
qbits = indices of qbits, to be used as input to gate.
Attributes
__________
input_length : int
valid length of input qbits
qbits : int
indices of qbits, to be used as input to gate
Methods
-------
symbol(self): Returns matrix symbol as lower case for provider transpiler
qbits(self):Returns qbit indices associated with applying the gate
to_gates(self):Returns number of gate objects applied to input qbit array. Ex: H([1,2]) will
return two hadamard gates objects applied to qbits indexed to 1 and 2
num_states(self):Returns the number of states associated with a state vector and its gate matrix
to_matrix(self): Return unitary matrix form of gate object
matrix(self): Call to_matrix which returns matrix form of gate object
invert(self): Return self
I(self): Calls invert(self)
"""
@property
def symbol(self):
return self.__class__.__name__.lower()
def __init__(self, *qbits: QbitOrIterable, **kwargs):
"""
Parameters
__________
qbits : int
qbits to which the gate is being applied
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
super().__init__(**kwargs)
self.qbits = flatten(qbits) if qbits else [0]
self.dimension = kwargs.get("dimension", 1)
assert all(map(lambda q: type(q) == int, self.qbits)), str(self.qbits)
try:
assert len(self.qbits) % self.dimension == 0
except AssertionError:
raise CircuitError(
f"The input qbits length {len(self.qbits)} is not divisible by the '{self.symbol}' "
f"gate's dimension {self.dimension}"
)
@property
def qubits(self):
"""Alias for qbits. Both refer to qbit inputs for this gate."""
return self.qbits
def to_gates(self):
"""Returns gate objects applied to provided qbit indices
Returns
-------
_Gate Object
The _Gate Objects applied to the provided qbits. Ex: H([1,2]) will return two gate objects such as
H(1) and H(2)
"""
if len(self.qbits) > self.dimension:
return [
self.__class__(self.qbits[i: i + self.dimension]) for i in range(0, len(self.qbits), self.dimension)
]
return [self]
@property
def num_states(self):
return np.power(2, self.dimension)
def to_matrix(self) -> np.ndarray:
return np.eye(self.num_states())
@property
def matrix(self):
return self.to_matrix()
def invert(self):
return self
@property
def I(self):
return self.invert()
def __invert__(self):
return self.invert()
[docs]class CNOT(_Gate):
"""
Apply the controlled X gate to control and target qbit
Inherits from gate class
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
list of length 2 containing qbit indices to which the controlled X gate is applied
dimension : int
number of qbits to which the controlled X gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "CX"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit indices apply CNOT gate. First is control
qbit and the second applies the Pauli-X gate to the target qbit.
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 2
if not qbits:
qbits = [0, 1]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2**n where n is the number of qbits
"""
return np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
[docs]class CY(_Gate):
"""
Apply the controlled Y gate to control and target qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
list of length 2 containing qbit indices controlled Y gate is applied to
dimension : int
number of qbits to which the controlled Y gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "CY"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit indices apply CY gate. First is control
qbit and the second applies the Pauli-Y gate to the target qbit.
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 2
if not qbits:
qbits = [0, 1]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2**n where n is the number of qbits
"""
return np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1 * 1j], [0, 0, 1j, 0]])
[docs]class CSWAP(_Gate):
"""
Apply the Fredkin gate or sometimes called the CSWAP gate to three qbits
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit indices CSWAP gate is applied to: the first being a control qbit and the
SWAP gate is applied to the second and third target qbits.
dimension : int
number of qbits to which the CSWAP gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "CSWAP"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit indexes apply CSWAP gate. First is control qbits and the second/third applies the SWAP gate.
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 3
if not qbits:
qbits = [0, 1, 2]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2**n where n is the number of qbits
"""
cswap_matrix = np.eye(8)
cswap_matrix[:, [5, 6]] = cswap_matrix[:, [6, 5]]
return cswap_matrix
[docs]class Hadamard(_Gate):
"""
Apply the hadamard gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which the hadamard gate is applied
dimension : int
number of qbits to which the hardamard gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "H"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index to which the hadamard gate is applied.
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2**n where n is the number of qbits
"""
return np.multiply(np.divide(1, np.sqrt(self.num_states)), np.array([[1, 1], [1, -1]]))
[docs]class PauliX(_Gate):
"""
Apply the PauliX gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which the PauliX gate is applied
dimension : int
number of qbits to which the PauliX gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "X"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index to which the PauliX gate is applied
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2**n where n is the number of qbits
"""
return np.array([[0, 1], [1, 0]])
[docs]class PauliY(_Gate):
"""
Apply the PauliY gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit indices to which the PauliY gate is applied
dimension : int
number of qbits to which the PauliY gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "Y"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index to which the PailiY gate is applied
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2**n where n is the number of qbits
"""
return np.array([[0, -1j], [1j, 0]])
[docs]class PauliZ(_Gate):
"""
Apply the PauliZ gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit indices to which the PauliZ gate is applied
dimension : int
number of qbits to which the PauliZ gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "Z"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index to which the PauliZ gate is applied
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2**n where n is the number of qbits
"""
return np.array([[1, 0], [0, -1]])
[docs]class QFT(_Gate):
"""
Apply the Quantum Fourier Transform gate to two qbits
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit indices to which the QFT gate is applied
dimension : int
number of qbits to which the QFT gate is applied
Methods
-------
get_nth_unity_root(self,k)
to_matrixSelf) -> np.ndarray
Returns matrix form of gate as numpy array
"""
# TODO: add documentation of class methods
def __init__(self, *qbits, **kwargs):
if not qbits:
qbits = [0, 1]
super().__init__(*qbits, dimension=len(qbits), **kwargs)
# def to_gates(self):
# # TODO: translate this gate to base gates / CNOTs
# pass
[docs] def to_matrix(self) -> np.ndarray:
m = np.array(np.ones((self.num_states, self.num_states)), dtype="complex")
for i in range(1, self.num_states):
for j in range(i, self.num_states):
w = self.get_nth_unity_root(i * j)
m[i, j] = w
m[j, i] = w
return np.around(np.multiply(1 / np.sqrt(self.num_states), m), decimals=15)
[docs]class SWAP(_Gate):
"""
Apply the SWAP gate to two qbits
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit indices SWAP gate is applied to
dimension : int
number of qbits SWAP gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "SWAP"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index SWAP gate is applied to
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 2
if not qbits:
qbits = [0, 1]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2**n where n is the number of qbits
"""
return np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
[docs]class Cx(_Gate):
"""
Apply the the Cx gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit indices Cx gate is applied to
dimension : int
number of qbits Cx gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "CX"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit indexes apply Cx gate. First is the control
qbit and second the target to which the X gate is applied.
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 2
if not qbits:
qbits = [0, 1]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 4x4
"""
return np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]])
[docs]class CCNOT(_Gate):
"""
Apply the CCNOT or CCX gate to three qbits. The first and second qbit being control qits and
the paulix gate is applied to the third qbit.
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit indices to which CCNOT gate is applied
dimension : int
number of qbits CCNOT gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "CCX"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit indices apply CCNOT gate. First and second are control
qbits and the third applies the Pauli-x gate to the third qbit.
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 3
if not qbits:
qbits = [0, 1, 2]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 9x9
"""
return np.array(
[
[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],
]
)
[docs]class CRZ(_Gate):
"""
Apply the CRZ gate to two qbits. The first being the control qbit
and the Rz gate is applied to the target qbit.
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index CRZ gate is applied to
angle : float
angle by which the CRZ gate rotates the second target qbit around the z-axis
dimension : int
number of qbits CRZ gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "CRZ"
def __init__(self, *qbits, angle=0, **kwargs):
"""
Parameters
__________
qbits : int
qbit indexes apply CRZ gate. First is a control
qbit and the second applies the RZ gate to the third qbit.
angle : float
angle by which the CRZ gate rotates the second target qbit around the z-axis
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 2
self.angle = angle
if not qbits:
qbits = [0, 1]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 4x4
"""
return np.array(
[
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, np.exp(-1j * self.angle / 2), 0],
[0, 0, 0, np.exp(1j * self.angle / 2)],
]
)
[docs]class CH(_Gate):
"""
Apply the CH gate to two qbits. The first being the control qbit
and the second applies the hadarmard gate to the target qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index CH gate is applied to
dimension : int
number of qbits CH gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "CH"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit indexes apply CH gate. First is control
qbit second applies the H gate to the target qbit.
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 2
if not qbits:
qbits = [0, 1]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 4x4
"""
return np.array(
[
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1 / np.sqrt(2), 1 / np.sqrt(2)],
[0, 0, 1 / np.sqrt(2), -1 / np.sqrt(2)],
]
)
[docs]class S(_Gate):
"""
Apply the S gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index S gate is applied to
dimension : int
number of qbits S gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "S"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index S gate is applied to
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array([[1, 0], [0, 1j]])
[docs]class Sdg(_Gate):
"""
Apply the Sdg gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which the Sdg gate is applied
dimension : int
number of qbits to which the Sdg gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "Sdg"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index Sdg gate is applied to
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array([[1, 0], [0, -1j]])
[docs]class T(_Gate):
"""
Apply the T gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which the T gate is applied
dimension : int
number of qbits to which the T gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "T"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index to which T gate is applied
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array([[1, 0], [0, np.exp(1j * np.pi / 4)]])
[docs]class Tdg(_Gate):
"""
Apply the Tdg gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which Tdg gate is applied
dimension : int
number of qbits to which Tdg gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "Tdg"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index to which Tdg gate is applied
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array([[1, 0], [0, np.exp(-1j * np.pi / 4)]])
[docs]class ID(_Gate):
"""
Apply the identity (ID) gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which ID gate is applied
dimension : int
number of qbits to which ID gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "I"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit index ID gate is applied to
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array([[1, 0], [0, 1]])
[docs]class U1(_Gate):
"""
Apply the U1 gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index U1 gate is applied to
angle : float
angle used to rotate qbit of choice around the z-axis
dimension : int
number of qbits U1 gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "U1"
def __init__(self, *qbits, angle=0, **kwargs):
"""
Parameters
__________
qbits : int
qbit indexes apply CRZ gate. First is a control
qbit and the second applies the RZ gate to the third qbit.
angle : float
angle used to rotate qbit of choice around the z-axis
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
self.angle = angle
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array([[1, 0], [0, np.exp(1j * self.angle)]])
[docs]class Cz(_Gate):
"""
Apply the Cz gate to a two qbits. First is control qbit and PauliZ gate is applied to the target qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index U1 gate is applied to
dimension : int
number of qbits U1 gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "CZ"
def __init__(self, *qbits, **kwargs):
"""
Parameters
__________
qbits : int
qbit indexes apply CZ gate. First is a control
qbit and the Z gate to the target qbit.
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 2
if not qbits:
qbits = [0, 1]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 4x4
"""
return np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]])
[docs]class Rx(_Gate):
"""
Apply the Rx gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index tow which Rx gate is applied
dimension : int
number of qbits to which Rx gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "RX"
def __init__(self, *qbits, angle=math.pi / 2, **kwargs):
"""
Parameters
__________
qbits : integer
qbit being rotated
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
self.angle = angle
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array(
[
[math.cos(self.angle / 2), -math.sin(self.angle / 2) * 1j],
[-math.sin(self.angle / 2) * 1j, math.cos(self.angle / 2)],
]
)
[docs]class Ry(_Gate):
"""
Apply the Ry gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which the Ry gate is applied
dimension : int
number of qbits to which the Ry gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "RY"
def __init__(self, *qbits, angle=math.pi / 2, **kwargs):
"""
Parameters
__________
qbits : integer
qbit being rotated
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
self.angle = angle
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array(
[
[math.cos(self.angle / 2), -math.sin(self.angle / 2)],
[math.sin(self.angle / 2), math.cos(self.angle / 2)],
]
)
[docs]class Rz(_Gate):
"""
Apply the Rz gate to a single qbit
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which the Rz gate is applied
dimension : int
number of qbits to which the Rz gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "RZ"
def __init__(self, *qbits, angle, **kwargs):
"""
Parameters
__________
qbits : integer
qbit being rotated
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
self.angle = angle
kwargs["dimension"] = 1
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array(
[[np.exp(-(1 / 2) * 1j * self.angle), 0], [0, np.exp((1 / 2) * 1j * self.angle)]], dtype="complex"
)
[docs]class U3(_Gate):
"""
apply U3 gate for single qbit rotation with 3 euler angles
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which the Rz gate is applied
theta : float
first angle used to rotate single qbit
phi : float
second angle used to rotate single qbit
lam : float
third angle used to rotate single qbit
dimension : int
number of qbits to which the Rz gate is applied
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "U3"
def __init__(self, *qbits, theta=0, phi=0, lam=0, **kwargs):
"""
Parameters
__________
qbits : integer
qbit being rotated
theta : float
angle used to rotate single qbit
phi : float
angle used to rotate single qbit
lam : float
angle used to rotate single qbit
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
kwargs["dimension"] = 1
self.theta = theta
self.phi = phi
self.lam = lam
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array(
[
[math.cos(self.theta / 2), -np.exp(1j * self.lam) * math.sin(self.theta / 2)],
[
np.exp(1j * self.phi) * math.sin(self.theta / 2),
np.exp(1j * (self.phi + self.lam)) * math.cos(self.theta / 2),
],
]
)
[docs]class U2(U3):
"""
apply U2 gate for single qbit rotation with 2 euler angles
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index Rz gate is applied to
phi : float
second angle used to rotate single qbit
lam : float
third angle used to rotate single qbit
dimension : int
number of qbits Rz gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "U2"
def __init__(self, *qbits, phi=0, lam=0, **kwargs):
"""
Parameters
__________
qbits : integer
qbit being rotated
phi : float
angle used to rotate single qbit
lam : float
angle used to rotate single qbit
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
super().__init__(*qbits, theta=np.pi / 2, phi=phi, lam=lam, **kwargs)
self.symbol = "u2"
[docs]class Init_x(_Gate):
"""
Initialize the qbits along x axis or |+> basis
Currently not implemented in qiskit and can only be used on shor simulator
Attributes
__________
qbits : int
qbit index init_x gate is applied to
dimension : int
number of qbits init_x gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
def __init__(self, *qbits, **kwargs):
self.H = Hadamard(0)
kwargs["dimension"] = 1
super().__init__(*qbits, **kwargs)
[docs]class Init_y(_Gate):
"""
Initialize the qbits along y axis or |-> basis
Currently not implimented in qiskit and can only be used on shor simulator
Attributes
__________
qbits : int
qbit index init_y gate is applied to
dimension : int
number of qbits init_y gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
def __init__(self, *qbits, **kwargs):
self.H = Hadamard(0)
self.S = S()
kwargs["dimension"] = 1
super().__init__(*qbits, **kwargs)
[docs]class Cr(_Gate):
"""
Apply the control phase shift gate Cr or sometimes referred as CU1. First qbit being the control and second target
qbit has a phase shift applied.
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit index to which the Cr gate is applied
angle : float
Floating point number containing angle of phase shift
dimension : int
number of qbits Cr gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
symbol = "CU1"
def __init__(self, *qbits, angle, **kwargs):
"""
Parameters
__________
qbits : int
qbit indexes apply Cr gate. First is a control
qbit and second is target qbit.
angle : float
angle used to rotate qbit of choice around the z-axis
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
self.angle = angle
kwargs["dimension"] = 2
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, np.exp(1j * self.angle)]], dtype="complex")
[docs]class CRk(_Gate):
"""
Apply the parameterized control phase shift gate Crk with angle pi/2**k. First qbit being the control and second
target qbit has a phase shift applied.
Attributes
__________
symbol : str
a string used to represent gate for provider transpiler
qbits : int
qbit indices to which Crk gate is applied
angle : float
Floating point number containing angle of phase shift
dimension : int
number of qbits Cr gate is applied to
Methods
-------
to_matrix(self) -> np.ndarray
Returns matrix form of gate as numpy array
"""
def __init__(self, *qbits, k, **kwargs):
"""
Parameters
__________
qbits : int
qbit indices to which Cr gate is applied. First is a control
qbit and second is target qbit.
angle : float
angle used to rotate qbit of choice around the z-axis
kwargs : dictionary containing key value arguments
keyword - dimension - the number of input qbits
"""
self.k = k
kwargs["dimension"] = 2
if not qbits:
qbits = [0]
super().__init__(*qbits, **kwargs)
[docs] def to_matrix(self) -> np.ndarray:
"""Returns matrix form of gate as numpy array
Returns
-------
numpy array
matrix form of gate with the size 2x2
"""
return np.array(
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, np.exp(2 * 1j * np.pi / 2 ** self.k)]], dtype="complex"
)
# Aliases
H = h = Hadamard
X = x = PauliX
Y = y = PauliY
Z = z = PauliZ
swap = SWAP
Fredkin = cswap = CSWAP
CX = cx = CNOT