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.capabilities.write().unwrap() = Some(capabilities);
130
131 let calibration = self.load_calibration_data().await?;
133 *self.calibration.write().unwrap() = calibration;
134
135 Ok(())
136 }
137
138 async fn load_capabilities(&self) -> DeviceResult<PhotonicCapabilities> {
140 let mut supported_systems = vec![PhotonicSystemType::ContinuousVariable];
141
142 match self.config.system_type {
144 PhotonicSystemType::ContinuousVariable => {
145 supported_systems.push(PhotonicSystemType::ContinuousVariable);
146 }
147 PhotonicSystemType::GateBased => {
148 supported_systems.push(PhotonicSystemType::GateBased);
149 }
150 PhotonicSystemType::MeasurementBased => {
151 supported_systems.push(PhotonicSystemType::MeasurementBased);
152 }
153 PhotonicSystemType::Hybrid => {
154 supported_systems.extend(&[
155 PhotonicSystemType::ContinuousVariable,
156 PhotonicSystemType::GateBased,
157 PhotonicSystemType::MeasurementBased,
158 ]);
159 }
160 }
161
162 let supported_gates = vec![
163 "displacement".to_string(),
164 "squeezing".to_string(),
165 "two_mode_squeezing".to_string(),
166 "beamsplitter".to_string(),
167 "phase_rotation".to_string(),
168 "kerr".to_string(),
169 "cross_kerr".to_string(),
170 "homodyne".to_string(),
171 "heterodyne".to_string(),
172 ];
173
174 let supported_measurements = vec![
175 "homodyne".to_string(),
176 "heterodyne".to_string(),
177 "photon_counting".to_string(),
178 "quadrature".to_string(),
179 ];
180
181 let mut hardware_features = HashMap::new();
182 hardware_features.insert("squeezed_light_source".to_string(), true);
183 hardware_features.insert("programmable_beamsplitters".to_string(), true);
184 hardware_features.insert("high_efficiency_detectors".to_string(), true);
185 hardware_features.insert(
186 "real_time_feedback".to_string(),
187 self.config.hardware_acceleration,
188 );
189
190 Ok(PhotonicCapabilities {
191 supported_systems,
192 max_modes: self.config.mode_count * 2, max_cutoff: self.config.cutoff_dimension.unwrap_or(20),
194 supported_gates,
195 max_squeezing: 10.0, min_detection_efficiency: 0.8,
197 supported_measurements,
198 hardware_features,
199 })
200 }
201
202 async fn load_calibration_data(&self) -> DeviceResult<PhotonicCalibrationData> {
204 let mut mode_losses = HashMap::new();
205 let mut detector_efficiencies = HashMap::new();
206 let mut phase_accuracies = HashMap::new();
207 let mut squeezing_calibration = HashMap::new();
208
209 for mode in 0..self.config.mode_count {
211 mode_losses.insert(mode, self.config.loss_rate.unwrap_or(0.01));
212 detector_efficiencies.insert(mode, self.config.detection_efficiency.unwrap_or(0.9));
213 phase_accuracies.insert(mode, 0.001); squeezing_calibration.insert(mode, (0.0, 0.0)); }
216
217 Ok(PhotonicCalibrationData {
218 mode_losses,
219 beamsplitter_transmittances: HashMap::new(),
220 detector_efficiencies,
221 phase_accuracies,
222 squeezing_calibration,
223 crosstalk_matrix: HashMap::new(),
224 last_calibration: Instant::now(),
225 validity_duration: Duration::from_secs(3600), })
227 }
228
229 fn update_metrics(&self, execution_time: Duration, success: bool, fidelity: Option<f64>) {
231 let mut metrics = self.metrics.write().unwrap();
232
233 metrics.circuits_executed += 1;
234
235 let total_time =
237 metrics.avg_execution_time * (metrics.circuits_executed - 1) as u32 + execution_time;
238 metrics.avg_execution_time = total_time / metrics.circuits_executed as u32;
239
240 let total_success = metrics.success_rate * (metrics.circuits_executed - 1) as f64
242 + if success { 1.0 } else { 0.0 };
243 metrics.success_rate = total_success / metrics.circuits_executed as f64;
244
245 if let Some(fid) = fidelity {
247 let total_fidelity =
248 metrics.avg_fidelity * (metrics.circuits_executed - 1) as f64 + fid;
249 metrics.avg_fidelity = total_fidelity / metrics.circuits_executed as f64;
250 }
251 }
252
253 fn is_calibration_valid(&self) -> bool {
255 let calibration = self.calibration.read().unwrap();
256 calibration.last_calibration.elapsed() < calibration.validity_duration
257 }
258
259 async fn ensure_calibrated(&self) -> DeviceResult<()> {
261 if !self.is_calibration_valid() {
262 let new_calibration = self.load_calibration_data().await?;
263 *self.calibration.write().unwrap() = new_calibration;
264 }
265 Ok(())
266 }
267}
268
269#[async_trait]
270impl QuantumDevice for PhotonicQuantumDeviceImpl {
271 async fn is_available(&self) -> DeviceResult<bool> {
272 self.client.check_availability().await
274 }
275
276 async fn qubit_count(&self) -> DeviceResult<usize> {
277 Ok(self.config.mode_count)
279 }
280
281 async fn properties(&self) -> DeviceResult<HashMap<String, String>> {
282 let mut properties = HashMap::new();
283
284 properties.insert(
285 "system_type".to_string(),
286 format!("{:?}", self.config.system_type),
287 );
288 properties.insert("mode_count".to_string(), self.config.mode_count.to_string());
289
290 if let Some(cutoff) = self.config.cutoff_dimension {
291 properties.insert("cutoff_dimension".to_string(), cutoff.to_string());
292 }
293
294 if let Some(loss_rate) = self.config.loss_rate {
295 properties.insert("loss_rate".to_string(), loss_rate.to_string());
296 }
297
298 if let Some(efficiency) = self.config.detection_efficiency {
299 properties.insert("detection_efficiency".to_string(), efficiency.to_string());
300 }
301
302 properties.insert(
304 "calibration_valid".to_string(),
305 self.is_calibration_valid().to_string(),
306 );
307
308 let metrics = self.metrics.read().unwrap();
310 properties.insert(
311 "circuits_executed".to_string(),
312 metrics.circuits_executed.to_string(),
313 );
314 properties.insert("success_rate".to_string(), metrics.success_rate.to_string());
315 properties.insert("avg_fidelity".to_string(), metrics.avg_fidelity.to_string());
316
317 Ok(properties)
318 }
319
320 async fn is_simulator(&self) -> DeviceResult<bool> {
321 self.client.is_simulator().await
323 }
324}
325
326#[async_trait]
327impl CircuitExecutor for PhotonicQuantumDeviceImpl {
328 async fn execute_circuit<const N: usize>(
329 &self,
330 circuit: &Circuit<N>,
331 shots: usize,
332 ) -> DeviceResult<CircuitResult> {
333 let photonic_result = self.execute_photonic_circuit(circuit, shots, None).await?;
334 Ok(photonic_result.circuit_result)
335 }
336
337 async fn execute_circuits<const N: usize>(
338 &self,
339 circuits: Vec<&Circuit<N>>,
340 shots: usize,
341 ) -> DeviceResult<Vec<CircuitResult>> {
342 let mut results = Vec::new();
343
344 for circuit in circuits {
345 let result = self.execute_circuit(circuit, shots).await?;
346 results.push(result);
347 }
348
349 Ok(results)
350 }
351
352 async fn can_execute_circuit<const N: usize>(
353 &self,
354 circuit: &Circuit<N>,
355 ) -> DeviceResult<bool> {
356 if N > self.config.mode_count {
360 return Ok(false);
361 }
362
363 Ok(true)
367 }
368
369 async fn estimated_queue_time<const N: usize>(
370 &self,
371 _circuit: &Circuit<N>,
372 ) -> DeviceResult<Duration> {
373 self.client.get_queue_time().await
376 }
377}
378
379#[async_trait]
380impl PhotonicQuantumDevice for PhotonicQuantumDeviceImpl {
381 async fn system_type(&self) -> DeviceResult<PhotonicSystemType> {
382 Ok(self.config.system_type)
383 }
384
385 async fn mode_count(&self) -> DeviceResult<usize> {
386 Ok(self.config.mode_count)
387 }
388
389 async fn cutoff_dimension(&self) -> DeviceResult<Option<usize>> {
390 Ok(self.config.cutoff_dimension)
391 }
392
393 async fn supports_cv_operations(&self) -> DeviceResult<bool> {
394 let capabilities = self.capabilities.read().unwrap();
395 if let Some(caps) = capabilities.as_ref() {
396 Ok(caps
397 .supported_systems
398 .contains(&PhotonicSystemType::ContinuousVariable))
399 } else {
400 Ok(false)
401 }
402 }
403
404 async fn supports_gate_based(&self) -> DeviceResult<bool> {
405 let capabilities = self.capabilities.read().unwrap();
406 if let Some(caps) = capabilities.as_ref() {
407 Ok(caps
408 .supported_systems
409 .contains(&PhotonicSystemType::GateBased))
410 } else {
411 Ok(false)
412 }
413 }
414
415 async fn supports_measurement_based(&self) -> DeviceResult<bool> {
416 let capabilities = self.capabilities.read().unwrap();
417 if let Some(caps) = capabilities.as_ref() {
418 Ok(caps
419 .supported_systems
420 .contains(&PhotonicSystemType::MeasurementBased))
421 } else {
422 Ok(false)
423 }
424 }
425
426 async fn quadrature_precision(&self) -> DeviceResult<f64> {
427 let calibration = self.calibration.read().unwrap();
429 let avg_precision = calibration.phase_accuracies.values().copied().sum::<f64>()
430 / calibration.phase_accuracies.len() as f64;
431 Ok(avg_precision)
432 }
433
434 async fn detection_efficiency(&self) -> DeviceResult<f64> {
435 Ok(self.config.detection_efficiency.unwrap_or(0.9))
436 }
437
438 async fn execute_photonic_circuit<const N: usize>(
439 &self,
440 circuit: &Circuit<N>,
441 shots: usize,
442 config: Option<PhotonicDeviceConfig>,
443 ) -> DeviceResult<PhotonicCircuitResult> {
444 let start_time = Instant::now();
445
446 self.ensure_calibrated().await?;
448
449 let exec_config = config.unwrap_or_else(|| self.config.clone());
451
452 let circuit_str = format!(
454 "{{\"gates\":{},\"qubits\":{}}}",
455 circuit.gates().len(),
456 circuit.num_qubits()
457 );
458
459 let config_json = serde_json::to_value(&exec_config).map_err(|e| {
461 DeviceError::CircuitConversion(format!("Failed to serialize config: {}", e))
462 })?;
463 let mut config_map = std::collections::HashMap::new();
464 if let serde_json::Value::Object(map) = config_json {
465 for (k, v) in map {
466 config_map.insert(k, v);
467 }
468 }
469
470 let circuit_result = self
472 .client
473 .execute_photonic_circuit(&circuit_str, shots, &config_map)
474 .await?;
475
476 let photonic_data = self.generate_photonic_measurements(circuit, shots).await?;
478
479 let execution_time = start_time.elapsed();
481 let metadata = PhotonicExecutionMetadata {
482 system_type: exec_config.system_type,
483 modes_used: N.min(exec_config.mode_count),
484 execution_time,
485 measured_loss_rate: self.config.loss_rate,
486 thermal_noise: self.config.thermal_photons,
487 gate_sequence: vec![], optimizations_applied: vec![], };
490
491 let fidelity = photonic_data.fidelities.get("overall").copied();
493 self.update_metrics(execution_time, true, fidelity);
494
495 let circuit_result_converted = CircuitResult {
497 counts: circuit_result
498 .results
499 .get("counts")
500 .and_then(|v| serde_json::from_value(v.clone()).ok())
501 .unwrap_or_else(|| {
502 let mut counts = HashMap::new();
503 counts.insert("0".repeat(circuit.num_qubits()), shots);
504 counts
505 }),
506 shots: circuit_result.shots_completed,
507 metadata: circuit_result.metadata,
508 };
509
510 Ok(PhotonicCircuitResult {
511 circuit_result: circuit_result_converted,
512 photonic_data,
513 execution_metadata: metadata,
514 })
515 }
516
517 async fn measure_quadratures(
518 &self,
519 modes: &[usize],
520 angles: &[f64],
521 ) -> DeviceResult<Vec<(f64, f64)>> {
522 self.client
523 .measure_quadratures(&self.device_id, modes, angles)
524 .await
525 }
526
527 async fn measure_photon_numbers(&self, modes: &[usize]) -> DeviceResult<Vec<usize>> {
528 self.client
529 .measure_photon_numbers(&self.device_id, modes)
530 .await
531 }
532
533 async fn homodyne_detection(
534 &self,
535 mode: usize,
536 phase: f64,
537 shots: usize,
538 ) -> DeviceResult<Vec<f64>> {
539 self.client
540 .homodyne_detection(&self.device_id, mode, phase, shots)
541 .await
542 }
543
544 async fn heterodyne_detection(
545 &self,
546 mode: usize,
547 shots: usize,
548 ) -> DeviceResult<Vec<(f64, f64)>> {
549 self.client
550 .heterodyne_detection(&self.device_id, mode, shots)
551 .await
552 }
553
554 async fn calculate_correlations(
555 &self,
556 modes: &[(usize, usize)],
557 correlation_type: &str,
558 ) -> DeviceResult<HashMap<String, f64>> {
559 self.client
560 .calculate_correlations(modes, correlation_type)
561 .await
562 }
563
564 async fn estimate_fidelity(
565 &self,
566 target_state: &str,
567 measurement_data: &PhotonicMeasurementData,
568 ) -> DeviceResult<f64> {
569 self.client
570 .estimate_fidelity(target_state, measurement_data)
571 .await
572 }
573}
574
575impl PhotonicQuantumDeviceImpl {
576 async fn generate_photonic_measurements<const N: usize>(
578 &self,
579 _circuit: &Circuit<N>,
580 shots: usize,
581 ) -> DeviceResult<PhotonicMeasurementData> {
582 let mut quadratures = Vec::new();
584 let mut photon_numbers = Vec::new();
585 let mut homodyne_results = Vec::new();
586 let mut heterodyne_results = Vec::new();
587 let mut correlations = HashMap::new();
588 let mut fidelities = HashMap::new();
589
590 for _ in 0..shots.min(100) {
592 quadratures.push((thread_rng().gen::<f64>() - 0.5, thread_rng().gen::<f64>() - 0.5));
595
596 photon_numbers.push((thread_rng().gen::<f64>() * 5.0) as usize);
598
599 homodyne_results.push(thread_rng().gen::<f64>() - 0.5);
601
602 heterodyne_results.push((thread_rng().gen::<f64>() - 0.5, thread_rng().gen::<f64>() - 0.5));
604 }
605
606 correlations.insert("g2".to_string(), 1.0 + thread_rng().gen::<f64>() * 0.1);
608 correlations.insert("visibility".to_string(), 0.9 + thread_rng().gen::<f64>() * 0.09);
609
610 fidelities.insert("overall".to_string(), 0.95 + thread_rng().gen::<f64>() * 0.04);
612 fidelities.insert(
613 "gate_fidelity".to_string(),
614 self.config.gate_fidelity.unwrap_or(0.99),
615 );
616
617 Ok(PhotonicMeasurementData {
618 quadratures,
619 photon_numbers,
620 homodyne_results,
621 heterodyne_results,
622 correlations,
623 fidelities,
624 })
625 }
626}
627
628impl Default for PhotonicCalibrationData {
629 fn default() -> Self {
630 Self {
631 mode_losses: HashMap::new(),
632 beamsplitter_transmittances: HashMap::new(),
633 detector_efficiencies: HashMap::new(),
634 phase_accuracies: HashMap::new(),
635 squeezing_calibration: HashMap::new(),
636 crosstalk_matrix: HashMap::new(),
637 last_calibration: Instant::now(),
638 validity_duration: Duration::from_secs(3600),
639 }
640 }
641}
642
643impl Default for PhotonicPerformanceMetrics {
644 fn default() -> Self {
645 Self {
646 circuits_executed: 0,
647 avg_execution_time: Duration::from_millis(0),
648 success_rate: 0.0,
649 avg_fidelity: 0.0,
650 mode_utilization: HashMap::new(),
651 gate_counts: HashMap::new(),
652 error_rates: HashMap::new(),
653 }
654 }
655}
656
657#[cfg(test)]
658mod tests {
659 use super::*;
660 use crate::photonic::{PhotonicClient, PhotonicConfig};
661
662 #[tokio::test]
663 async fn test_photonic_device_creation() {
664 let client = PhotonicClient::new(
665 "http://localhost:8080".to_string(),
666 "test_token".to_string(),
667 )
668 .unwrap();
669 let config = PhotonicDeviceConfig::default();
670
671 let device =
672 PhotonicQuantumDeviceImpl::new("test_device".to_string(), client, config).await;
673 assert!(device.is_ok());
674 }
675
676 #[tokio::test]
677 async fn test_device_properties() {
678 let client = PhotonicClient::new(
679 "http://localhost:8080".to_string(),
680 "test_token".to_string(),
681 )
682 .unwrap();
683 let config = PhotonicDeviceConfig::default();
684 let device = PhotonicQuantumDeviceImpl::new("test_device".to_string(), client, config)
685 .await
686 .unwrap();
687
688 let properties = device.properties().await.unwrap();
689 assert!(properties.contains_key("system_type"));
690 assert!(properties.contains_key("mode_count"));
691 }
692
693 #[tokio::test]
694 async fn test_capabilities() {
695 let client = PhotonicClient::new(
696 "http://localhost:8080".to_string(),
697 "test_token".to_string(),
698 )
699 .unwrap();
700 let config = PhotonicDeviceConfig::default();
701 let device = PhotonicQuantumDeviceImpl::new("test_device".to_string(), client, config)
702 .await
703 .unwrap();
704
705 assert!(device.supports_cv_operations().await.unwrap());
706 assert_eq!(device.mode_count().await.unwrap(), 8);
707 }
708}