diff --git a/QElephant/Matrix.py b/QElephant/Matrix.py index 3c82d57..68c5730 100644 --- a/QElephant/Matrix.py +++ b/QElephant/Matrix.py @@ -64,6 +64,13 @@ class Matrix: [0, 1], [1, 0] ]) + + @staticmethod + def SQRTX() -> "Matrix": + return Matrix([ + [(1+I)/2, (1-I)/2], + [(1-I)/2, (1+I)/2] + ]) @staticmethod def Y() -> "Matrix": @@ -141,7 +148,7 @@ class Matrix: ]) @staticmethod - def CNOT() -> "Matrix": + def CX() -> "Matrix": return Matrix([ [1, 0, 0, 0], [0, 1, 0, 0], @@ -149,6 +156,24 @@ class Matrix: [0, 0, 1, 0] ]) + @staticmethod + def CY() -> "Matrix": + return Matrix([ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, -I], + [0, 0, I, 0] + ]) + + @staticmethod + def CZ() -> "Matrix": + return Matrix([ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, -1] + ]) + @staticmethod def SWAP() -> "Matrix": return Matrix([ diff --git a/QElephant/QuBit.py b/QElephant/QuBit.py index 58cac2a..9bea0e6 100644 --- a/QElephant/QuBit.py +++ b/QElephant/QuBit.py @@ -256,7 +256,7 @@ class IQuBit(QuBit): 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(matrix, self.__n) def observe(self) -> int: r = rd.random() @@ -288,6 +288,14 @@ def X(q: QuBit) -> None: else: raise TypeError(f"a QuBit was expected, but a {type(q)} was given") +def SQRTX(q: QuBit) -> None: + if type(q) == IQuBit: + q._IQuBit__apply(Matrix.SQRTX()) + elif type(q) == QuBit: + q._QuBit__apply(Matrix.SQRTX()) + else: + raise TypeError(f"a QuBit was expected, but a {type(q)} was given") + def Y(q: QuBit) -> None: if type(q) == IQuBit: q._IQuBit__apply(Matrix.Y()) @@ -364,7 +372,7 @@ def R1(q: QuBit, phi: float) -> None: else: raise TypeError(f"a QuBit was expected, but a {type(q)} was given") -def CNOT(q: MuBit, n1: int, n2: int) -> None: +def CX(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(n1) is not int: @@ -380,7 +388,47 @@ def CNOT(q: MuBit, n1: int, n2: int) -> None: SWAP(q, 0, n1) SWAP(q, 1, n2) - q._MuBit__mapply(Matrix.CNOT(), 0) + q._MuBit__mapply(Matrix.CX(), 0) + SWAP(q, 0, n1) + SWAP(q, 1, n2) + +def CY(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(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 > q._MuBit__n or n2 > q._MuBit__n: + ValueError("Mubit index out of range") + n1 = n1%q._MuBit__n + n2 = n2%q._MuBit__n + if n1==n2: + ValueError("the CNOT gate must be applied on two differents QuBits") + + SWAP(q, 0, n1) + SWAP(q, 1, n2) + q._MuBit__mapply(Matrix.CY(), 0) + SWAP(q, 0, n1) + SWAP(q, 1, n2) + +def CZ(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(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 > q._MuBit__n or n2 > q._MuBit__n: + ValueError("Mubit index out of range") + n1 = n1%q._MuBit__n + n2 = n2%q._MuBit__n + if n1==n2: + ValueError("the CNOT gate must be applied on two differents QuBits") + + SWAP(q, 0, n1) + SWAP(q, 1, n2) + q._MuBit__mapply(Matrix.CZ(), 0) SWAP(q, 0, n1) SWAP(q, 1, n2) diff --git a/docs/Gate.md b/docs/Gate.md index 1b6d363..5ecddf3 100644 --- a/docs/Gate.md +++ b/docs/Gate.md @@ -28,6 +28,19 @@ Here is the list of all the main gates in quantum algorithm available in the lib \end{pmatrix} ``` +## SQRTX(q: QuBit) -> None +`Square-Root of X`. Inplementes the square root of the X-gate. + +- q: the qubit manipulated by the gate. This function is in-place. + +- matrix: +```math +\begin{pmatrix} +\frac {1+i} {2} & \frac {1-i} {2}\\ +\frac {1-i} {2} & \frac {1+i} {2} +\end{pmatrix} +``` + ## Y(q: QuBit) -> None `Pauli-Y gate`. Inplementes a rotation aroud the y-axis of $\pi$ radians. @@ -119,7 +132,7 @@ e^{-i\frac\phi2} & 0\\ \end{pmatrix} ``` -## CNOT(q: MuBit, n1: int, n2: int) -> None +## CX(q: MuBit, n1: int, n2: int) -> None `X-controlled gate`. Invert the state |0> and |1> of the QuiBit in n2 if the state of the QuBit in n1 is 1. - q: the qubit manipulated by the gate. This function is in-place. @@ -136,6 +149,40 @@ e^{-i\frac\phi2} & 0\\ \end{pmatrix} ``` +## CY(q: MuBit, n1: int, n2: int) -> None +`X-controlled gate`. Invert the state |0> and |1> of the QuiBit in n2 if the state of the QuBit in n1 is 1. + +- q: the qubit manipulated by the gate. This function is in-place. +- n1: the first QuBit to manipualte. +- n2: the second QuBit to manipulate + +- matrix: +```math +\begin{pmatrix} +1 & 0 & 0 & 0\\ +0 & 1 & 0 & 0\\ +0 & 0 & 0 & -i\\ +0 & 0 & i & 0 +\end{pmatrix} +``` + +## CZ(q: MuBit, n1: int, n2: int) -> None +`X-controlled gate`. Invert the state |0> and |1> of the QuiBit in n2 if the state of the QuBit in n1 is 1. + +- q: the qubit manipulated by the gate. This function is in-place. +- n1: the first QuBit to manipualte. +- n2: the second QuBit to manipulate + +- matrix: +```math +\begin{pmatrix} +1 & 0 & 0 & 0\\ +0 & 1 & 0 & 0\\ +0 & 0 & 1 & 0\\ +0 & 0 & 0 & -1 +\end{pmatrix} +``` + ## SWAP(q: MuBit, n1: int, n2: int) -> None `NOT gate`. Invert the state |0> and |1> of the QuiBit q. diff --git a/docs/Matrix.md b/docs/Matrix.md index 03a1d5d..51863e6 100644 --- a/docs/Matrix.md +++ b/docs/Matrix.md @@ -68,6 +68,17 @@ Matrix(l: list[list[complexe]]) \end{pmatrix} ``` +- ```SQRTX() -> Matrix``` + + returns the matrix + +```math +\begin{pmatrix} +\frac {1+i} {2} & \frac {1-i} {2}\\ +\frac {1-i} {2} & \frac {1+i} {2} +\end{pmatrix} +``` + - ```Y() -> Matrix``` returns the matrix @@ -156,7 +167,7 @@ e^{-i\frac \phi 2} & 0\\ \end{pmatrix} ``` -- ```CNOT() -> Matrix``` +- ```CX() -> Matrix``` returns the matrix @@ -169,6 +180,32 @@ e^{-i\frac \phi 2} & 0\\ \end{pmatrix} ``` +- ```CY() -> Matrix``` + + returns the matrix + +```math +\begin{pmatrix} +1 & 0 & 0 & 0\\ +0 & 1 & 0 & 0\\ +0 & 0 & 0 & -i\\ +0 & 0 & i & 0 +\end{pmatrix} +``` + +- ```CZ() -> Matrix``` + + returns the matrix + +```math +\begin{pmatrix} +1 & 0 & 0 & 0\\ +0 & 1 & 0 & 0\\ +0 & 0 & 1 & 0\\ +0 & 0 & 0 & -1 +\end{pmatrix} +``` + - ```SWAP() -> Matrix``` returns the matrix