From 74fe724570cc836d783af528da814ffa4ca64819 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 22 Nov 2023 09:55:18 +0400 Subject: [PATCH 01/12] matrix --- src/qibo/backends/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qibo/backends/__init__.py b/src/qibo/backends/__init__.py index 14bfaa169d..4b25c71bbb 100644 --- a/src/qibo/backends/__init__.py +++ b/src/qibo/backends/__init__.py @@ -100,6 +100,7 @@ def create(self, dtype): self.S = self.matrices.S self.SDG = self.matrices.SDG self.CNOT = self.matrices.CNOT + self.CY = self.matrices.CY self.CZ = self.matrices.CZ self.CSX = self.matrices.CSX self.CSXDG = self.matrices.CSXDG From 18c1e1dad9499717f70964cf14636e9d86ed8b1d Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 22 Nov 2023 09:55:32 +0400 Subject: [PATCH 02/12] numpy matrix --- src/qibo/backends/npmatrices.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qibo/backends/npmatrices.py b/src/qibo/backends/npmatrices.py index 490489833c..68f67a5401 100644 --- a/src/qibo/backends/npmatrices.py +++ b/src/qibo/backends/npmatrices.py @@ -121,6 +121,12 @@ def CNOT(self): [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], dtype=self.dtype ) + @cached_property + def CY(self): + return self.np.array( + [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0]], dtype=self.dtype + ) + @cached_property def CZ(self): return self.np.array( From f37c74daf5bbf62b7cccf5c9450824d8c5f9b0e2 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 22 Nov 2023 09:55:37 +0400 Subject: [PATCH 03/12] gate --- src/qibo/gates/gates.py | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/qibo/gates/gates.py b/src/qibo/gates/gates.py index f289b33c66..0e94225fca 100644 --- a/src/qibo/gates/gates.py +++ b/src/qibo/gates/gates.py @@ -178,6 +178,15 @@ def __init__(self, q): def qasm_label(self): return "y" + @Gate.check_controls + def controlled_by(self, *q): + """Fall back to CY if there is only one control.""" + if len(q) == 1: + gate = CY(q[0], self.target_qubits[0]) + else: + gate = super().controlled_by(*q) + return gate + def basis_rotation(self): from qibo import matrices # pylint: disable=C0415 @@ -972,6 +981,49 @@ def decompose(self, *free, use_toffolis: bool = True) -> List[Gate]: return [self.__class__(q0, q1)] +class CY(Gate): + """The Controlled-:math:`Y` gate. + + Corresponds to the following unitary matrix + + .. math:: + \\begin{pmatrix} + 1 & 0 & 0 & 0 \\\\ + 0 & 1 & 0 & 0 \\\\ + 0 & 0 & 0 & -i \\\\ + 0 & 0 & i & 0 \\\\ + \\end{pmatrix} + + Args: + q0 (int): the control qubit id number. + q1 (int): the target qubit id number. + """ + + def __init__(self, q0, q1): + super().__init__() + self.name = "cy" + self.draw_label = "Y" + self.control_qubits = (q0,) + self.target_qubits = (q1,) + self.init_args = [q0, q1] + self.clifford = True + self.unitary = True + + @property + def qasm_label(self): + return "cy" + + def decompose(self) -> List[Gate]: + """Decomposition of :math:`\\text{CY}` gate. + + Decompose :math:`\\text{CY}` gate into :class:`qibo.gates.SDG` in + the target qubit, followed by :class:`qibo.gates.CNOT`, followed + by a :class:`qibo.gates.S` in the target qubit. + """ + q0, q1 = self.init_args + return [SDG(q1), CNOT(q0, q1), S(q1)] + + class CZ(Gate): """The Controlled-Phase gate. From 05f3aa4486a24ddaa32edb2865859f4179696642 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 22 Nov 2023 09:55:47 +0400 Subject: [PATCH 04/12] test abstract --- tests/test_gates_abstract.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_gates_abstract.py b/tests/test_gates_abstract.py index efeb527d3f..708a9046da 100644 --- a/tests/test_gates_abstract.py +++ b/tests/test_gates_abstract.py @@ -228,10 +228,13 @@ def test_one_qubit_rotations_controlled_by(gatename, params): assert gate.parameters == params -def test_cnot_and_cz_init(): +def test_cnot_and_cy_and_cz_init(): gate = gates.CNOT(0, 1) assert gate.target_qubits == (1,) assert gate.control_qubits == (0,) + gate = gates.CZ(4, 7) + assert gate.target_qubits == (7,) + assert gate.control_qubits == (4,) gate = gates.CZ(3, 2) assert gate.target_qubits == (2,) assert gate.control_qubits == (3,) From 0f1255d814da1ee5ab4b3139d479dfdf7d858ca3 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 22 Nov 2023 09:55:57 +0400 Subject: [PATCH 05/12] test gate --- tests/test_gates_gates.py | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/test_gates_gates.py b/tests/test_gates_gates.py index 957d1e9c20..8bb0e190ea 100644 --- a/tests/test_gates_gates.py +++ b/tests/test_gates_gates.py @@ -478,6 +478,56 @@ def test_cnot(backend, applyx): assert gates.CNOT(0, 1).unitary +@pytest.mark.parametrize("seed_observable", list(range(1, 10 + 1))) +@pytest.mark.parametrize("seed_state", list(range(1, 10 + 1))) +@pytest.mark.parametrize("controlled_by", [False, True]) +def test_cy(backend, controlled_by, seed_state, seed_observable): + nqubits = 2 + initial_state = random_statevector(2**nqubits, seed=seed_state, backend=backend) + matrix = np.array( + [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, -1j], + [0, 0, 1j, 0], + ] + ) + matrix = backend.cast(matrix, dtype=matrix.dtype) + + target_state = np.dot(matrix, initial_state) + # test decomposition + final_state_decompose = apply_gates( + backend, + gates.CY(0, 1).decompose(), + nqubits=nqubits, + initial_state=initial_state, + ) + + if controlled_by: + gate = gates.Y(1).controlled_by(0) + else: + gate = gates.CY(0, 1) + + final_state = apply_gates(backend, [gate], initial_state=initial_state) + + assert gate.name == "cy" + + backend.assert_allclose(final_state, target_state) + + # testing random expectation value due to global phase difference + observable = random_hermitian(2**nqubits, seed=seed_observable, backend=backend) + backend.assert_allclose( + np.transpose(np.conj(final_state_decompose)) + @ observable + @ final_state_decompose, + np.transpose(np.conj(target_state)) @ observable @ target_state, + ) + + assert gates.CY(0, 1).qasm_label == "cy" + assert gates.CY(0, 1).clifford + assert gates.CY(0, 1).unitary + + @pytest.mark.parametrize("seed_observable", list(range(1, 10 + 1))) @pytest.mark.parametrize("seed_state", list(range(1, 10 + 1))) @pytest.mark.parametrize("controlled_by", [False, True]) From 9a88f9251640da4648e7cd062687b9b53f075467 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 06:01:01 +0000 Subject: [PATCH 06/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/qibo/backends/npmatrices.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qibo/backends/npmatrices.py b/src/qibo/backends/npmatrices.py index 68f67a5401..366c466cd7 100644 --- a/src/qibo/backends/npmatrices.py +++ b/src/qibo/backends/npmatrices.py @@ -124,7 +124,8 @@ def CNOT(self): @cached_property def CY(self): return self.np.array( - [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0]], dtype=self.dtype + [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0]], + dtype=self.dtype, ) @cached_property From 46e006dbda3710e54aef5bcd0530362c0deeaba8 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 22 Nov 2023 10:04:03 +0400 Subject: [PATCH 07/12] api ref --- doc/source/api-reference/qibo.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/source/api-reference/qibo.rst b/doc/source/api-reference/qibo.rst index 8a47c74ae7..514dffa734 100644 --- a/doc/source/api-reference/qibo.rst +++ b/doc/source/api-reference/qibo.rst @@ -548,6 +548,13 @@ Controlled-NOT (CNOT) :members: :member-order: bysource +Controlled-Y (CY) +""""""""""""""""""""" + +.. autoclass:: qibo.gates.CY + :members: + :member-order: bysource + Controlled-phase (CZ) """"""""""""""""""""" From 739009e4a7017a0e5a5fb5a78c579beb393165cd Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 27 Nov 2023 13:55:28 +0400 Subject: [PATCH 08/12] update tests --- tests/test_gates_density_matrix.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/test_gates_density_matrix.py b/tests/test_gates_density_matrix.py index cd0c025c5d..2b6c3fabd1 100644 --- a/tests/test_gates_density_matrix.py +++ b/tests/test_gates_density_matrix.py @@ -78,14 +78,15 @@ def test_one_qubit_gates(backend, gatename, gatekwargs): @pytest.mark.parametrize("gatename", ["H", "X", "Y", "Z", "S", "SDG", "T", "TDG"]) def test_controlled_by_one_qubit_gates(backend, gatename): nqubits = 2 - initial_rho = random_density_matrix(2**nqubits, backend=backend) + initial_rho = random_density_matrix(2**nqubits, seed=1, backend=backend) gate = getattr(gates, gatename)(1).controlled_by(0) - final_rho = apply_gates(backend, [gate], 2, initial_rho) + final_rho = apply_gates(backend, [gate], 2, np.copy(initial_rho)) matrix = backend.to_numpy(backend.matrix(getattr(gates, gatename)(1))) cmatrix = np.eye(4, dtype=matrix.dtype) cmatrix[2:, 2:] = matrix - target_rho = np.einsum("ab,bc,cd->ad", cmatrix, initial_rho, cmatrix.conj().T) + cmatrix = backend.cast(cmatrix, dtype=cmatrix.dtype) + target_rho = np.einsum("ab,bc,cd->ad", cmatrix, initial_rho, np.transpose(np.conj(cmatrix))) backend.assert_allclose(final_rho, target_rho) @@ -93,6 +94,7 @@ def test_controlled_by_one_qubit_gates(backend, gatename): "gatename,gatekwargs", [ ("CNOT", {}), + ("CY", {}), ("CZ", {}), ("SWAP", {}), ("CRX", {"theta": 0.123}), @@ -111,8 +113,8 @@ def test_two_qubit_gates(backend, gatename, gatekwargs): gate = getattr(gates, gatename)(0, 1, **gatekwargs) final_rho = apply_gates(backend, [gate], 2, initial_rho) - matrix = backend.to_numpy(gate.matrix(backend)) - target_rho = np.einsum("ab,bc,cd->ad", matrix, initial_rho, matrix.conj().T) + matrix = gate.matrix(backend) + target_rho = np.einsum("ab,bc,cd->ad", matrix, initial_rho, np.transpose(np.conj(matrix))) backend.assert_allclose(final_rho, target_rho, atol=PRECISION_TOL) From 66c837e31ae519c1d80ba3c63504678946e855a9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 09:56:41 +0000 Subject: [PATCH 09/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_gates_density_matrix.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_gates_density_matrix.py b/tests/test_gates_density_matrix.py index 2b6c3fabd1..c40825099c 100644 --- a/tests/test_gates_density_matrix.py +++ b/tests/test_gates_density_matrix.py @@ -86,7 +86,9 @@ def test_controlled_by_one_qubit_gates(backend, gatename): cmatrix = np.eye(4, dtype=matrix.dtype) cmatrix[2:, 2:] = matrix cmatrix = backend.cast(cmatrix, dtype=cmatrix.dtype) - target_rho = np.einsum("ab,bc,cd->ad", cmatrix, initial_rho, np.transpose(np.conj(cmatrix))) + target_rho = np.einsum( + "ab,bc,cd->ad", cmatrix, initial_rho, np.transpose(np.conj(cmatrix)) + ) backend.assert_allclose(final_rho, target_rho) @@ -114,7 +116,9 @@ def test_two_qubit_gates(backend, gatename, gatekwargs): final_rho = apply_gates(backend, [gate], 2, initial_rho) matrix = gate.matrix(backend) - target_rho = np.einsum("ab,bc,cd->ad", matrix, initial_rho, np.transpose(np.conj(matrix))) + target_rho = np.einsum( + "ab,bc,cd->ad", matrix, initial_rho, np.transpose(np.conj(matrix)) + ) backend.assert_allclose(final_rho, target_rho, atol=PRECISION_TOL) From 2d48cf322d8370bd180fe45e2ca89a3d5b714f81 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 29 Nov 2023 10:53:42 +0400 Subject: [PATCH 10/12] change qibojit branch --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index eb8ec3c736..6cd29de6e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,7 @@ scikit-learn = "^1.2.1" dill = "^0.3.6" pytest-cov = "^4.0.0" pylint = "^2.16.2" -qibojit = { git = "https://github.com/qiboteam/qibojit.git" } +qibojit = { git = "https://github.com/qiboteam/qibojit.git@controlled_y" } tensorflow = { version = "^2.12.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'" } # TODO: the marker is a temporary solution due to the lack of the tensorflow-io 0.32.0's wheels for Windows, this package is one of # the tensorflow requirements From ea34649cdc150295569516c5b9937e4d31564b1d Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 29 Nov 2023 11:15:08 +0400 Subject: [PATCH 11/12] undo --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6cd29de6e9..eb8ec3c736 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,7 @@ scikit-learn = "^1.2.1" dill = "^0.3.6" pytest-cov = "^4.0.0" pylint = "^2.16.2" -qibojit = { git = "https://github.com/qiboteam/qibojit.git@controlled_y" } +qibojit = { git = "https://github.com/qiboteam/qibojit.git" } tensorflow = { version = "^2.12.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'" } # TODO: the marker is a temporary solution due to the lack of the tensorflow-io 0.32.0's wheels for Windows, this package is one of # the tensorflow requirements From 12751a6b2a4eec18aa1276ebf51d3eea1387aa03 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 29 Nov 2023 10:13:40 +0000 Subject: [PATCH 12/12] Update tests/test_gates_abstract.py Co-authored-by: BrunoLiegiBastonLiegi <45011234+BrunoLiegiBastonLiegi@users.noreply.github.com> --- tests/test_gates_abstract.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_gates_abstract.py b/tests/test_gates_abstract.py index 708a9046da..05c4b9a92b 100644 --- a/tests/test_gates_abstract.py +++ b/tests/test_gates_abstract.py @@ -232,7 +232,7 @@ def test_cnot_and_cy_and_cz_init(): gate = gates.CNOT(0, 1) assert gate.target_qubits == (1,) assert gate.control_qubits == (0,) - gate = gates.CZ(4, 7) + gate = gates.CY(4, 7) assert gate.target_qubits == (7,) assert gate.control_qubits == (4,) gate = gates.CZ(3, 2)