did lots of things...
This commit is contained in:
parent
afa22cb193
commit
cfcf40b186
6 changed files with 552 additions and 117 deletions
17
Gate_test.py
17
Gate_test.py
|
|
@ -1,4 +1,5 @@
|
|||
from QElephant.QuBit import *
|
||||
import pytest
|
||||
|
||||
## MuBit
|
||||
mq = MuBit(2)
|
||||
|
|
@ -10,6 +11,22 @@ H(q)
|
|||
assert mq._MuBit__state == [1/math.sqrt(2), -1/math.sqrt(2), 0, 0]
|
||||
CX(mq, 0, 1)
|
||||
assert mq._MuBit__state == [1/math.sqrt(2), -1/math.sqrt(2), 0, 0]
|
||||
Bell(mq, 0, 1, "phi+")
|
||||
assert mq._MuBit__state == [1/math.sqrt(2), 0, 0, 1/math.sqrt(2)]
|
||||
Bell(mq, 0, 1, "phi-")
|
||||
assert mq._MuBit__state == [1/math.sqrt(2), 0, 0, -1/math.sqrt(2)]
|
||||
Bell(mq, 0, 1, "psi+")
|
||||
assert mq._MuBit__state == [0, 1/math.sqrt(2), 1/math.sqrt(2), 0]
|
||||
Bell(mq, 0, 1, "psi-")
|
||||
assert mq._MuBit__state == [0, 1/math.sqrt(2), -1/math.sqrt(2), 0]
|
||||
|
||||
mq = MuBit(3)
|
||||
H(mq[1])
|
||||
CZ(mq, 1, 2)
|
||||
GHZ(mq)
|
||||
assert mq._MuBit__state == [1/math.sqrt(2), 0, 0, 0, 0, 0, 0, 1/math.sqrt(2)]
|
||||
W(mq)
|
||||
assert mq._MuBit__state == [0, 1/math.sqrt(3), 1/math.sqrt(3), 0, 1/math.sqrt(3), 0, 0, 0]
|
||||
|
||||
## QuBit
|
||||
q = QuBit()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from QElephant.Matrix import *
|
||||
import pytest
|
||||
|
||||
m = Matrix([[1, 2, 3], [4, 5, 6]])
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ from matplotlib.patches import Rectangle, Circle
|
|||
from QElephant.QuBit import *
|
||||
|
||||
class Circuit:
|
||||
def __init__(self, n: int, instructions=[]):
|
||||
self.__instr = instructions
|
||||
def __init__(self, n: int):
|
||||
self.__instr = []
|
||||
self.__n = n
|
||||
self.__mubit = MuBit(self.__n)
|
||||
self.__mubit._MuBit__callBack = self.__recv
|
||||
|
|
@ -30,8 +30,19 @@ class Circuit:
|
|||
def __cross(self, x: float, y: float):
|
||||
self.__line((x-0.25, y-0.25), (x+0.25, y+0.25))
|
||||
self.__line((x-0.25, y+0.25), (x+0.25, y-0.25))
|
||||
|
||||
def get_MuBit(self) -> MuBit:
|
||||
"""returns the MuBit of the Circuit
|
||||
"""
|
||||
return self.__mubit
|
||||
|
||||
def get_size(self) -> int:
|
||||
"""returns the number of entangled QuBit in the Circuit"""
|
||||
return self.__n
|
||||
|
||||
def draw(self) -> None:
|
||||
"""draw and display a representation of the Circuit
|
||||
"""
|
||||
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)])
|
||||
|
|
@ -44,34 +55,75 @@ class Circuit:
|
|||
self.__line((i+1.25, q_i), (i+1.5, q_i))
|
||||
|
||||
if q_i == index:
|
||||
if txt == "X":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
self.__line((i+1, q_i-0.25), (i+1, q_i+0.25))
|
||||
elif txt == "SWAP":
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
self.__cross(i+1, q_i)
|
||||
self.__cross(i+1, neigbhor[0])
|
||||
self.__line((i+1, q_i), (i+1, neigbhor[0]))
|
||||
elif txt == "CX":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
self.__line((i+1, q_i-0.25), (i+1, q_i+0.25))
|
||||
self.__circle(i+1, neigbhor[0], 0.05)
|
||||
self.__line((i+1, q_i), (i+1, neigbhor[0]))
|
||||
elif txt == "obs":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__circle(i+1, q_i, 0.05)
|
||||
else:
|
||||
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))
|
||||
match txt:
|
||||
case "X":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
self.__line((i+1, q_i-0.25), (i+1, q_i+0.25))
|
||||
case "SWAP":
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
self.__cross(i+1, q_i)
|
||||
self.__cross(i+1, neigbhor[0])
|
||||
self.__line((i+1, q_i), (i+1, neigbhor[0]))
|
||||
case "CX":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
self.__line((i+1, q_i-0.25), (i+1, q_i+0.25))
|
||||
self.__circle(i+1, neigbhor[0], 0.05)
|
||||
self.__line((i+1, q_i), (i+1, neigbhor[0]))
|
||||
case "obs":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__circle(i+1, q_i, 0.05)
|
||||
case "Φ⁺" | "Φ⁻" | "Ψ⁺" | "Ψ⁻":
|
||||
self.__rect(i+1, q_i, txt, n)
|
||||
if neigbhor[0] > q_i:
|
||||
self.__line((i+1, q_i+0.25), (i+1, neigbhor[0]-0.25))
|
||||
elif neigbhor[0] < q_i:
|
||||
self.__line((i+1, q_i-0.25), (i+1, neigbhor[0]+0.25))
|
||||
else:
|
||||
raise ValueError("Cannot apply gate twice on the same QuBit")
|
||||
case "Mobserve":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__circle(i+1, q_i, 0.05)
|
||||
for k in range(1, self.__n):
|
||||
self.__line((i+1, k-0.75), (i+1, k-0.25))
|
||||
case "MX":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
self.__line((i+1, q_i-0.25), (i+1, q_i+0.25))
|
||||
for k in range(1, self.__n):
|
||||
self.__line((i+1, k-1), (i+1, k))
|
||||
case _:
|
||||
if txt[:2] == "M-":
|
||||
self.__rect(i+1, q_i, txt[2:], n)
|
||||
for k in range(1, self.__n):
|
||||
self.__line((i+1, k-0.75), (i+1, k-0.25))
|
||||
else:
|
||||
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")
|
||||
elif q_i in neigbhor:
|
||||
match txt:
|
||||
case "Φ⁺" | "Φ⁻" | "Ψ⁺" | "Ψ⁻":
|
||||
self.__rect(i+1, q_i, txt, n)
|
||||
case "Mobserve":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__circle(i+1, q_i, 0.05)
|
||||
case "MX":
|
||||
self.__circle(i+1, q_i, 0.25, False)
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
self.__line((i+1, q_i-0.25), (i+1, q_i+0.25))
|
||||
case _:
|
||||
if txt[:2] == "M-":
|
||||
self.__rect(i+1, q_i, txt[2:], n)
|
||||
else:
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
else:
|
||||
self.__line((i+0.75, q_i), (i+1.25, q_i))
|
||||
i += 1
|
||||
|
|
@ -79,4 +131,5 @@ class Circuit:
|
|||
|
||||
if __name__=="__main__":
|
||||
c = Circuit(3, [("CS", 0, [1]), ("CX", 2, [0]), ("TX", 1, [0, 2])])
|
||||
print(c.get_size())
|
||||
c.draw()
|
||||
|
|
@ -43,7 +43,8 @@ class Matrix:
|
|||
def __str__(self) -> str:
|
||||
return str(self.__m)
|
||||
|
||||
def to_list(self) -> list[list[complex]]:
|
||||
def to_list(self) -> list[list[complex]]:
|
||||
"""convert the Matrix into a list representation"""
|
||||
return self._Matrix__m.copy()
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import matplotlib.pyplot as plt
|
|||
|
||||
from QElephant.Matrix import *
|
||||
|
||||
I = complex(0, 1)
|
||||
|
||||
## Classes
|
||||
|
||||
class MuBit:
|
||||
|
|
@ -13,7 +11,7 @@ class MuBit:
|
|||
if type(n) is not int:
|
||||
raise TypeError(f"number of state must be an intergers, not {type(n)}")
|
||||
if not n >= 2:
|
||||
raise ValueError("a MuBit must have at least two intricated QuBit")
|
||||
raise ValueError("a MuBit must have at least two entangled QuBit")
|
||||
|
||||
self.__n = n
|
||||
self.__state: list[complex] = [0]*(2**self.__n)
|
||||
|
|
@ -24,9 +22,6 @@ class MuBit:
|
|||
if self.__callBack is not None:
|
||||
self.__callBack(gate, target, neighbor)
|
||||
|
||||
def get_size(self) -> int:
|
||||
return self.__n
|
||||
|
||||
def __str__(self) -> str:
|
||||
def next(N: str) -> str:
|
||||
if N == "":
|
||||
|
|
@ -51,23 +46,26 @@ class MuBit:
|
|||
raise IndexError("MuBit index out of range")
|
||||
if not value in {0, 1}:
|
||||
raise ValueError(f"QuBit state must be 0 or 1, not {value}")
|
||||
|
||||
if self.__getProb(i) != value: # when prob==1 and we want prob==0. Value is in {0, 1}
|
||||
l = []
|
||||
a, d = 1-value, value
|
||||
for k in range(i, self.__n-1):
|
||||
self.__SWITCH(k)
|
||||
j = 0
|
||||
while j < 2**self.__n:
|
||||
x1, x2 = self.__state[j], self.__state[j+1]
|
||||
l.append(a*x1)
|
||||
l.append(d*x2)
|
||||
j += 2
|
||||
self.__state = l
|
||||
for k in range(self.__n-2, i-1, -1):
|
||||
self.__SWITCH(k)
|
||||
|
||||
l = []
|
||||
a, d = 1-value, value
|
||||
for k in range(i, self.__n-1):
|
||||
self.__SWITCH(k)
|
||||
j = 0
|
||||
while j < 2**self.__n:
|
||||
x1, x2 = self.__state[j], self.__state[j+1]
|
||||
l.append(a*x1)
|
||||
l.append(d*x2)
|
||||
j += 2
|
||||
self.__state = l
|
||||
for k in range(self.__n-2, i-1, -1):
|
||||
self.__SWITCH(k)
|
||||
|
||||
norm = math.sqrt(sum([abs(x)**2 for x in self.__state]))
|
||||
self.__state = [x/norm for x in self.__state]
|
||||
norm = math.sqrt(sum([abs(x)**2 for x in self.__state]))
|
||||
self.__state = [x/norm for x in self.__state]
|
||||
else:
|
||||
self.__apply(Matrix.X(), i)
|
||||
|
||||
def __iter__(self):
|
||||
return iter([IQuBit(i, self) for i in range(self.__n)])
|
||||
|
|
@ -160,7 +158,42 @@ class MuBit:
|
|||
self.__state[A:B], self.__state[B:C] = self.__state[B:C], self.__state[A:B]
|
||||
K += lng
|
||||
|
||||
def draw(self) -> None:
|
||||
def __SWAP(self, n1: int, n2: int) -> None:
|
||||
"""exchange the place between the two targeted QuBit
|
||||
|
||||
Args:
|
||||
n1 (int): index of the first QuBit
|
||||
n2 (int): index of the second QuBit
|
||||
emit (bool):
|
||||
"""
|
||||
if type(n1) is not int:
|
||||
TypeError(f"MuBit indices must be intergers, not {type(n1)}")
|
||||
if type(n2) is not int:
|
||||
TypeError(f"MuBit indices must be intergers, not {type(n2)}")
|
||||
if n1 > self.__n or n2 > self.__n:
|
||||
raise ValueError("Mubit index out of range")
|
||||
n1 = n1%self.__n
|
||||
n2 = n2%self.__n
|
||||
|
||||
if n1 != n2:
|
||||
nmin = min(n1, n2)
|
||||
nmax = max(n1, n2)
|
||||
for i in range(nmin, nmax):
|
||||
self.__SWITCH(i)
|
||||
for i in range(nmax-2, nmin-1, -1):
|
||||
self.__SWITCH(i)
|
||||
|
||||
def get_size(self) -> int:
|
||||
"""returns the number of entangled QuBits
|
||||
"""
|
||||
return self.__n
|
||||
|
||||
def draw(self, show_state=False) -> None:
|
||||
"""draw in a histogram the probability of each state in the order from |0...0> to |1...1>
|
||||
|
||||
Args:
|
||||
show_state (bool, optional): if True, shows the name of each state in the histogram. Defaults to False.
|
||||
"""
|
||||
def next(N: str) -> str:
|
||||
if N == "":
|
||||
return ""
|
||||
|
|
@ -177,11 +210,19 @@ class MuBit:
|
|||
|
||||
X = [n for n in range(2**self.__n)]
|
||||
Y = [abs(self.__state[int(k)])**2 for k in X]
|
||||
plt.hist(X, weights=Y, bins=2**self.__n-1)
|
||||
plt.xticks([x+0.5 for x in X], [f"|{xlab}>" for xlab in xlabels])
|
||||
plt.hist(X+[2**self.__n], weights=Y+[0], bins=2**self.__n)
|
||||
if show_state:
|
||||
plt.xticks([x+0.5 for x in X], [f"|{xlab}>" for xlab in xlabels])
|
||||
else:
|
||||
plt.xticks([0, 2**self.__n-1], ["", ""])
|
||||
plt.show()
|
||||
|
||||
def observe(self) -> list[int]:
|
||||
"""fixe all the QuBit in one state according their probabilities
|
||||
|
||||
Returns:
|
||||
list[int]: the list of the fixed state of the QuBits
|
||||
"""
|
||||
r = rd.random()
|
||||
s = 0
|
||||
state = 0
|
||||
|
|
@ -200,17 +241,27 @@ class MuBit:
|
|||
l.insert(0, state%2)
|
||||
state -= state%2
|
||||
state //= 2
|
||||
|
||||
self.__emit("Mobserve", 0, range(self.get_size()))
|
||||
return l
|
||||
|
||||
def reset(self) -> None:
|
||||
"""reset the state to |0...0>
|
||||
"""
|
||||
self.__state = [0]*2**self.__n
|
||||
self.__state[0] = 1
|
||||
self.__emit("M-|0>", 0, range(self.get_size()))
|
||||
|
||||
@staticmethod
|
||||
def intricateThem(*args: "QuBit") -> "MuBit":
|
||||
"""creates a situation where all the given QuBit are now entangled
|
||||
|
||||
Returns:
|
||||
MuBit: a copy of the given QuBits, but entangled
|
||||
"""
|
||||
for q in args:
|
||||
if type(q) is IQuBit:
|
||||
raise TypeError("cannot intricate QuBit that are already intricated")
|
||||
raise TypeError("cannot intricate QuBit that are already entangled")
|
||||
if type(q) is not QuBit:
|
||||
raise TypeError(f"cannot intricate QuBit and {type(q)}")
|
||||
if len(args) < 2:
|
||||
|
|
@ -234,13 +285,7 @@ class QuBit:
|
|||
raise ValueError(f"the initial state must be normalized. Here, |alpha|**2+|beta|**2={abs(alpha)**2 + abs(beta)**2}")
|
||||
|
||||
self.__state = [alpha, beta]
|
||||
self.__intricated = False
|
||||
|
||||
def is_intricated(self) -> bool:
|
||||
return self.__intricated
|
||||
|
||||
def get_Mubit(self) -> None:
|
||||
return None
|
||||
self.__entangled = False
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{round(self.__state[0], 3)} |0> + {round(self.__state[1], 3)} |1>"
|
||||
|
|
@ -251,7 +296,20 @@ class QuBit:
|
|||
|
||||
self.__state = matrix._Matrix__apply(self.__state)
|
||||
|
||||
def is_entangled(self) -> bool:
|
||||
"""tells if the corresponding QuBit is entangled
|
||||
|
||||
Returns:
|
||||
bool: True if this is the case, or else False
|
||||
"""
|
||||
return self.__entangled
|
||||
|
||||
def observe(self) -> list[int]:
|
||||
"""set the state to |0> or |1> according its probabilities
|
||||
|
||||
Returns:
|
||||
int: the new state of the QuBit
|
||||
"""
|
||||
r = rd.random()
|
||||
if r < abs(self.__state[0])**2:
|
||||
self.__state = [1, 0]
|
||||
|
|
@ -260,6 +318,8 @@ class QuBit:
|
|||
return 1
|
||||
|
||||
def reset(self) -> None:
|
||||
"""reset the state to |0>
|
||||
"""
|
||||
self.__state = [1, 0]
|
||||
|
||||
class IQuBit(QuBit):
|
||||
|
|
@ -275,13 +335,7 @@ class IQuBit(QuBit):
|
|||
super().__init__()
|
||||
self.__n = n
|
||||
self.__muBit = mb
|
||||
self.__intricated = True
|
||||
|
||||
def is_intricated(self) -> bool:
|
||||
return self.__intricated
|
||||
|
||||
def get_Mubit(self) -> tuple[MuBit, int]:
|
||||
return (self.__muBit, self.__n)
|
||||
self.__entangled = True
|
||||
|
||||
def __str__(self) -> str:
|
||||
p = self.__muBit._MuBit__getProb(self.__n)
|
||||
|
|
@ -293,7 +347,28 @@ class IQuBit(QuBit):
|
|||
|
||||
self.__muBit._MuBit__apply(matrix, self.__n)
|
||||
|
||||
def is_entangled(self) -> bool:
|
||||
"""tells if the corresponding QuBit is entangled
|
||||
|
||||
Returns:
|
||||
bool: True if this is the case, or else False
|
||||
"""
|
||||
return self.__entangled
|
||||
|
||||
def get_Mubit(self) -> tuple[MuBit, int]:
|
||||
"""returns the MuBit in wich the MuBit is stocked
|
||||
|
||||
Returns:
|
||||
tuple[MuBit, int]: the corresponding MuBit and its place among all the QuBits contained in the same MuBit
|
||||
"""
|
||||
return (self.__muBit, self.__n)
|
||||
|
||||
def observe(self) -> int:
|
||||
"""set the state to |0> or |1> according its probabilities
|
||||
|
||||
Returns:
|
||||
int: the new state of the QuBit
|
||||
"""
|
||||
r = rd.random()
|
||||
self.__muBit._MuBit__emit("obs", self.__n, [])
|
||||
if r < self.__muBit._MuBit__getProb(self.__n):
|
||||
|
|
@ -303,6 +378,8 @@ class IQuBit(QuBit):
|
|||
return 1
|
||||
|
||||
def reset(self) -> None:
|
||||
"""reset the state to |0>
|
||||
"""
|
||||
self.__muBit._MuBit__set(self.__n, 0)
|
||||
self.__muBit._MuBit__emit("|0>", self.__n, [])
|
||||
|
||||
|
|
@ -312,70 +389,139 @@ class IQuBit(QuBit):
|
|||
|
||||
## Fonctions
|
||||
|
||||
def H(q: QuBit) -> None:
|
||||
def H(q: (QuBit | MuBit)) -> None:
|
||||
"""apply the gate H to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
"""
|
||||
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())
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.H())
|
||||
q._MuBit__emit("M-H", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def X(q: QuBit) -> None:
|
||||
def X(q: (QuBit | MuBit)) -> None:
|
||||
"""apply the gate X to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
"""
|
||||
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())
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.X())
|
||||
q._MuBit__emit("MX", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def SQRTX(q: QuBit) -> None:
|
||||
def SQRTX(q: (QuBit | MuBit)) -> None:
|
||||
"""apply the gate corresponding of the square root of the X-gate to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
"""
|
||||
if type(q) == IQuBit:
|
||||
q._IQuBit__apply(Matrix.SQRTX())
|
||||
q._IQuBit__muBit._MuBit__emit("√¬", q._IQuBit__n, [])
|
||||
elif type(q) == QuBit:
|
||||
q._QuBit__apply(Matrix.SQRTX())
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.SQRTX())
|
||||
q._MuBit__emit("M-√¬", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def Y(q: QuBit) -> None:
|
||||
def Y(q: (QuBit | MuBit)) -> None:
|
||||
"""apply the gate Y to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
"""
|
||||
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())
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.Y())
|
||||
q._MuBit__emit("M-Y", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def Z(q: QuBit) -> None:
|
||||
def Z(q: (QuBit | MuBit)) -> None:
|
||||
"""apply the gate Z to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
"""
|
||||
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())
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.Z())
|
||||
q._MuBit__emit("M-Z", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def S(q: QuBit) -> None:
|
||||
def S(q: (QuBit | MuBit)) -> None:
|
||||
"""apply the gate S to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
"""
|
||||
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())
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.S())
|
||||
q._MuBit__emit("M-S", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def T(q: QuBit) -> None:
|
||||
def T(q: (QuBit | MuBit)) -> None:
|
||||
"""apply the gate T to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
"""
|
||||
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())
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.T())
|
||||
q._MuBit__emit("M-T", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def Rx(q: QuBit, phi: float) -> None:
|
||||
def Rx(q: (QuBit | MuBit), phi: float) -> None:
|
||||
"""apply a rotation around the x-axis to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
phi (float): the angle or the rotation
|
||||
"""
|
||||
if type(phi) not in {int, float}:
|
||||
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
||||
|
||||
|
|
@ -384,10 +530,20 @@ def Rx(q: QuBit, phi: float) -> None:
|
|||
q._IQuBit__muBit._MuBit__emit("Rx", q._IQuBit__n, [])
|
||||
elif type(q) == QuBit:
|
||||
q._QuBit__apply(Matrix.Rx(phi))
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.Rx(phi))
|
||||
q._MuBit__emit("M-Rx", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def Ry(q: QuBit, phi: float) -> None:
|
||||
def Ry(q: (QuBit | MuBit), phi: float) -> None:
|
||||
"""apply a rotation around the y-axis to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
phi (float): the angle or the rotation
|
||||
"""
|
||||
if type(phi) not in {int, float}:
|
||||
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
||||
|
||||
|
|
@ -396,22 +552,42 @@ def Ry(q: QuBit, phi: float) -> None:
|
|||
q._IQuBit__muBit._MuBit__emit("Ry", q._IQuBit__n, [])
|
||||
elif type(q) == QuBit:
|
||||
q._QuBit__apply(Matrix.Ry(phi))
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.Ry(phi))
|
||||
q._MuBit__emit("M-Ry", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def Rz(q: QuBit, phi: float) -> None:
|
||||
def Rz(q: (QuBit | MuBit), phi: float) -> None:
|
||||
"""apply a rotation around the z-axis to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
phi (float): the angle or the rotation
|
||||
"""
|
||||
if type(phi) not in {int, float}:
|
||||
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
||||
|
||||
if type(q) == IQuBit:
|
||||
q._IQuBit__apply(Matrix.Rz(phi))
|
||||
q._IQuBit__muBit._MuBit__emit("H", q._IQuBit__n, [])
|
||||
q._IQuBit__muBit._MuBit__emit("Rz", q._IQuBit__n, [])
|
||||
elif type(q) == QuBit:
|
||||
q._QuBit__apply(Matrix.Rz(phi))
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.Rz(phi))
|
||||
q._MuBit__emit("M-Rz", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def R1(q: QuBit, phi: float) -> None:
|
||||
def R1(q: (QuBit | MuBit), phi: float) -> None:
|
||||
"""apply the gate R1(phi) to the QuBit or all the QuBit of a MuBit
|
||||
|
||||
Args:
|
||||
q (QuBit | MuBit): the target
|
||||
phi (float): the angle or the rotation
|
||||
"""
|
||||
if type(phi) not in {int, float}:
|
||||
raise TypeError(f"an angle must be integer or float, not {type(phi)}")
|
||||
|
||||
|
|
@ -420,10 +596,141 @@ def R1(q: QuBit, phi: float) -> None:
|
|||
q._IQuBit__muBit._MuBit__emit("R1", q._IQuBit__n, [])
|
||||
elif type(q) == QuBit:
|
||||
q._QuBit__apply(Matrix.R1(phi))
|
||||
elif type(q) == MuBit:
|
||||
for i in range(q.get_size()):
|
||||
q[i]._IQuBit__apply(Matrix.R1(phi))
|
||||
q._MuBit__emit("M-R1", 0, range(q._MuBit__n))
|
||||
else:
|
||||
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
|
||||
raise TypeError(f"a QuBit or a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
def Bell(q: MuBit, n1: int, n2: int, phase: str="phi+") -> None:
|
||||
"""set the state of the two QuBits to:
|
||||
- |00> + |11> if phase = 'phi+'
|
||||
- |00> - |11> if phase = 'phi-'
|
||||
- |01> + |10> if phase = 'psi+'
|
||||
- |01> - |10> if phase = 'psi-'
|
||||
|
||||
Args:
|
||||
q (MuBit): the MuBit containing the targeted QuBits
|
||||
n1 (int): index of the first QuBit
|
||||
n2 (int): index of the second QuBit
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
if type(n1) is not int:
|
||||
raise TypeError(f"MuBit indices must be intergers, not {type(n1)}")
|
||||
if type(n2) is not int:
|
||||
raise TypeError(f"MuBit indices must be intergers, not {type(n2)}")
|
||||
if n1 >= q._MuBit__n or n2 >= q._MuBit__n:
|
||||
raise ValueError("Mubit index out of range")
|
||||
if type(phase) is not str:
|
||||
raise TypeError(f"expected a str for a phase, not {type(phase)}")
|
||||
if phase not in {"phi+", "phi-", "psi+", "psi-"}:
|
||||
raise ValueError("phase must be a value among 'phi+', 'phi-', 'psi+', 'psi-'")
|
||||
|
||||
|
||||
n = q._MuBit__n
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
q._MuBit__set(n-2, 0)
|
||||
q._MuBit__set(n-1, 0)
|
||||
q._MuBit__apply(Matrix.H(), n-2)
|
||||
q._MuBit__mapply(Matrix.CX(), n-2)
|
||||
|
||||
if phase[-1] == '-':
|
||||
q._MuBit__apply(Matrix.Z(), n-1)
|
||||
if phase[1] == "s":
|
||||
q._MuBit__apply(Matrix.X(), n-1)
|
||||
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
|
||||
match phase:
|
||||
case "phi+":
|
||||
q._MuBit__emit("Φ⁺", n1, [n2])
|
||||
case "phi-":
|
||||
q._MuBit__emit("Φ⁻", n1, [n2])
|
||||
case "psi+":
|
||||
q._MuBit__emit("Ψ⁺", n1, [n2])
|
||||
case "psi-":
|
||||
q._MuBit__emit("Ψ⁻", n1, [n2])
|
||||
|
||||
def Dicke(q: MuBit, k: int) -> None:
|
||||
"""set the state to |1,K>|0,n-k>
|
||||
|
||||
Args:
|
||||
q (MuBit): the targeted QuBits
|
||||
k (int): number of 1. If out of range, set k to 0 or n
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
if type(k) is not int:
|
||||
raise TypeError(f"MuBit indices must be intergers, not {type(k)}")
|
||||
k = min(k, q._MuBit__n)
|
||||
k = max(0, k)
|
||||
|
||||
state = [0]*(q._MuBit__n-k) + [1]*k
|
||||
i = 0
|
||||
for j in range(len(state)):
|
||||
i += state[j]*2**j
|
||||
|
||||
q._MuBit__state = [0]*2**q._MuBit__n
|
||||
q._MuBit__state[i] = 1
|
||||
|
||||
q._MuBit__emit(f"M-|D({q._MuBit__n}, {k})>", 0, range(q._MuBit__n))
|
||||
|
||||
def Wigner(q: MuBit, a: complex) -> None:
|
||||
"""set the state given a complexe formula
|
||||
|
||||
Args:
|
||||
q (MuBit): the targeted QuBits
|
||||
a (complex): complexe ratio of the serie
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
if type(a) not in {int, float, complex}:
|
||||
raise TypeError(f"QuBit state must be int, float or complex, not {type(a)}")
|
||||
|
||||
state = [a**k/math.sqrt(math.factorial(k)) for k in range(2**q._MuBit__n)]
|
||||
norm = sum(abs(x)**2 for x in state)
|
||||
q._MuBit__state = [x/norm for x in state]
|
||||
|
||||
q._MuBit__emit("M-W(α)", 0, range(q._MuBit__n))
|
||||
|
||||
def Cat(q: MuBit, a: complex, parity: int=0) -> None:
|
||||
"""set the state given a complexe formula
|
||||
|
||||
Args:
|
||||
q (MuBit): the targeted QuBits
|
||||
a (complex): complexe ratio of the serie
|
||||
parity (int, optional): give the parity of the chossen terms. Defaults to 0.
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
if parity not in {0, 1}:
|
||||
raise ValueError(f"parity must be 0 or 1, not {parity}")
|
||||
if type(a) not in {int, float, complex}:
|
||||
raise TypeError(f"QuBit state must be int, float or complex, not {type(a)}")
|
||||
|
||||
state = [((k+1+parity)%2)*a**k/math.sqrt(math.factorial(k)) for k in range(2**q._MuBit__n)]
|
||||
norm = sum(abs(x)**2 for x in state)
|
||||
q._MuBit__state = [x/norm for x in state]
|
||||
|
||||
if parity==0:
|
||||
q._MuBit__emit("M-Catₑ(α)", 0, range(q._MuBit__n))
|
||||
else:
|
||||
q._MuBit__emit("M-Cat₀(α)", 0, range(q._MuBit__n))
|
||||
|
||||
# def
|
||||
|
||||
def CX(q: MuBit, n1: int, n2: int) -> None:
|
||||
"""apply the controlled gate X to the two given QuBits
|
||||
|
||||
Args:
|
||||
q (MuBit): the MuBit containing the targeted QuBits
|
||||
n1 (int): index of the controller QuBit
|
||||
n2 (int): index of the controlled QuBit
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
if type(n1) is not int:
|
||||
|
|
@ -438,14 +745,21 @@ def CX(q: MuBit, n1: int, n2: int) -> None:
|
|||
raise ValueError("the CNOT gate must be applied on two differents QuBits")
|
||||
|
||||
n = q._MuBit__n
|
||||
SWAP(q, n-2, n1, False)
|
||||
SWAP(q, n-1, n2, False)
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
q._MuBit__mapply(Matrix.CX(), n-2)
|
||||
SWAP(q, n-2, n1, False)
|
||||
SWAP(q, n-1, n2, False)
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
q._MuBit__emit("CX", n1, [n2])
|
||||
|
||||
def CY(q: MuBit, n1: int, n2: int) -> None:
|
||||
"""apply the controlled gate Y to the two given QuBits
|
||||
|
||||
Args:
|
||||
q (MuBit): the MuBit containing the targeted QuBits
|
||||
n1 (int): index of the controller QuBit
|
||||
n2 (int): index of the controlled QuBit
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
if type(n1) is not int:
|
||||
|
|
@ -460,14 +774,21 @@ def CY(q: MuBit, n1: int, n2: int) -> None:
|
|||
raise ValueError("the CNOT gate must be applied on two differents QuBits")
|
||||
|
||||
n = q._MuBit__n
|
||||
SWAP(q, n-2, n1, False)
|
||||
SWAP(q, n-1, n2, False)
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
q._MuBit__mapply(Matrix.CY(), n-2)
|
||||
SWAP(q, n-2, n1, False)
|
||||
SWAP(q, n-1, n2, False)
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
q._MuBit__emit("Y", n1, [n2])
|
||||
|
||||
def CZ(q: MuBit, n1: int, n2: int) -> None:
|
||||
"""apply the controlled gate Z to the two given QuBits
|
||||
|
||||
Args:
|
||||
q (MuBit): the MuBit containing the targeted QuBits
|
||||
n1 (int): index of the controller QuBit
|
||||
n2 (int): index of the controlled QuBit
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
if type(n1) is not int:
|
||||
|
|
@ -482,14 +803,21 @@ def CZ(q: MuBit, n1: int, n2: int) -> None:
|
|||
raise ValueError("the CNOT gate must be applied on two differents QuBits")
|
||||
|
||||
n = q._MuBit__n
|
||||
SWAP(q, n-2, n1, False)
|
||||
SWAP(q, n-1, n2, False)
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
q._MuBit__mapply(Matrix.CZ(), n-2)
|
||||
SWAP(q, n-2, n1, False)
|
||||
SWAP(q, n-1, n2, False)
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
q._MuBit__emit("Z", n1, [n2])
|
||||
|
||||
def SWAP(q: MuBit, n1: int, n2: int, emit: bool=True) -> None:
|
||||
def SWAP(q: MuBit, n1: int, n2: int) -> None:
|
||||
"""exchange the place between the two given QuBits
|
||||
|
||||
Args:
|
||||
q (MuBit): the MuBit containing the targeted QuBits
|
||||
n1 (int): index of the controller QuBit
|
||||
n2 (int): index of the controlled QuBit
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
if type(n1) is not int:
|
||||
|
|
@ -509,10 +837,17 @@ def SWAP(q: MuBit, n1: int, n2: int, emit: bool=True) -> None:
|
|||
for i in range(nmax-2, nmin-1, -1):
|
||||
q._MuBit__SWITCH(i)
|
||||
|
||||
if emit:
|
||||
q._MuBit__emit("SWAP", n1, [n2])
|
||||
q._MuBit__emit("SWAP", n1, [n2])
|
||||
|
||||
def Cu(q: MuBit, u: list[list[complex]], n1: int, n2: int) -> None:
|
||||
"""apply the controlled gate u
|
||||
|
||||
Args:
|
||||
q (MuBit): the MuBit containing the targeted QuBit
|
||||
u (list[list[complex]]): matrix representation of the gate u
|
||||
n1 (int): index of the controller QuBit
|
||||
n2 (int): index of the controlled QuBit
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
if type(n1) is not int:
|
||||
|
|
@ -540,9 +875,37 @@ def Cu(q: MuBit, u: list[list[complex]], n1: int, n2: int) -> None:
|
|||
raise ValueError(f"the size of the matrix was expected to be (2, 2). A matrix of size ({len(u)}, {u[0]}) has been given")
|
||||
|
||||
n = q._MuBit__n
|
||||
SWAP(q, n-2, n1, False)
|
||||
SWAP(q, n-1, n2,False)
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
q._MuBit__mapply(Matrix.Cu(u), n-2)
|
||||
SWAP(q, n-2, n1, False)
|
||||
SWAP(q, n-1, n2, False)
|
||||
q._MuBit__emit("U", n1, [n2])
|
||||
q._MuBit__SWAP(n-2, n1)
|
||||
q._MuBit__SWAP(n-1, n2)
|
||||
q._MuBit__emit("U", n1, [n2])
|
||||
|
||||
def GHZ(q: MuBit):
|
||||
"""set the state to |0...0> + |1...1>
|
||||
|
||||
Args:
|
||||
q (MuBit): the targeted QuBit
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
q._MuBit__state = [1/math.sqrt(2)] + [0]*(2**q.get_size()-2) + [1/math.sqrt(2)]
|
||||
|
||||
q._MuBit__emit("M-GHZ", 0, range(q.get_size()))
|
||||
|
||||
def W(q: MuBit) -> None:
|
||||
"""set the state to |10...0> + |010...0> +...+ |0...01>
|
||||
|
||||
Args:
|
||||
q (MuBit): the targeted QuBit
|
||||
"""
|
||||
if type(q) is not MuBit:
|
||||
raise TypeError(f"a MuBit was expected, but a {type(q)} was given")
|
||||
|
||||
q._MuBit__state = [0]*(2**q.get_size())
|
||||
for k in range(q.get_size()):
|
||||
q._MuBit__state[2**k] = 1/math.sqrt(q.get_size())
|
||||
|
||||
q._MuBit__emit("M-W", 0, range(q.get_size()))
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
from QElephant.QuBit import *
|
||||
import pytest
|
||||
|
||||
q = QuBit(0, 1)
|
||||
|
||||
assert q._QuBit__state == [0, 1]
|
||||
assert q._QuBit__intricated == False
|
||||
assert q.is_intricated() == False
|
||||
assert q.get_Mubit() == None
|
||||
assert q._QuBit__entangled == False
|
||||
assert q.is_entangled() == False
|
||||
assert str(q) == "0 |0> + 1 |1>"
|
||||
q._QuBit__apply(Matrix([[1, 2], [3, 4]]))
|
||||
assert q._QuBit__state == [2, 4]
|
||||
|
|
@ -25,8 +25,8 @@ assert mq._MuBit__state == [0, 1/math.sqrt(2), 0, 1/math.sqrt(2)]
|
|||
q = mq[0]
|
||||
assert q._IQuBit__n == 0
|
||||
assert q._IQuBit__muBit == mq
|
||||
assert q._IQuBit__intricated == True
|
||||
assert q.is_intricated() == True
|
||||
assert q._IQuBit__entangled == True
|
||||
assert q.is_entangled() == True
|
||||
assert q.get_Mubit() == (mq, 0)
|
||||
assert str(q) == "0.707 |0> + 0.707 |1>"
|
||||
q._IQuBit__apply(Matrix([[1, 1], [1, -1]]))
|
||||
|
|
|
|||
Loading…
Reference in a new issue