1use crate::error::QuantRS2Result;
4use scirs2_core::ndarray::Array2;
5use scirs2_core::Complex64 as Complex;
6
7#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum NoiseModel {
10 Depolarizing { probability: f64 },
12 AmplitudeDamping { gamma: f64 },
14 PhaseDamping { lambda: f64 },
16 BitFlip { probability: f64 },
18 PhaseFlip { probability: f64 },
20 BitPhaseFlip { probability: f64 },
22 Pauli { p_x: f64, p_y: f64, p_z: f64 },
24 ThermalRelaxation { t1: f64, t2: f64, time: f64 },
26}
27
28impl NoiseModel {
29 pub fn kraus_operators(&self) -> Vec<Array2<Complex>> {
31 match self {
32 Self::Depolarizing { probability } => {
33 let p = *probability;
34 let sqrt_p = p.sqrt();
35 let sqrt_1_p = (1.0 - p).sqrt();
36
37 vec![
38 Array2::from_shape_vec(
39 (2, 2),
40 vec![
41 Complex::new(sqrt_1_p, 0.0),
42 Complex::new(0.0, 0.0),
43 Complex::new(0.0, 0.0),
44 Complex::new(sqrt_1_p, 0.0),
45 ],
46 )
47 .expect("2x2 matrix creation"),
48 Array2::from_shape_vec(
49 (2, 2),
50 vec![
51 Complex::new(0.0, 0.0),
52 Complex::new(sqrt_p / 3.0_f64.sqrt(), 0.0),
53 Complex::new(sqrt_p / 3.0_f64.sqrt(), 0.0),
54 Complex::new(0.0, 0.0),
55 ],
56 )
57 .expect("2x2 matrix creation"),
58 Array2::from_shape_vec(
59 (2, 2),
60 vec![
61 Complex::new(0.0, 0.0),
62 Complex::new(0.0, -sqrt_p / 3.0_f64.sqrt()),
63 Complex::new(0.0, sqrt_p / 3.0_f64.sqrt()),
64 Complex::new(0.0, 0.0),
65 ],
66 )
67 .expect("2x2 matrix creation"),
68 Array2::from_shape_vec(
69 (2, 2),
70 vec![
71 Complex::new(sqrt_p / 3.0_f64.sqrt(), 0.0),
72 Complex::new(0.0, 0.0),
73 Complex::new(0.0, 0.0),
74 Complex::new(-sqrt_p / 3.0_f64.sqrt(), 0.0),
75 ],
76 )
77 .expect("2x2 matrix creation"),
78 ]
79 }
80 Self::AmplitudeDamping { gamma } => {
81 let g = *gamma;
82 vec![
83 Array2::from_shape_vec(
84 (2, 2),
85 vec![
86 Complex::new(1.0, 0.0),
87 Complex::new(0.0, 0.0),
88 Complex::new(0.0, 0.0),
89 Complex::new((1.0 - g).sqrt(), 0.0),
90 ],
91 )
92 .expect("2x2 matrix creation"),
93 Array2::from_shape_vec(
94 (2, 2),
95 vec![
96 Complex::new(0.0, 0.0),
97 Complex::new(g.sqrt(), 0.0),
98 Complex::new(0.0, 0.0),
99 Complex::new(0.0, 0.0),
100 ],
101 )
102 .expect("2x2 matrix creation"),
103 ]
104 }
105 Self::PhaseDamping { lambda } => {
106 let l = *lambda;
107 vec![
108 Array2::from_shape_vec(
109 (2, 2),
110 vec![
111 Complex::new(1.0, 0.0),
112 Complex::new(0.0, 0.0),
113 Complex::new(0.0, 0.0),
114 Complex::new((1.0 - l).sqrt(), 0.0),
115 ],
116 )
117 .expect("2x2 matrix creation"),
118 Array2::from_shape_vec(
119 (2, 2),
120 vec![
121 Complex::new(0.0, 0.0),
122 Complex::new(0.0, 0.0),
123 Complex::new(0.0, 0.0),
124 Complex::new(l.sqrt(), 0.0),
125 ],
126 )
127 .expect("2x2 matrix creation"),
128 ]
129 }
130 Self::BitFlip { probability } => {
131 let p = *probability;
132 vec![
133 Array2::from_shape_vec(
134 (2, 2),
135 vec![
136 Complex::new((1.0 - p).sqrt(), 0.0),
137 Complex::new(0.0, 0.0),
138 Complex::new(0.0, 0.0),
139 Complex::new((1.0 - p).sqrt(), 0.0),
140 ],
141 )
142 .expect("2x2 matrix creation"),
143 Array2::from_shape_vec(
144 (2, 2),
145 vec![
146 Complex::new(0.0, 0.0),
147 Complex::new(p.sqrt(), 0.0),
148 Complex::new(p.sqrt(), 0.0),
149 Complex::new(0.0, 0.0),
150 ],
151 )
152 .expect("2x2 matrix creation"),
153 ]
154 }
155 Self::PhaseFlip { probability } => {
156 let p = *probability;
157 vec![
158 Array2::from_shape_vec(
159 (2, 2),
160 vec![
161 Complex::new((1.0 - p).sqrt(), 0.0),
162 Complex::new(0.0, 0.0),
163 Complex::new(0.0, 0.0),
164 Complex::new((1.0 - p).sqrt(), 0.0),
165 ],
166 )
167 .expect("2x2 matrix creation"),
168 Array2::from_shape_vec(
169 (2, 2),
170 vec![
171 Complex::new(p.sqrt(), 0.0),
172 Complex::new(0.0, 0.0),
173 Complex::new(0.0, 0.0),
174 Complex::new(-p.sqrt(), 0.0),
175 ],
176 )
177 .expect("2x2 matrix creation"),
178 ]
179 }
180 Self::BitPhaseFlip { probability } => {
181 let p = *probability;
182 vec![
183 Array2::from_shape_vec(
184 (2, 2),
185 vec![
186 Complex::new((1.0 - p).sqrt(), 0.0),
187 Complex::new(0.0, 0.0),
188 Complex::new(0.0, 0.0),
189 Complex::new((1.0 - p).sqrt(), 0.0),
190 ],
191 )
192 .expect("2x2 matrix creation"),
193 Array2::from_shape_vec(
194 (2, 2),
195 vec![
196 Complex::new(0.0, 0.0),
197 Complex::new(0.0, -p.sqrt()),
198 Complex::new(0.0, p.sqrt()),
199 Complex::new(0.0, 0.0),
200 ],
201 )
202 .expect("2x2 matrix creation"),
203 ]
204 }
205 Self::Pauli { p_x, p_y, p_z } => {
206 let p_i = 1.0 - p_x - p_y - p_z;
207 vec![
208 Array2::from_shape_vec(
209 (2, 2),
210 vec![
211 Complex::new(p_i.sqrt(), 0.0),
212 Complex::new(0.0, 0.0),
213 Complex::new(0.0, 0.0),
214 Complex::new(p_i.sqrt(), 0.0),
215 ],
216 )
217 .expect("2x2 matrix creation"),
218 Array2::from_shape_vec(
219 (2, 2),
220 vec![
221 Complex::new(0.0, 0.0),
222 Complex::new(p_x.sqrt(), 0.0),
223 Complex::new(p_x.sqrt(), 0.0),
224 Complex::new(0.0, 0.0),
225 ],
226 )
227 .expect("2x2 matrix creation"),
228 Array2::from_shape_vec(
229 (2, 2),
230 vec![
231 Complex::new(0.0, 0.0),
232 Complex::new(0.0, -p_y.sqrt()),
233 Complex::new(0.0, p_y.sqrt()),
234 Complex::new(0.0, 0.0),
235 ],
236 )
237 .expect("2x2 matrix creation"),
238 Array2::from_shape_vec(
239 (2, 2),
240 vec![
241 Complex::new(p_z.sqrt(), 0.0),
242 Complex::new(0.0, 0.0),
243 Complex::new(0.0, 0.0),
244 Complex::new(-p_z.sqrt(), 0.0),
245 ],
246 )
247 .expect("2x2 matrix creation"),
248 ]
249 }
250 Self::ThermalRelaxation { t1, t2, time } => {
251 let p1 = 1.0 - (-time / t1).exp();
252 let p2 = 1.0 - (-time / t2).exp();
253
254 let gamma = p1;
255 let lambda = (p2 - p1 / 2.0).max(0.0);
256
257 vec![
258 Array2::from_shape_vec(
259 (2, 2),
260 vec![
261 Complex::new(1.0, 0.0),
262 Complex::new(0.0, 0.0),
263 Complex::new(0.0, 0.0),
264 Complex::new((1.0 - gamma) * (1.0 - lambda).sqrt(), 0.0),
265 ],
266 )
267 .expect("2x2 matrix creation"),
268 Array2::from_shape_vec(
269 (2, 2),
270 vec![
271 Complex::new(0.0, 0.0),
272 Complex::new(gamma.sqrt(), 0.0),
273 Complex::new(0.0, 0.0),
274 Complex::new(0.0, 0.0),
275 ],
276 )
277 .expect("2x2 matrix creation"),
278 ]
279 }
280 }
281 }
282
283 pub fn apply_to_density_matrix(
285 &self,
286 rho: &Array2<Complex>,
287 ) -> QuantRS2Result<Array2<Complex>> {
288 let kraus_ops = self.kraus_operators();
289 let dim = rho.nrows();
290 let mut result = Array2::<Complex>::zeros((dim, dim));
291
292 for k in &kraus_ops {
293 let k_rho = k.dot(rho);
294 let k_dag = k.t().mapv(|x| x.conj());
295 let k_rho_k_dag = k_rho.dot(&k_dag);
296 result = result + k_rho_k_dag;
297 }
298
299 Ok(result)
300 }
301}