added circuit

This commit is contained in:
Didictateur 2023-10-29 23:34:08 +01:00
parent 1441be93ce
commit 8afb859dd0
2 changed files with 93 additions and 12 deletions

59
QElephant/Circuit.py Normal file
View 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()

View file

@ -18,6 +18,11 @@ class MuBit:
self.__n = n
self.__state: list[complex] = [0]*(2**self.__n)
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:
return self.__n
@ -308,6 +313,7 @@ class IQuBit(QuBit):
def H(q: QuBit) -> None:
if type(q) == IQuBit:
q._IQuBit__apply(Matrix.H())
q._IQuBit__muBit._MuBit__emit("H", q._IQuBit__n, [])
elif type(q) == QuBit:
q._QuBit__apply(Matrix.H())
else:
@ -316,6 +322,7 @@ def H(q: QuBit) -> None:
def X(q: QuBit) -> None:
if type(q) == IQuBit:
q._IQuBit__apply(Matrix.X())
q._IQuBit__muBit._MuBit__emit("X", q._IQuBit__n, [])
elif type(q) == QuBit:
q._QuBit__apply(Matrix.X())
else:
@ -324,6 +331,7 @@ def X(q: QuBit) -> None:
def SQRTX(q: QuBit) -> None:
if type(q) == IQuBit:
q._IQuBit__apply(Matrix.SQRTX())
q._IQuBit__muBit._MuBit__emit("SQRTX", q._IQuBit__n, [])
elif type(q) == QuBit:
q._QuBit__apply(Matrix.SQRTX())
else:
@ -332,6 +340,7 @@ def SQRTX(q: QuBit) -> None:
def Y(q: QuBit) -> None:
if type(q) == IQuBit:
q._IQuBit__apply(Matrix.Y())
q._IQuBit__muBit._MuBit__emit("Y", q._IQuBit__n, [])
elif type(q) == QuBit:
q._QuBit__apply(Matrix.Y())
else:
@ -340,6 +349,7 @@ def Y(q: QuBit) -> None:
def Z(q: QuBit) -> None:
if type(q) == IQuBit:
q._IQuBit__apply(Matrix.Z())
q._IQuBit__muBit._MuBit__emit("Z", q._IQuBit__n, [])
elif type(q) == QuBit:
q._QuBit__apply(Matrix.Z())
else:
@ -348,6 +358,7 @@ def Z(q: QuBit) -> None:
def S(q: QuBit) -> None:
if type(q) == IQuBit:
q._IQuBit__apply(Matrix.S())
q._IQuBit__muBit._MuBit__emit("S", q._IQuBit__n, [])
elif type(q) == QuBit:
q._QuBit__apply(Matrix.S())
else:
@ -356,6 +367,7 @@ def S(q: QuBit) -> None:
def T(q: QuBit) -> None:
if type(q) == IQuBit:
q._IQuBit__apply(Matrix.T())
q._IQuBit__muBit._MuBit__emit("T", q._IQuBit__n, [])
elif type(q) == QuBit:
q._QuBit__apply(Matrix.T())
else:
@ -365,10 +377,11 @@ def Rx(q: QuBit, phi: float) -> None:
if type(phi) not in {int, float}:
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
if type(q) == QuBit:
q._QuBit__apply(Matrix.Rx(phi))
elif type(q) == IQuBit:
if type(q) == IQuBit:
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:
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}:
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
if type(q) == QuBit:
q._QuBit__apply(Matrix.Ry(phi))
elif type(q) == IQuBit:
if type(q) == IQuBit:
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:
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}:
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
if type(q) == QuBit:
q._QuBit__apply(Matrix.Rz(phi))
elif type(q) == IQuBit:
if type(q) == IQuBit:
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:
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}:
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
if type(q) == QuBit:
q._QuBit__apply(Matrix.R1(phi))
elif type(q) == IQuBit:
if type(q) == IQuBit:
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:
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)
SWAP(q, n-2, n1)
SWAP(q, n-1, n2)
q._MuBit__emit("CX", n1, [n2])
def CY(q: MuBit, n1: int, n2: int) -> None:
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)
SWAP(q, n-2, n1)
SWAP(q, n-1, n2)
q._MuBit__emit("CY", n1, [n2])
def CZ(q: MuBit, n1: int, n2: int) -> None:
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)
SWAP(q, n-2, n1)
SWAP(q, n-1, n2)
q._MuBit__emit("CZ", n1, [n2])
def SWAP(q: MuBit, n1: int, n2: int) -> None:
if type(q) is not MuBit:
@ -488,6 +507,8 @@ def SWAP(q: MuBit, n1: int, n2: int) -> None:
for i in range(nmax-2, nmin-1, -1):
q._MuBit__SWITCH(i)
q._MuBit__emit("SWAP", n1, [n2])
def Cu(q: MuBit, u: list[list[complex]], n1: int, n2: int) -> None:
if type(q) is not MuBit:
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
@ -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)
SWAP(q, n-2, n1)
SWAP(q, n-1, n2)
q._MuBit__emit("Cu", n1, [n2])