@@ -50,11 +50,9 @@ def kraus_to_choi(kraus_operators: Sequence[np.ndarray]) -> np.ndarray:
50
50
Choi matrix of the channel specified by kraus_operators.
51
51
"""
52
52
d = np .prod (kraus_operators [0 ].shape , dtype = np .int64 )
53
- c = np .zeros ((d , d ), dtype = np .complex128 )
54
- for k in kraus_operators :
55
- v = np .reshape (k , d )
56
- c += np .outer (v , v .conj ())
57
- return c
53
+ choi_rank = len (kraus_operators )
54
+ k = np .reshape (kraus_operators , (choi_rank , d ))
55
+ return np .einsum ('bi,bj->ij' , k , k .conj ())
58
56
59
57
60
58
def choi_to_kraus (choi : np .ndarray , atol : float = 1e-10 ) -> Sequence [np .ndarray ]:
@@ -105,7 +103,8 @@ def choi_to_kraus(choi: np.ndarray, atol: float = 1e-10) -> Sequence[np.ndarray]
105
103
106
104
w = np .maximum (w , 0 )
107
105
u = np .sqrt (w ) * v
108
- return [k .reshape (d , d ) for k in u .T if np .linalg .norm (k ) > atol ]
106
+ keep = np .linalg .norm (u .T , axis = - 1 ) > atol
107
+ return [k .reshape (d , d ) for k , keep_i in zip (u .T , keep ) if keep_i ]
109
108
110
109
111
110
def kraus_to_superoperator (kraus_operators : Sequence [np .ndarray ]) -> np .ndarray :
@@ -140,10 +139,9 @@ def kraus_to_superoperator(kraus_operators: Sequence[np.ndarray]) -> np.ndarray:
140
139
Superoperator matrix of the channel specified by kraus_operators.
141
140
"""
142
141
d_out , d_in = kraus_operators [0 ].shape
143
- m = np .zeros ((d_out * d_out , d_in * d_in ), dtype = np .complex128 )
144
- for k in kraus_operators :
145
- m += np .kron (k , k .conj ())
146
- return m
142
+ ops_arr = np .asarray (kraus_operators )
143
+ m = np .einsum ('bij,bkl->ikjl' , ops_arr , ops_arr .conj ())
144
+ return m .reshape ((d_out * d_out , d_in * d_in ))
147
145
148
146
149
147
def superoperator_to_kraus (superoperator : np .ndarray , atol : float = 1e-10 ) -> Sequence [np .ndarray ]:
0 commit comments