Source code for toqito.channel_props.is_unitary

"""Determines if a channel is unitary."""

import numpy as np

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


[docs] def is_unitary(phi: np.ndarray | list[list[np.ndarray]]) -> bool: r"""Given a quantum channel, determine if it is unitary. (Section 2.2.1: Definitions and Basic Notions Concerning Channels from [@Watrous_2018_TQI]). Let \(\mathcal{X}\) be a complex Euclidean space an let \(U \in U(\mathcal{X})\) be a unitary operator. Then a unitary channel is defined as: \[ \Phi(X) = U X U^*. \] Examples: The identity channel is one example of a unitary channel: \[ U = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}. \] We can verify this as follows: ```python exec="1" source="above" import numpy as np from toqito.channel_props import is_unitary kraus_ops = [[np.identity(2), np.identity(2)]] print(is_unitary(kraus_ops)) ``` We can also specify the input as a Choi matrix. For instance, consider the Choi matrix corresponding to the \(2\)-dimensional completely depolarizing channel. \[ \Omega = \frac{1}{2} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix}. \] We may verify that this channel is not a unitary channel. ```python exec="1" source="above" from toqito.channels import depolarizing from toqito.channel_props import is_unitary print(is_unitary(depolarizing(2))) ``` Args: phi: The channel provided as either a Choi matrix or a list of Kraus operators. Returns: `True` if the channel is a unitary channel, and `False` otherwise. """ # If the variable `phi` is provided as a ndarray, we assume this is a # Choi matrix. if isinstance(phi, np.ndarray): 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)