191 lines
4.8 KiB
Python
191 lines
4.8 KiB
Python
import random
|
|
import numpy as np
|
|
|
|
class Gate():
|
|
def __init__(self, childGates=[]):
|
|
self.childGates = childGates
|
|
self._condense()
|
|
|
|
def _condense(self):
|
|
self.mat = np.identity(2)
|
|
for gate in self.childGates:
|
|
self.mat = np.dot(self.mat, gate.mat)
|
|
return True
|
|
|
|
def __call__(self,*arg):
|
|
if len(arg)==0:
|
|
return self
|
|
elif len(arg)==1:
|
|
return self._mul(inp)
|
|
else:
|
|
raise Exception("NaBrO")
|
|
|
|
def __mul__(self, other):
|
|
return self._mul(other)
|
|
|
|
def __repr__(self):
|
|
return "<qGate ["+str(self)+"]>"
|
|
|
|
def __str__(self):
|
|
return "".join(str(gate) for gate in self.childGates)
|
|
|
|
def _mul(self, obj):
|
|
if isinstance(obj, Gate):
|
|
return self._op(obj)
|
|
elif isinstance(obj, State):
|
|
return State(np.dot(self.mat, obj.vec))
|
|
|
|
def _op(self, obj):
|
|
return Gate(self.childGates + [obj])
|
|
|
|
@property
|
|
def adj(self):
|
|
return AdjGate(self)
|
|
|
|
def shorten(self):
|
|
newGates = []
|
|
changes = 0
|
|
i=0
|
|
while i < len(self.childGates):
|
|
gate = self.childGates[i]
|
|
if i < len(self.childGates)-1:
|
|
nextChild = self.childGates[i+1]
|
|
else:
|
|
nextChild = None
|
|
changes += 1
|
|
if np.all(gate.mat==np.identity(2)):
|
|
pass
|
|
elif isinstance(gate, AdjGate) and isinstance(gate.origGate, AdjGate):
|
|
newGates.append(gate.origGate.origGate)
|
|
elif isinstance(gate, AdjGate) and str(gate.origGate) == "H":
|
|
newGates.append(H)
|
|
elif isinstance(gate, AdjGate) and str(gate.origGate) == str(nextChild):
|
|
newGates.append(gate.origGate)
|
|
i += 1
|
|
elif i != len(self.childGates) and isinstance(nextChild, AdjGate) and str(nextChild.origGate) == str(gate):
|
|
newGates.append(nextChild.origGate)
|
|
i += 1
|
|
else:
|
|
newGates.append(gate)
|
|
changes -= 1
|
|
i += 1
|
|
|
|
if len(newGates)==0:
|
|
newGates = I()
|
|
|
|
newGate = Gate(newGates)
|
|
|
|
if changes != 0:
|
|
return newGate.shorten()
|
|
|
|
return newGate
|
|
|
|
class AdjGate(Gate):
|
|
def __init__(self, gate):
|
|
self.origGate = gate
|
|
self._condense()
|
|
|
|
def __str__(self):
|
|
return "("+str(self.origGate)+")'"
|
|
|
|
def _condense(self):
|
|
self.mat = self.origGate.mat.H
|
|
|
|
def _op(self, obj):
|
|
return Gate([self, obj])
|
|
|
|
def shorten(self):
|
|
wrap = Gate([self])
|
|
return wrap.shorten()
|
|
|
|
class BaseGate(Gate):
|
|
def __init__(self, mat, symb):
|
|
self.childGates = None
|
|
self.mat = mat
|
|
self.symb = symb
|
|
|
|
def __str__(self):
|
|
return self.symb
|
|
|
|
def _condense(self):
|
|
return False
|
|
|
|
def _op(self, obj):
|
|
return Gate([self, obj])
|
|
|
|
def shorten(self):
|
|
wrap = Gate([self])
|
|
return wrap.shorten()
|
|
|
|
class I(BaseGate):
|
|
def __init__(self):
|
|
super().__init__(np.matrix([[1,0],[0,1]]), "I")
|
|
|
|
class H(BaseGate):
|
|
def __init__(self):
|
|
q = 1/np.sqrt(2)
|
|
super().__init__(np.matrix([[q,q],[q,-1*q]]), "H")
|
|
|
|
class X(BaseGate):
|
|
def __init__(self):
|
|
super().__init__(np.matrix([[0,1],[1,0]]), "X")
|
|
|
|
class Y(BaseGate):
|
|
def __init__(self):
|
|
i = complex(0, 1)
|
|
super().__init__(np.matrix([[0,-i],[i,0]]), "Y")
|
|
|
|
class Z(BaseGate):
|
|
def __init__(self):
|
|
super().__init__(np.matrix([[1,0],[0,-1]]), "Z")
|
|
|
|
class T(BaseGate):
|
|
def __init__(self, angle):
|
|
super().__init__(np.matrix([[np.cos(angle),-1*np.sin(angle)],[np.sin(angle),np.cos(angle)]]), "T{"+str(angle)+"}")
|
|
|
|
class State():
|
|
def __init__(self, array):
|
|
self.vec = array
|
|
|
|
def __call__(self,*arg):
|
|
if len(arg)==0:
|
|
return self
|
|
elif len(arg)==1:
|
|
return self._mul(inp)
|
|
else:
|
|
raise Exception("NaBrO")
|
|
|
|
def __mul__(self, other):
|
|
return self._mul(other)
|
|
|
|
def __repr__(self):
|
|
return "<qState ["+str(self)+"]>"
|
|
|
|
def __str__(self):
|
|
return "("+str(self.vec[0])+"|0> + "+str(self.vec[1])+"|1>)"
|
|
|
|
def __int__(self):
|
|
return int(0 + 1*(random.random() < self.vec[1]**2))
|
|
|
|
def _mul(self, other):
|
|
if isinstance(other, Gate):
|
|
return State(np.dot(self.vec, other.mat))
|
|
elif isinstance(other, State):
|
|
return np.dot(self.vec, other.vec)
|
|
|
|
def measure(self):
|
|
if random.random() < self.vec[0]**2:
|
|
return Zero()
|
|
else:
|
|
return One()
|
|
|
|
class Zero(State):
|
|
def __init__(self):
|
|
super().__init__(np.array([1,0]))
|
|
|
|
class One(State):
|
|
def __init__(self):
|
|
super().__init__(np.array([0,1]))
|
|
|
|
I, H, X, Y, Z, One, Zero = I(), H(), X(), Y(), Z(), One(), Zero()
|