Skip to content

Commit

Permalink
Merge pull request #164 from georgios-ts/fix-is-unitary-channel
Browse files Browse the repository at this point in the history
Fix `is_unitary` for channels.
  • Loading branch information
vprusso committed Jun 2, 2023
2 parents c8890c5 + 1524937 commit 150aa3a
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
28 changes: 26 additions & 2 deletions tests/test_channel_props/test_is_unitary.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,43 @@

from toqito.channel_props import is_unitary
from toqito.channels import depolarizing
from toqito.perms import swap_operator


def test_is_completely_positive_kraus_false():
def test_is_unitary_identity_channel_true():
"""Verify that the identity channel is a unitary channel."""
kraus_ops = [[np.identity(2), np.identity(2)]]

np.testing.assert_equal(is_unitary(kraus_ops), True)


def test_is_completely_positive_choi_true():
def test_is_unitary_depolarizing_false():
"""Verify that the Choi matrix of the depolarizing map is not a unitary channel."""
np.testing.assert_equal(is_unitary(depolarizing(2)), False)


def test_is_unitary_isometry_false():
"""Verify that an isometry is not a unitary channel."""
kraus_ops = [np.array([[1, 0, 0], [0, 1, 0]])]
np.testing.assert_equal(is_unitary(kraus_ops), False)


def test_is_unitary_cp_channel_false():
"""Verify that a CP channel with two kraus ops is not a unitary channel."""
kraus_ops = [np.identity(2), np.array([[0, 1], [1, 0]])]
np.testing.assert_equal(is_unitary(kraus_ops), False)


def test_is_unitary_false():
"""Verify that a channel with one left and right kraus ops is not a unitary channel."""
kraus_ops = [[np.identity(2), np.array([[0, 1], [1, 0]])]]
np.testing.assert_equal(is_unitary(kraus_ops), False)


def test_is_unitary_transpose_map_false():
"""Verify that the channel that transposes 3x2 matrices is not unitary."""
np.testing.assert_equal(is_unitary(swap_operator([2, 3])), False)


if __name__ == "__main__":
np.testing.run_module_suite()
24 changes: 20 additions & 4 deletions toqito/channel_props/is_unitary.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import numpy as np

from toqito.channel_ops import choi_to_kraus
from toqito.matrix_props import is_unitary as is_unitary_matrix


def is_unitary(phi: np.ndarray | list[list[np.ndarray]]) -> bool:
Expand Down Expand Up @@ -68,7 +69,22 @@ def is_unitary(phi: np.ndarray | list[list[np.ndarray]]) -> bool:
# If the variable `phi` is provided as a ndarray, we assume this is a
# Choi matrix.
if isinstance(phi, np.ndarray):
phi = choi_to_kraus(phi)

# If the length of the list of krauss operarator is equal to one, the channel is unitary.
return len(phi) == 1
try:
phi = choi_to_kraus(phi)
except ValueError:
# if we fail to obtain a Kraus representation then input/ouput spaces might be
# non squares or their dimensions are not equal. Hence the channel is not unitary.
return False

# If there is a unique Kraus operator and it's a unitary matrix then the channel is unitary.
if len(phi) != 1:
return False

u_mat = phi[0]
if isinstance(phi[0], list):
# we enter here if phi is specified as: [[U, U]] or [[U]]
u_mat = phi[0][0]
if len(phi[0]) > 2 or (len(phi[0]) == 2 and not np.allclose(phi[0][0], phi[0][1])):
return False

return is_unitary_matrix(u_mat)

0 comments on commit 150aa3a

Please sign in to comment.