added circuit
This commit is contained in:
parent
1441be93ce
commit
8afb859dd0
2 changed files with 93 additions and 12 deletions
59
QElephant/Circuit.py
Normal file
59
QElephant/Circuit.py
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.patches import Rectangle, Circle
|
||||||
|
from QElephant.QuBit import *
|
||||||
|
|
||||||
|
class Circuit:
|
||||||
|
def __init__(self, n: int, instructions=[]):
|
||||||
|
self.__instr = instructions
|
||||||
|
self.__n = n
|
||||||
|
self.__mubit = MuBit(self.__n)
|
||||||
|
self.__mubit._MuBit__callBack = self.__recv
|
||||||
|
|
||||||
|
def __recv(self, gate: str, target: int, neighbor: list[int]):
|
||||||
|
self.__instr.append((gate, target, neighbor))
|
||||||
|
|
||||||
|
def __rect(self, q_i: int, i: int, txt: str, size: int) -> None:
|
||||||
|
rec = Rectangle((q_i-0.25, i-0.25), 0.5, 0.5, fill=False)
|
||||||
|
if len(txt) >= 4:
|
||||||
|
plt.text(q_i, i, txt, size=min(int(40/size), int(40/self.__n)), ha='center', va='center')
|
||||||
|
else:
|
||||||
|
plt.text(q_i, i, txt, size=min(int(70/size), int(70/self.__n)), ha='center', va='center')
|
||||||
|
plt.gca().add_patch(rec)
|
||||||
|
|
||||||
|
def __line(self, A, B) -> None:
|
||||||
|
plt.plot([A[0], B[0]], [A[1], B[1]], color='Black')
|
||||||
|
|
||||||
|
def __circle(self, x: float, y: float, radius: float) -> None:
|
||||||
|
circ = Circle((x, y), radius, fill=True, color='Black')
|
||||||
|
plt.gca().add_patch(circ)
|
||||||
|
|
||||||
|
def draw(self) -> None:
|
||||||
|
n = len(self.__instr)
|
||||||
|
plt.yticks(range(self.__n), [f"QuBit {i}" for i in range(self.__n)])
|
||||||
|
plt.xticks(range(1, n+1), [f"Step {i+1}" for i in range(n)])
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
while i < n:
|
||||||
|
txt, index, neigbhor = self.__instr[i]
|
||||||
|
for q_i in range(self.__n):
|
||||||
|
self.__line((i+0.5, q_i), (i+0.75, q_i))
|
||||||
|
self.__line((i+1.25, q_i), (i+1.5, q_i))
|
||||||
|
|
||||||
|
if q_i == index:
|
||||||
|
self.__rect(i+1, q_i, txt, n)
|
||||||
|
for neig in neigbhor:
|
||||||
|
self.__circle(i+1, neig, 0.05)
|
||||||
|
if neig > q_i:
|
||||||
|
self.__line((i+1, q_i+0.25), (i+1, neig))
|
||||||
|
elif neig < q_i:
|
||||||
|
self.__line((i+1, q_i-0.25), (i+1, neig))
|
||||||
|
else:
|
||||||
|
raise ValueError("Cannot apply gate twice on the same QuBit")
|
||||||
|
else:
|
||||||
|
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||||
|
i += 1
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
if __name__=="__main__":
|
||||||
|
c = Circuit(3, [("CS", 0, [1]), ("CX", 2, [0]), ("TX", 1, [0, 2])])
|
||||||
|
c.draw()
|
||||||
|
|
@ -18,6 +18,11 @@ class MuBit:
|
||||||
self.__n = n
|
self.__n = n
|
||||||
self.__state: list[complex] = [0]*(2**self.__n)
|
self.__state: list[complex] = [0]*(2**self.__n)
|
||||||
self.__state[0] = 1
|
self.__state[0] = 1
|
||||||
|
self.__callBack = None
|
||||||
|
|
||||||
|
def __emit(self, gate: str, target: int, neighbor: list[int]=[]) -> None:
|
||||||
|
if self.__callBack is not None:
|
||||||
|
self.__callBack(gate, target, neighbor)
|
||||||
|
|
||||||
def get_size(self) -> int:
|
def get_size(self) -> int:
|
||||||
return self.__n
|
return self.__n
|
||||||
|
|
@ -308,6 +313,7 @@ class IQuBit(QuBit):
|
||||||
def H(q: QuBit) -> None:
|
def H(q: QuBit) -> None:
|
||||||
if type(q) == IQuBit:
|
if type(q) == IQuBit:
|
||||||
q._IQuBit__apply(Matrix.H())
|
q._IQuBit__apply(Matrix.H())
|
||||||
|
q._IQuBit__muBit._MuBit__emit("H", q._IQuBit__n, [])
|
||||||
elif type(q) == QuBit:
|
elif type(q) == QuBit:
|
||||||
q._QuBit__apply(Matrix.H())
|
q._QuBit__apply(Matrix.H())
|
||||||
else:
|
else:
|
||||||
|
|
@ -316,6 +322,7 @@ def H(q: QuBit) -> None:
|
||||||
def X(q: QuBit) -> None:
|
def X(q: QuBit) -> None:
|
||||||
if type(q) == IQuBit:
|
if type(q) == IQuBit:
|
||||||
q._IQuBit__apply(Matrix.X())
|
q._IQuBit__apply(Matrix.X())
|
||||||
|
q._IQuBit__muBit._MuBit__emit("X", q._IQuBit__n, [])
|
||||||
elif type(q) == QuBit:
|
elif type(q) == QuBit:
|
||||||
q._QuBit__apply(Matrix.X())
|
q._QuBit__apply(Matrix.X())
|
||||||
else:
|
else:
|
||||||
|
|
@ -324,6 +331,7 @@ def X(q: QuBit) -> None:
|
||||||
def SQRTX(q: QuBit) -> None:
|
def SQRTX(q: QuBit) -> None:
|
||||||
if type(q) == IQuBit:
|
if type(q) == IQuBit:
|
||||||
q._IQuBit__apply(Matrix.SQRTX())
|
q._IQuBit__apply(Matrix.SQRTX())
|
||||||
|
q._IQuBit__muBit._MuBit__emit("SQRTX", q._IQuBit__n, [])
|
||||||
elif type(q) == QuBit:
|
elif type(q) == QuBit:
|
||||||
q._QuBit__apply(Matrix.SQRTX())
|
q._QuBit__apply(Matrix.SQRTX())
|
||||||
else:
|
else:
|
||||||
|
|
@ -332,6 +340,7 @@ def SQRTX(q: QuBit) -> None:
|
||||||
def Y(q: QuBit) -> None:
|
def Y(q: QuBit) -> None:
|
||||||
if type(q) == IQuBit:
|
if type(q) == IQuBit:
|
||||||
q._IQuBit__apply(Matrix.Y())
|
q._IQuBit__apply(Matrix.Y())
|
||||||
|
q._IQuBit__muBit._MuBit__emit("Y", q._IQuBit__n, [])
|
||||||
elif type(q) == QuBit:
|
elif type(q) == QuBit:
|
||||||
q._QuBit__apply(Matrix.Y())
|
q._QuBit__apply(Matrix.Y())
|
||||||
else:
|
else:
|
||||||
|
|
@ -340,6 +349,7 @@ def Y(q: QuBit) -> None:
|
||||||
def Z(q: QuBit) -> None:
|
def Z(q: QuBit) -> None:
|
||||||
if type(q) == IQuBit:
|
if type(q) == IQuBit:
|
||||||
q._IQuBit__apply(Matrix.Z())
|
q._IQuBit__apply(Matrix.Z())
|
||||||
|
q._IQuBit__muBit._MuBit__emit("Z", q._IQuBit__n, [])
|
||||||
elif type(q) == QuBit:
|
elif type(q) == QuBit:
|
||||||
q._QuBit__apply(Matrix.Z())
|
q._QuBit__apply(Matrix.Z())
|
||||||
else:
|
else:
|
||||||
|
|
@ -348,6 +358,7 @@ def Z(q: QuBit) -> None:
|
||||||
def S(q: QuBit) -> None:
|
def S(q: QuBit) -> None:
|
||||||
if type(q) == IQuBit:
|
if type(q) == IQuBit:
|
||||||
q._IQuBit__apply(Matrix.S())
|
q._IQuBit__apply(Matrix.S())
|
||||||
|
q._IQuBit__muBit._MuBit__emit("S", q._IQuBit__n, [])
|
||||||
elif type(q) == QuBit:
|
elif type(q) == QuBit:
|
||||||
q._QuBit__apply(Matrix.S())
|
q._QuBit__apply(Matrix.S())
|
||||||
else:
|
else:
|
||||||
|
|
@ -356,6 +367,7 @@ def S(q: QuBit) -> None:
|
||||||
def T(q: QuBit) -> None:
|
def T(q: QuBit) -> None:
|
||||||
if type(q) == IQuBit:
|
if type(q) == IQuBit:
|
||||||
q._IQuBit__apply(Matrix.T())
|
q._IQuBit__apply(Matrix.T())
|
||||||
|
q._IQuBit__muBit._MuBit__emit("T", q._IQuBit__n, [])
|
||||||
elif type(q) == QuBit:
|
elif type(q) == QuBit:
|
||||||
q._QuBit__apply(Matrix.T())
|
q._QuBit__apply(Matrix.T())
|
||||||
else:
|
else:
|
||||||
|
|
@ -365,10 +377,11 @@ def Rx(q: QuBit, phi: float) -> None:
|
||||||
if type(phi) not in {int, float}:
|
if type(phi) not in {int, float}:
|
||||||
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
||||||
|
|
||||||
if type(q) == QuBit:
|
if type(q) == IQuBit:
|
||||||
q._QuBit__apply(Matrix.Rx(phi))
|
|
||||||
elif type(q) == IQuBit:
|
|
||||||
q._IQuBit__apply(Matrix.Rx(phi))
|
q._IQuBit__apply(Matrix.Rx(phi))
|
||||||
|
q._IQuBit__muBit._MuBit__emit("Rx", q._IQuBit__n, [])
|
||||||
|
elif type(q) == QuBit:
|
||||||
|
q._QuBit__apply(Matrix.Rx(phi))
|
||||||
else:
|
else:
|
||||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||||
|
|
||||||
|
|
@ -376,10 +389,11 @@ def Ry(q: QuBit, phi: float) -> None:
|
||||||
if type(phi) not in {int, float}:
|
if type(phi) not in {int, float}:
|
||||||
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
||||||
|
|
||||||
if type(q) == QuBit:
|
if type(q) == IQuBit:
|
||||||
q._QuBit__apply(Matrix.Ry(phi))
|
|
||||||
elif type(q) == IQuBit:
|
|
||||||
q._IQuBit__apply(Matrix.Ry(phi))
|
q._IQuBit__apply(Matrix.Ry(phi))
|
||||||
|
q._IQuBit__muBit._MuBit__emit("Ry", q._IQuBit__n, [])
|
||||||
|
elif type(q) == QuBit:
|
||||||
|
q._QuBit__apply(Matrix.Ry(phi))
|
||||||
else:
|
else:
|
||||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||||
|
|
||||||
|
|
@ -387,10 +401,11 @@ def Rz(q: QuBit, phi: float) -> None:
|
||||||
if type(phi) not in {int, float}:
|
if type(phi) not in {int, float}:
|
||||||
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
||||||
|
|
||||||
if type(q) == QuBit:
|
if type(q) == IQuBit:
|
||||||
q._QuBit__apply(Matrix.Rz(phi))
|
|
||||||
elif type(q) == IQuBit:
|
|
||||||
q._IQuBit__apply(Matrix.Rz(phi))
|
q._IQuBit__apply(Matrix.Rz(phi))
|
||||||
|
q._IQuBit__muBit._MuBit__emit("H", q._IQuBit__n, [])
|
||||||
|
elif type(q) == QuBit:
|
||||||
|
q._QuBit__apply(Matrix.Rz(phi))
|
||||||
else:
|
else:
|
||||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||||
|
|
||||||
|
|
@ -398,10 +413,11 @@ def R1(q: QuBit, phi: float) -> None:
|
||||||
if type(phi) not in {int, float}:
|
if type(phi) not in {int, float}:
|
||||||
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
||||||
|
|
||||||
if type(q) == QuBit:
|
if type(q) == IQuBit:
|
||||||
q._QuBit__apply(Matrix.R1(phi))
|
|
||||||
elif type(q) == IQuBit:
|
|
||||||
q._IQuBit__apply(Matrix.R1(phi))
|
q._IQuBit__apply(Matrix.R1(phi))
|
||||||
|
q._IQuBit__muBit._MuBit__emit("R1", q._IQuBit__n, [])
|
||||||
|
elif type(q) == QuBit:
|
||||||
|
q._QuBit__apply(Matrix.R1(phi))
|
||||||
else:
|
else:
|
||||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||||
|
|
||||||
|
|
@ -425,6 +441,7 @@ def CX(q: MuBit, n1: int, n2: int) -> None:
|
||||||
q._MuBit__mapply(Matrix.CX(), n-2)
|
q._MuBit__mapply(Matrix.CX(), n-2)
|
||||||
SWAP(q, n-2, n1)
|
SWAP(q, n-2, n1)
|
||||||
SWAP(q, n-1, n2)
|
SWAP(q, n-1, n2)
|
||||||
|
q._MuBit__emit("CX", n1, [n2])
|
||||||
|
|
||||||
def CY(q: MuBit, n1: int, n2: int) -> None:
|
def CY(q: MuBit, n1: int, n2: int) -> None:
|
||||||
if type(q) is not MuBit:
|
if type(q) is not MuBit:
|
||||||
|
|
@ -446,6 +463,7 @@ def CY(q: MuBit, n1: int, n2: int) -> None:
|
||||||
q._MuBit__mapply(Matrix.CY(), n-2)
|
q._MuBit__mapply(Matrix.CY(), n-2)
|
||||||
SWAP(q, n-2, n1)
|
SWAP(q, n-2, n1)
|
||||||
SWAP(q, n-1, n2)
|
SWAP(q, n-1, n2)
|
||||||
|
q._MuBit__emit("CY", n1, [n2])
|
||||||
|
|
||||||
def CZ(q: MuBit, n1: int, n2: int) -> None:
|
def CZ(q: MuBit, n1: int, n2: int) -> None:
|
||||||
if type(q) is not MuBit:
|
if type(q) is not MuBit:
|
||||||
|
|
@ -467,6 +485,7 @@ def CZ(q: MuBit, n1: int, n2: int) -> None:
|
||||||
q._MuBit__mapply(Matrix.CZ(), n-2)
|
q._MuBit__mapply(Matrix.CZ(), n-2)
|
||||||
SWAP(q, n-2, n1)
|
SWAP(q, n-2, n1)
|
||||||
SWAP(q, n-1, n2)
|
SWAP(q, n-1, n2)
|
||||||
|
q._MuBit__emit("CZ", n1, [n2])
|
||||||
|
|
||||||
def SWAP(q: MuBit, n1: int, n2: int) -> None:
|
def SWAP(q: MuBit, n1: int, n2: int) -> None:
|
||||||
if type(q) is not MuBit:
|
if type(q) is not MuBit:
|
||||||
|
|
@ -487,6 +506,8 @@ def SWAP(q: MuBit, n1: int, n2: int) -> None:
|
||||||
q._MuBit__SWITCH(i)
|
q._MuBit__SWITCH(i)
|
||||||
for i in range(nmax-2, nmin-1, -1):
|
for i in range(nmax-2, nmin-1, -1):
|
||||||
q._MuBit__SWITCH(i)
|
q._MuBit__SWITCH(i)
|
||||||
|
|
||||||
|
q._MuBit__emit("SWAP", n1, [n2])
|
||||||
|
|
||||||
def Cu(q: MuBit, u: list[list[complex]], n1: int, n2: int) -> None:
|
def Cu(q: MuBit, u: list[list[complex]], n1: int, n2: int) -> None:
|
||||||
if type(q) is not MuBit:
|
if type(q) is not MuBit:
|
||||||
|
|
@ -521,3 +542,4 @@ def Cu(q: MuBit, u: list[list[complex]], n1: int, n2: int) -> None:
|
||||||
q._MuBit__mapply(Matrix.Cu(u), n-2)
|
q._MuBit__mapply(Matrix.Cu(u), n-2)
|
||||||
SWAP(q, n-2, n1)
|
SWAP(q, n-2, n1)
|
||||||
SWAP(q, n-1, n2)
|
SWAP(q, n-1, n2)
|
||||||
|
q._MuBit__emit("Cu", n1, [n2])
|
||||||
Loading…
Reference in a new issue