1use crate::{CircuitExecutor, CircuitResult, DeviceError, DeviceResult, QuantumDevice};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::f64::consts::PI;
11use std::time::Duration;
12
13pub mod cluster_states;
14pub mod cv_gates;
15pub mod error_correction;
16pub mod gaussian_states;
17pub mod heterodyne;
18pub mod homodyne;
19pub mod measurements;
20
21pub use cluster_states::*;
22pub use cv_gates::*;
23pub use error_correction::*;
24pub use gaussian_states::*;
25pub use heterodyne::*;
26pub use homodyne::*;
27pub use measurements::*;
28
29#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
31pub struct Complex {
32 pub real: f64,
33 pub imag: f64,
34}
35
36impl Complex {
37 pub const fn new(real: f64, imag: f64) -> Self {
38 Self { real, imag }
39 }
40
41 pub const fn zero() -> Self {
42 Self {
43 real: 0.0,
44 imag: 0.0,
45 }
46 }
47
48 pub const fn one() -> Self {
49 Self {
50 real: 1.0,
51 imag: 0.0,
52 }
53 }
54
55 pub const fn i() -> Self {
56 Self {
57 real: 0.0,
58 imag: 1.0,
59 }
60 }
61
62 pub fn magnitude(&self) -> f64 {
63 self.real.hypot(self.imag)
64 }
65
66 pub fn phase(&self) -> f64 {
67 self.imag.atan2(self.real)
68 }
69
70 #[must_use]
71 pub fn conjugate(&self) -> Self {
72 Self {
73 real: self.real,
74 imag: -self.imag,
75 }
76 }
77}
78
79impl std::ops::Add for Complex {
80 type Output = Self;
81 fn add(self, other: Self) -> Self {
82 Self {
83 real: self.real + other.real,
84 imag: self.imag + other.imag,
85 }
86 }
87}
88
89impl std::ops::Mul for Complex {
90 type Output = Self;
91 fn mul(self, other: Self) -> Self {
92 Self {
93 real: self.real.mul_add(other.real, -(self.imag * other.imag)),
94 imag: self.real.mul_add(other.imag, self.imag * other.real),
95 }
96 }
97}
98
99impl std::ops::Mul<f64> for Complex {
100 type Output = Self;
101 fn mul(self, scalar: f64) -> Self {
102 Self {
103 real: self.real * scalar,
104 imag: self.imag * scalar,
105 }
106 }
107}
108
109#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
111pub enum CVSystemType {
112 GaussianStates,
114 ClusterState,
116 MeasurementBased,
118 HybridDvCv,
120}
121
122pub struct CVQuantumDevice {
124 pub system_type: CVSystemType,
126 pub num_modes: usize,
128 pub mode_frequencies: Vec<f64>,
130 pub gaussian_state: GaussianState,
132 pub config: CVDeviceConfig,
134 pub is_connected: bool,
136 pub measurement_history: Vec<CVMeasurementResult>,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct CVDeviceConfig {
143 pub max_squeezing_db: f64,
145 pub optical_power_mw: f64,
147 pub detection_efficiency: f64,
149 pub electronic_noise_db: f64,
151 pub homodyne_bandwidth_hz: f64,
153 pub phase_noise: f64,
155 pub temperature_k: f64,
157 pub enable_error_correction: bool,
159}
160
161impl Default for CVDeviceConfig {
162 fn default() -> Self {
163 Self {
164 max_squeezing_db: 15.0,
165 optical_power_mw: 1.0,
166 detection_efficiency: 0.95,
167 electronic_noise_db: -90.0,
168 homodyne_bandwidth_hz: 10e6,
169 phase_noise: 1e-6,
170 temperature_k: 0.1,
171 enable_error_correction: true,
172 }
173 }
174}
175
176impl CVQuantumDevice {
177 pub fn new(
179 system_type: CVSystemType,
180 num_modes: usize,
181 config: CVDeviceConfig,
182 ) -> DeviceResult<Self> {
183 let mode_frequencies = (0..num_modes)
184 .map(|i| (i as f64).mul_add(1e12, 1e14)) .collect();
186
187 let gaussian_state = GaussianState::vacuum_state(num_modes);
188
189 Ok(Self {
190 system_type,
191 num_modes,
192 mode_frequencies,
193 gaussian_state,
194 config,
195 is_connected: false,
196 measurement_history: Vec::new(),
197 })
198 }
199
200 pub async fn connect(&mut self) -> DeviceResult<()> {
202 tokio::time::sleep(Duration::from_millis(200)).await;
204
205 self.initialize_optical_system().await?;
207
208 self.is_connected = true;
209 Ok(())
210 }
211
212 async fn initialize_optical_system(&mut self) -> DeviceResult<()> {
214 for (i, &freq) in self.mode_frequencies.iter().enumerate() {
216 println!("Initializing mode {i} at frequency {freq:.2e} Hz");
217 }
218
219 println!("Initializing homodyne detection system");
221
222 println!("Initializing squeezing apparatus");
224
225 Ok(())
226 }
227
228 pub async fn disconnect(&mut self) -> DeviceResult<()> {
230 self.is_connected = false;
231 Ok(())
232 }
233
234 pub async fn displacement(
236 &mut self,
237 mode: usize,
238 amplitude: f64,
239 phase: f64,
240 ) -> DeviceResult<()> {
241 if mode >= self.num_modes {
242 return Err(DeviceError::InvalidInput(format!(
243 "Mode {} exceeds available modes {}",
244 mode, self.num_modes
245 )));
246 }
247
248 let displacement = Complex::new(amplitude * phase.cos(), amplitude * phase.sin());
249
250 self.gaussian_state.apply_displacement(mode, displacement)?;
251 Ok(())
252 }
253
254 pub async fn squeezing(
256 &mut self,
257 mode: usize,
258 squeezing_param: f64,
259 phase: f64,
260 ) -> DeviceResult<()> {
261 if mode >= self.num_modes {
262 return Err(DeviceError::InvalidInput(format!(
263 "Mode {} exceeds available modes {}",
264 mode, self.num_modes
265 )));
266 }
267
268 if squeezing_param.abs() > self.config.max_squeezing_db / 8.686 {
269 return Err(DeviceError::InvalidInput(format!(
270 "Squeezing parameter {squeezing_param} exceeds maximum"
271 )));
272 }
273
274 self.gaussian_state
275 .apply_squeezing(mode, squeezing_param, phase)?;
276 Ok(())
277 }
278
279 pub async fn two_mode_squeezing(
281 &mut self,
282 mode1: usize,
283 mode2: usize,
284 squeezing_param: f64,
285 phase: f64,
286 ) -> DeviceResult<()> {
287 if mode1 >= self.num_modes || mode2 >= self.num_modes {
288 return Err(DeviceError::InvalidInput(
289 "One or both modes exceed available modes".to_string(),
290 ));
291 }
292
293 self.gaussian_state
294 .apply_two_mode_squeezing(mode1, mode2, squeezing_param, phase)?;
295 Ok(())
296 }
297
298 pub async fn beamsplitter(
300 &mut self,
301 mode1: usize,
302 mode2: usize,
303 transmittance: f64,
304 phase: f64,
305 ) -> DeviceResult<()> {
306 if mode1 >= self.num_modes || mode2 >= self.num_modes {
307 return Err(DeviceError::InvalidInput(
308 "One or both modes exceed available modes".to_string(),
309 ));
310 }
311
312 if !(0.0..=1.0).contains(&transmittance) {
313 return Err(DeviceError::InvalidInput(
314 "Transmittance must be between 0 and 1".to_string(),
315 ));
316 }
317
318 self.gaussian_state
319 .apply_beamsplitter(mode1, mode2, transmittance, phase)?;
320 Ok(())
321 }
322
323 pub async fn phase_rotation(&mut self, mode: usize, phase: f64) -> DeviceResult<()> {
325 if mode >= self.num_modes {
326 return Err(DeviceError::InvalidInput(format!(
327 "Mode {} exceeds available modes {}",
328 mode, self.num_modes
329 )));
330 }
331
332 self.gaussian_state.apply_phase_rotation(mode, phase)?;
333 Ok(())
334 }
335
336 pub async fn homodyne_measurement(&mut self, mode: usize, phase: f64) -> DeviceResult<f64> {
338 if mode >= self.num_modes {
339 return Err(DeviceError::InvalidInput(format!(
340 "Mode {} exceeds available modes {}",
341 mode, self.num_modes
342 )));
343 }
344
345 let result = self
346 .gaussian_state
347 .homodyne_measurement(mode, phase, &self.config)?;
348
349 self.measurement_history.push(CVMeasurementResult {
350 mode,
351 measurement_type: CVMeasurementType::Homodyne { phase },
352 result: CVMeasurementOutcome::Real(result),
353 timestamp: std::time::SystemTime::now()
354 .duration_since(std::time::UNIX_EPOCH)
355 .unwrap_or_default()
356 .as_secs_f64(),
357 });
358
359 Ok(result)
360 }
361
362 pub async fn heterodyne_measurement(&mut self, mode: usize) -> DeviceResult<Complex> {
364 if mode >= self.num_modes {
365 return Err(DeviceError::InvalidInput(format!(
366 "Mode {} exceeds available modes {}",
367 mode, self.num_modes
368 )));
369 }
370
371 let result = self
372 .gaussian_state
373 .heterodyne_measurement(mode, &self.config)?;
374
375 self.measurement_history.push(CVMeasurementResult {
376 mode,
377 measurement_type: CVMeasurementType::Heterodyne,
378 result: CVMeasurementOutcome::Complex(result),
379 timestamp: std::time::SystemTime::now()
380 .duration_since(std::time::UNIX_EPOCH)
381 .unwrap_or_default()
382 .as_secs_f64(),
383 });
384
385 Ok(result)
386 }
387
388 pub async fn reset_mode(&mut self, mode: usize) -> DeviceResult<()> {
390 if mode >= self.num_modes {
391 return Err(DeviceError::InvalidInput(format!(
392 "Mode {} exceeds available modes {}",
393 mode, self.num_modes
394 )));
395 }
396
397 self.gaussian_state.reset_mode_to_vacuum(mode)?;
398 Ok(())
399 }
400
401 pub fn get_mode_state(&self, mode: usize) -> DeviceResult<CVModeState> {
403 if mode >= self.num_modes {
404 return Err(DeviceError::InvalidInput(format!(
405 "Mode {} exceeds available modes {}",
406 mode, self.num_modes
407 )));
408 }
409
410 self.gaussian_state.get_mode_state(mode)
411 }
412
413 pub fn get_entanglement_measures(&self) -> CVEntanglementMeasures {
415 self.gaussian_state.calculate_entanglement_measures()
416 }
417
418 pub async fn get_diagnostics(&self) -> CVDeviceDiagnostics {
420 CVDeviceDiagnostics {
421 is_connected: self.is_connected,
422 num_modes: self.num_modes,
423 total_measurements: self.measurement_history.len(),
424 average_squeezing: self.gaussian_state.calculate_average_squeezing(),
425 system_purity: self.gaussian_state.calculate_purity(),
426 entanglement_entropy: self.gaussian_state.calculate_entanglement_entropy(),
427 optical_power_mw: self.config.optical_power_mw,
428 detection_efficiency: self.config.detection_efficiency,
429 }
430 }
431}
432
433#[derive(Debug, Clone, Serialize, Deserialize)]
435pub enum CVMeasurementType {
436 Homodyne { phase: f64 },
438 Heterodyne,
440 PhotonNumber,
442 Parity,
444}
445
446#[derive(Debug, Clone, Serialize, Deserialize)]
448pub enum CVMeasurementOutcome {
449 Real(f64),
450 Complex(Complex),
451 Integer(i32),
452 Boolean(bool),
453}
454
455#[derive(Debug, Clone, Serialize, Deserialize)]
457pub struct CVMeasurementResult {
458 pub mode: usize,
459 pub measurement_type: CVMeasurementType,
460 pub result: CVMeasurementOutcome,
461 pub timestamp: f64,
462}
463
464#[derive(Debug, Clone, Serialize, Deserialize)]
466pub struct CVModeState {
467 pub mean_amplitude: Complex,
469 pub quadrature_variances: (f64, f64),
471 pub squeezing_parameter: f64,
473 pub squeezing_phase: f64,
475 pub purity: f64,
477}
478
479#[derive(Debug, Clone, Serialize, Deserialize)]
481pub struct CVEntanglementMeasures {
482 pub logarithmic_negativity: f64,
484 pub entanglement_of_formation: f64,
486 pub mutual_information: f64,
488 pub epr_correlation: f64,
490}
491
492#[derive(Debug, Clone, Serialize, Deserialize)]
494pub struct CVDeviceDiagnostics {
495 pub is_connected: bool,
496 pub num_modes: usize,
497 pub total_measurements: usize,
498 pub average_squeezing: f64,
499 pub system_purity: f64,
500 pub entanglement_entropy: f64,
501 pub optical_power_mw: f64,
502 pub detection_efficiency: f64,
503}
504
505#[cfg(feature = "ibm")]
506#[async_trait::async_trait]
507impl QuantumDevice for CVQuantumDevice {
508 async fn is_available(&self) -> DeviceResult<bool> {
509 Ok(self.is_connected)
510 }
511
512 async fn qubit_count(&self) -> DeviceResult<usize> {
513 Ok(self.num_modes)
515 }
516
517 async fn properties(&self) -> DeviceResult<HashMap<String, String>> {
518 let mut props = HashMap::new();
519 props.insert("device_type".to_string(), "continuous_variable".to_string());
520 props.insert("system_type".to_string(), format!("{:?}", self.system_type));
521 props.insert("num_modes".to_string(), self.num_modes.to_string());
522 props.insert(
523 "max_squeezing_db".to_string(),
524 self.config.max_squeezing_db.to_string(),
525 );
526 props.insert(
527 "detection_efficiency".to_string(),
528 self.config.detection_efficiency.to_string(),
529 );
530 props.insert(
531 "optical_power_mw".to_string(),
532 self.config.optical_power_mw.to_string(),
533 );
534 Ok(props)
535 }
536
537 async fn is_simulator(&self) -> DeviceResult<bool> {
538 Ok(true) }
540}
541
542#[cfg(not(feature = "ibm"))]
543impl QuantumDevice for CVQuantumDevice {
544 fn is_available(&self) -> DeviceResult<bool> {
545 Ok(self.is_connected)
546 }
547
548 fn qubit_count(&self) -> DeviceResult<usize> {
549 Ok(self.num_modes)
551 }
552
553 fn properties(&self) -> DeviceResult<HashMap<String, String>> {
554 let mut props = HashMap::new();
555 props.insert("device_type".to_string(), "continuous_variable".to_string());
556 props.insert("system_type".to_string(), format!("{:?}", self.system_type));
557 props.insert("num_modes".to_string(), self.num_modes.to_string());
558 props.insert(
559 "max_squeezing_db".to_string(),
560 self.config.max_squeezing_db.to_string(),
561 );
562 props.insert(
563 "detection_efficiency".to_string(),
564 self.config.detection_efficiency.to_string(),
565 );
566 props.insert(
567 "optical_power_mw".to_string(),
568 self.config.optical_power_mw.to_string(),
569 );
570 Ok(props)
571 }
572
573 fn is_simulator(&self) -> DeviceResult<bool> {
574 Ok(true) }
576}
577
578pub fn create_gaussian_cv_device(
580 num_modes: usize,
581 config: Option<CVDeviceConfig>,
582) -> DeviceResult<CVQuantumDevice> {
583 let config = config.unwrap_or_default();
584 CVQuantumDevice::new(CVSystemType::GaussianStates, num_modes, config)
585}
586
587pub fn create_cluster_state_cv_device(
589 num_modes: usize,
590 config: Option<CVDeviceConfig>,
591) -> DeviceResult<CVQuantumDevice> {
592 let config = config.unwrap_or_default();
593 CVQuantumDevice::new(CVSystemType::ClusterState, num_modes, config)
594}
595
596#[cfg(test)]
597mod tests {
598 use super::*;
599
600 #[tokio::test]
601 async fn test_cv_device_creation() {
602 let device = create_gaussian_cv_device(4, None).expect("Failed to create CV device");
603 assert_eq!(device.num_modes, 4);
604 assert_eq!(device.system_type, CVSystemType::GaussianStates);
605 }
606
607 #[tokio::test]
608 async fn test_cv_device_connection() {
609 let mut device = create_gaussian_cv_device(2, None).expect("Failed to create CV device");
610 assert!(!device.is_connected);
611
612 device.connect().await.expect("Failed to connect");
613 assert!(device.is_connected);
614
615 device.disconnect().await.expect("Failed to disconnect");
616 assert!(!device.is_connected);
617 }
618
619 #[tokio::test]
620 async fn test_displacement_operation() {
621 let mut device = create_gaussian_cv_device(2, None).expect("Failed to create CV device");
622 device.connect().await.expect("Failed to connect");
623
624 device
625 .displacement(0, 1.0, PI / 4.0)
626 .await
627 .expect("Failed to apply displacement");
628
629 let state = device.get_mode_state(0).expect("Failed to get mode state");
630 assert!(state.mean_amplitude.magnitude() > 0.0);
631 }
632
633 #[tokio::test]
634 async fn test_squeezing_operation() {
635 let mut device = create_gaussian_cv_device(2, None).expect("Failed to create CV device");
636 device.connect().await.expect("Failed to connect");
637
638 device
639 .squeezing(0, 1.0, 0.0)
640 .await
641 .expect("Failed to apply squeezing");
642
643 let state = device.get_mode_state(0).expect("Failed to get mode state");
644 assert!(state.squeezing_parameter > 0.0);
645 }
646
647 #[tokio::test]
648 async fn test_homodyne_measurement() {
649 let mut device = create_gaussian_cv_device(2, None).expect("Failed to create CV device");
650 device.connect().await.expect("Failed to connect");
651
652 device
654 .displacement(0, 2.0, 0.0)
655 .await
656 .expect("Failed to apply displacement");
657
658 let result = device
659 .homodyne_measurement(0, 0.0)
660 .await
661 .expect("Failed to perform homodyne measurement");
662 assert!(result.is_finite());
663
664 assert_eq!(device.measurement_history.len(), 1);
665 }
666
667 #[test]
668 fn test_complex_number_operations() {
669 let z1 = Complex::new(1.0, 2.0);
670 let z2 = Complex::new(3.0, 4.0);
671
672 let sum = z1 + z2;
673 assert_eq!(sum.real, 4.0);
674 assert_eq!(sum.imag, 6.0);
675
676 let product = z1 * z2;
677 assert_eq!(product.real, -5.0);
678 assert_eq!(product.imag, 10.0);
679
680 assert!((z1.magnitude() - (5.0_f64).sqrt()).abs() < 1e-10);
681 }
682}