1use super::{CVDeviceConfig, Complex, GaussianState};
7use crate::{DeviceError, DeviceResult};
8use scirs2_core::random::prelude::*;
9use scirs2_core::random::{Distribution, RandNormal, Poisson};
10use serde::{Deserialize, Serialize};
11use std::f64::consts::PI;
12
13type Normal<T> = RandNormal<T>;
15
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18pub enum CVMeasurementScheme {
19 Homodyne { phase: f64 },
21 Heterodyne,
23 PhotonNumber,
25 Parity,
27 Bell { basis: BellBasis },
29 FockProjection { n: usize },
31 CoherentProjection { alpha: Complex },
33}
34
35#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
37pub enum BellBasis {
38 XBasis,
40 PBasis,
42 MixedBasis { phase: f64 },
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct CVMeasurementResult {
49 pub outcome: CVMeasurementOutcome,
51 pub fidelity: f64,
53 pub standard_deviation: f64,
55 pub sample_count: usize,
57 pub timestamp: f64,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
63pub enum CVMeasurementOutcome {
64 Real(f64),
66 Complex(Complex),
68 Integer(i32),
70 Boolean(bool),
72 BellCorrelation { correlation: f64, phase: f64 },
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct CVMeasurementConfig {
79 pub num_samples: usize,
81 pub integration_time: f64,
83 pub lo_power_mw: f64,
85 pub bandwidth_hz: f64,
87 pub phase_stability: f64,
89 pub enable_post_processing: bool,
91 pub calibration: MeasurementCalibration,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct MeasurementCalibration {
98 pub efficiency: Vec<f64>,
100 pub electronic_noise_db: f64,
102 pub dark_count_rate: f64,
104 pub gain_factors: Vec<f64>,
106 pub phase_offsets: Vec<f64>,
108}
109
110impl Default for CVMeasurementConfig {
111 fn default() -> Self {
112 Self {
113 num_samples: 10000,
114 integration_time: 0.001, lo_power_mw: 10.0,
116 bandwidth_hz: 10e6,
117 phase_stability: 0.01,
118 enable_post_processing: true,
119 calibration: MeasurementCalibration::default(),
120 }
121 }
122}
123
124impl Default for MeasurementCalibration {
125 fn default() -> Self {
126 Self {
127 efficiency: vec![0.95; 10], electronic_noise_db: -90.0,
129 dark_count_rate: 100.0,
130 gain_factors: vec![1.0; 10],
131 phase_offsets: vec![0.0; 10],
132 }
133 }
134}
135
136pub struct CVMeasurementEngine {
138 config: CVMeasurementConfig,
140 measurement_history: Vec<CVMeasurementResult>,
142 is_calibrated: bool,
144}
145
146impl CVMeasurementEngine {
147 pub fn new(config: CVMeasurementConfig) -> Self {
149 Self {
150 config,
151 measurement_history: Vec::new(),
152 is_calibrated: false,
153 }
154 }
155
156 pub async fn calibrate(&mut self) -> DeviceResult<()> {
158 println!("Calibrating CV measurement system...");
159
160 tokio::time::sleep(std::time::Duration::from_millis(500)).await;
162
163 for i in 0..self.config.calibration.efficiency.len() {
165 self.config.calibration.efficiency[i] = 0.95 + 0.03 * thread_rng().gen::<f64>();
166 self.config.calibration.gain_factors[i] = 1.0 + 0.1 * (thread_rng().gen::<f64>() - 0.5);
167 self.config.calibration.phase_offsets[i] = 0.1 * (thread_rng().gen::<f64>() - 0.5);
168 }
169
170 self.is_calibrated = true;
171 println!("Calibration complete");
172 Ok(())
173 }
174
175 pub async fn homodyne_measurement(
177 &mut self,
178 state: &mut GaussianState,
179 mode: usize,
180 phase: f64,
181 ) -> DeviceResult<CVMeasurementResult> {
182 if !self.is_calibrated {
183 return Err(DeviceError::DeviceNotInitialized(
184 "Measurement system not calibrated".to_string(),
185 ));
186 }
187
188 if mode >= state.num_modes {
189 return Err(DeviceError::InvalidInput(format!(
190 "Mode {} exceeds available modes",
191 mode
192 )));
193 }
194
195 let calibrated_phase = phase
197 + self
198 .config
199 .calibration
200 .phase_offsets
201 .get(mode)
202 .unwrap_or(&0.0);
203
204 let cos_phi = calibrated_phase.cos();
206 let sin_phi = calibrated_phase.sin();
207
208 let mean_x = state.mean_vector[2 * mode];
209 let mean_p = state.mean_vector[2 * mode + 1];
210 let theoretical_mean = cos_phi * mean_x + sin_phi * mean_p;
211
212 let var_x = state.covariancematrix[2 * mode][2 * mode];
213 let var_p = state.covariancematrix[2 * mode + 1][2 * mode + 1];
214 let cov_xp = state.covariancematrix[2 * mode][2 * mode + 1];
215
216 let theoretical_variance =
217 cos_phi.powi(2) * var_x + sin_phi.powi(2) * var_p + 2.0 * cos_phi * sin_phi * cov_xp;
218
219 let efficiency = self
221 .config
222 .calibration
223 .efficiency
224 .get(mode)
225 .unwrap_or(&0.95);
226 let gain = self
227 .config
228 .calibration
229 .gain_factors
230 .get(mode)
231 .unwrap_or(&1.0);
232
233 let noise_variance = self.calculate_detection_noise(mode);
234 let total_variance = theoretical_variance / efficiency + noise_variance;
235
236 let mut samples = Vec::new();
238 let distribution = Normal::new(theoretical_mean, total_variance.sqrt())
239 .map_err(|e| DeviceError::InvalidInput(format!("Distribution error: {}", e)))?;
240
241 let mut rng = StdRng::seed_from_u64(thread_rng().gen::<u64>());
242 for _ in 0..self.config.num_samples {
243 let sample = distribution.sample(&mut rng) * gain;
244 samples.push(sample);
245 }
246
247 let mean_outcome = samples.iter().sum::<f64>() / samples.len() as f64;
249 let variance = samples
250 .iter()
251 .map(|x| (x - mean_outcome).powi(2))
252 .sum::<f64>()
253 / samples.len() as f64;
254 let std_dev = variance.sqrt();
255
256 let fidelity =
258 self.estimate_measurement_fidelity(&samples, theoretical_mean, total_variance);
259
260 let result = CVMeasurementResult {
261 outcome: CVMeasurementOutcome::Real(mean_outcome),
262 fidelity,
263 standard_deviation: std_dev,
264 sample_count: samples.len(),
265 timestamp: std::time::SystemTime::now()
266 .duration_since(std::time::UNIX_EPOCH)
267 .unwrap()
268 .as_secs_f64(),
269 };
270
271 state.condition_on_homodyne_measurement(mode, calibrated_phase, mean_outcome)?;
273
274 self.measurement_history.push(result.clone());
275 Ok(result)
276 }
277
278 pub async fn heterodyne_measurement(
280 &mut self,
281 state: &mut GaussianState,
282 mode: usize,
283 ) -> DeviceResult<CVMeasurementResult> {
284 if !self.is_calibrated {
285 return Err(DeviceError::DeviceNotInitialized(
286 "Measurement system not calibrated".to_string(),
287 ));
288 }
289
290 if mode >= state.num_modes {
291 return Err(DeviceError::InvalidInput(format!(
292 "Mode {} exceeds available modes",
293 mode
294 )));
295 }
296
297 let efficiency = self
298 .config
299 .calibration
300 .efficiency
301 .get(mode)
302 .unwrap_or(&0.95);
303 let gain = self
304 .config
305 .calibration
306 .gain_factors
307 .get(mode)
308 .unwrap_or(&1.0);
309
310 let mean_x = state.mean_vector[2 * mode];
312 let mean_p = state.mean_vector[2 * mode + 1];
313 let var_x = state.covariancematrix[2 * mode][2 * mode];
314 let var_p = state.covariancematrix[2 * mode + 1][2 * mode + 1];
315
316 let noise_variance = self.calculate_detection_noise(mode);
318
319 let mut x_samples = Vec::new();
321 let mut p_samples = Vec::new();
322
323 let x_distribution =
324 Normal::new(mean_x, (var_x / efficiency + noise_variance / 2.0).sqrt())
325 .map_err(|e| DeviceError::InvalidInput(format!("Distribution error: {}", e)))?;
326 let p_distribution =
327 Normal::new(mean_p, (var_p / efficiency + noise_variance / 2.0).sqrt())
328 .map_err(|e| DeviceError::InvalidInput(format!("Distribution error: {}", e)))?;
329
330 let mut rng = StdRng::seed_from_u64(thread_rng().gen::<u64>());
331 for _ in 0..self.config.num_samples {
332 x_samples.push(x_distribution.sample(&mut rng) * gain);
333 p_samples.push(p_distribution.sample(&mut rng) * gain);
334 }
335
336 let mean_x_outcome = x_samples.iter().sum::<f64>() / x_samples.len() as f64;
338 let mean_p_outcome = p_samples.iter().sum::<f64>() / p_samples.len() as f64;
339
340 let complex_outcome = Complex::new(
341 (mean_x_outcome + mean_p_outcome * Complex::i().real) / (2.0_f64).sqrt(),
342 (mean_p_outcome - mean_x_outcome * Complex::i().imag) / (2.0_f64).sqrt(),
343 );
344
345 let x_var = x_samples
347 .iter()
348 .map(|x| (x - mean_x_outcome).powi(2))
349 .sum::<f64>()
350 / x_samples.len() as f64;
351 let p_var = p_samples
352 .iter()
353 .map(|p| (p - mean_p_outcome).powi(2))
354 .sum::<f64>()
355 / p_samples.len() as f64;
356 let std_dev = (x_var + p_var).sqrt();
357
358 let theoretical_variance = (var_x + var_p) / efficiency + noise_variance;
360 let fidelity = 1.0 / (1.0 + theoretical_variance);
361
362 let result = CVMeasurementResult {
363 outcome: CVMeasurementOutcome::Complex(complex_outcome),
364 fidelity,
365 standard_deviation: std_dev,
366 sample_count: self.config.num_samples,
367 timestamp: std::time::SystemTime::now()
368 .duration_since(std::time::UNIX_EPOCH)
369 .unwrap()
370 .as_secs_f64(),
371 };
372
373 state.condition_on_heterodyne_measurement(mode, complex_outcome)?;
375
376 self.measurement_history.push(result.clone());
377 Ok(result)
378 }
379
380 pub async fn photon_number_measurement(
382 &mut self,
383 state: &GaussianState,
384 mode: usize,
385 ) -> DeviceResult<CVMeasurementResult> {
386 if !self.is_calibrated {
387 return Err(DeviceError::DeviceNotInitialized(
388 "Measurement system not calibrated".to_string(),
389 ));
390 }
391
392 if mode >= state.num_modes {
393 return Err(DeviceError::InvalidInput(format!(
394 "Mode {} exceeds available modes",
395 mode
396 )));
397 }
398
399 let mean_x = state.mean_vector[2 * mode];
401 let mean_p = state.mean_vector[2 * mode + 1];
402 let var_x = state.covariancematrix[2 * mode][2 * mode];
403 let var_p = state.covariancematrix[2 * mode + 1][2 * mode + 1];
404
405 let mean_n = 0.5 * ((mean_x.powi(2) + mean_p.powi(2)) / 2.0 + (var_x + var_p) - 1.0);
407
408 let efficiency = self
411 .config
412 .calibration
413 .efficiency
414 .get(mode)
415 .unwrap_or(&0.95);
416 let dark_counts = self.config.calibration.dark_count_rate * self.config.integration_time;
417
418 let detected_n = mean_n * efficiency + dark_counts;
419
420 let mut samples = Vec::new();
422 let mut rng = StdRng::seed_from_u64(thread_rng().gen::<u64>());
423 for _ in 0..self.config.num_samples {
424 let sample = if detected_n > 0.0 {
425 let poisson = Poisson::new(detected_n)
426 .map_err(|e| DeviceError::InvalidInput(format!("Poisson error: {}", e)))?;
427 poisson.sample(&mut rng) as f64
428 } else {
429 0.0
430 };
431 samples.push(sample);
432 }
433
434 let mean_outcome = samples.iter().sum::<f64>() / samples.len() as f64;
435 let variance = samples
436 .iter()
437 .map(|x| (x - mean_outcome).powi(2))
438 .sum::<f64>()
439 / samples.len() as f64;
440
441 let rounded_outcome = mean_outcome.round() as i32;
442 let fidelity = 1.0 / (1.0 + variance / (mean_outcome + 1.0));
443
444 let result = CVMeasurementResult {
445 outcome: CVMeasurementOutcome::Integer(rounded_outcome),
446 fidelity,
447 standard_deviation: variance.sqrt(),
448 sample_count: samples.len(),
449 timestamp: std::time::SystemTime::now()
450 .duration_since(std::time::UNIX_EPOCH)
451 .unwrap()
452 .as_secs_f64(),
453 };
454
455 self.measurement_history.push(result.clone());
456 Ok(result)
457 }
458
459 pub async fn parity_measurement(
461 &mut self,
462 state: &GaussianState,
463 mode: usize,
464 ) -> DeviceResult<CVMeasurementResult> {
465 let photon_result = self.photon_number_measurement(state, mode).await?;
467
468 let parity = match photon_result.outcome {
469 CVMeasurementOutcome::Integer(n) => n % 2 == 0,
470 _ => {
471 return Err(DeviceError::InvalidInput(
472 "Invalid photon number result".to_string(),
473 ))
474 }
475 };
476
477 let result = CVMeasurementResult {
478 outcome: CVMeasurementOutcome::Boolean(parity),
479 fidelity: photon_result.fidelity,
480 standard_deviation: if parity { 0.0 } else { 1.0 },
481 sample_count: photon_result.sample_count,
482 timestamp: std::time::SystemTime::now()
483 .duration_since(std::time::UNIX_EPOCH)
484 .unwrap()
485 .as_secs_f64(),
486 };
487
488 self.measurement_history.push(result.clone());
489 Ok(result)
490 }
491
492 pub async fn bell_measurement(
494 &mut self,
495 state: &mut GaussianState,
496 mode1: usize,
497 mode2: usize,
498 basis: BellBasis,
499 ) -> DeviceResult<CVMeasurementResult> {
500 if mode1 >= state.num_modes || mode2 >= state.num_modes {
501 return Err(DeviceError::InvalidInput(
502 "One or both modes exceed available modes".to_string(),
503 ));
504 }
505
506 let (phase1, phase2) = match basis {
507 BellBasis::XBasis => (0.0, 0.0),
508 BellBasis::PBasis => (PI / 2.0, PI / 2.0),
509 BellBasis::MixedBasis { phase } => (0.0, phase),
510 };
511
512 let result1 = self.homodyne_measurement(state, mode1, phase1).await?;
514 let result2 = self.homodyne_measurement(state, mode2, phase2).await?;
515
516 let (val1, val2) = match (result1.outcome, result2.outcome) {
518 (CVMeasurementOutcome::Real(v1), CVMeasurementOutcome::Real(v2)) => (v1, v2),
519 _ => {
520 return Err(DeviceError::InvalidInput(
521 "Invalid homodyne results".to_string(),
522 ))
523 }
524 };
525
526 let correlation = val1 * val2;
527 let avg_phase = (phase1 + phase2) / 2.0;
528
529 let result = CVMeasurementResult {
530 outcome: CVMeasurementOutcome::BellCorrelation {
531 correlation,
532 phase: avg_phase,
533 },
534 fidelity: (result1.fidelity + result2.fidelity) / 2.0,
535 standard_deviation: (result1.standard_deviation.powi(2)
536 + result2.standard_deviation.powi(2))
537 .sqrt(),
538 sample_count: result1.sample_count.min(result2.sample_count),
539 timestamp: std::time::SystemTime::now()
540 .duration_since(std::time::UNIX_EPOCH)
541 .unwrap()
542 .as_secs_f64(),
543 };
544
545 self.measurement_history.push(result.clone());
546 Ok(result)
547 }
548
549 fn calculate_detection_noise(&self, mode: usize) -> f64 {
551 let electronic_noise = 10.0_f64.powf(self.config.calibration.electronic_noise_db / 10.0);
552 let efficiency = self
553 .config
554 .calibration
555 .efficiency
556 .get(mode)
557 .unwrap_or(&0.95);
558 let phase_noise = self.config.phase_stability.powi(2);
559
560 electronic_noise + (1.0 - efficiency) / efficiency + phase_noise
561 }
562
563 fn estimate_measurement_fidelity(
565 &self,
566 samples: &[f64],
567 theoretical_mean: f64,
568 theoretical_variance: f64,
569 ) -> f64 {
570 let sample_mean = samples.iter().sum::<f64>() / samples.len() as f64;
571 let sample_variance = samples
572 .iter()
573 .map(|x| (x - sample_mean).powi(2))
574 .sum::<f64>()
575 / samples.len() as f64;
576
577 let mean_error = (sample_mean - theoretical_mean).abs();
578 let variance_error = (sample_variance - theoretical_variance).abs();
579
580 let fidelity = 1.0 / (1.0 + mean_error + variance_error);
582 fidelity.clamp(0.0, 1.0)
583 }
584
585 pub fn get_measurement_history(&self) -> &[CVMeasurementResult] {
587 &self.measurement_history
588 }
589
590 pub fn clear_history(&mut self) {
592 self.measurement_history.clear();
593 }
594
595 pub fn get_measurement_statistics(&self) -> MeasurementStatistics {
597 if self.measurement_history.is_empty() {
598 return MeasurementStatistics::default();
599 }
600
601 let total_measurements = self.measurement_history.len();
602 let avg_fidelity = self
603 .measurement_history
604 .iter()
605 .map(|r| r.fidelity)
606 .sum::<f64>()
607 / total_measurements as f64;
608
609 let avg_std_dev = self
610 .measurement_history
611 .iter()
612 .map(|r| r.standard_deviation)
613 .sum::<f64>()
614 / total_measurements as f64;
615
616 let total_samples = self
617 .measurement_history
618 .iter()
619 .map(|r| r.sample_count)
620 .sum::<usize>();
621
622 MeasurementStatistics {
623 total_measurements,
624 average_fidelity: avg_fidelity,
625 average_standard_deviation: avg_std_dev,
626 total_samples,
627 is_calibrated: self.is_calibrated,
628 }
629 }
630}
631
632#[derive(Debug, Clone, Serialize, Deserialize)]
634pub struct MeasurementStatistics {
635 pub total_measurements: usize,
636 pub average_fidelity: f64,
637 pub average_standard_deviation: f64,
638 pub total_samples: usize,
639 pub is_calibrated: bool,
640}
641
642impl Default for MeasurementStatistics {
643 fn default() -> Self {
644 Self {
645 total_measurements: 0,
646 average_fidelity: 0.0,
647 average_standard_deviation: 0.0,
648 total_samples: 0,
649 is_calibrated: false,
650 }
651 }
652}
653
654#[cfg(test)]
655mod tests {
656 use super::*;
657
658 #[tokio::test]
659 async fn test_measurement_engine_creation() {
660 let config = CVMeasurementConfig::default();
661 let engine = CVMeasurementEngine::new(config);
662 assert!(!engine.is_calibrated);
663 assert_eq!(engine.measurement_history.len(), 0);
664 }
665
666 #[tokio::test]
667 async fn test_calibration() {
668 let config = CVMeasurementConfig::default();
669 let mut engine = CVMeasurementEngine::new(config);
670
671 engine.calibrate().await.unwrap();
672 assert!(engine.is_calibrated);
673 }
674
675 #[tokio::test]
676 async fn test_homodyne_measurement() {
677 let config = CVMeasurementConfig::default();
678 let mut engine = CVMeasurementEngine::new(config);
679 engine.calibrate().await.unwrap();
680
681 let mut state =
682 GaussianState::coherent_state(2, vec![Complex::new(2.0, 0.0), Complex::new(0.0, 0.0)])
683 .unwrap();
684
685 let result = engine
686 .homodyne_measurement(&mut state, 0, 0.0)
687 .await
688 .unwrap();
689
690 match result.outcome {
691 CVMeasurementOutcome::Real(value) => {
692 assert!(value > 0.0); }
694 _ => panic!("Expected real outcome"),
695 }
696
697 assert!(result.fidelity > 0.0);
698 assert_eq!(engine.measurement_history.len(), 1);
699 }
700
701 #[tokio::test]
702 async fn test_heterodyne_measurement() {
703 let config = CVMeasurementConfig::default();
704 let mut engine = CVMeasurementEngine::new(config);
705 engine.calibrate().await.unwrap();
706
707 let mut state = GaussianState::coherent_state(1, vec![Complex::new(1.0, 0.5)]).unwrap();
708
709 let result = engine.heterodyne_measurement(&mut state, 0).await.unwrap();
710
711 match result.outcome {
712 CVMeasurementOutcome::Complex(z) => {
713 assert!(z.magnitude() > 0.0);
714 }
715 _ => panic!("Expected complex outcome"),
716 }
717 }
718
719 #[tokio::test]
720 async fn test_photon_number_measurement() {
721 let config = CVMeasurementConfig::default();
722 let mut engine = CVMeasurementEngine::new(config);
723 engine.calibrate().await.unwrap();
724
725 let state = GaussianState::coherent_state(1, vec![Complex::new(2.0, 0.0)]).unwrap();
726
727 let result = engine.photon_number_measurement(&state, 0).await.unwrap();
728
729 match result.outcome {
730 CVMeasurementOutcome::Integer(n) => {
731 assert!(n >= 0); }
733 _ => panic!("Expected integer outcome"),
734 }
735 }
736
737 #[tokio::test]
738 async fn test_parity_measurement() {
739 let config = CVMeasurementConfig::default();
740 let mut engine = CVMeasurementEngine::new(config);
741 engine.calibrate().await.unwrap();
742
743 let state = GaussianState::vacuum_state(1);
744
745 let result = engine.parity_measurement(&state, 0).await.unwrap();
746
747 match result.outcome {
748 CVMeasurementOutcome::Boolean(parity) => {
749 assert!(parity);
751 }
752 _ => panic!("Expected boolean outcome"),
753 }
754 }
755
756 #[test]
757 fn test_measurement_config_defaults() {
758 let config = CVMeasurementConfig::default();
759 assert_eq!(config.num_samples, 10000);
760 assert_eq!(config.integration_time, 0.001);
761 assert!(config.enable_post_processing);
762 }
763
764 #[test]
765 fn test_measurement_statistics() {
766 let config = CVMeasurementConfig::default();
767 let engine = CVMeasurementEngine::new(config);
768
769 let stats = engine.get_measurement_statistics();
770 assert_eq!(stats.total_measurements, 0);
771 assert!(!stats.is_calibrated);
772 }
773}