Skip to content

Commit

Permalink
Merge pull request #996 from qiboteam/stinespring
Browse files Browse the repository at this point in the history
Include `stinespring` representation in `random_quantum_channel`
  • Loading branch information
renatomello authored Sep 23, 2023
2 parents 460ec88 + a1b093e commit b713021
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 5 deletions.
45 changes: 41 additions & 4 deletions src/qibo/quantum_info/random_ensembles.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -16,6 +14,7 @@
choi_to_kraus,
choi_to_liouville,
choi_to_pauli,
choi_to_stinespring,
vectorization,
)

Expand Down Expand Up @@ -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)
Expand All @@ -206,6 +207,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,
):
Expand All @@ -220,7 +224,8 @@ def random_quantum_channel(
returns Liouville representation. If ``"pauli"``, returns Pauli-Liouville
representation. If "pauli-<pauli_order>" or "chi-<pauli_order>", (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
Expand All @@ -236,6 +241,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``.
Expand All @@ -252,7 +272,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
Expand Down Expand Up @@ -296,6 +323,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

Expand Down
11 changes: 10 additions & 1 deletion tests/test_quantum_info_random.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,16 @@ def test_random_unitary(backend):
@pytest.mark.parametrize("measure", [None, "haar"])
@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):
with pytest.raises(TypeError):
Expand Down

0 comments on commit b713021

Please sign in to comment.