diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 28659812dd..41e4c04179 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: - id: isort args: ["--profile", "black"] - repo: https://github.com/asottile/pyupgrade - rev: v3.10.1 + rev: v3.11.0 hooks: - id: pyupgrade - repo: https://github.com/hadialqattan/pycln diff --git a/README.md b/README.md index a96583f00c..bdb1e6f4f8 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ ![Tests](https://github.com/qiboteam/qibo/workflows/Tests/badge.svg) [![codecov](https://codecov.io/gh/qiboteam/qibo/branch/master/graph/badge.svg?token=1EKZKVEVX0)](https://codecov.io/gh/qiboteam/qibo) [![DOI](https://zenodo.org/badge/241307936.svg)](https://zenodo.org/badge/latestdoi/241307936) +[![Matrix](https://img.shields.io/matrix/qibo%3Amatrix.org?logo=matrix)](https://matrix.to/#/#qibo:matrix.org) Qibo is an open-source full stack API for quantum simulation and quantum hardware control. @@ -51,6 +52,12 @@ In both cases, the simulation will run in a single device CPU or GPU in double p If you use the package please refer to [the documentation](https://qibo.science/qibo/stable/appendix/citing-qibo.html#publications) for citation instructions. +## Contacts + +To get in touch with the community and the developers, consider joining the Qibo workspace on Matrix: + +https://matrix.to/#/#qibo:matrix.org + ## Supporters and collaborators - Quantum Research Center, Technology Innovation Institute (TII), United Arab Emirates diff --git a/src/qibo/quantum_info/random_ensembles.py b/src/qibo/quantum_info/random_ensembles.py index 85fe7d964b..1f7a653dfe 100644 --- a/src/qibo/quantum_info/random_ensembles.py +++ b/src/qibo/quantum_info/random_ensembles.py @@ -4,8 +4,6 @@ from typing import Optional, Union import numpy as np -from scipy import stats -from scipy.linalg import expm from qibo import Circuit, gates from qibo.backends import GlobalBackend, NumpyBackend @@ -16,6 +14,7 @@ choi_to_kraus, choi_to_liouville, choi_to_pauli, + choi_to_stinespring, vectorization, ) @@ -192,6 +191,8 @@ def random_unitary(dims: int, measure: Optional[str] = None, seed=None, backend= R = np.diag(D) unitary = np.dot(Q, R) elif measure is None: + from scipy.linalg import expm + H = random_hermitian(dims, seed=seed, backend=NumpyBackend()) unitary = expm(-1.0j * H / 2) unitary = backend.cast(unitary, dtype=unitary.dtype) @@ -207,6 +208,9 @@ def random_quantum_channel( order: str = "row", normalize: bool = False, precision_tol: Optional[float] = None, + validate_cp: bool = True, + nqubits: Optional[int] = None, + initial_state_env=None, seed=None, backend=None, ): @@ -221,7 +225,8 @@ def random_quantum_channel( returns Liouville representation. If ``"pauli"``, returns Pauli-Liouville representation. If "pauli-" or "chi-", (e.g. "pauli-IZXY"), returns it in the Pauli basis with the corresponding order of single-qubit Pauli elements - (see :func:`qibo.quantum_info.pauli_basis`). Defaults to ``"liouville"``. + (see :func:`qibo.quantum_info.pauli_basis`). If ``"stinespring"``, + returns random channel in the Stinespring representation. Defaults to ``"liouville"``. measure (str, optional): probability measure in which to sample the unitary from. If ``None``, functions returns :math:`\\exp{(-i \\, H)}`, where :math:`H` is a Hermitian operator. If ``"haar"``, returns an Unitary @@ -240,6 +245,21 @@ def random_quantum_channel( problem. Any eigenvalue :math:`\\lambda <` ``precision_tol`` is set to 0 (zero). If ``None``, ``precision_tol`` defaults to ``qibo.config.PRECISION_TOL=1e-8``. Defaults to ``None``. + validate_cp (bool, optional): used when ``representation="stinespring"``. + If ``True``, checks if the Choi representation of superoperator + used as intermediate step is a completely positive map. + If ``False``, it assumes that it is completely positive (and Hermitian). + Defaults to ``True``. + nqubits (int, optional): used when ``representation="stinespring"``. + Total number of qubits in the system that is interacting with + the environment. Must be equal or greater than the number of + qubits that Kraus representation of the system superoperator acts on. + If ``None``, defaults to the number of qubits in the Kraus operators. + Defauts to ``None``. + initial_state_env (ndarray, optional): used when ``representation="stinespring"``. + Statevector representing the initial state of the enviroment. + If ``None``, it assumes the environment in its ground state. + Defaults to ``None``. seed (int or :class:`numpy.random.Generator`, optional): Either a generator of random numbers or a fixed seed to initialize a generator. If ``None``, initializes a generator with a random seed. Defaults to ``None``. @@ -256,7 +276,14 @@ def random_quantum_channel( f"representation must be type str, but it is type {type(representation)}", ) - if representation not in ["chi", "choi", "kraus", "liouville", "pauli"]: + if representation not in [ + "chi", + "choi", + "kraus", + "liouville", + "pauli", + "stinespring", + ]: if ( ("chi-" not in representation and "pauli-" not in representation) or len(representation.split("-")) != 2 @@ -343,6 +370,16 @@ def random_quantum_channel( pauli_order=pauli_order, backend=backend, ) + elif representation == "stinespring": + super_op = choi_to_stinespring( + super_op, + precision_tol=precision_tol, + order=order, + validate_cp=validate_cp, + nqubits=nqubits, + initial_state_env=initial_state_env, + backend=backend, + ) return super_op diff --git a/tests/test_quantum_info_random.py b/tests/test_quantum_info_random.py index 7abedc5499..0967f7ff7d 100644 --- a/tests/test_quantum_info_random.py +++ b/tests/test_quantum_info_random.py @@ -150,7 +150,16 @@ def test_random_unitary(backend): @pytest.mark.parametrize("measure", [None, "haar", "bcsz"]) @pytest.mark.parametrize( "representation", - ["chi", "chi-IZXY", "choi", "kraus", "liouville", "pauli", "pauli-IZXY"], + [ + "chi", + "chi-IZXY", + "choi", + "kraus", + "liouville", + "pauli", + "pauli-IZXY", + "stinespring", + ], ) def test_random_quantum_channel(backend, representation, measure, rank, order): with pytest.raises(TypeError):