begin exceptions

This commit is contained in:
Didictateur 2023-10-23 11:15:57 +02:00
parent af11de0c6a
commit ab1dbcf7cb
4 changed files with 118 additions and 5 deletions

View file

@ -9,6 +9,11 @@ I = complex(0, 1)
class MuBit: class MuBit:
def __init__(self, n: int=2) -> None: def __init__(self, n: int=2) -> None:
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")
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
@ -34,8 +39,14 @@ class MuBit:
def __set(self, i: int, value: int) -> None: def __set(self, i: int, value: int) -> None:
"""Set the nth QuBit into value""" """Set the nth QuBit into value"""
assert(value in {0, 1}) if type(i) is not int:
raise TypeError(f"MuBit indices must be integers, not {type(i)}")
if i > self.__n:
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}")
i = i%self.__n
M = Matrix([[1]]) M = Matrix([[1]])
for j in range(self.__n): for j in range(self.__n):
if j == i: if j == i:
@ -50,12 +61,26 @@ class MuBit:
return iter([IQuBit(i, self) for i in range(self.__n)]) return iter([IQuBit(i, self) for i in range(self.__n)])
def __getitem__(self, item: int) -> "QuBit": def __getitem__(self, item: int) -> "QuBit":
if type(item) is not int:
raise TypeError(f"MuBit indices must be integers, not {type(item)}")
if item > self.__n:
raise IndexError("MuBit index out of range")
item = item%self.__n
return IQuBit(item, self) return IQuBit(item, self)
def __apply(self, i: int, matrix: Matrix) -> None: def __apply(self, i: int, matrix: Matrix) -> None:
if type(i) is not int:
raise TypeError(f"MuBit indices must be integers, not {type(i)}")
if i > self.__n:
raise IndexError("MuBit index out of range")
if type(matrix) is not Matrix:
raise TypeError(f"can only manipulate MuBit with Matrix, not {type(matrix)}")
i = i%self.__n
M = Matrix([[1]]) M = Matrix([[1]])
for j in range(self.n): for j in range(self.__n):
if j == i: if j == i:
M *= matrix M *= matrix
else: else:
@ -64,6 +89,14 @@ class MuBit:
self.__state = M._Matrix__apply(self.__state) self.__state = M._Matrix__apply(self.__state)
def __mapply(self, matrix: Matrix, i: int) -> None: def __mapply(self, matrix: Matrix, i: int) -> None:
if type(i) is not int:
raise TypeError(f"MuBit indices must be integers, not {type(i)}")
if i > self.__n:
raise IndexError("MuBit index out of range")
if type(matrix) is not Matrix:
raise TypeError(f"can only manipulate MuBit with Matrix, not {type(matrix)}")
i = i%self.__n
M = Matrix([[1]]) M = Matrix([[1]])
j = 0 j = 0
while j < self.__n: while j < self.__n:
@ -77,6 +110,12 @@ class MuBit:
def __getProb(self, i: int) -> float: def __getProb(self, i: int) -> float:
"""Probs for i to be zero""" """Probs for i to be zero"""
if type(i) is not int:
raise TypeError(f"MuBit indices must be integers, not {type(i)}")
if i > self.__n:
raise IndexError("MuBit index out of range")
i = i%self.__n
M = Matrix([[1]]) M = Matrix([[1]])
for j in range(self.__n): for j in range(self.__n):
@ -94,10 +133,33 @@ class MuBit:
l.append(IQuBit(i, self).observe()) l.append(IQuBit(i, self).observe())
return l return l
@staticmethod
def intricateThem(*args: "QuBit") -> "MuBit":
for q in args:
if type(q) is IQuBit:
raise TypeError("cannot intricate QuBit that are already intricated")
if type(q) is not QuBit:
raise TypeError(f"cannot intricate QuBit and {type(q)}")
if len(args) < 2:
raise ValueError("cannot intricate less than two QuBits")
S = Matrix([[1]])
for q in args:
S *= Matrix([q._QuBit__state])
mq = MuBit(len(args))
mq._MuBit__state = S._Matrix__m[0]
return mq
class QuBit: class QuBit:
def __init__(self, alpha: complex=1, beta: complex=0): def __init__(self, alpha: complex=1, beta: complex=0):
if type(alpha) not in {int, float, complex}:
TypeError(f"QuBit state must be int, float or complex, not {type(alpha)}")
if type(beta) not in {int, float, complex}:
TypeError(f"QuBit state must be int, float or complex, not {type(alpha)}")
if abs(alpha)**2 + abs(beta)**2 != 1: if abs(alpha)**2 + abs(beta)**2 != 1:
raise Exception("The initial state must be normalized") 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.__state = [alpha, beta]
self.__intricated = False self.__intricated = False
@ -111,6 +173,9 @@ class QuBit:
return f"{round(self.__state[0], 3)} |0> + {round(self.__state[1], 3)} |1>" return f"{round(self.__state[0], 3)} |0> + {round(self.__state[1], 3)} |1>"
def __apply(self, matrix: Matrix) -> None: def __apply(self, matrix: Matrix) -> None:
if type(matrix) is not Matrix:
raise TypeError(f"can only manipulate QuBit with Matrix, not {type(matrix)}")
self.__state = matrix._Matrix__apply(self.__state) self.__state = matrix._Matrix__apply(self.__state)
def observe(self) -> list[int]: def observe(self) -> list[int]:
@ -123,6 +188,14 @@ class QuBit:
class IQuBit(QuBit): class IQuBit(QuBit):
def __init__(self, n: int, mb: MuBit) -> None: def __init__(self, n: int, mb: MuBit) -> None:
if type(n) is not int:
raise TypeError(f"MuBit indices must be interger, not {type(n)}")
if n > mb._MuBit__n:
raise ValueError(f"MuBit index out of range")
if type(mb) is not MuBit:
TypeError(f"an intricate QuBit should be associated with a MuBit, not a {type(mb)}")
n = n%mb._MuBit__n
super().__init__() super().__init__()
self.__n = n self.__n = n
self.__muBit = mb self.__muBit = mb
@ -139,6 +212,9 @@ class IQuBit(QuBit):
return str(QuBit(math.sqrt(p), math.sqrt(1-p))) return str(QuBit(math.sqrt(p), math.sqrt(1-p)))
def __apply(self, matrix: Matrix) -> None: def __apply(self, matrix: Matrix) -> None:
if type(matrix) is not Matrix:
raise TypeError(f"can only manipulate QuBit with Matrix, not {type(matrix)}")
self.__muBit._MuBit__apply(self.__n, matrix) self.__muBit._MuBit__apply(self.__n, matrix)
def observe(self) -> int: def observe(self) -> int:
@ -160,62 +236,98 @@ def H(q: QuBit) -> None:
q._IQuBit__apply(Matrix.H()) q._IQuBit__apply(Matrix.H())
elif type(q) == QuBit: elif type(q) == QuBit:
q._QuBit__apply(Matrix.H()) q._QuBit__apply(Matrix.H())
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
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())
elif type(q) == QuBit: elif type(q) == QuBit:
q._QuBit__apply(Matrix.X()) q._QuBit__apply(Matrix.X())
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
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())
elif type(q) == QuBit: elif type(q) == QuBit:
q._QuBit__apply(Matrix.Y()) q._QuBit__apply(Matrix.Y())
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
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())
elif type(q) == QuBit: elif type(q) == QuBit:
q._QuBit__apply(Matrix.Z()) q._QuBit__apply(Matrix.Z())
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
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())
elif type(q) == QuBit: elif type(q) == QuBit:
q._QuBit__apply(Matrix.S()) q._QuBit__apply(Matrix.S())
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
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())
elif type(q) == QuBit: elif type(q) == QuBit:
q._QuBit__apply(Matrix.T()) q._QuBit__apply(Matrix.T())
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
def Rx(q: QuBit, phi: float) -> None: def Rx(q: QuBit, phi: float) -> None:
if type(phi) not in {int, float}:
TypeError(f"an angle must be integer or float, not {type(phi)}")
if type(q) == QuBit: if type(q) == QuBit:
q._QuBit__apply(Matrix.Rx(phi)) q._QuBit__apply(Matrix.Rx(phi))
elif type(q) == IQuBit: elif type(q) == IQuBit:
q._IQuBit__apply(Matrix.Rx(phi)) q._IQuBit__apply(Matrix.Rx(phi))
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
def Ry(q: QuBit, phi: float) -> None: def Ry(q: QuBit, phi: float) -> None:
if type(phi) not in {int, float}:
TypeError(f"an angle must be integer or float, not {type(phi)}")
if type(q) == QuBit: if type(q) == QuBit:
q._QuBit__apply(Matrix.Ry(phi)) q._QuBit__apply(Matrix.Ry(phi))
elif type(q) == IQuBit: elif type(q) == IQuBit:
q._IQuBit__apply(Matrix.Ry(phi)) q._IQuBit__apply(Matrix.Ry(phi))
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
def Rz(q: QuBit, phi: float) -> None: def Rz(q: QuBit, phi: float) -> None:
if type(phi) not in {int, float}:
TypeError(f"an angle must be integer or float, not {type(phi)}")
if type(q) == QuBit: if type(q) == QuBit:
q._QuBit__apply(Matrix.Rz(phi)) q._QuBit__apply(Matrix.Rz(phi))
elif type(q) == IQuBit: elif type(q) == IQuBit:
q._IQuBit__apply(Matrix.Rz(phi)) q._IQuBit__apply(Matrix.Rz(phi))
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
def R1(q: QuBit, phi: float) -> None: def R1(q: QuBit, phi: float) -> None:
if type(phi) not in {int, float}:
TypeError(f"an angle must be integer or float, not {type(phi)}")
if type(q) == QuBit: if type(q) == QuBit:
q._QuBit__apply(Matrix.R1(phi)) q._QuBit__apply(Matrix.R1(phi))
elif type(q) == IQuBit: elif type(q) == IQuBit:
q._IQuBit__apply(Matrix.R1(phi)) q._IQuBit__apply(Matrix.R1(phi))
else:
raise TypeError(f"a QuBit was expected, but a {type(q)} was given")
def CNOT(q: MuBit, n1: int, n2: int) -> None: def CNOT(q: MuBit, n1: int, n2: int) -> None:
if type(q) is not MuBit:
TypeError(f"a MuBit was expected, but a {type(q)} was given")
if type()
SWAP(q, 0, n1) SWAP(q, 0, n1)
SWAP(q, 1, n2) SWAP(q, 1, n2)
q._MuBit__mapply(Matrix.CNOT(), 0) q._MuBit__mapply(Matrix.CNOT(), 0)
@ -246,5 +358,6 @@ def test(q: QuBit) -> None:
print(varName) print(varName)
if __name__=="__main__": if __name__=="__main__":
q = MuBit(3) q = MuBit(2)
s = q[1].get_Mubit()
print(q[0])

Binary file not shown.

Binary file not shown.

Binary file not shown.