1use async_trait::async_trait;
7use std::collections::HashMap;
8use std::sync::{Arc, RwLock};
9use std::time::{Duration, Instant};
10use thiserror::Error;
11
12use quantrs2_circuit::prelude::Circuit;
13use quantrs2_core::qubit::QubitId;
14
15use super::{
16 validate_photonic_config, PhotonicCircuitResult, PhotonicClient, PhotonicDeviceConfig,
17 PhotonicExecutionMetadata, PhotonicMeasurementData, PhotonicQuantumDevice, PhotonicSystemType,
18};
19use crate::{CircuitExecutor, CircuitResult, DeviceError, DeviceResult, QuantumDevice};
20use scirs2_core::random::prelude::*;
21
22#[derive(Debug, Clone)]
24pub struct PhotonicQuantumDeviceImpl {
25 pub device_id: String,
27 pub client: PhotonicClient,
29 pub config: PhotonicDeviceConfig,
31 capabilities: Arc<RwLock<Option<PhotonicCapabilities>>>,
33 calibration: Arc<RwLock<PhotonicCalibrationData>>,
35 metrics: Arc<RwLock<PhotonicPerformanceMetrics>>,
37}
38
39#[derive(Debug, Clone)]
41pub struct PhotonicCapabilities {
42 pub supported_systems: Vec<PhotonicSystemType>,
44 pub max_modes: usize,
46 pub max_cutoff: usize,
48 pub supported_gates: Vec<String>,
50 pub max_squeezing: f64,
52 pub min_detection_efficiency: f64,
54 pub supported_measurements: Vec<String>,
56 pub hardware_features: HashMap<String, bool>,
58}
59
60#[derive(Debug, Clone)]
62pub struct PhotonicCalibrationData {
63 pub mode_losses: HashMap<usize, f64>,
65 pub beamsplitter_transmittances: HashMap<(usize, usize), f64>,
67 pub detector_efficiencies: HashMap<usize, f64>,
69 pub phase_accuracies: HashMap<usize, f64>,
71 pub squeezing_calibration: HashMap<usize, (f64, f64)>,
73 pub crosstalk_matrix: HashMap<(usize, usize), f64>,
75 pub last_calibration: Instant,
77 pub validity_duration: Duration,
79}
80
81#[derive(Debug, Clone)]
83pub struct PhotonicPerformanceMetrics {
84 pub circuits_executed: u64,
86 pub avg_execution_time: Duration,
88 pub success_rate: f64,
90 pub avg_fidelity: f64,
92 pub mode_utilization: HashMap<usize, f64>,
94 pub gate_counts: HashMap<String, u64>,
96 pub error_rates: HashMap<String, f64>,
98}
99
100impl PhotonicQuantumDeviceImpl {
101 pub async fn new(
103 device_id: String,
104 client: PhotonicClient,
105 config: PhotonicDeviceConfig,
106 ) -> DeviceResult<Self> {
107 validate_photonic_config(&config)?;
109
110 let device = Self {
111 device_id,
112 client,
113 config,
114 capabilities: Arc::new(RwLock::new(None)),
115 calibration: Arc::new(RwLock::new(PhotonicCalibrationData::default())),
116 metrics: Arc::new(RwLock::new(PhotonicPerformanceMetrics::default())),
117 };
118
119 device.initialize().await?;
121
122 Ok(device)
123 }
124
125 async fn initialize(&self) -> DeviceResult<()> {
127 let capabilities = self.load_capabilities().await?;
129 *self
130 .capabilities
131 .write()
132 .map_err(|e| DeviceError::LockError(format!("Capabilities lock poisoned: {e}")))? =
133 Some(capabilities);
134
135 let calibration = self.load_calibration_data().await?;
137 *self
138 .calibration
139 .write()
140 .map_err(|e| DeviceError::LockError(format!("Calibration lock poisoned: {e}")))? =
141 calibration;
142
143 Ok(())
144 }
145
146 async fn load_capabilities(&self) -> DeviceResult<PhotonicCapabilities> {
148 let mut supported_systems = vec![PhotonicSystemType::ContinuousVariable];
149
150 match self.config.system_type {
152 PhotonicSystemType::ContinuousVariable => {
153 supported_systems.push(PhotonicSystemType::ContinuousVariable);
154 }
155 PhotonicSystemType::GateBased => {
156 supported_systems.push(PhotonicSystemType::GateBased);
157 }
158 PhotonicSystemType::MeasurementBased => {
159 supported_systems.push(PhotonicSystemType::MeasurementBased);
160 }
161 PhotonicSystemType::Hybrid => {
162 supported_systems.extend(&[
163 PhotonicSystemType::ContinuousVariable,
164 PhotonicSystemType::GateBased,
165 PhotonicSystemType::MeasurementBased,
166 ]);
167 }
168 }
169
170 let supported_gates = vec![
171 "displacement".to_string(),
172 "squeezing".to_string(),
173 "two_mode_squeezing".to_string(),
174 "beamsplitter".to_string(),
175 "phase_rotation".to_string(),
176 "kerr".to_string(),
177 "cross_kerr".to_string(),
178 "homodyne".to_string(),
179 "heterodyne".to_string(),
180 ];
181
182 let supported_measurements = vec![
183 "homodyne".to_string(),
184 "heterodyne".to_string(),
185 "photon_counting".to_string(),
186 "quadrature".to_string(),
187 ];
188
189 let mut hardware_features = HashMap::new();
190 hardware_features.insert("squeezed_light_source".to_string(), true);
191 hardware_features.insert("programmable_beamsplitters".to_string(), true);
192 hardware_features.insert("high_efficiency_detectors".to_string(), true);
193 hardware_features.insert(
194 "real_time_feedback".to_string(),
195 self.config.hardware_acceleration,
196 );
197
198 Ok(PhotonicCapabilities {
199 supported_systems,
200 max_modes: self.config.mode_count * 2, max_cutoff: self.config.cutoff_dimension.unwrap_or(20),
202 supported_gates,
203 max_squeezing: 10.0, min_detection_efficiency: 0.8,
205 supported_measurements,
206 hardware_features,
207 })
208 }
209
210 async fn load_calibration_data(&self) -> DeviceResult<PhotonicCalibrationData> {
212 let mut mode_losses = HashMap::new();
213 let mut detector_efficiencies = HashMap::new();
214 let mut phase_accuracies = HashMap::new();
215 let mut squeezing_calibration = HashMap::new();
216
217 for mode in 0..self.config.mode_count {
219 mode_losses.insert(mode, self.config.loss_rate.unwrap_or(0.01));
220 detector_efficiencies.insert(mode, self.config.detection_efficiency.unwrap_or(0.9));
221 phase_accuracies.insert(mode, 0.001); squeezing_calibration.insert(mode, (0.0, 0.0)); }
224
225 Ok(PhotonicCalibrationData {
226 mode_losses,
227 beamsplitter_transmittances: HashMap::new(),
228 detector_efficiencies,
229 phase_accuracies,
230 squeezing_calibration,
231 crosstalk_matrix: HashMap::new(),
232 last_calibration: Instant::now(),
233 validity_duration: Duration::from_secs(3600), })
235 }
236
237 fn update_metrics(&self, execution_time: Duration, success: bool, fidelity: Option<f64>) {
239 let Ok(mut metrics) = self.metrics.write() else {
240 return;
242 };
243
244 metrics.circuits_executed += 1;
245
246 let total_time =
248 metrics.avg_execution_time * (metrics.circuits_executed - 1) as u32 + execution_time;
249 metrics.avg_execution_time = total_time / metrics.circuits_executed as u32;
250
251 let total_success = metrics.success_rate.mul_add(
253 (metrics.circuits_executed - 1) as f64,
254 if success { 1.0 } else { 0.0 },
255 );
256 metrics.success_rate = total_success / metrics.circuits_executed as f64;
257
258 if let Some(fid) = fidelity {
260 let total_fidelity = metrics
261 .avg_fidelity
262 .mul_add((metrics.circuits_executed - 1) as f64, fid);
263 metrics.avg_fidelity = total_fidelity / metrics.circuits_executed as f64;
264 }
265 }
266
267 fn is_calibration_valid(&self) -> bool {
269 let Ok(calibration) = self.calibration.read() else {
270 return false;
272 };
273 calibration.last_calibration.elapsed() < calibration.validity_duration
274 }
275
276 async fn ensure_calibrated(&self) -> DeviceResult<()> {
278 if !self.is_calibration_valid() {
279 let new_calibration = self.load_calibration_data().await?;
280 *self
281 .calibration
282 .write()
283 .map_err(|e| DeviceError::LockError(format!("Calibration lock poisoned: {e}")))? =
284 new_calibration;
285 }
286 Ok(())
287 }
288}
289
290#[async_trait]
291impl QuantumDevice for PhotonicQuantumDeviceImpl {
292 async fn is_available(&self) -> DeviceResult<bool> {
293 self.client.check_availability().await
295 }
296
297 async fn qubit_count(&self) -> DeviceResult<usize> {
298 Ok(self.config.mode_count)
300 }
301
302 async fn properties(&self) -> DeviceResult<HashMap<String, String>> {
303 let mut properties = HashMap::new();
304
305 properties.insert(
306 "system_type".to_string(),
307 format!("{:?}", self.config.system_type),
308 );
309 properties.insert("mode_count".to_string(), self.config.mode_count.to_string());
310
311 if let Some(cutoff) = self.config.cutoff_dimension {
312 properties.insert("cutoff_dimension".to_string(), cutoff.to_string());
313 }
314
315 if let Some(loss_rate) = self.config.loss_rate {
316 properties.insert("loss_rate".to_string(), loss_rate.to_string());
317 }
318
319 if let Some(efficiency) = self.config.detection_efficiency {
320 properties.insert("detection_efficiency".to_string(), efficiency.to_string());
321 }
322
323 properties.insert(
325 "calibration_valid".to_string(),
326 self.is_calibration_valid().to_string(),
327 );
328
329 let metrics = self
331 .metrics
332 .read()
333 .map_err(|e| DeviceError::LockError(format!("Metrics lock poisoned: {e}")))?;
334 properties.insert(
335 "circuits_executed".to_string(),
336 metrics.circuits_executed.to_string(),
337 );
338 properties.insert("success_rate".to_string(), metrics.success_rate.to_string());
339 properties.insert("avg_fidelity".to_string(), metrics.avg_fidelity.to_string());
340
341 Ok(properties)
342 }
343
344 async fn is_simulator(&self) -> DeviceResult<bool> {
345 self.client.is_simulator().await
347 }
348}
349
350#[async_trait]
351impl CircuitExecutor for PhotonicQuantumDeviceImpl {
352 async fn execute_circuit<const N: usize>(
353 &self,
354 circuit: &Circuit<N>,
355 shots: usize,
356 ) -> DeviceResult<CircuitResult> {
357 let photonic_result = self.execute_photonic_circuit(circuit, shots, None).await?;
358 Ok(photonic_result.circuit_result)
359 }
360
361 async fn execute_circuits<const N: usize>(
362 &self,
363 circuits: Vec<&Circuit<N>>,
364 shots: usize,
365 ) -> DeviceResult<Vec<CircuitResult>> {
366 let mut results = Vec::new();
367
368 for circuit in circuits {
369 let result = self.execute_circuit(circuit, shots).await?;
370 results.push(result);
371 }
372
373 Ok(results)
374 }
375
376 async fn can_execute_circuit<const N: usize>(
377 &self,
378 circuit: &Circuit<N>,
379 ) -> DeviceResult<bool> {
380 if N > self.config.mode_count {
384 return Ok(false);
385 }
386
387 Ok(true)
391 }
392
393 async fn estimated_queue_time<const N: usize>(
394 &self,
395 _circuit: &Circuit<N>,
396 ) -> DeviceResult<Duration> {
397 self.client.get_queue_time().await
400 }
401}
402
403#[async_trait]
404impl PhotonicQuantumDevice for PhotonicQuantumDeviceImpl {
405 async fn system_type(&self) -> DeviceResult<PhotonicSystemType> {
406 Ok(self.config.system_type)
407 }
408
409 async fn mode_count(&self) -> DeviceResult<usize> {
410 Ok(self.config.mode_count)
411 }
412
413 async fn cutoff_dimension(&self) -> DeviceResult<Option<usize>> {
414 Ok(self.config.cutoff_dimension)
415 }
416
417 async fn supports_cv_operations(&self) -> DeviceResult<bool> {
418 let capabilities = self
419 .capabilities
420 .read()
421 .map_err(|e| DeviceError::LockError(format!("Capabilities lock poisoned: {e}")))?;
422 Ok(capabilities.as_ref().map_or(false, |caps| {
423 caps.supported_systems
424 .contains(&PhotonicSystemType::ContinuousVariable)
425 }))
426 }
427
428 async fn supports_gate_based(&self) -> DeviceResult<bool> {
429 let capabilities = self
430 .capabilities
431 .read()
432 .map_err(|e| DeviceError::LockError(format!("Capabilities lock poisoned: {e}")))?;
433 Ok(capabilities.as_ref().map_or(false, |caps| {
434 caps.supported_systems
435 .contains(&PhotonicSystemType::GateBased)
436 }))
437 }
438
439 async fn supports_measurement_based(&self) -> DeviceResult<bool> {
440 let capabilities = self
441 .capabilities
442 .read()
443 .map_err(|e| DeviceError::LockError(format!("Capabilities lock poisoned: {e}")))?;
444 Ok(capabilities.as_ref().map_or(false, |caps| {
445 caps.supported_systems
446 .contains(&PhotonicSystemType::MeasurementBased)
447 }))
448 }
449
450 async fn quadrature_precision(&self) -> DeviceResult<f64> {
451 let calibration = self
453 .calibration
454 .read()
455 .map_err(|e| DeviceError::LockError(format!("Calibration lock poisoned: {e}")))?;
456 let len = calibration.phase_accuracies.len();
457 if len == 0 {
458 return Ok(0.0);
459 }
460 let avg_precision =
461 calibration.phase_accuracies.values().copied().sum::<f64>() / len as f64;
462 Ok(avg_precision)
463 }
464
465 async fn detection_efficiency(&self) -> DeviceResult<f64> {
466 Ok(self.config.detection_efficiency.unwrap_or(0.9))
467 }
468
469 async fn execute_photonic_circuit<const N: usize>(
470 &self,
471 circuit: &Circuit<N>,
472 shots: usize,
473 config: Option<PhotonicDeviceConfig>,
474 ) -> DeviceResult<PhotonicCircuitResult> {
475 let start_time = Instant::now();
476
477 self.ensure_calibrated().await?;
479
480 let exec_config = config.unwrap_or_else(|| self.config.clone());
482
483 let circuit_str = format!(
485 "{{\"gates\":{},\"qubits\":{}}}",
486 circuit.gates().len(),
487 circuit.num_qubits()
488 );
489
490 let config_json = serde_json::to_value(&exec_config).map_err(|e| {
492 DeviceError::CircuitConversion(format!("Failed to serialize config: {e}"))
493 })?;
494 let mut config_map = std::collections::HashMap::new();
495 if let serde_json::Value::Object(map) = config_json {
496 for (k, v) in map {
497 config_map.insert(k, v);
498 }
499 }
500
501 let circuit_result = self
503 .client
504 .execute_photonic_circuit(&circuit_str, shots, &config_map)
505 .await?;
506
507 let photonic_data = self.generate_photonic_measurements(circuit, shots).await?;
509
510 let execution_time = start_time.elapsed();
512 let metadata = PhotonicExecutionMetadata {
513 system_type: exec_config.system_type,
514 modes_used: N.min(exec_config.mode_count),
515 execution_time,
516 measured_loss_rate: self.config.loss_rate,
517 thermal_noise: self.config.thermal_photons,
518 gate_sequence: vec![], optimizations_applied: vec![], };
521
522 let fidelity = photonic_data.fidelities.get("overall").copied();
524 self.update_metrics(execution_time, true, fidelity);
525
526 let circuit_result_converted = CircuitResult {
528 counts: circuit_result
529 .results
530 .get("counts")
531 .and_then(|v| serde_json::from_value(v.clone()).ok())
532 .unwrap_or_else(|| {
533 let mut counts = HashMap::new();
534 counts.insert("0".repeat(circuit.num_qubits()), shots);
535 counts
536 }),
537 shots: circuit_result.shots_completed,
538 metadata: circuit_result.metadata,
539 };
540
541 Ok(PhotonicCircuitResult {
542 circuit_result: circuit_result_converted,
543 photonic_data,
544 execution_metadata: metadata,
545 })
546 }
547
548 async fn measure_quadratures(
549 &self,
550 modes: &[usize],
551 angles: &[f64],
552 ) -> DeviceResult<Vec<(f64, f64)>> {
553 self.client
554 .measure_quadratures(&self.device_id, modes, angles)
555 .await
556 }
557
558 async fn measure_photon_numbers(&self, modes: &[usize]) -> DeviceResult<Vec<usize>> {
559 self.client
560 .measure_photon_numbers(&self.device_id, modes)
561 .await
562 }
563
564 async fn homodyne_detection(
565 &self,
566 mode: usize,
567 phase: f64,
568 shots: usize,
569 ) -> DeviceResult<Vec<f64>> {
570 self.client
571 .homodyne_detection(&self.device_id, mode, phase, shots)
572 .await
573 }
574
575 async fn heterodyne_detection(
576 &self,
577 mode: usize,
578 shots: usize,
579 ) -> DeviceResult<Vec<(f64, f64)>> {
580 self.client
581 .heterodyne_detection(&self.device_id, mode, shots)
582 .await
583 }
584
585 async fn calculate_correlations(
586 &self,
587 modes: &[(usize, usize)],
588 correlation_type: &str,
589 ) -> DeviceResult<HashMap<String, f64>> {
590 self.client
591 .calculate_correlations(modes, correlation_type)
592 .await
593 }
594
595 async fn estimate_fidelity(
596 &self,
597 target_state: &str,
598 measurement_data: &PhotonicMeasurementData,
599 ) -> DeviceResult<f64> {
600 self.client
601 .estimate_fidelity(target_state, measurement_data)
602 .await
603 }
604}
605
606impl PhotonicQuantumDeviceImpl {
607 async fn generate_photonic_measurements<const N: usize>(
609 &self,
610 _circuit: &Circuit<N>,
611 shots: usize,
612 ) -> DeviceResult<PhotonicMeasurementData> {
613 let mut quadratures = Vec::new();
615 let mut photon_numbers = Vec::new();
616 let mut homodyne_results = Vec::new();
617 let mut heterodyne_results = Vec::new();
618 let mut correlations = HashMap::new();
619 let mut fidelities = HashMap::new();
620
621 for _ in 0..shots.min(100) {
623 quadratures.push((
626 thread_rng().gen::<f64>() - 0.5,
627 thread_rng().gen::<f64>() - 0.5,
628 ));
629
630 photon_numbers.push((thread_rng().gen::<f64>() * 5.0) as usize);
632
633 homodyne_results.push(thread_rng().gen::<f64>() - 0.5);
635
636 heterodyne_results.push((
638 thread_rng().gen::<f64>() - 0.5,
639 thread_rng().gen::<f64>() - 0.5,
640 ));
641 }
642
643 correlations.insert(
645 "g2".to_string(),
646 thread_rng().gen::<f64>().mul_add(0.1, 1.0),
647 );
648 correlations.insert(
649 "visibility".to_string(),
650 thread_rng().gen::<f64>().mul_add(0.09, 0.9),
651 );
652
653 fidelities.insert(
655 "overall".to_string(),
656 thread_rng().gen::<f64>().mul_add(0.04, 0.95),
657 );
658 fidelities.insert(
659 "gate_fidelity".to_string(),
660 self.config.gate_fidelity.unwrap_or(0.99),
661 );
662
663 Ok(PhotonicMeasurementData {
664 quadratures,
665 photon_numbers,
666 homodyne_results,
667 heterodyne_results,
668 correlations,
669 fidelities,
670 })
671 }
672}
673
674impl Default for PhotonicCalibrationData {
675 fn default() -> Self {
676 Self {
677 mode_losses: HashMap::new(),
678 beamsplitter_transmittances: HashMap::new(),
679 detector_efficiencies: HashMap::new(),
680 phase_accuracies: HashMap::new(),
681 squeezing_calibration: HashMap::new(),
682 crosstalk_matrix: HashMap::new(),
683 last_calibration: Instant::now(),
684 validity_duration: Duration::from_secs(3600),
685 }
686 }
687}
688
689impl Default for PhotonicPerformanceMetrics {
690 fn default() -> Self {
691 Self {
692 circuits_executed: 0,
693 avg_execution_time: Duration::from_millis(0),
694 success_rate: 0.0,
695 avg_fidelity: 0.0,
696 mode_utilization: HashMap::new(),
697 gate_counts: HashMap::new(),
698 error_rates: HashMap::new(),
699 }
700 }
701}
702
703#[cfg(test)]
704mod tests {
705 use super::*;
706 use crate::photonic::{PhotonicClient, PhotonicConfig};
707
708 #[tokio::test]
709 async fn test_photonic_device_creation() {
710 let client = PhotonicClient::new(
711 "http://localhost:8080".to_string(),
712 "test_token".to_string(),
713 )
714 .expect("Failed to create photonic client");
715 let config = PhotonicDeviceConfig::default();
716
717 let device =
718 PhotonicQuantumDeviceImpl::new("test_device".to_string(), client, config).await;
719 assert!(device.is_ok());
720 }
721
722 #[tokio::test]
723 async fn test_device_properties() {
724 let client = PhotonicClient::new(
725 "http://localhost:8080".to_string(),
726 "test_token".to_string(),
727 )
728 .expect("Failed to create photonic client");
729 let config = PhotonicDeviceConfig::default();
730 let device = PhotonicQuantumDeviceImpl::new("test_device".to_string(), client, config)
731 .await
732 .expect("Failed to create photonic device");
733
734 let properties = device
735 .properties()
736 .await
737 .expect("Failed to get device properties");
738 assert!(properties.contains_key("system_type"));
739 assert!(properties.contains_key("mode_count"));
740 }
741
742 #[tokio::test]
743 async fn test_capabilities() {
744 let client = PhotonicClient::new(
745 "http://localhost:8080".to_string(),
746 "test_token".to_string(),
747 )
748 .expect("Failed to create photonic client");
749 let config = PhotonicDeviceConfig::default();
750 let device = PhotonicQuantumDeviceImpl::new("test_device".to_string(), client, config)
751 .await
752 .expect("Failed to create photonic device");
753
754 assert!(device
755 .supports_cv_operations()
756 .await
757 .expect("Failed to check CV operations support"));
758 assert_eq!(
759 device.mode_count().await.expect("Failed to get mode count"),
760 8
761 );
762 }
763}