qGround/qG.py

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()