Skip to content

Commit

Permalink
Add gate classes
Browse files Browse the repository at this point in the history
  • Loading branch information
BoxiLi committed Oct 2, 2021
1 parent 527c3c8 commit ace9cdf
Show file tree
Hide file tree
Showing 2 changed files with 293 additions and 30 deletions.
41 changes: 12 additions & 29 deletions src/qutip_qip/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
expand_operator,
gate_sequence_product,
)
from .operations.gates import _gate_label
from .operations.gates import _gate_label, GATE_CLASS_MAP
from qutip import basis, ket2dm, qeye
from qutip import Qobj
from qutip.measurement import measurement_statistics
Expand Down Expand Up @@ -348,41 +348,26 @@ def add_gate(
2 ** len(classical_controls) - 1
(i.e. all classical controls are 1).
"""
if isinstance(gate, Gate):
name = gate.name
targets = gate.targets
controls = gate.controls
arg_value = gate.arg_value
arg_label = gate.arg_label
classical_controls = gate.classical_controls
control_value = gate.control_value

else:
name = gate

if index is None:
gate = Gate(
name,
if not isinstance(gate, Gate):
if gate in GATE_CLASS_MAP:
gate_class = GATE_CLASS_MAP[gate]
else:
gate_class = Gate
gate = gate_class(
name=gate,
targets=targets,
controls=controls,
arg_value=arg_value,
arg_label=arg_label,
classical_controls=classical_controls,
control_value=control_value,
)

if index is None:
self.gates.append(gate)

else:
for position in index:
gate = Gate(
name,
targets=targets,
controls=controls,
arg_value=arg_value,
arg_label=arg_label,
classical_controls=classical_controls,
control_value=control_value,
)
self.gates.insert(position, gate)

def add_gates(self, gates):
Expand Down Expand Up @@ -447,8 +432,7 @@ def add_1q_gate(

if qubits is not None:
for _, i in enumerate(qubits):
gate = Gate(
name,
gate = GATE_CLASS_MAP[name](
targets=qubits[i],
controls=None,
arg_value=arg_value,
Expand All @@ -462,8 +446,7 @@ def add_1q_gate(
if end is None:
end = self.N - 1
for i in range(start, end + 1):
gate = Gate(
name,
gate = GATE_CLASS_MAP[name](
targets=i,
controls=None,
arg_value=arg_value,
Expand Down
282 changes: 281 additions & 1 deletion src/qutip_qip/operations/gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
import numpy as np
import scipy.sparse as sp

import qutip
from qutip import Qobj, identity, qeye, sigmax, sigmay, sigmaz, tensor, fock_dm


__all__ = [
"Gate",
"GATE_CLASS_MAP",
"rx",
"ry",
"rz",
Expand Down Expand Up @@ -143,7 +145,7 @@ class Gate:

def __init__(
self,
name,
name=None,
targets=None,
controls=None,
arg_value=None,
Expand Down Expand Up @@ -227,6 +229,7 @@ def __init__(

self.arg_value = arg_value
self.arg_label = arg_label
self.latex_str = r"U"

def get_all_qubits(self):
"""
Expand Down Expand Up @@ -468,6 +471,283 @@ def _gate_label(name, arg_label):
return r"%s" % gate_label


class ParameterizedGate(Gate):
def __init__(self, targets, arg_value, **kwargs):
super().__init__(targets=targets, arg_value=arg_value, **kwargs)
self.name = "ParameterizedGate"
if arg_value is None:
raise ValueError(
f"Gate {self.__class__.__name__} requires an argument value."
)


class SingleQubitGate(Gate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "SingleQubitGate"
if self.targets is None or len(self.targets) != 1:
raise ValueError(
f"Gate {self.__class__.__name__} requires one target"
)
if self.controls:
raise ValueError(
f"Gate {self.__class__.__name__} cannot have a control"
)


class XGate(SingleQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "X"
self.latex_str = r"X"

def get_compact_qobj(self):
return qutip.sigmax()


class YGate(SingleQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "Y"
self.latex_str = r"Y"

def get_compact_qobj(self):
return qutip.sigmay()


class ZGate(SingleQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "Z"
self.latex_str = r"Z"

def get_compact_qobj(self):
return qutip.sigmaz()


class RX(SingleQubitGate, ParameterizedGate):
def __init__(self, targets, arg_value, **kwargs):
super().__init__(targets=targets, arg_value=arg_value, **kwargs)
self.name = "RX"
self.latex_str = r"R_x"

def get_compact_qobj(self):
return rx(self.arg_value)


class RY(SingleQubitGate, ParameterizedGate):
def __init__(self, targets, arg_value, **kwargs):
super().__init__(targets=targets, arg_value=arg_value, **kwargs)
self.name = "RY"
self.latex_str = r"R_y"

def get_compact_qobj(self):
return ry(self.arg_value)


class RZ(SingleQubitGate, ParameterizedGate):
def __init__(self, targets, arg_value, **kwargs):
super().__init__(targets=targets, arg_value=arg_value, **kwargs)
self.name = "RZ"
self.latex_str = r"R_z"

def get_compact_qobj(self):
return rz(self.arg_value)


class H(SingleQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "H"
self.latex_str = r"{\rm H}"

def get_compact_qobj(self):
return snot()


class SNOT(H):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "SNOT"
self.latex_str = r"{\rm H}"


class SQRTNOT(SingleQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "SQRTNOT"

def get_compact_qobj(self):
return sqrtnot()
self.latex_str = r"\sqrt{\rm NOT}"


class S(SingleQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "S"
self.latex_str = r"{\rm S}"

def get_compact_qobj(self):
return s_gate()


class T(SingleQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "T"
self.latex_str = r"{\rm T}"

def get_compact_qobj(self):
return t_gate()


class QASMU(SingleQubitGate):
def __init__(self, targets, arg_value=None, **kwargs):
super().__init__(targets=targets, arg_value=arg_value, **kwargs)
self.name = "QASMU"
self.latex_str = r"{\rm QASM-U}"

def get_compact_qobj(self):
return qasmu_gate(self.arg_value)


class TwoQubitGate(Gate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "TwoQubitGate"
if len(self.get_all_qubits()) != 2:
raise ValueError(
f"Gate {self.__class__.__name__} requires two targets"
)


class SWAP(TwoQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "SWAP"
self.latex_str = r"{\rm SWAP}"

def get_compact_qobj(self):
return swap()


class ISWAP(TwoQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "ISWAP"
self.latex_str = r"{i}{\rm SWAP}"

def get_compact_qobj(self):
return iswap()


class CNOT(TwoQubitGate):
def __init__(self, targets, controls, **kwargs):
super().__init__(targets=targets, controls=controls, **kwargs)
self.name = "CNOT"
self.latex_str = r"{\rm CNOT}"

def get_compact_qobj(self):
return cnot()


class SQRTSWAP(TwoQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "SQRTSWAP"
self.latex_str = r"\sqrt{\rm SWAP}"

def get_compact_qobj(self):
return sqrtswap()


class SQRTISWAP(TwoQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "SQRTISWAP"
self.latex_str = r"\sqrt{{i}\rm SWAP}"

def get_compact_qobj(self):
return sqrtiswap()


class BERKELEY(TwoQubitGate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "BERKELEY"
self.latex_str = r"{\rm BERKELEY}"

def get_compact_qobj(self):
return berkeley()


class SWAPALPHA(TwoQubitGate, ParameterizedGate):
def __init__(self, targets, arg_value, **kwargs):
super().__init__(targets=targets, arg_value=arg_value, **kwargs)
self.name = "SWAPALPHA"
self.latex_str = r"{\rm SWAPALPHA}"

def get_compact_qobj(self):
return swapalpha(self.arg_value)


class MS(TwoQubitGate, ParameterizedGate):
def __init__(self, targets, arg_value, **kwargs):
super().__init__(targets=targets, arg_value=arg_value, **kwargs)
self.name = "MS"
self.latex_str = r"{\rm MS}"

def get_compact_qobj(self):
return molmer_sorensen(self.arg_value)


class TOFFOLI(Gate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "TOFFOLI"
self.latex_str = r"{\rm TOFFOLI}"

def get_compact_qobj(self):
return toffoli()


class FREDKIN(Gate):
def __init__(self, targets, **kwargs):
super().__init__(targets=targets, **kwargs)
self.name = "FREDKIN"
self.latex_str = r"{\rm FREDKIN}"

def get_compact_qobj(self):
return fredkin()


GATE_CLASS_MAP = {
"X": XGate,
"Y": YGate,
"Z": ZGate,
"RX": RX,
"RY": RY,
"RZ": RZ,
"H": H,
"SNOT": SNOT,
"SQRTNOT": SQRTNOT,
"S": S,
"T": T,
"QASMU": QASMU,
"SWAP": SWAP,
"ISWAP": ISWAP,
"iSWAP": ISWAP,
"CNOT": CNOT,
"SQRTSWAP": SQRTSWAP,
"SQRTISWAP": SQRTISWAP,
"SWAPALPHA": SWAPALPHA,
"SWAPalpha": SWAPALPHA,
"MS": MS,
"TOFFOLI": TOFFOLI,
"FREDKIN": FREDKIN,
}

#
# Single Qubit Gates
#
Expand Down

0 comments on commit ace9cdf

Please sign in to comment.