From b14b1cc594c5893cbbd74ab8feae263e0c966971 Mon Sep 17 00:00:00 2001 From: Canoming Date: Mon, 5 Feb 2024 16:06:39 +0800 Subject: [PATCH 01/15] minor fix: [@BrunoLiegiBastonLiegi](https://github.com/qiboteam/qibo/pull/1137#discussion_r1475722863) --- src/qibo/quantum_info/quantum_networks.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index af549a46fa..89c9a6a8e2 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -42,7 +42,7 @@ def __init__( self.partition = partition self.system_output = system_output self._pure = pure - self._backend = backend + self._backend = backend if backend is not None else GlobalBackend() self.dims = reduce(mul, self.partition) self._set_tensor_and_parameters() @@ -211,7 +211,7 @@ def causal( return float(norm) <= precision_tol def positive_semidefinite(self, precision_tol: float = 1e-8): - """Returns bool indicating if Choi operator :math:`\\mathcal{E}` of the networn is positive-semidefinite. + """Returns bool indicating if Choi operator :math:`\\mathcal{E}` of the network is positive-semidefinite. Args: precision_tol (float, optional): threshold value used to check if eigenvalues of @@ -478,20 +478,12 @@ def __truediv__(self, number: Union[float, int]): "It is not possible to divide a ``QuantumNetwork`` by a non-scalar.", ) - if self.pure() and number > 0.0: - return QuantumNetwork( - self.matrix(backend=self._backend) / np.sqrt(number), - partition=self.partition, - system_output=self.system_output, - pure=True, - backend=self._backend, - ) - + number = np.sqrt(number) if self.pure() and number > 0.0 else number return QuantumNetwork( self.matrix(backend=self._backend) / number, partition=self.partition, system_output=self.system_output, - pure=False, + pure=self.pure(), backend=self._backend, ) From f0ba5adfa670cb61d145aff353b5f04a3f4d179a Mon Sep 17 00:00:00 2001 From: Canoming Date: Mon, 5 Feb 2024 22:16:48 +0800 Subject: [PATCH 02/15] update doc strings for `QuantumNetwork` --- src/qibo/quantum_info/quantum_networks.py | 34 ++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index 89c9a6a8e2..f7ea285373 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -1,4 +1,4 @@ -"""Module defining the QuantumNetwork class and adjacent functions.""" +"""Module defining the `QuantumNetwork` class and adjacent functions.""" import re from functools import reduce @@ -12,7 +12,19 @@ class QuantumNetwork: - """Quantum network object that holds a Choi operator as a tensor. + """ Quantum network that unifies the representation of quantum states, channels, + observables, and higher-order quantum operators [1]_. The class stores the Choi operator of + the quantum network as a tensor, which is an unique representation of the quantum network. + + A minimum quantum network is a quantum channel, which is a quantum network of the form + `J[n -> m]`, where `n` is the dimension of the input system and `m` is the dimension of the + output system. A quantum state is a quantum network of the form `J[1 -> n]`, such that the + input system is trivial. An observable is a quantum network of the form `J[n -> 1]`, such that + the output system is trivial. + + A quantum network may contain multipy input systems and output systems. For example, a + "quantum comb" is a quantum network of the form `J[n', n -> m, m']`, which convert a quantum + channel of the form `J[n -> m]` to a quantum channel of the form `J[n' -> m']`. Args: matrix (ndarray): input Choi operator. @@ -21,11 +33,15 @@ class QuantumNetwork: Choi operator. If ``None``, defaults to ``(False,True,False,True,...)``, where ``len(system_output)=len(partition)``. Defaults to ``None``. - pure (bool, optional): ``True`` when ``matrix`` is a rank-:math:`1` operator, - ``False`` otherwise. Defaults to ``False``. + pure (bool, optional): ``True`` when ``matrix`` is a "pure" representation (e.g. a pure + state, a unitary operator, etc.), ``False`` otherwise. Defaults to ``False``. backend (:class:`qibo.backends.abstract.Backend`, optional): Backend to be used in calculations. If ``None``, defaults to :class:`qibo.backends.GlobalBackend`. Defaults to ``None``. + + References: + 1. G. Chiribella *et al.*, *Theoretical framework for quantum networks.* + `Physical Review A 80.2 (2009): 022339 `. """ def __init__( @@ -426,6 +442,11 @@ def __add__(self, second_network): def __mul__(self, number: Union[float, int]): """Returns quantum network with its Choi operator multiplied by a scalar. + If the quantum network is pure and ``number > 0.0``, the method returns a pure quantum + network with its Choi operator multiplied by the square root of ``number``. + This is equivelant to multiplying `self.to_full()` by the ``number``. + Otherwise, this method will return a full quantum network. + Args: number (float or int): scalar to multiply the Choi operator of the network with. @@ -465,6 +486,11 @@ def __rmul__(self, number: Union[float, int]): def __truediv__(self, number: Union[float, int]): """Returns quantum network with its Choi operator divided by a scalar. + If the quantum network is pure and ``number > 0.0``, the method returns a pure quantum + network with its Choi operator divided by the square root of ``number``. + This is equivelant to dividing `self.to_full()` by the ``number``. + Otherwise, this method will return a full quantum network. + Args: number (float or int): scalar to divide the Choi operator of the network with. From 09256fcc71c09037cf23ac93c18e4d049e5fda65 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:42:32 +0000 Subject: [PATCH 03/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/qibo/quantum_info/quantum_networks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index f7ea285373..41c4c4acd4 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -12,7 +12,7 @@ class QuantumNetwork: - """ Quantum network that unifies the representation of quantum states, channels, + """Quantum network that unifies the representation of quantum states, channels, observables, and higher-order quantum operators [1]_. The class stores the Choi operator of the quantum network as a tensor, which is an unique representation of the quantum network. From a0a4c5321e63ee81e150215801fec8c5e36fbaaf Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Tue, 6 Feb 2024 08:33:24 +0400 Subject: [PATCH 04/15] small fixes --- src/qibo/quantum_info/quantum_networks.py | 64 +++++++++++---------- tests/test_quantum_info_quantum_networks.py | 28 ++++----- 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index 41c4c4acd4..5ae8902d43 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -12,19 +12,24 @@ class QuantumNetwork: - """Quantum network that unifies the representation of quantum states, channels, - observables, and higher-order quantum operators [1]_. The class stores the Choi operator of - the quantum network as a tensor, which is an unique representation of the quantum network. + """Quantum network is an object that unifies the representation of quantum states, channels, + observables, and higher-order quantum operators [1]. - A minimum quantum network is a quantum channel, which is a quantum network of the form - `J[n -> m]`, where `n` is the dimension of the input system and `m` is the dimension of the - output system. A quantum state is a quantum network of the form `J[1 -> n]`, such that the - input system is trivial. An observable is a quantum network of the form `J[n -> 1]`, such that - the output system is trivial. + This class stores the Choi operator of the quantum network as a tensor, + which is an unique representation of the quantum network. - A quantum network may contain multipy input systems and output systems. For example, a - "quantum comb" is a quantum network of the form `J[n', n -> m, m']`, which convert a quantum - channel of the form `J[n -> m]` to a quantum channel of the form `J[n' -> m']`. + A minimum quantum network is a quantum channel, which is a quantum network of the form + :math:`J[n \\to m]`, where :math:`n` is the dimension of the input system , + and :math:`m` is the dimension of the output system. + A quantum state is a quantum network of the form :math:`J[1 \\to n]`, + such that the input system is trivial. + An observable is a quantum network of the form :math:`J[n \\to 1]`, + such that the output system is trivial. + + A quantum network may contain multiple input and output systems. + For example, a "quantum comb" is a quantum network of the form :math:`J[n', n \\to m, m']`, + which convert a quantum channel of the form :math:`J[n \\to m]` + to a quantum channel of the form :math:`J[n' \\to m']`. Args: matrix (ndarray): input Choi operator. @@ -41,7 +46,7 @@ class QuantumNetwork: References: 1. G. Chiribella *et al.*, *Theoretical framework for quantum networks.* - `Physical Review A 80.2 (2009): 022339 `. + `Physical Review A 80.2 (2009): 022339 `_. """ def __init__( @@ -58,7 +63,7 @@ def __init__( self.partition = partition self.system_output = system_output self._pure = pure - self._backend = backend if backend is not None else GlobalBackend() + self._backend = backend self.dims = reduce(mul, self.partition) self._set_tensor_and_parameters() @@ -80,11 +85,11 @@ def matrix(self, backend=None): return backend.cast(self._matrix, dtype=self._matrix.dtype) - def pure(self): + def is_pure(self): """Returns bool indicading if the Choi operator of the network is pure.""" return self._pure - def hermitian( + def is_hermitian( self, order: Optional[Union[int, str]] = None, precision_tol: float = 1e-8 ): """Returns bool indicating if the Choi operator :math:`\\mathcal{E}` of the network is Hermitian. @@ -130,7 +135,7 @@ def hermitian( return float(norm) <= precision_tol - def unital( + def is_unital( self, order: Optional[Union[int, str]] = None, precision_tol: float = 1e-8 ): """Returns bool indicating if the Choi operator :math:`\\mathcal{E}` of the network is unital. @@ -178,7 +183,7 @@ def unital( return float(norm) <= precision_tol - def causal( + def is_causal( self, order: Optional[Union[int, str]] = None, precision_tol: float = 1e-8 ): """Returns bool indicating if the Choi operator :math:`\\mathcal{E}` of the network satisfies the causal order condition. @@ -226,7 +231,7 @@ def causal( return float(norm) <= precision_tol - def positive_semidefinite(self, precision_tol: float = 1e-8): + def is_positive_semidefinite(self, precision_tol: float = 1e-8): """Returns bool indicating if Choi operator :math:`\\mathcal{E}` of the network is positive-semidefinite. Args: @@ -244,7 +249,7 @@ def positive_semidefinite(self, precision_tol: float = 1e-8): reshaped = np.reshape(self._matrix, (self.dims, self.dims)) - if self.hermitian(): + if self.is_hermitian(): eigenvalues = np.linalg.eigvalsh(reshaped) else: if self._backend.__class__.__name__ in [ @@ -256,7 +261,7 @@ def positive_semidefinite(self, precision_tol: float = 1e-8): return all(eigenvalue >= -precision_tol for eigenvalue in eigenvalues) - def channel( + def is_channel( self, order: Optional[Union[int, str]] = None, precision_tol_causal: float = 1e-8, @@ -279,9 +284,9 @@ def channel( Returns: bool: Channel condition. """ - return self.causal(order, precision_tol_causal) and self.positive_semidefinite( - precision_tol_psd - ) + return self.is_causal( + order, precision_tol_causal + ) and self.is_positive_semidefinite(precision_tol_psd) def apply(self, state): """Apply the Choi operator :math:`\\mathcal{E}` to ``state`` :math:`\\varrho`. @@ -296,7 +301,7 @@ def apply(self, state): """ matrix = np.copy(self._matrix) - if self.pure(): + if self.is_pure(): return np.einsum("kj,ml,jl -> km", matrix, np.conj(matrix), state) return np.einsum("jklm,km -> jl", matrix, state) @@ -392,7 +397,7 @@ def to_full(self, backend=None): if backend is None: # pragma: no cover backend = self._backend - if self.pure(): + if self.is_pure(): self._matrix = self._full() self._pure = False @@ -460,7 +465,7 @@ def __mul__(self, number: Union[float, int]): "It is not possible to multiply a ``QuantumNetwork`` by a non-scalar.", ) - if self.pure() and number > 0.0: + if self.is_pure() and number > 0.0: return QuantumNetwork( np.sqrt(number) * self.matrix(backend=self._backend), partition=self.partition, @@ -504,12 +509,13 @@ def __truediv__(self, number: Union[float, int]): "It is not possible to divide a ``QuantumNetwork`` by a non-scalar.", ) - number = np.sqrt(number) if self.pure() and number > 0.0 else number + number = np.sqrt(number) if self.is_pure() and number > 0.0 else number + return QuantumNetwork( self.matrix(backend=self._backend) / number, partition=self.partition, system_output=self.system_output, - pure=self.pure(), + pure=self.is_pure(), backend=self._backend, ) @@ -643,7 +649,7 @@ def _set_tensor_and_parameters(self): def _full(self): """Reshapes input matrix based on purity.""" matrix = np.copy(self._matrix) - if self.pure(): + if self.is_pure(): matrix = np.einsum("jk,lm -> kjml", matrix, np.conj(matrix)) return matrix diff --git a/tests/test_quantum_info_quantum_networks.py b/tests/test_quantum_info_quantum_networks.py index a84103ece5..e02537eae1 100644 --- a/tests/test_quantum_info_quantum_networks.py +++ b/tests/test_quantum_info_quantum_networks.py @@ -46,13 +46,13 @@ def test_errors(backend): QuantumNetwork(channel.to_choi(backend=backend), partition=(1, 2), pure="True") with pytest.raises(ValueError): - network.hermitian(precision_tol=-1e-8) + network.is_hermitian(precision_tol=-1e-8) with pytest.raises(ValueError): - network.unital(precision_tol=-1e-8) + network.is_unital(precision_tol=-1e-8) with pytest.raises(ValueError): - network.causal(precision_tol=-1e-8) + network.is_causal(precision_tol=-1e-8) with pytest.raises(TypeError): network + 1 @@ -155,11 +155,11 @@ def test_parameters(backend): backend.assert_allclose(network.partition, partition) backend.assert_allclose(network.system_output, (False, True)) - assert network.causal() - assert network.unital() - assert network.hermitian() - assert network.positive_semidefinite() - assert network.channel() + assert network.is_causal() + assert network.is_unital() + assert network.is_hermitian() + assert network.is_positive_semidefinite() + assert network.is_channel() def test_with_states(backend): @@ -186,8 +186,8 @@ def test_with_states(backend): state_output_link.matrix(backend=backend).reshape((dims, dims)), state_output ) - assert network_state.hermitian() - assert network_state.positive_semidefinite() + assert network_state.is_hermitian() + assert network_state.is_positive_semidefinite() @pytest.mark.parametrize("subscript", ["jk,kl->jl", "jk,lj->lk"]) @@ -265,9 +265,9 @@ def test_non_hermitian_and_prints(backend): matrix = random_gaussian_matrix(dims**2, backend=backend) network = QuantumNetwork(matrix, (dims, dims), pure=False, backend=backend) - assert not network.hermitian() - assert not network.causal() - assert not network.positive_semidefinite() - assert not network.channel() + assert not network.is_hermitian() + assert not network.is_causal() + assert not network.is_positive_semidefinite() + assert not network.is_channel() assert network.__str__() == "J[4 -> 4]" From a87ef8509220d93a166d76fc779a12eec3d0216a Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Tue, 6 Feb 2024 09:43:14 +0400 Subject: [PATCH 05/15] move couple of lines to `qibo.rst` --- doc/source/api-reference/qibo.rst | 7 +++++++ src/qibo/quantum_info/quantum_networks.py | 9 +-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/source/api-reference/qibo.rst b/doc/source/api-reference/qibo.rst index 980faf2c70..6d83e5446c 100644 --- a/doc/source/api-reference/qibo.rst +++ b/doc/source/api-reference/qibo.rst @@ -1680,6 +1680,13 @@ Frame Potential Quantum Networks ^^^^^^^^^^^^^^^^ +Quantum network is an object that unifies the representation of quantum states, channels, +observables, and higher-order quantum operators. + +For more details, see G. Chiribella *et al.*, *Theoretical framework for quantum networks*, +`Physical Review A 80.2 (2009): 022339 +`_. + .. autoclass:: qibo.quantum_info.quantum_networks.QuantumNetwork :members: :member-order: bysource diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index 5ae8902d43..a5ba0a77af 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -12,10 +12,7 @@ class QuantumNetwork: - """Quantum network is an object that unifies the representation of quantum states, channels, - observables, and higher-order quantum operators [1]. - - This class stores the Choi operator of the quantum network as a tensor, + """This class stores the Choi operator of the quantum network as a tensor, which is an unique representation of the quantum network. A minimum quantum network is a quantum channel, which is a quantum network of the form @@ -43,10 +40,6 @@ class QuantumNetwork: backend (:class:`qibo.backends.abstract.Backend`, optional): Backend to be used in calculations. If ``None``, defaults to :class:`qibo.backends.GlobalBackend`. Defaults to ``None``. - - References: - 1. G. Chiribella *et al.*, *Theoretical framework for quantum networks.* - `Physical Review A 80.2 (2009): 022339 `_. """ def __init__( From 65914fae1e35302b8e2a33e4a5d0b29c6bf05842 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Tue, 6 Feb 2024 11:50:32 +0000 Subject: [PATCH 06/15] Update src/qibo/quantum_info/quantum_networks.py Co-authored-by: Alejandro Sopena <44305203+AlejandroSopena@users.noreply.github.com> --- src/qibo/quantum_info/quantum_networks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index 7dd0a7735b..7e2068a77d 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -442,7 +442,7 @@ def __mul__(self, number: Union[float, int]): If the quantum network is pure and ``number > 0.0``, the method returns a pure quantum network with its Choi operator multiplied by the square root of ``number``. - This is equivelant to multiplying `self.to_full()` by the ``number``. + This is equivalent to multiplying `self.to_full()` by the ``number``. Otherwise, this method will return a full quantum network. Args: From 3abdec788d88604ca7dcb5be1e5bb50c6bb3639f Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Tue, 6 Feb 2024 11:50:38 +0000 Subject: [PATCH 07/15] Update src/qibo/quantum_info/quantum_networks.py Co-authored-by: Alejandro Sopena <44305203+AlejandroSopena@users.noreply.github.com> --- src/qibo/quantum_info/quantum_networks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index 7e2068a77d..91ba7bce2a 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -486,7 +486,7 @@ def __truediv__(self, number: Union[float, int]): If the quantum network is pure and ``number > 0.0``, the method returns a pure quantum network with its Choi operator divided by the square root of ``number``. - This is equivelant to dividing `self.to_full()` by the ``number``. + This is equivalent to dividing `self.to_full()` by the ``number``. Otherwise, this method will return a full quantum network. Args: From 8b6ca7794ba6efeaa18ba27d7086ad004c0a7275 Mon Sep 17 00:00:00 2001 From: Canoming Date: Wed, 7 Feb 2024 00:06:25 +0800 Subject: [PATCH 08/15] correct the behavior of applying a quantum comb to a quantum channel --- src/qibo/quantum_info/quantum_networks.py | 50 +++++++++++++++------ tests/test_quantum_info_quantum_networks.py | 28 ++++++------ 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index 91ba7bce2a..a688800258 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -337,8 +337,8 @@ def link_product(self, second_network, subscripts: str = "ij,jk -> ik"): inv_subscripts = pattern_two and subscripts[0] == subscripts[4] super_subscripts = ( pattern_four - and subscripts[2] == subscripts[5] - and subscripts[3] == subscripts[6] + and subscripts[1] == subscripts[5] + and subscripts[2] == subscripts[6] ) if not channel_subscripts and not inv_subscripts and not super_subscripts: @@ -351,10 +351,10 @@ def link_product(self, second_network, subscripts: str = "ij,jk -> ik"): second_matrix = second_network._full() # pylint: disable=W0212 if super_subscripts: - cexpr = "jklmnopq,nopqrstu->jklmrstu" + cexpr = "jklmnopq,klop->jmnq" return QuantumNetwork( np.einsum(cexpr, first_matrix, second_matrix), - self.partition[:2] + second_network.partition[2:], + [self.partition[0] + self.partition[-1]], ) cexpr = "jkab,klbc->jlac" @@ -532,17 +532,39 @@ def __matmul__(self, second_network): + "``QuantumNetwork`` by a non-``QuantumNetwork``.", ) - if self.partition != second_network.partition: - raise_error( - ValueError, - "partitions of the networks do not match: " - + f"{self.partition} != {second_network.partition}.", - ) + if len(self.partition) == 2: # `self` is a channel + if len(second_network.partition) != 2: + raise_error( + ValueError, + f"`QuantumNetwork {second_network} is assumed to be a channel, but it is not. " + + "Use `link_product` method to specify the subscript.", + ) + if self.partition[1] != second_network.partition[0]: + raise_error( + ValueError, + "partitions of the networks do not match: " + + f"{self.partition[1]} != {second_network.partition[0]}.", + ) - if len(self.partition) == 2: subscripts = "jk,kl -> jl" - elif len(self.partition) == 4: - subscripts = "jklm,lmno -> jkno" + + + elif len(self.partition) == 4: # `self` is a super-channel + if len(second_network.partition) != 2: + raise_error( + ValueError, + f"`QuantumNetwork {second_network} is assumed to be a channel, but it is not. " + + "Use `link_product` method to specify the subscript.", + ) + if self.partition[1] != second_network.partition[0]: + raise_error( + ValueError, + "Systems of the channel do not match the super-channel: " + + f"{self.partition[1], self.partition[2]} != " + + f"{second_network.partition[0],second_network.partition[1]}.", + ) + + subscripts = "jklm,kl -> jm" else: raise_error( NotImplementedError, @@ -652,7 +674,7 @@ def _check_subscript_pattern(self, subscripts: str): """Checks if input subscript match any implemented pattern.""" braket = "[a-z]" pattern_two = re.compile(braket * 2 + "," + braket * 2 + "->" + braket * 2) - pattern_four = re.compile(braket * 4 + "," + braket * 4 + "->" + braket * 4) + pattern_four = re.compile(braket * 4 + "," + braket * 2 + "->" + braket * 2) return bool(re.match(pattern_two, subscripts)), bool( re.match(pattern_four, subscripts) diff --git a/tests/test_quantum_info_quantum_networks.py b/tests/test_quantum_info_quantum_networks.py index e02537eae1..b9d3b214ed 100644 --- a/tests/test_quantum_info_quantum_networks.py +++ b/tests/test_quantum_info_quantum_networks.py @@ -223,25 +223,25 @@ def test_with_unitaries(backend, subscript): def test_with_comb(backend): - subscript = "jklm,lmno->jkno" - partition = (2,) * 4 - sys_out = (False, True) * 2 + subscript = "jklm,kl->jm" + comb_partition = (2,) * 4 + channel_partition = (2,) * 2 + comb_sys_out = (False, True) * 2 + channel_sys_out = (False, True) * 2 comb = random_density_matrix(2**4, backend=backend) - comb_2 = random_density_matrix(2**4, backend=backend) + channel = random_density_matrix(2**2, backend=backend) - comb_choi = QuantumNetwork(comb, partition, system_output=sys_out, backend=backend) - comb_choi_2 = QuantumNetwork( - comb_2, partition, system_output=sys_out, backend=backend - ) - comb_choi_3 = QuantumNetwork( - comb @ comb_2, partition, system_output=sys_out, backend=backend - ).to_full(backend) + comb_choi = QuantumNetwork(comb, comb_partition, system_output=comb_sys_out, backend=backend) + channel_choi = QuantumNetwork(channel, channel_partition, system_output=channel_sys_out, backend=backend) + # channel_choi_2 = QuantumNetwork( + # comb @ channel, comb_partition, system_output=comb_sys_out, backend=backend + # ).to_full(backend) - test = comb_choi.link_product(comb_choi_2, subscript).to_full(backend) + test = comb_choi.link_product(channel_choi, subscript).to_full(backend) - backend.assert_allclose(test, comb_choi_3, atol=1e-5) - backend.assert_allclose(test, (comb_choi @ comb_choi_2).to_full(backend), atol=1e-5) + # backend.assert_allclose(test, comb_choi_3, atol=1e-5) + # backend.assert_allclose(test, (comb_choi @ comb_choi_2).to_full(backend), atol=1e-5) def test_apply(backend): From 2869d3ed6a08c335e0410d1b85100f8beb52bef1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 16:09:52 +0000 Subject: [PATCH 09/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/qibo/quantum_info/quantum_networks.py | 5 ++--- tests/test_quantum_info_quantum_networks.py | 8 ++++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index a688800258..8992169ae5 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -532,7 +532,7 @@ def __matmul__(self, second_network): + "``QuantumNetwork`` by a non-``QuantumNetwork``.", ) - if len(self.partition) == 2: # `self` is a channel + if len(self.partition) == 2: # `self` is a channel if len(second_network.partition) != 2: raise_error( ValueError, @@ -548,8 +548,7 @@ def __matmul__(self, second_network): subscripts = "jk,kl -> jl" - - elif len(self.partition) == 4: # `self` is a super-channel + elif len(self.partition) == 4: # `self` is a super-channel if len(second_network.partition) != 2: raise_error( ValueError, diff --git a/tests/test_quantum_info_quantum_networks.py b/tests/test_quantum_info_quantum_networks.py index b9d3b214ed..18f377eabb 100644 --- a/tests/test_quantum_info_quantum_networks.py +++ b/tests/test_quantum_info_quantum_networks.py @@ -232,8 +232,12 @@ def test_with_comb(backend): comb = random_density_matrix(2**4, backend=backend) channel = random_density_matrix(2**2, backend=backend) - comb_choi = QuantumNetwork(comb, comb_partition, system_output=comb_sys_out, backend=backend) - channel_choi = QuantumNetwork(channel, channel_partition, system_output=channel_sys_out, backend=backend) + comb_choi = QuantumNetwork( + comb, comb_partition, system_output=comb_sys_out, backend=backend + ) + channel_choi = QuantumNetwork( + channel, channel_partition, system_output=channel_sys_out, backend=backend + ) # channel_choi_2 = QuantumNetwork( # comb @ channel, comb_partition, system_output=comb_sys_out, backend=backend # ).to_full(backend) From e6c9809b9662009f2af2fc7ddf0c10ecbae32102 Mon Sep 17 00:00:00 2001 From: Canoming Date: Wed, 7 Feb 2024 14:25:05 +0800 Subject: [PATCH 10/15] update test for combs --- tests/test_quantum_info_quantum_networks.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/test_quantum_info_quantum_networks.py b/tests/test_quantum_info_quantum_networks.py index 18f377eabb..9345ee3ede 100644 --- a/tests/test_quantum_info_quantum_networks.py +++ b/tests/test_quantum_info_quantum_networks.py @@ -88,7 +88,7 @@ def test_errors(backend): with pytest.raises(NotImplementedError): net @ net - with pytest.raises(ValueError): + with pytest.raises(NotImplementedError): net @ network with pytest.raises(ValueError): @@ -227,7 +227,7 @@ def test_with_comb(backend): comb_partition = (2,) * 4 channel_partition = (2,) * 2 comb_sys_out = (False, True) * 2 - channel_sys_out = (False, True) * 2 + channel_sys_out = (False, True) comb = random_density_matrix(2**4, backend=backend) channel = random_density_matrix(2**2, backend=backend) @@ -238,14 +238,11 @@ def test_with_comb(backend): channel_choi = QuantumNetwork( channel, channel_partition, system_output=channel_sys_out, backend=backend ) - # channel_choi_2 = QuantumNetwork( - # comb @ channel, comb_partition, system_output=comb_sys_out, backend=backend - # ).to_full(backend) test = comb_choi.link_product(channel_choi, subscript).to_full(backend) + channel_choi2 = comb_choi @ channel_choi - # backend.assert_allclose(test, comb_choi_3, atol=1e-5) - # backend.assert_allclose(test, (comb_choi @ comb_choi_2).to_full(backend), atol=1e-5) + backend.assert_allclose(test, channel_choi2.to_full(backend), atol=1e-5) def test_apply(backend): From a876281e39a27b316af9ca98caa2d4b98bbc2db5 Mon Sep 17 00:00:00 2001 From: Canoming Date: Wed, 7 Feb 2024 15:32:52 +0800 Subject: [PATCH 11/15] add a tutorial for `QuantumNetwork` --- .../tutorials/quantum_networks/README.md | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 doc/source/code-examples/tutorials/quantum_networks/README.md diff --git a/doc/source/code-examples/tutorials/quantum_networks/README.md b/doc/source/code-examples/tutorials/quantum_networks/README.md new file mode 100644 index 0000000000..8b9f1197c4 --- /dev/null +++ b/doc/source/code-examples/tutorials/quantum_networks/README.md @@ -0,0 +1,126 @@ +# Quantum Networks + +## The Quantum Network Model + +The quantum network model is a mathematical framework that allows us to uniquely describe quantum information processing that involves multiple points in time and space. +Each distinguished point in time and space is treated as a linear system $\mathcal{H}_i$. +A quantum network involving $n$ points in time and space is a Hermitian operator $\mathcal{N}$ that acts on the tensor product of the linear systems $\mathcal{H}_0 \otimes \mathcal{H}_1 \otimes \cdots \otimes \mathcal{H}_{n-1}$. +Each system $\mathcal{H}_i$ is either an input or an output of the network. + +A physically implementable quantum network is described by a semi-positive definite operator $\mathcal{N}$ that satisfies the causal constraints. + +A simple example is a quantum channel $\Gamma: \mathcal{H}_0 \to \mathcal{H}_1$, where $\mathcal{H}_0$ is the input system and $\mathcal{H}_1$ is the output system. +The quantum channel is a linear map, such that it maps any input quantum state to an output quantum state, which is a sufficient and necessary condition for the map to be physical. +A Hermitian operator $J^\Gamma$ acting on $\mathcal{H}_0\otimes \mathcal{H}_1$ is associated with a quantum channel $\Gamma$, if $J^\Gamma$ satisfies the following conditions: +$$ +J^\Gamma \geq 0, \quad \text{and} \quad \text{Tr}_{\mathcal{H}_1} J^\Gamma = \mathbb{I}_{\mathcal{H}_0}. +$$ +The first condition is called *complete positivity*, and the second condition is called *trace-preserving*. +In particular, the second condition ensures that the information of the input system is only accessible through the output system. + +In particular, a quantum state $\rho$ may be also considered as a quantum network, where the input system is the trivial system $\mathbb{C}$, and the output system is the quantum system $\mathcal{H}$. +The constraints on the quantum channels are then equivalent to the constraints on the quantum states: +$$ +\rho \geq 0, \quad \text{and} \quad \text{Tr} \rho = \mathbb{I}_\mathbb{C} = 1. +$$ + +> For more details, see G. Chiribella *et al.*, *Theoretical framework for quantum networks*, +> [Physical Review A 80.2 (2009): 022339](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.80.022339). + +## Quantum Network in `qibo` + +The manipulation of quantum networks in `qibo` is done through the `QuantumNetwork` class. + +```python +from qibo.quantum_info.quantum_networks import QuantumNetwork +``` + +A quantum state is a quantum network with a single input system and a single output system, where the input system is the trivial 1-dimensional system. +We need to specify the dimensions of each system in the `partition` argument. + +```python +from qibo.quantum_info import random_density_matrix, random_unitary + +state = random_density_matrix(2) +state_choi = QuantumNetwork(state, (1,2)) +print(f'A quantum state is a quantum netowrk of the form {state_choi}') +``` + +``` +>>> A quantum state is a quantum netowrk of the form J[1 -> 2] +``` + +A general quantum channel can be created in a similar way. + +```python +from qibo.gates import DepolarizingChannel + +test_ch = DepolarizingChannel(0,0.5) +N = len(test_ch.target_qubits) +partition = (2**N, 2**N) + +depolar_choi = QuantumNetwork(test_ch.to_choi(), partition) +print(f'A quantum channel is a quantum netowrk of the form {depolar_choi}') +``` + +``` +>>> A quantum channel is a quantum netowrk of the form J[2 -> 2] +``` + +One may apply a quantum channel to a quantum state, or compose two quantum channels, using the `@` operator. + +```python +new_state = depolar_choi @ depolar_choi @ state_choi +``` + +## Example + +For 3-dimensional systems, an unital channel may not be a mixed unitary channel. + +> Example 4.3 in (Watrous, John. The theory of quantum information. Cambridge university press, 2018.) + +```python +A1 = np.array([ + [0,0,0], + [0,0,1/np.sqrt(2)], + [0,-1/np.sqrt(2),0], +]) +A2 = np.array([ + [0,0,1/np.sqrt(2)], + [0,0,0], + [-1/np.sqrt(2),0,0], +]) +A3 = np.array([ + [0,1/np.sqrt(2),0], + [-1/np.sqrt(2),0,0], + [0,0,0], +]) + +Choi1 = QuantumNetwork(A1, (3,3), pure=True) * 3 +Choi2 = QuantumNetwork(A2, (3,3), pure=True)*3 +Choi3 = QuantumNetwork(A3, (3,3), pure=True)*3 +``` + +The three channels are pure but not unital. Which means they are not unitary. + +```python +print(f"Choi1 is unital: {Choi1.unital()}") +print(f"Choi2 is unital: {Choi2.unital()}") +print(f"Choi3 is unital: {Choi3.unital()}") +``` + +``` +>>> Choi1 is unital: False +Choi2 is unital: False +Choi3 is unital: False +``` + +However, the mixture of the three operators are unital. +As the matrices are orthogonal, they are the extreme points of the convex set of the unital channels. +Therefore, this mixed channel is not a mixed unitary channel. + +```python +Choi = Choi1/3 + Choi2/3 + Choi3/3 +print(f"The mixed channel is unital: {Choi.unital()}") +``` + From ee58ad83b1c8b787c1eb842a4ab0d988ee7e3693 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 07:35:09 +0000 Subject: [PATCH 12/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/source/code-examples/tutorials/quantum_networks/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/source/code-examples/tutorials/quantum_networks/README.md b/doc/source/code-examples/tutorials/quantum_networks/README.md index 8b9f1197c4..75ca3254f4 100644 --- a/doc/source/code-examples/tutorials/quantum_networks/README.md +++ b/doc/source/code-examples/tutorials/quantum_networks/README.md @@ -123,4 +123,3 @@ Therefore, this mixed channel is not a mixed unitary channel. Choi = Choi1/3 + Choi2/3 + Choi3/3 print(f"The mixed channel is unital: {Choi.unital()}") ``` - From c1cfe94ffc2bd7535905d84c9e050fa562510375 Mon Sep 17 00:00:00 2001 From: Canoming Date: Wed, 7 Feb 2024 19:16:18 +0800 Subject: [PATCH 13/15] fix math rendering in docs --- .../tutorials/quantum_networks/README.md | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/doc/source/code-examples/tutorials/quantum_networks/README.md b/doc/source/code-examples/tutorials/quantum_networks/README.md index 75ca3254f4..26cb7e8752 100644 --- a/doc/source/code-examples/tutorials/quantum_networks/README.md +++ b/doc/source/code-examples/tutorials/quantum_networks/README.md @@ -3,26 +3,27 @@ ## The Quantum Network Model The quantum network model is a mathematical framework that allows us to uniquely describe quantum information processing that involves multiple points in time and space. -Each distinguished point in time and space is treated as a linear system $\mathcal{H}_i$. -A quantum network involving $n$ points in time and space is a Hermitian operator $\mathcal{N}$ that acts on the tensor product of the linear systems $\mathcal{H}_0 \otimes \mathcal{H}_1 \otimes \cdots \otimes \mathcal{H}_{n-1}$. -Each system $\mathcal{H}_i$ is either an input or an output of the network. +Each distinguished point in time and space is treated as a linear system \(\mathcal{H}_ i\). +A quantum network involving $n$ points in time and space is a Hermitian operator \(\mathcal{N}\) that acts on the tensor product of the linear systems \(\mathcal{H}_ 0 \otimes \mathcal{H}_ 1 \otimes \cdots \otimes \mathcal{H}_ {n-1}\). +Each system \(\mathcal{H}_ {i}\) is either an input or an output of the network. -A physically implementable quantum network is described by a semi-positive definite operator $\mathcal{N}$ that satisfies the causal constraints. +A physically implementable quantum network is described by a semi-positive definite operator \(\mathcal{N}\) that satisfies the causal constraints. -A simple example is a quantum channel $\Gamma: \mathcal{H}_0 \to \mathcal{H}_1$, where $\mathcal{H}_0$ is the input system and $\mathcal{H}_1$ is the output system. +A simple example is a quantum channel \(\Gamma: \mathcal{H}_ 0 \to \mathcal{H}_ 1\), where \(\mathcal{H}_ 0\) is the input system and \(\mathcal{H}_ 1\) is the output system. The quantum channel is a linear map, such that it maps any input quantum state to an output quantum state, which is a sufficient and necessary condition for the map to be physical. -A Hermitian operator $J^\Gamma$ acting on $\mathcal{H}_0\otimes \mathcal{H}_1$ is associated with a quantum channel $\Gamma$, if $J^\Gamma$ satisfies the following conditions: -$$ -J^\Gamma \geq 0, \quad \text{and} \quad \text{Tr}_{\mathcal{H}_1} J^\Gamma = \mathbb{I}_{\mathcal{H}_0}. -$$ +A Hermitian operator \(J^\Gamma\) acting on \(\mathcal{H}_ 0\otimes \mathcal{H}_ 1\) is associated with a quantum channel \(\Gamma\), if \(J^\Gamma\) satisfies the following conditions: +\[ +J^\Gamma \geq 0, \quad \text{and} \quad \text{Tr}_ {\mathcal{H}_ 1} J^\Gamma = \mathbb{I}_ {\mathcal{H} _0} \ . +\] + The first condition is called *complete positivity*, and the second condition is called *trace-preserving*. In particular, the second condition ensures that the information of the input system is only accessible through the output system. -In particular, a quantum state $\rho$ may be also considered as a quantum network, where the input system is the trivial system $\mathbb{C}$, and the output system is the quantum system $\mathcal{H}$. +In particular, a quantum state \(\rho\) may be also considered as a quantum network, where the input system is the trivial system \(\mathbb{C}\), and the output system is the quantum system \(\mathcal{H}\). The constraints on the quantum channels are then equivalent to the constraints on the quantum states: -$$ -\rho \geq 0, \quad \text{and} \quad \text{Tr} \rho = \mathbb{I}_\mathbb{C} = 1. -$$ +\[ +\rho \geq 0, \quad \text{and} \quad \text{Tr} \rho = \mathbb{I}_ \mathbb{C} = 1\ . +\] > For more details, see G. Chiribella *et al.*, *Theoretical framework for quantum networks*, > [Physical Review A 80.2 (2009): 022339](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.80.022339). From 48e4aa9b732aef71c5f8d68eb8e8210fa245552d Mon Sep 17 00:00:00 2001 From: Canoming Date: Wed, 7 Feb 2024 19:20:05 +0800 Subject: [PATCH 14/15] fix math rendering in docs --- .../tutorials/quantum_networks/README.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/source/code-examples/tutorials/quantum_networks/README.md b/doc/source/code-examples/tutorials/quantum_networks/README.md index 26cb7e8752..349fc10fa0 100644 --- a/doc/source/code-examples/tutorials/quantum_networks/README.md +++ b/doc/source/code-examples/tutorials/quantum_networks/README.md @@ -3,27 +3,27 @@ ## The Quantum Network Model The quantum network model is a mathematical framework that allows us to uniquely describe quantum information processing that involves multiple points in time and space. -Each distinguished point in time and space is treated as a linear system \(\mathcal{H}_ i\). -A quantum network involving $n$ points in time and space is a Hermitian operator \(\mathcal{N}\) that acts on the tensor product of the linear systems \(\mathcal{H}_ 0 \otimes \mathcal{H}_ 1 \otimes \cdots \otimes \mathcal{H}_ {n-1}\). -Each system \(\mathcal{H}_ {i}\) is either an input or an output of the network. +Each distinguished point in time and space is treated as a linear system $\mathcal{H}_ i$. +A quantum network involving $n$ points in time and space is a Hermitian operator $\mathcal{N}$ that acts on the tensor product of the linear systems $\mathcal{H}_ 0 \otimes \mathcal{H}_ 1 \otimes \cdots \otimes \mathcal{H}_ {n-1}$. +Each system $\mathcal{H}_ {i}$ is either an input or an output of the network. -A physically implementable quantum network is described by a semi-positive definite operator \(\mathcal{N}\) that satisfies the causal constraints. +A physically implementable quantum network is described by a semi-positive definite operator $\mathcal{N}$ that satisfies the causal constraints. -A simple example is a quantum channel \(\Gamma: \mathcal{H}_ 0 \to \mathcal{H}_ 1\), where \(\mathcal{H}_ 0\) is the input system and \(\mathcal{H}_ 1\) is the output system. +A simple example is a quantum channel $\Gamma: \mathcal{H}_ 0 \to \mathcal{H}_ 1$, where $\mathcal{H}_ 0$ is the input system and $\mathcal{H}_ 1$ is the output system. The quantum channel is a linear map, such that it maps any input quantum state to an output quantum state, which is a sufficient and necessary condition for the map to be physical. -A Hermitian operator \(J^\Gamma\) acting on \(\mathcal{H}_ 0\otimes \mathcal{H}_ 1\) is associated with a quantum channel \(\Gamma\), if \(J^\Gamma\) satisfies the following conditions: -\[ +A Hermitian operator $J^\Gamma$ acting on $\mathcal{H}_ 0\otimes \mathcal{H}_ 1$ is associated with a quantum channel $\Gamma$, if $J^\Gamma$ satisfies the following conditions: +$$ J^\Gamma \geq 0, \quad \text{and} \quad \text{Tr}_ {\mathcal{H}_ 1} J^\Gamma = \mathbb{I}_ {\mathcal{H} _0} \ . -\] +$$ The first condition is called *complete positivity*, and the second condition is called *trace-preserving*. In particular, the second condition ensures that the information of the input system is only accessible through the output system. -In particular, a quantum state \(\rho\) may be also considered as a quantum network, where the input system is the trivial system \(\mathbb{C}\), and the output system is the quantum system \(\mathcal{H}\). +In particular, a quantum state $\rho$ may be also considered as a quantum network, where the input system is the trivial system $\mathbb{C}$, and the output system is the quantum system $\mathcal{H}$. The constraints on the quantum channels are then equivalent to the constraints on the quantum states: -\[ +$$ \rho \geq 0, \quad \text{and} \quad \text{Tr} \rho = \mathbb{I}_ \mathbb{C} = 1\ . -\] +$$ > For more details, see G. Chiribella *et al.*, *Theoretical framework for quantum networks*, > [Physical Review A 80.2 (2009): 022339](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.80.022339). From d5f8ab14a2ede5b39e0117b02550ff8fbc138b3d Mon Sep 17 00:00:00 2001 From: Canoming Date: Wed, 7 Feb 2024 19:32:06 +0800 Subject: [PATCH 15/15] fix math rendering in docs --- .../code-examples/tutorials/quantum_networks/README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/doc/source/code-examples/tutorials/quantum_networks/README.md b/doc/source/code-examples/tutorials/quantum_networks/README.md index 349fc10fa0..e0b074640c 100644 --- a/doc/source/code-examples/tutorials/quantum_networks/README.md +++ b/doc/source/code-examples/tutorials/quantum_networks/README.md @@ -12,18 +12,14 @@ A physically implementable quantum network is described by a semi-positive defin A simple example is a quantum channel $\Gamma: \mathcal{H}_ 0 \to \mathcal{H}_ 1$, where $\mathcal{H}_ 0$ is the input system and $\mathcal{H}_ 1$ is the output system. The quantum channel is a linear map, such that it maps any input quantum state to an output quantum state, which is a sufficient and necessary condition for the map to be physical. A Hermitian operator $J^\Gamma$ acting on $\mathcal{H}_ 0\otimes \mathcal{H}_ 1$ is associated with a quantum channel $\Gamma$, if $J^\Gamma$ satisfies the following conditions: -$$ -J^\Gamma \geq 0, \quad \text{and} \quad \text{Tr}_ {\mathcal{H}_ 1} J^\Gamma = \mathbb{I}_ {\mathcal{H} _0} \ . -$$ +$$J^\Gamma \geq 0, \quad \text{and} \quad \text{Tr}_ {\mathcal{H}_ 1} J^\Gamma = \mathbb{I}_ {\mathcal{H} _0} .$$ The first condition is called *complete positivity*, and the second condition is called *trace-preserving*. In particular, the second condition ensures that the information of the input system is only accessible through the output system. In particular, a quantum state $\rho$ may be also considered as a quantum network, where the input system is the trivial system $\mathbb{C}$, and the output system is the quantum system $\mathcal{H}$. The constraints on the quantum channels are then equivalent to the constraints on the quantum states: -$$ -\rho \geq 0, \quad \text{and} \quad \text{Tr} \rho = \mathbb{I}_ \mathbb{C} = 1\ . -$$ +$$\rho \geq 0, \quad \text{and} \quad \text{Tr} \rho = \mathbb{I}_ \mathbb{C} = 1\ .$$ > For more details, see G. Chiribella *et al.*, *Theoretical framework for quantum networks*, > [Physical Review A 80.2 (2009): 022339](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.80.022339). @@ -116,7 +112,7 @@ Choi2 is unital: False Choi3 is unital: False ``` -However, the mixture of the three operators are unital. +However, the mixture of the three operators is unital. As the matrices are orthogonal, they are the extreme points of the convex set of the unital channels. Therefore, this mixed channel is not a mixed unitary channel.