Skip to content

Commit

Permalink
Channel matrix -> superoperator (#4433)
Browse files Browse the repository at this point in the history
Implements results of [this vote](#4179 (comment)). The vote will also affect the name of the corresponding protocol, but it is WIP.
  • Loading branch information
viathor committed Aug 18, 2021
1 parent ac873c6 commit 601a923
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 16 deletions.
2 changes: 2 additions & 0 deletions cirq-core/cirq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,11 @@
fidelity,
kraus_to_channel_matrix,
kraus_to_choi,
kraus_to_superoperator,
one_hot,
operation_to_channel_matrix,
operation_to_choi,
operation_to_superoperator,
QUANTUM_STATE_LIKE,
QuantumState,
quantum_state,
Expand Down
2 changes: 2 additions & 0 deletions cirq-core/cirq/qis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
from cirq.qis.channels import (
kraus_to_channel_matrix,
kraus_to_choi,
kraus_to_superoperator,
operation_to_channel_matrix,
operation_to_choi,
operation_to_superoperator,
)

from cirq.qis.clifford_tableau import CliffordTableau
Expand Down
31 changes: 28 additions & 3 deletions cirq-core/cirq/qis/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import numpy as np

from cirq import protocols
from cirq._compat import deprecated


def kraus_to_choi(kraus_operators: Sequence[np.ndarray]) -> np.ndarray:
Expand All @@ -29,7 +30,13 @@ def kraus_to_choi(kraus_operators: Sequence[np.ndarray]) -> np.ndarray:
return c


@deprecated(deadline='v0.14', fix='use cirq.kraus_to_superoperator instead')
def kraus_to_channel_matrix(kraus_operators: Sequence[np.ndarray]) -> np.ndarray:
"""Returns the matrix representation of the linear map with given Kraus operators."""
return kraus_to_superoperator(kraus_operators)


def kraus_to_superoperator(kraus_operators: Sequence[np.ndarray]) -> np.ndarray:
"""Returns the matrix representation of the linear map with given Kraus operators."""
d_out, d_in = kraus_operators[0].shape
m = np.zeros((d_out * d_out, d_in * d_in), dtype=np.complex128)
Expand All @@ -39,7 +46,7 @@ def kraus_to_channel_matrix(kraus_operators: Sequence[np.ndarray]) -> np.ndarray


def operation_to_choi(operation: 'protocols.SupportsChannel') -> np.ndarray:
r"""Returns the unique Choi matrix associated with a superoperator.
r"""Returns the unique Choi matrix associated with an operation .
Choi matrix J(E) of a linear map E: L(H1) -> L(H2) which takes linear operators
on Hilbert space H1 to linear operators on Hilbert space H2 is defined as
Expand All @@ -60,8 +67,26 @@ def operation_to_choi(operation: 'protocols.SupportsChannel') -> np.ndarray:
return kraus_to_choi(protocols.kraus(operation))


@deprecated(deadline='v0.14', fix='use cirq.operation_to_superoperator instead')
def operation_to_channel_matrix(operation: 'protocols.SupportsChannel') -> np.ndarray:
"""Returns the matrix representation of a superoperator in standard basis.
"""Returns the matrix representation of an operation in standard basis.
Let E: L(H1) -> L(H2) denote a linear map which takes linear operators on Hilbert space H1
to linear operators on Hilbert space H2 and let d1 = dim H1 and d2 = dim H2. Also, let Fij
denote an operator whose matrix has one in ith row and jth column and zeros everywhere else.
Note that d1-by-d1 operators Fij form a basis of L(H1). Similarly, d2-by-d2 operators Fij
form a basis of L(H2). This function returns the matrix of E in these bases.
Args:
operation: Quantum channel.
Returns:
Matrix representation of operation.
"""
return operation_to_superoperator(operation)


def operation_to_superoperator(operation: 'protocols.SupportsChannel') -> np.ndarray:
"""Returns the matrix representation of an operation in standard basis.
Let E: L(H1) -> L(H2) denote a linear map which takes linear operators on Hilbert space H1
to linear operators on Hilbert space H2 and let d1 = dim H1 and d2 = dim H2. Also, let Fij
Expand All @@ -74,4 +99,4 @@ def operation_to_channel_matrix(operation: 'protocols.SupportsChannel') -> np.nd
Returns:
Matrix representation of operation.
"""
return kraus_to_channel_matrix(protocols.kraus(operation))
return kraus_to_superoperator(protocols.kraus(operation))
29 changes: 16 additions & 13 deletions cirq-core/cirq/qis/channels_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def compute_choi(channel: cirq.SupportsChannel) -> np.ndarray:
return c


def compute_channel_matrix(channel: cirq.SupportsChannel) -> np.ndarray:
def compute_superoperator(channel: cirq.SupportsChannel) -> np.ndarray:
ks = cirq.kraus(channel)
d_out, d_in = ks[0].shape
m = np.zeros((d_out * d_out, d_in * d_in), dtype=np.complex128)
Expand Down Expand Up @@ -102,7 +102,7 @@ def test_choi_for_completely_dephasing_channel():


@pytest.mark.parametrize(
'kraus_operators, expected_channel_matrix',
'kraus_operators, expected_superoperator',
(
([np.eye(2)], np.eye(4)),
(
Expand All @@ -125,9 +125,11 @@ def test_choi_for_completely_dephasing_channel():
),
),
)
def test_kraus_to_channel_matrix(kraus_operators, expected_channel_matrix):
"""Verifies that cirq.kraus_to_channel_matrix computes the correct channel matrix."""
assert np.allclose(cirq.kraus_to_channel_matrix(kraus_operators), expected_channel_matrix)
def test_kraus_to_superoperator(kraus_operators, expected_superoperator):
"""Verifies that cirq.kraus_to_superoperator computes the correct channel matrix."""
assert np.allclose(cirq.kraus_to_superoperator(kraus_operators), expected_superoperator)
with cirq.testing.assert_deprecated(deadline='v0.14'):
assert np.allclose(cirq.kraus_to_channel_matrix(kraus_operators), expected_superoperator)


@pytest.mark.parametrize(
Expand All @@ -141,13 +143,14 @@ def test_kraus_to_channel_matrix(kraus_operators, expected_channel_matrix):
cirq.amplitude_damp(0.2),
),
)
def test_operation_to_channel_matrix(channel):
"""Verifies that cirq.channel_matrix correctly computes the channel matrix."""
actual = cirq.operation_to_channel_matrix(channel)
expected = compute_channel_matrix(channel)
assert np.all(actual == expected)
def test_operation_to_superoperator(channel):
"""Verifies that cirq.operation_to_superoperator correctly computes the channel matrix."""
expected = compute_superoperator(channel)
assert np.all(expected == cirq.operation_to_superoperator(channel))
with cirq.testing.assert_deprecated(deadline='v0.14'):
assert np.all(expected == cirq.operation_to_channel_matrix(channel))


def test_channel_matrix_for_completely_dephasing_channel():
"""Checks cirq.operation_to_channel_matrix on the completely dephasing channel."""
assert np.all(cirq.operation_to_channel_matrix(cirq.phase_damp(1)) == np.diag([1, 0, 0, 1]))
def test_superoperator_for_completely_dephasing_channel():
"""Checks cirq.operation_to_superoperator on the completely dephasing channel."""
assert np.all(cirq.operation_to_superoperator(cirq.phase_damp(1)) == np.diag([1, 0, 0, 1]))

0 comments on commit 601a923

Please sign in to comment.