Skip to main content

quantrs2_core/characterization/
noise_model.rs

1//! Noise model types and Kraus operator implementations
2
3use crate::error::QuantRS2Result;
4use scirs2_core::ndarray::Array2;
5use scirs2_core::Complex64 as Complex;
6
7/// Noise model types for quantum systems
8#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum NoiseModel {
10    /// Depolarizing channel: ρ → (1-p)ρ + p(I/d)
11    Depolarizing { probability: f64 },
12    /// Amplitude damping: models energy dissipation
13    AmplitudeDamping { gamma: f64 },
14    /// Phase damping: models loss of quantum coherence
15    PhaseDamping { lambda: f64 },
16    /// Bit flip channel: X error with probability p
17    BitFlip { probability: f64 },
18    /// Phase flip channel: Z error with probability p
19    PhaseFlip { probability: f64 },
20    /// Bit-phase flip channel: Y error with probability p
21    BitPhaseFlip { probability: f64 },
22    /// Pauli channel: general combination of X, Y, Z errors
23    Pauli { p_x: f64, p_y: f64, p_z: f64 },
24    /// Thermal relaxation (T1 and T2 processes)
25    ThermalRelaxation { t1: f64, t2: f64, time: f64 },
26}
27
28impl NoiseModel {
29    /// Get Kraus operators for this noise model
30    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    /// Apply noise model to a density matrix
284    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}