commit 17ff8eae495d2fcbea3a8aac89be7f5dd67f6897 Author: Didictateur Date: Fri Oct 13 11:17:35 2023 +0200 first commit diff --git a/Matrix.py b/Matrix.py new file mode 100644 index 0000000..0e056b1 --- /dev/null +++ b/Matrix.py @@ -0,0 +1,155 @@ +import math + +I = complex(0, 1) + +class Matrix: + def __init__(self, l: list[list[complex]]=[]) -> None: + self.__m = l + if l == []: + self.__m = [[0, 0], [0, 0]] + self.__size = (len(self.__m), len(self.__m[0])) + + def __mul__(self, __value: "Matrix") -> "Matrix": + l: list[list[complex]] = [] + for i in range(self.__size[0]*__value.__size[0]): + l.append([0]*(self.__size[1]*__value.__size[1])) + + for i in range(self.__size[0]): + for j in range(self.__size[1]): + for x in range(__value.__size[0]): + for y in range(__value.__size[1]): + pos = (i*__value.__size[0]+x, j*__value.__size[1]+y) + l[pos[0]][pos[1]] = self.__m[i][j]*__value.__m[x][y] + + return Matrix(l) + + def __apply(self, x: list[complex]) -> list[complex]: + assert(self.__size[1] == len(x)) + + y: list[complex] = [0]*self.__size[0] + for i in range(self.__size[0]): + for j in range(self.__size[1]): + y[i] += self.__m[i][j]*x[j] + return y + + def __str__(self) -> str: + return str(self.__m) + + @staticmethod + def I() -> "Matrix": + return Matrix([ + [1, 0], + [0, 1] + ]) + + @staticmethod + def H() -> "Matrix": + s = 1/math.sqrt(2) + return Matrix([ + [s, s], + [s, -s] + ]) + + @staticmethod + def X() -> "Matrix": + return Matrix([ + [0, 1], + [1, 0] + ]) + + @staticmethod + def Y() -> "Matrix": + return Matrix([ + [0, -I], + [I, 0] + ]) + + @staticmethod + def Z() -> "Matrix": + return Matrix([ + [1, 0], + [0, -1] + ]) + + @staticmethod + def S() -> "Matrix": + return Matrix([ + [1, 0], + [0, I] + ]) + + @staticmethod + def T() -> "Matrix": + s = math.e**(I*math.pi/4) + return Matrix([ + [1, 0], + [0, s] + ]) + + @staticmethod + def Rx(phi: float) -> "Matrix": + c = math.cos(phi/2) + s = math.sin(phi/2) + return Matrix([ + [c, -I*s], + [-I*s, c] + ]) + + @staticmethod + def Ry(phi: float) -> "Matrix": + c = math.cos(phi/2) + s = math.sin(phi/2) + return Matrix([ + [c, -s], + [s, c] + ]) + + @staticmethod + def Rz(phi: float) -> "Matrix": + s = math.e**(I*phi/2) + return Matrix([ + [1/s, 0], + [0, s] + ]) + + @staticmethod + def R1(phi: float) -> "Matrix": + s = math.e**(I*phi) + return Matrix([ + [1, 0], + [0, s] + ]) + + @staticmethod + def CNOT() -> "Matrix": + return Matrix([ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, 1], + [0, 0, 1, 0] + ]) + + @staticmethod + def SWAP() -> "Matrix": + return Matrix([ + [1, 0, 0, 0], + [0, 0, 1, 0], + [0, 1, 0, 0], + [0, 0, 0, 1] + ]) + + @staticmethod + def Cu(u: "Matrix") -> "Matrix": + assert(u.size == (2, 2)) + l = [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, u[0][0], u[0][1]], + [0, 0, u[1][0], u[1][1]] + ] + +if __name__=="__main__": + m1 = Matrix([[1]]) + m2 = Matrix([[1, 1], [0, 1]]) + + print(m1*m2) \ No newline at end of file diff --git a/QuBit.py b/QuBit.py new file mode 100644 index 0000000..f7f6b18 --- /dev/null +++ b/QuBit.py @@ -0,0 +1,200 @@ +import math +import random as rd + +from Matrix import * + +I = complex(0, 1) + +class QuBit: + def __init__(self, alpha: complex=1, beta: complex=0): + if abs(alpha)**2 + abs(beta)**2 != 1: + raise Exception("The initial state must be normalized") + self.__state = [alpha, beta] + + def __str__(self) -> str: + return f"{round(self.__state[0], 3)} |0> + {round(self.__state[1], 3)} |1>" + + def __apply(self, matrix: Matrix) -> None: + self.__state = matrix._Matrix__apply(self.__state) + + def observe(self) -> list[int]: + r = rd.random() + if r < abs(self.__state[0])**2: + self.__state = [1, 0] + return 0 + self.__state = [0, 1] + return 1 + +class MuBit: + def __init__(self, n: int) -> None: + self.__n = n + self.__state: list[complex] = [0]*(2**self.__n) + self.__state[0] = 1 + + def __str__(self) -> str: + def next(N: str) -> str: + if N == "": + return "" + if N[-1] == "0": + return N[:-1]+"1" + else: + return (next(N[:-1]))+"0" + + txt = "" + N = "0"*self.__n + for i in range(2**self.__n): + txt += f"{round(self.__state[i], 3)} |{N}>\n" + N = next(N) + return txt + + def __set(self, i: int, value: int) -> None: + """Set the nth QuBit into value""" + assert(value in {0, 1}) + + M = Matrix([[1]]) + for j in range(self.__n): + if j == i: + M *= Matrix([[1-value, 0], [0, value]]) + else: + M *= Matrix([[1, 0], [0, 1]]) + self.__state = M._Matrix__apply(self.__state) + norm = math.sqrt(sum([abs(x)**2 for x in self.__state])) + self.__state = [x/norm for x in self.__state] + + def __iter__(self): + return iter([IQuBit(i, self) for i in range(self.__n)]) + + def __getitem__(self, item: int) -> "IQuBit": + return IQuBit(item, self) + + def __apply(self, i: int, matrix: Matrix) -> None: + M = Matrix([[1]]) + + for j in range(self.__n): + if j == i: + M *= matrix + else: + M *= Matrix.I() + + self.__state = M._Matrix__apply(self.__state) + + def __mapply(self, matrix: Matrix) -> None: + self.__state = matrix.__MuBit__apply(self.__state) + + def __getProb(self, i: int) -> float: + """Probs for i to be zero""" + M = Matrix([[1]]) + + for j in range(self.__n): + if j == i: + M *= Matrix([[1, 0], [0, 0]]) + else: + M *= Matrix.I() + + l = M._Matrix__apply(self.__state) + return sum([abs(x)**2 for x in l]) + + def observe(self) -> list[0]: + l = [] + for i in range(self.__n): + l.append(IQuBit(i, self).observe()) + return l + +class IQuBit: + def __init__(self, n: int, mb: MuBit) -> None: + self.__n = n + self.__muBit = mb + + def __apply(self, matrix: Matrix) -> None: + self.__muBit._MuBit__apply(self.__n, matrix) + + def observe(self) -> int: + r = rd.random() + if r < self.__muBit._MuBit__getProb(self.__n): + self.__muBit._MuBit__set(self.__n, 0) + return 0 + self.__muBit._MuBit__set(self.__n, 1) + return 1 + +def H(q: (QuBit | IQuBit)) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.H()) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.H()) + +def X(q: (QuBit | IQuBit)) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.X()) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.X()) + +def Y(q: (QuBit | IQuBit)) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.Y()) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.Y()) + +def Z(q: (QuBit | IQuBit)) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.Z()) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.Z()) + +def S(q: (QuBit | IQuBit)) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.S()) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.S()) + +def T(q: (QuBit | IQuBit)) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.T()) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.T()) + +def Rx(q: (QuBit | IQuBit), phi: float) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.Rx(phi)) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.Rx(phi)) + +def Ry(q: (QuBit | IQuBit), phi: float) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.Ry(phi)) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.Ry(phi)) + +def Rz(q: (QuBit | IQuBit), phi: float) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.Rz(phi)) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.Rz(phi)) + +def R1(q: (QuBit | IQuBit), phi: float) -> None: + if type(q) == QuBit: + q._Qubit__apply(Matrix.R1(phi)) + elif type(q) == IQuBit: + q._IQuBit__apply(Matrix.R1(phi)) + +def CNOT(q: MuBit) -> None: + q._MuBit__mapply(Matrix.CNOT()) + +def SWAP(q: MuBit) -> None: + q._MuBit__mapply(Matrix.SWAP()) + +def Cu(q: MuBit, u: list[list[complex]]) -> None: + q._MuBit__mapply(Matrix.Cu(u)) + +def test(q: QuBit) -> None: + varName = None + + for name, value in locals().items(): + if value == q: + varName = name + print(varName) + +if __name__=="__main__": + q1 = QuBit() + q2 = QuBit() + + test(q1) \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/__pycache__/Matrix.cpython-311.pyc b/__pycache__/Matrix.cpython-311.pyc new file mode 100644 index 0000000..19da287 Binary files /dev/null and b/__pycache__/Matrix.cpython-311.pyc differ diff --git a/__pycache__/QuBit.cpython-311.pyc b/__pycache__/QuBit.cpython-311.pyc new file mode 100644 index 0000000..20d92f7 Binary files /dev/null and b/__pycache__/QuBit.cpython-311.pyc differ