From ab426cb611cba0440f382ec0e5727693be16e357 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 16 Oct 2024 12:45:49 +0400 Subject: [PATCH 1/9] function first try --- .../superoperator_transformations.py | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/qibo/quantum_info/superoperator_transformations.py b/src/qibo/quantum_info/superoperator_transformations.py index bae06d6402..5ec54a41eb 100644 --- a/src/qibo/quantum_info/superoperator_transformations.py +++ b/src/qibo/quantum_info/superoperator_transformations.py @@ -1,7 +1,7 @@ """Module with the most commom superoperator transformations.""" import warnings -from typing import Optional +from typing import List, Optional, Tuple, Union import numpy as np from scipy.optimize import minimize @@ -303,6 +303,48 @@ def to_chi( return channel +def to_stinespring( + channel, + partition: Optional[Union[List[int], Tuple[int, ...]]] = None, + nqubits: Optional[int] = None, + initial_state_env=None, + backend=None, +): + """_summary_ + + Args: + channel (ndarray): quantum channel. + nqubits (int, optional): total number of qubits in the system that is + interacting with the environment. Must be equal or greater than + the number of qubits ``kraus_ops`` acts on. If ``None``, + defaults to the number of qubits in ``kraus_ops``. + Defauts to ``None``. + initial_state_env (ndarray, optional): statevector representing the + initial state of the enviroment. If ``None``, it assumes the + environment in its ground state. Defaults to ``None``. + backend (:class:`qibo.backends.abstract.Backend`, optional): backend + to be used in the execution. If ``None``, it uses + :class:`qibo.backends.GlobalBackend`. Defaults to ``None``. + + Returns: + ndarray: _description_ + """ + backend = _check_backend(backend) + + if partition is None: + nqubits_channel = int(np.log2(channel.shape[-1])) + partition = tuple(range(nqubits_channel)) + + channel = kraus_to_stinespring( + [(partition, channel)], + nqubits=nqubits, + initial_state_env=initial_state_env, + backend=backend, + ) + + return channel + + def choi_to_liouville(choi_super_op, order: str = "row", backend=None): """Converts Choi representation :math:`\\Lambda` of quantum channel to its Liouville representation :math:`\\mathcal{E}`. @@ -320,7 +362,6 @@ def choi_to_liouville(choi_super_op, order: str = "row", backend=None): \\Lambda_{\\alpha\\beta, \\, \\gamma\\delta} \\mapsto \\Lambda_{\\delta\\beta, \\, \\gamma\\alpha} \\equiv \\mathcal{E} - Args: choi_super_op: Choi representation of quantum channel. order (str, optional): If ``"row"``, reshuffling is performed @@ -640,7 +681,7 @@ def choi_to_stinespring( if nqubits is None: nqubits = int(np.log2(kraus_ops[0].shape[0])) - nqubits_list = [tuple(range(nqubits)) for _ in range(len(kraus_ops))] + nqubits_list = [tuple(range(nqubits))] * len(kraus_ops) kraus_ops = list(zip(nqubits_list, kraus_ops)) From e65c5e6c23f161cbf77f34477b0231cfbfc45d2e Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 16 Oct 2024 12:46:47 +0400 Subject: [PATCH 2/9] api reference --- doc/source/api-reference/qibo.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/source/api-reference/qibo.rst b/doc/source/api-reference/qibo.rst index b4beedfe8e..bcbf266ca0 100644 --- a/doc/source/api-reference/qibo.rst +++ b/doc/source/api-reference/qibo.rst @@ -2164,6 +2164,12 @@ To Chi .. autofunction:: qibo.quantum_info.to_chi +To Stinespring +"""""""""""""" + +.. autofunction:: qibo.quantum_info.to_stinespring + + Choi to Liouville """"""""""""""""" From 7b88e640f85e956d1ece9cb8e9a42695b65fe465 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 16 Oct 2024 12:50:47 +0400 Subject: [PATCH 3/9] finish docstring --- src/qibo/quantum_info/superoperator_transformations.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qibo/quantum_info/superoperator_transformations.py b/src/qibo/quantum_info/superoperator_transformations.py index 5ec54a41eb..d8db70142a 100644 --- a/src/qibo/quantum_info/superoperator_transformations.py +++ b/src/qibo/quantum_info/superoperator_transformations.py @@ -310,7 +310,9 @@ def to_stinespring( initial_state_env=None, backend=None, ): - """_summary_ + """Converts quantum ``channel`` :math:`U` to its Stinespring representation :math:`U_{0}`. + + It uses the Kraus representation as an intermediate step. Args: channel (ndarray): quantum channel. @@ -327,7 +329,7 @@ def to_stinespring( :class:`qibo.backends.GlobalBackend`. Defaults to ``None``. Returns: - ndarray: _description_ + ndarray: Quantum channel in its Stinespring representation :math:`U_{0}`. """ backend = _check_backend(backend) From 30c2f7b581c3824214b195ede87b2b5a7ccdc755 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 16 Oct 2024 15:47:24 +0400 Subject: [PATCH 4/9] tests --- ...ntum_info_superoperator_transformations.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_quantum_info_superoperator_transformations.py b/tests/test_quantum_info_superoperator_transformations.py index 4f382b6300..4938071631 100644 --- a/tests/test_quantum_info_superoperator_transformations.py +++ b/tests/test_quantum_info_superoperator_transformations.py @@ -3,6 +3,7 @@ from qibo import matrices from qibo.config import PRECISION_TOL +from qibo.quantum_info.linalg_operations import partial_trace from qibo.quantum_info.random_ensembles import random_density_matrix, random_statevector from qibo.quantum_info.superoperator_transformations import ( chi_to_choi, @@ -40,6 +41,7 @@ to_choi, to_liouville, to_pauli_liouville, + to_stinespring, unvectorization, vectorization, ) @@ -363,6 +365,25 @@ def test_to_chi(backend, normalize, order, pauli_order): backend.assert_allclose(chi, test_chi, atol=PRECISION_TOL) +@pytest.mark.parametrize("test_a0", [test_a0]) +def test_to_stinespring(backend, test_a0): + test_a0_ = backend.cast(test_a0) + state = random_density_matrix(2**1, seed=8, backend=backend) + + target = test_a0_ @ state @ backend.np.conj(test_a0_.T) + + environment = (1, 2) + + global_state = backend.identity_density_matrix(len(environment), normalize=True) + global_state = backend.np.kron(state, global_state) + + stinespring = to_stinespring(test_a0_, (0,), len(environment) + 1, backend=backend) + stinespring = stinespring @ global_state @ backend.np.conj(stinespring.T) + stinespring = partial_trace(stinespring, traced_qubits=environment, backend=backend) + + backend.assert_allclose(stinespring, target, atol=PRECISION_TOL) + + @pytest.mark.parametrize("test_superop", [test_superop]) @pytest.mark.parametrize("order", ["row", "column"]) def test_choi_to_liouville(backend, order, test_superop): From fa1a24a0784f970cd52ede0d2e7d7754c375932d Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Wed, 16 Oct 2024 15:50:06 +0400 Subject: [PATCH 5/9] fix coverage --- tests/test_quantum_info_superoperator_transformations.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/test_quantum_info_superoperator_transformations.py b/tests/test_quantum_info_superoperator_transformations.py index 4938071631..5df46b4e40 100644 --- a/tests/test_quantum_info_superoperator_transformations.py +++ b/tests/test_quantum_info_superoperator_transformations.py @@ -365,8 +365,9 @@ def test_to_chi(backend, normalize, order, pauli_order): backend.assert_allclose(chi, test_chi, atol=PRECISION_TOL) +@pytest.mark.parametrize("partition", [None, (0,)]) @pytest.mark.parametrize("test_a0", [test_a0]) -def test_to_stinespring(backend, test_a0): +def test_to_stinespring(backend, test_a0, partition): test_a0_ = backend.cast(test_a0) state = random_density_matrix(2**1, seed=8, backend=backend) @@ -377,7 +378,9 @@ def test_to_stinespring(backend, test_a0): global_state = backend.identity_density_matrix(len(environment), normalize=True) global_state = backend.np.kron(state, global_state) - stinespring = to_stinespring(test_a0_, (0,), len(environment) + 1, backend=backend) + stinespring = to_stinespring( + test_a0_, partition=partition, nqubits=len(environment) + 1, backend=backend + ) stinespring = stinespring @ global_state @ backend.np.conj(stinespring.T) stinespring = partial_trace(stinespring, traced_qubits=environment, backend=backend) From a1062b43880cbfb4d8be726251f9f121d9d7eaaa Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 28 Oct 2024 05:18:10 +0000 Subject: [PATCH 6/9] Update src/qibo/quantum_info/superoperator_transformations.py Co-authored-by: Matteo Robbiati <62071516+MatteoRobbiati@users.noreply.github.com> --- src/qibo/quantum_info/superoperator_transformations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/superoperator_transformations.py b/src/qibo/quantum_info/superoperator_transformations.py index 97125ac87e..932162a00f 100644 --- a/src/qibo/quantum_info/superoperator_transformations.py +++ b/src/qibo/quantum_info/superoperator_transformations.py @@ -310,7 +310,7 @@ def to_stinespring( initial_state_env=None, backend=None, ): - """Converts quantum ``channel`` :math:`U` to its Stinespring representation :math:`U_{0}`. + """Convert quantum ``channel`` :math:`U` to its Stinespring representation :math:`U_{0}`. It uses the Kraus representation as an intermediate step. From 78c812ecb701e9aebf526dd139f3d5e90123ed79 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 28 Oct 2024 05:18:18 +0000 Subject: [PATCH 7/9] Update src/qibo/quantum_info/superoperator_transformations.py Co-authored-by: Matteo Robbiati <62071516+MatteoRobbiati@users.noreply.github.com> --- src/qibo/quantum_info/superoperator_transformations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/superoperator_transformations.py b/src/qibo/quantum_info/superoperator_transformations.py index 932162a00f..d79373500b 100644 --- a/src/qibo/quantum_info/superoperator_transformations.py +++ b/src/qibo/quantum_info/superoperator_transformations.py @@ -329,7 +329,7 @@ def to_stinespring( :class:`qibo.backends.GlobalBackend`. Defaults to ``None``. Returns: - ndarray: Quantum channel in its Stinespring representation :math:`U_{0}`. + ndarray: quantum channel in its Stinespring representation :math:`U_{0}`. """ backend = _check_backend(backend) From df84eaa6a90084b7f91b85c1a62cd2413f9a2b13 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 28 Oct 2024 05:18:40 +0000 Subject: [PATCH 8/9] Update tests/test_quantum_info_superoperator_transformations.py Co-authored-by: Matteo Robbiati <62071516+MatteoRobbiati@users.noreply.github.com> --- tests/test_quantum_info_superoperator_transformations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_quantum_info_superoperator_transformations.py b/tests/test_quantum_info_superoperator_transformations.py index 5df46b4e40..03f0ae2baf 100644 --- a/tests/test_quantum_info_superoperator_transformations.py +++ b/tests/test_quantum_info_superoperator_transformations.py @@ -369,7 +369,7 @@ def test_to_chi(backend, normalize, order, pauli_order): @pytest.mark.parametrize("test_a0", [test_a0]) def test_to_stinespring(backend, test_a0, partition): test_a0_ = backend.cast(test_a0) - state = random_density_matrix(2**1, seed=8, backend=backend) + state = random_density_matrix(2, seed=8, backend=backend) target = test_a0_ @ state @ backend.np.conj(test_a0_.T) From 475279b39fc80dd741dd8c19d369f94bc497b4c2 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Mon, 28 Oct 2024 09:21:55 +0400 Subject: [PATCH 9/9] fix docstring --- src/qibo/quantum_info/superoperator_transformations.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/qibo/quantum_info/superoperator_transformations.py b/src/qibo/quantum_info/superoperator_transformations.py index d79373500b..fa7d2902ba 100644 --- a/src/qibo/quantum_info/superoperator_transformations.py +++ b/src/qibo/quantum_info/superoperator_transformations.py @@ -318,8 +318,8 @@ def to_stinespring( channel (ndarray): quantum channel. nqubits (int, optional): total number of qubits in the system that is interacting with the environment. Must be equal or greater than - the number of qubits ``kraus_ops`` acts on. If ``None``, - defaults to the number of qubits in ``kraus_ops``. + the number of qubits ``channel`` acts on. If ``None``, + defaults to the number of qubits in ``channel``. Defauts to ``None``. initial_state_env (ndarray, optional): statevector representing the initial state of the enviroment. If ``None``, it assumes the @@ -329,7 +329,7 @@ def to_stinespring( :class:`qibo.backends.GlobalBackend`. Defaults to ``None``. Returns: - ndarray: quantum channel in its Stinespring representation :math:`U_{0}`. + ndarray: Quantum channel in its Stinespring representation :math:`U_{0}`. """ backend = _check_backend(backend)