12
12
# See the License for the specific language governing permissions and
13
13
# limitations under the License.
14
14
"""Tests for channels."""
15
+ from typing import Iterable
16
+
15
17
import numpy as np
16
18
import pytest
17
19
@@ -28,32 +30,38 @@ def apply_channel(channel: cirq.SupportsChannel, rho: np.ndarray) -> np.ndarray:
28
30
return out
29
31
30
32
31
- def expected_choi (channel : cirq .SupportsChannel ) -> np .ndarray :
33
+ def generate_standard_operator_basis (d_out : int , d_in : int ) -> Iterable [np .ndarray ]:
34
+ for i in range (d_out ):
35
+ for j in range (d_in ):
36
+ e_ij = np .zeros ((d_out , d_in ))
37
+ e_ij [i , j ] = 1
38
+ yield e_ij
39
+
40
+
41
+ def compute_choi (channel : cirq .SupportsChannel ) -> np .ndarray :
32
42
ks = cirq .channel (channel )
33
43
d_out , d_in = ks [0 ].shape
34
44
d = d_in * d_out
35
45
c = np .zeros ((d , d ), dtype = np .complex128 )
36
- for i in range (d_in ):
37
- for j in range (d_in ):
38
- e_ij = np .zeros ((d_in , d_in ))
39
- e_ij [i , j ] = 1
40
- c += np .kron (apply_channel (channel , e_ij ), e_ij )
46
+ for e in generate_standard_operator_basis (d_in , d_in ):
47
+ c += np .kron (apply_channel (channel , e ), e )
41
48
return c
42
49
43
50
51
+ def compute_channel_matrix (channel : cirq .SupportsChannel ) -> np .ndarray :
52
+ ks = cirq .channel (channel )
53
+ d_out , d_in = ks [0 ].shape
54
+ m = np .zeros ((d_out * d_out , d_in * d_in ), dtype = np .complex128 )
55
+ for k , e_in in enumerate (generate_standard_operator_basis (d_in , d_in )):
56
+ m [:, k ] = np .reshape (apply_channel (channel , e_in ), d_out * d_out )
57
+ return m
58
+
59
+
44
60
@pytest .mark .parametrize (
45
61
'kraus_operators, expected_choi' ,
46
62
(
47
63
([np .eye (2 )], np .array ([[1 , 0 , 0 , 1 ], [0 , 0 , 0 , 0 ], [0 , 0 , 0 , 0 ], [1 , 0 , 0 , 1 ]])),
48
- (
49
- [
50
- np .eye (2 ) / 2 ,
51
- np .array ([[0 , 1 ], [1 , 0 ]]) / 2 ,
52
- np .array ([[0 , - 1j ], [1j , 0 ]]) / 2 ,
53
- np .diag ([1 , - 1 ]) / 2 ,
54
- ],
55
- np .eye (4 ) / 2 ,
56
- ),
64
+ (cirq .channel (cirq .depolarize (0.75 )), np .eye (4 ) / 2 ),
57
65
(
58
66
[
59
67
np .array ([[1 , 0 , 0 ], [0 , 0 , 1 ]]) / np .sqrt (2 ),
@@ -80,14 +88,66 @@ def test_kraus_to_choi(kraus_operators, expected_choi):
80
88
),
81
89
)
82
90
def test_operation_to_choi (channel ):
83
- """Verifies that cirq.choi correctly computes the Choi matrix."""
91
+ """Verifies that cirq.operation_to_choi correctly computes the Choi matrix."""
84
92
n_qubits = cirq .num_qubits (channel )
85
93
actual = cirq .operation_to_choi (channel )
86
- expected = expected_choi (channel )
94
+ expected = compute_choi (channel )
87
95
assert np .isclose (np .trace (actual ), 2 ** n_qubits )
88
96
assert np .all (actual == expected )
89
97
90
98
91
- def test_choi_on_completely_dephasing_channel ():
92
- """Checks that cirq.choi returns the right matrix for the completely dephasing channel."""
99
+ def test_choi_for_completely_dephasing_channel ():
100
+ """Checks cirq.operation_to_choi on the completely dephasing channel."""
93
101
assert np .all (cirq .operation_to_choi (cirq .phase_damp (1 )) == np .diag ([1 , 0 , 0 , 1 ]))
102
+
103
+
104
+ @pytest .mark .parametrize (
105
+ 'kraus_operators, expected_channel_matrix' ,
106
+ (
107
+ ([np .eye (2 )], np .eye (4 )),
108
+ (
109
+ cirq .channel (cirq .depolarize (0.75 )),
110
+ np .array ([[1 , 0 , 0 , 1 ], [0 , 0 , 0 , 0 ], [0 , 0 , 0 , 0 ], [1 , 0 , 0 , 1 ]]) / 2 ,
111
+ ),
112
+ (
113
+ [
114
+ np .array ([[0 , 1 , 0 ], [0 , 0 , 1 ]]) / np .sqrt (2 ),
115
+ np .array ([[0 , 1 , 0 ], [0 , 0 , - 1 ]]) / np .sqrt (2 ),
116
+ ],
117
+ np .array (
118
+ [
119
+ [0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 ],
120
+ [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
121
+ [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ],
122
+ [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ],
123
+ ]
124
+ ),
125
+ ),
126
+ ),
127
+ )
128
+ def test_kraus_to_channel_matrix (kraus_operators , expected_channel_matrix ):
129
+ """Verifies that cirq.kraus_to_channel_matrix computes the correct channel matrix."""
130
+ assert np .allclose (cirq .kraus_to_channel_matrix (kraus_operators ), expected_channel_matrix )
131
+
132
+
133
+ @pytest .mark .parametrize (
134
+ 'channel' ,
135
+ (
136
+ cirq .I ,
137
+ cirq .X ,
138
+ cirq .CNOT ,
139
+ cirq .depolarize (0.1 ),
140
+ cirq .depolarize (0.1 , n_qubits = 2 ),
141
+ cirq .amplitude_damp (0.2 ),
142
+ ),
143
+ )
144
+ def test_operation_to_channel_matrix (channel ):
145
+ """Verifies that cirq.channel_matrix correctly computes the channel matrix."""
146
+ actual = cirq .operation_to_channel_matrix (channel )
147
+ expected = compute_channel_matrix (channel )
148
+ assert np .all (actual == expected )
149
+
150
+
151
+ def test_channel_matrix_for_completely_dephasing_channel ():
152
+ """Checks cirq.operation_to_channel_matrix on the completely dephasing channel."""
153
+ assert np .all (cirq .operation_to_channel_matrix (cirq .phase_damp (1 )) == np .diag ([1 , 0 , 0 , 1 ]))
0 commit comments