quantrs2_device/photonic/
noise_models.rs1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::f64::consts::PI;
9use thiserror::Error;
10
11use super::continuous_variable::{CVError, CVResult, Complex, GaussianState};
12use super::{PhotonicMode, PhotonicSystemType};
13use crate::DeviceResult;
14
15#[derive(Error, Debug)]
17pub enum PhotonicNoiseError {
18 #[error("Invalid noise parameter: {0}")]
19 InvalidParameter(String),
20 #[error("Noise model not supported: {0}")]
21 UnsupportedModel(String),
22 #[error("Noise application failed: {0}")]
23 ApplicationFailed(String),
24}
25
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
28pub enum PhotonicNoiseType {
29 Loss { rate: f64 },
31 Thermal { temperature: f64, frequency: f64 },
33 DetectorInefficiency { efficiency: f64 },
35 PhaseNoise { variance: f64 },
37 AmplitudeNoise { variance: f64 },
39 Crosstalk { coupling_strength: f64 },
41 Nonlinear { coefficient: f64 },
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct PhotonicNoiseModel {
48 pub noise_types: Vec<PhotonicNoiseType>,
50 pub mode_specific: HashMap<usize, Vec<PhotonicNoiseType>>,
52 pub global_parameters: NoiseParameters,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct NoiseParameters {
59 pub noise_strength: f64,
61 pub correlation_time: f64,
63 pub environment_temperature: f64,
65 pub bandwidth: f64,
67}
68
69impl Default for NoiseParameters {
70 fn default() -> Self {
71 Self {
72 noise_strength: 0.01,
73 correlation_time: 1e-6, environment_temperature: 0.01, bandwidth: 1e9, }
77 }
78}
79
80pub struct PhotonicNoiseSimulator {
82 pub noise_models: Vec<PhotonicNoiseModel>,
84 pub noise_cache: HashMap<String, Vec<f64>>,
86 rng_state: u64,
88}
89
90impl PhotonicNoiseSimulator {
91 pub fn new() -> Self {
92 Self {
93 noise_models: Vec::new(),
94 noise_cache: HashMap::new(),
95 rng_state: 42, }
97 }
98
99 pub fn apply_noise(
101 &mut self,
102 state: &mut GaussianState,
103 noise_model: &PhotonicNoiseModel,
104 ) -> Result<(), PhotonicNoiseError> {
105 for noise_type in &noise_model.noise_types {
106 self.apply_noise_type(state, noise_type)?;
107 }
108
109 for (&mode, noise_types) in &noise_model.mode_specific {
111 if mode < state.num_modes {
112 for noise_type in noise_types {
113 self.apply_mode_specific_noise(state, mode, noise_type)?;
114 }
115 }
116 }
117
118 Ok(())
119 }
120
121 fn apply_noise_type(
123 &mut self,
124 state: &mut GaussianState,
125 noise_type: &PhotonicNoiseType,
126 ) -> Result<(), PhotonicNoiseError> {
127 match noise_type {
128 PhotonicNoiseType::Loss { rate } => {
129 self.apply_loss_noise(state, *rate)?;
130 }
131 PhotonicNoiseType::Thermal {
132 temperature,
133 frequency,
134 } => {
135 self.apply_thermal_noise(state, *temperature, *frequency)?;
136 }
137 PhotonicNoiseType::PhaseNoise { variance } => {
138 self.apply_phase_noise(state, *variance)?;
139 }
140 PhotonicNoiseType::AmplitudeNoise { variance } => {
141 self.apply_amplitude_noise(state, *variance)?;
142 }
143 PhotonicNoiseType::DetectorInefficiency { efficiency } => {
144 self.apply_detector_noise(state, *efficiency)?;
145 }
146 PhotonicNoiseType::Crosstalk { coupling_strength } => {
147 self.apply_crosstalk_noise(state, *coupling_strength)?;
148 }
149 PhotonicNoiseType::Nonlinear { coefficient } => {
150 self.apply_nonlinear_noise(state, *coefficient)?;
151 }
152 }
153 Ok(())
154 }
155
156 fn apply_loss_noise(
158 &mut self,
159 state: &mut GaussianState,
160 loss_rate: f64,
161 ) -> Result<(), PhotonicNoiseError> {
162 if !(0.0..=1.0).contains(&loss_rate) {
163 return Err(PhotonicNoiseError::InvalidParameter(format!(
164 "Loss rate must be between 0 and 1, got {loss_rate}"
165 )));
166 }
167
168 let transmission = 1.0 - loss_rate;
169
170 for mode in 0..state.num_modes {
172 let x_idx = 2 * mode;
173 let p_idx = 2 * mode + 1;
174
175 state.mean[x_idx] *= transmission.sqrt();
177 state.mean[p_idx] *= transmission.sqrt();
178
179 state.covariance[x_idx][x_idx] =
181 transmission * state.covariance[x_idx][x_idx] + (1.0 - transmission) * 0.5;
182 state.covariance[p_idx][p_idx] =
183 transmission * state.covariance[p_idx][p_idx] + (1.0 - transmission) * 0.5;
184 state.covariance[x_idx][p_idx] *= transmission;
185 state.covariance[p_idx][x_idx] *= transmission;
186 }
187
188 Ok(())
189 }
190
191 fn apply_thermal_noise(
193 &mut self,
194 state: &mut GaussianState,
195 temperature: f64,
196 frequency: f64,
197 ) -> Result<(), PhotonicNoiseError> {
198 if temperature < 0.0 {
199 return Err(PhotonicNoiseError::InvalidParameter(
200 "Temperature must be non-negative".to_string(),
201 ));
202 }
203
204 let thermal_photons = temperature / frequency;
207
208 for mode in 0..state.num_modes {
210 let x_idx = 2 * mode;
211 let p_idx = 2 * mode + 1;
212
213 state.covariance[x_idx][x_idx] += thermal_photons;
215 state.covariance[p_idx][p_idx] += thermal_photons;
216 }
217
218 Ok(())
219 }
220
221 fn apply_phase_noise(
223 &mut self,
224 state: &mut GaussianState,
225 variance: f64,
226 ) -> Result<(), PhotonicNoiseError> {
227 if variance < 0.0 {
228 return Err(PhotonicNoiseError::InvalidParameter(
229 "Phase noise variance must be non-negative".to_string(),
230 ));
231 }
232
233 for mode in 0..state.num_modes {
235 let phase_noise = self.generate_gaussian_noise(0.0, variance);
236 if let Err(e) = state.phase_rotation(phase_noise, mode) {
237 return Err(PhotonicNoiseError::ApplicationFailed(format!(
238 "Failed to apply phase noise: {e:?}"
239 )));
240 }
241 }
242
243 Ok(())
244 }
245
246 fn apply_amplitude_noise(
248 &mut self,
249 state: &mut GaussianState,
250 variance: f64,
251 ) -> Result<(), PhotonicNoiseError> {
252 if variance < 0.0 {
253 return Err(PhotonicNoiseError::InvalidParameter(
254 "Amplitude noise variance must be non-negative".to_string(),
255 ));
256 }
257
258 for mode in 0..state.num_modes {
260 let x_idx = 2 * mode;
261 let p_idx = 2 * mode + 1;
262
263 let x_noise = self.generate_gaussian_noise(0.0, variance);
264 let p_noise = self.generate_gaussian_noise(0.0, variance);
265
266 state.mean[x_idx] += x_noise;
267 state.mean[p_idx] += p_noise;
268 }
269
270 Ok(())
271 }
272
273 fn apply_detector_noise(
275 &mut self,
276 state: &mut GaussianState,
277 efficiency: f64,
278 ) -> Result<(), PhotonicNoiseError> {
279 if !(0.0..=1.0).contains(&efficiency) {
280 return Err(PhotonicNoiseError::InvalidParameter(format!(
281 "Detector efficiency must be between 0 and 1, got {efficiency}"
282 )));
283 }
284
285 self.apply_loss_noise(state, 1.0 - efficiency)
288 }
289
290 fn apply_crosstalk_noise(
292 &mut self,
293 state: &mut GaussianState,
294 coupling_strength: f64,
295 ) -> Result<(), PhotonicNoiseError> {
296 if state.num_modes < 2 {
297 return Ok(()); }
299
300 for mode in 0..(state.num_modes - 1) {
302 let coupling_angle = coupling_strength * PI / 4.0;
303 if let Err(e) = state.beamsplitter(coupling_angle, 0.0, mode, mode + 1) {
304 return Err(PhotonicNoiseError::ApplicationFailed(format!(
305 "Failed to apply crosstalk: {e:?}"
306 )));
307 }
308 }
309
310 Ok(())
311 }
312
313 fn apply_nonlinear_noise(
315 &mut self,
316 state: &mut GaussianState,
317 coefficient: f64,
318 ) -> Result<(), PhotonicNoiseError> {
319 let phase_variance = coefficient.abs() * 0.1;
322 self.apply_phase_noise(state, phase_variance)
323 }
324
325 fn apply_mode_specific_noise(
327 &mut self,
328 state: &mut GaussianState,
329 mode: usize,
330 noise_type: &PhotonicNoiseType,
331 ) -> Result<(), PhotonicNoiseError> {
332 match noise_type {
333 PhotonicNoiseType::PhaseNoise { variance } => {
334 let phase_noise = self.generate_gaussian_noise(0.0, *variance);
335 if let Err(e) = state.phase_rotation(phase_noise, mode) {
336 return Err(PhotonicNoiseError::ApplicationFailed(format!(
337 "Mode-specific phase noise failed: {e:?}"
338 )));
339 }
340 }
341 PhotonicNoiseType::AmplitudeNoise { variance } => {
342 let x_idx = 2 * mode;
343 let p_idx = 2 * mode + 1;
344
345 let x_noise = self.generate_gaussian_noise(0.0, *variance);
346 let p_noise = self.generate_gaussian_noise(0.0, *variance);
347
348 state.mean[x_idx] += x_noise;
349 state.mean[p_idx] += p_noise;
350 }
351 _ => {
352 self.apply_noise_type(state, noise_type)?;
354 }
355 }
356 Ok(())
357 }
358
359 fn generate_gaussian_noise(&mut self, mean: f64, variance: f64) -> f64 {
361 self.rng_state = self
363 .rng_state
364 .wrapping_mul(1_664_525)
365 .wrapping_add(1_013_904_223);
366 let u1 = (self.rng_state as f64) / (u64::MAX as f64);
367
368 self.rng_state = self
369 .rng_state
370 .wrapping_mul(1_664_525)
371 .wrapping_add(1_013_904_223);
372 let u2 = (self.rng_state as f64) / (u64::MAX as f64);
373
374 let z = (-2.0 * u1.ln()).sqrt() * (2.0 * PI * u2).cos();
375 variance.sqrt().mul_add(z, mean)
376 }
377
378 pub fn create_realistic_noise_model(
380 loss_rate: f64,
381 thermal_temperature: f64,
382 detector_efficiency: f64,
383 ) -> PhotonicNoiseModel {
384 let noise_types = vec![
385 PhotonicNoiseType::Loss { rate: loss_rate },
386 PhotonicNoiseType::Thermal {
387 temperature: thermal_temperature,
388 frequency: 1e14, },
390 PhotonicNoiseType::DetectorInefficiency {
391 efficiency: detector_efficiency,
392 },
393 PhotonicNoiseType::PhaseNoise { variance: 0.001 },
394 PhotonicNoiseType::AmplitudeNoise { variance: 0.0005 },
395 ];
396
397 PhotonicNoiseModel {
398 noise_types,
399 mode_specific: HashMap::new(),
400 global_parameters: NoiseParameters::default(),
401 }
402 }
403
404 pub fn estimate_noise_impact(
406 &self,
407 initial_fidelity: f64,
408 noise_model: &PhotonicNoiseModel,
409 ) -> f64 {
410 let mut fidelity = initial_fidelity;
411
412 for noise_type in &noise_model.noise_types {
413 match noise_type {
414 PhotonicNoiseType::Loss { rate } => {
415 fidelity *= 1.0 - rate * 0.5; }
417 PhotonicNoiseType::Thermal { temperature, .. } => {
418 fidelity *= 1.0 - temperature * 0.1;
419 }
420 PhotonicNoiseType::PhaseNoise { variance } => {
421 fidelity *= 1.0 - variance * 2.0;
422 }
423 PhotonicNoiseType::DetectorInefficiency { efficiency } => {
424 fidelity *= efficiency;
425 }
426 _ => {
427 fidelity *= 0.99; }
429 }
430 }
431
432 fidelity.clamp(0.0, 1.0)
433 }
434}
435
436impl Default for PhotonicNoiseSimulator {
437 fn default() -> Self {
438 Self::new()
439 }
440}
441
442#[cfg(test)]
443mod tests {
444 use super::*;
445 use crate::photonic::continuous_variable::GaussianState;
446
447 #[test]
448 fn test_noise_simulator_creation() {
449 let simulator = PhotonicNoiseSimulator::new();
450 assert_eq!(simulator.noise_models.len(), 0);
451 }
452
453 #[test]
454 fn test_loss_noise() {
455 let mut simulator = PhotonicNoiseSimulator::new();
456 let mut state = GaussianState::coherent(Complex::new(2.0, 0.0), 0, 1)
457 .expect("Coherent state creation should succeed");
458
459 let original_mean = state.mean[0];
460 simulator
461 .apply_loss_noise(&mut state, 0.1)
462 .expect("Loss noise application should succeed with valid rate");
463
464 assert!(state.mean[0] < original_mean);
466 }
467
468 #[test]
469 fn test_thermal_noise() {
470 let mut simulator = PhotonicNoiseSimulator::new();
471 let mut state = GaussianState::vacuum(1);
472
473 let original_variance = state.covariance[0][0];
474 simulator
475 .apply_thermal_noise(&mut state, 0.01, 1e14)
476 .expect("Thermal noise application should succeed with valid parameters");
477
478 assert!(state.covariance[0][0] > original_variance);
480 }
481
482 #[test]
483 fn test_realistic_noise_model() {
484 let model = PhotonicNoiseSimulator::create_realistic_noise_model(0.05, 0.01, 0.9);
485 assert_eq!(model.noise_types.len(), 5);
486 }
487
488 #[test]
489 fn test_noise_impact_estimation() {
490 let simulator = PhotonicNoiseSimulator::new();
491 let model = PhotonicNoiseSimulator::create_realistic_noise_model(0.1, 0.01, 0.95);
492
493 let initial_fidelity = 0.99;
494 let final_fidelity = simulator.estimate_noise_impact(initial_fidelity, &model);
495
496 assert!(final_fidelity < initial_fidelity);
497 assert!(final_fidelity > 0.0);
498 }
499}