1use std::collections::{HashMap, VecDeque};
4use std::sync::{mpsc, Arc, Mutex, RwLock};
5use std::time::{Duration, SystemTime, UNIX_EPOCH};
6
7use super::analysis::{
8 compute_cost_analysis, compute_cost_metrics, compute_cross_platform_analysis,
9 compute_performance_metrics, compute_reliability_metrics, compute_resource_analysis,
10 default_algorithm_level_results, default_circuit_level_results, default_gate_level_results,
11 default_scirs2_analysis, default_system_level_results,
12};
13use super::config::{
14 AlgorithmBenchmarkConfig, CircuitBenchmarkConfig, GateBenchmarkConfig, SystemBenchmarkConfig,
15 UnifiedBenchmarkConfig,
16};
17use super::events::BenchmarkEvent;
18use super::optimization::OptimizationEngine;
19use super::reporting::ReportGenerator;
20use super::results::{
21 AlgorithmLevelResults, CircuitLevelResults, CoherenceTimes, ConnectivityInfo,
22 CostAnalysisResult, CostMetrics, CrossPlatformAnalysis, DeviceInfo, DeviceSpecifications,
23 DeviceStatus, ExecutionMetadata, GateLevelResults, HistoricalComparisonResult,
24 OptimizationRecommendation, PlatformBenchmarkResult, PlatformPerformanceMetrics,
25 QuantumTechnology, ReliabilityMetrics, ResourceAnalysisResult, SciRS2AnalysisResult,
26 SystemLevelResults, TopologyType, UnifiedBenchmarkResult,
27};
28use super::types::{PerformanceBaseline, QuantumPlatform};
29
30use crate::{
31 advanced_benchmarking_suite::{AdvancedBenchmarkConfig, AdvancedHardwareBenchmarkSuite},
32 calibration::CalibrationManager,
33 cross_platform_benchmarking::{CrossPlatformBenchmarkConfig, CrossPlatformBenchmarker},
34 topology::HardwareTopology,
35 DeviceError, DeviceResult, QuantumDevice,
36};
37use quantrs2_core::error::{QuantRS2Error, QuantRS2Result};
38
39use scirs2_core::ndarray::Array2;
40
41pub struct UnifiedQuantumBenchmarkSystem {
43 config: Arc<RwLock<UnifiedBenchmarkConfig>>,
45 platform_clients: Arc<RwLock<HashMap<QuantumPlatform, Box<dyn QuantumDevice + Send + Sync>>>>,
47 cross_platform_benchmarker: Arc<Mutex<CrossPlatformBenchmarker>>,
49 advanced_suite: Arc<Mutex<AdvancedHardwareBenchmarkSuite>>,
51 calibration_manager: Arc<Mutex<CalibrationManager>>,
53 historical_data: Arc<RwLock<VecDeque<UnifiedBenchmarkResult>>>,
55 baselines: Arc<RwLock<HashMap<String, PerformanceBaseline>>>,
57 monitoring_handle: Arc<Mutex<Option<std::thread::JoinHandle<()>>>>,
59 event_publisher: mpsc::Sender<BenchmarkEvent>,
61 optimization_engine: Arc<Mutex<OptimizationEngine>>,
63 report_generator: Arc<Mutex<ReportGenerator>>,
65}
66
67impl UnifiedQuantumBenchmarkSystem {
68 pub async fn new(
70 config: UnifiedBenchmarkConfig,
71 calibration_manager: CalibrationManager,
72 ) -> DeviceResult<Self> {
73 let (event_publisher, _) = mpsc::channel();
74 let config = Arc::new(RwLock::new(config));
75
76 let platform_clients = Arc::new(RwLock::new(HashMap::new()));
78
79 let cross_platform_config = CrossPlatformBenchmarkConfig::default();
81 let cross_platform_benchmarker = Arc::new(Mutex::new(CrossPlatformBenchmarker::new(
82 cross_platform_config,
83 calibration_manager.clone(),
84 )));
85
86 let advanced_config = AdvancedBenchmarkConfig::default();
88 let topology = HardwareTopology::linear_topology(8); let advanced_suite = Arc::new(Mutex::new(
90 AdvancedHardwareBenchmarkSuite::new(
91 advanced_config,
92 calibration_manager.clone(),
93 topology,
94 )
95 .await?,
96 ));
97
98 let historical_data = Arc::new(RwLock::new(VecDeque::with_capacity(10000)));
99 let baselines = Arc::new(RwLock::new(HashMap::new()));
100 let monitoring_handle = Arc::new(Mutex::new(None));
101
102 let optimization_engine = Arc::new(Mutex::new(OptimizationEngine::new()));
103 let report_generator = Arc::new(Mutex::new(ReportGenerator::new()));
104
105 Ok(Self {
106 config,
107 platform_clients,
108 cross_platform_benchmarker,
109 advanced_suite,
110 calibration_manager: Arc::new(Mutex::new(calibration_manager)),
111 historical_data,
112 baselines,
113 monitoring_handle,
114 event_publisher,
115 optimization_engine,
116 report_generator,
117 })
118 }
119
120 pub async fn register_platform(
122 &self,
123 platform: QuantumPlatform,
124 device: Box<dyn QuantumDevice + Send + Sync>,
125 ) -> DeviceResult<()> {
126 let mut clients = self
127 .platform_clients
128 .write()
129 .unwrap_or_else(|e| e.into_inner());
130 clients.insert(platform, device);
131 Ok(())
132 }
133
134 pub async fn run_comprehensive_benchmark(&self) -> DeviceResult<UnifiedBenchmarkResult> {
136 let execution_id = self.generate_execution_id();
137 let start_time = SystemTime::now();
138
139 let config = self
141 .config
142 .read()
143 .unwrap_or_else(|e| e.into_inner())
144 .clone();
145 let _ = self.event_publisher.send(BenchmarkEvent::BenchmarkStarted {
146 execution_id: execution_id.clone(),
147 platforms: config.target_platforms.clone(),
148 timestamp: start_time,
149 });
150
151 let mut platform_results = HashMap::new();
153
154 for platform in &config.target_platforms {
155 match self.run_platform_benchmark(platform, &execution_id).await {
156 Ok(result) => {
157 let _ = self
158 .event_publisher
159 .send(BenchmarkEvent::PlatformBenchmarkCompleted {
160 execution_id: execution_id.clone(),
161 platform: platform.clone(),
162 result: result.clone(),
163 timestamp: SystemTime::now(),
164 });
165 platform_results.insert(platform.clone(), result);
166 }
167 Err(e) => {
168 eprintln!("Platform benchmark failed for {platform:?}: {e}");
169 }
171 }
172 }
173
174 let cross_platform_analysis = self
176 .perform_cross_platform_analysis(&platform_results)
177 .await?;
178 let scirs2_analysis = self.perform_scirs2_analysis(&platform_results).await?;
179 let resource_analysis = self.perform_resource_analysis(&platform_results).await?;
180 let cost_analysis = self.perform_cost_analysis(&platform_results).await?;
181
182 let optimization_recommendations = self
184 .generate_optimization_recommendations(
185 &platform_results,
186 &cross_platform_analysis,
187 &scirs2_analysis,
188 )
189 .await?;
190
191 let historical_comparison = self
193 .perform_historical_comparison(&platform_results)
194 .await?;
195
196 let execution_metadata = ExecutionMetadata {
198 execution_start_time: start_time,
199 execution_end_time: SystemTime::now(),
200 total_duration: SystemTime::now()
201 .duration_since(start_time)
202 .unwrap_or(Duration::ZERO),
203 platforms_tested: config.target_platforms.clone(),
204 benchmarks_executed: platform_results.len(),
205 system_info: self.get_system_info(),
206 };
207
208 let result = UnifiedBenchmarkResult {
209 execution_id: execution_id.clone(),
210 timestamp: start_time,
211 config,
212 platform_results,
213 cross_platform_analysis,
214 scirs2_analysis,
215 resource_analysis,
216 cost_analysis,
217 optimization_recommendations,
218 historical_comparison,
219 execution_metadata,
220 };
221
222 self.store_historical_result(&result).await;
224
225 self.update_baselines(&result).await;
227
228 if result
230 .config
231 .optimization_config
232 .enable_intelligent_allocation
233 {
234 self.trigger_optimization(&result).await?;
235 }
236
237 if result
239 .config
240 .reporting_config
241 .automated_reports
242 .enable_automated
243 {
244 self.generate_automated_reports(&result).await?;
245 }
246
247 let _ = self
249 .event_publisher
250 .send(BenchmarkEvent::BenchmarkCompleted {
251 execution_id: execution_id.clone(),
252 result: result.clone(),
253 timestamp: SystemTime::now(),
254 });
255
256 Ok(result)
257 }
258
259 async fn run_platform_benchmark(
261 &self,
262 platform: &QuantumPlatform,
263 execution_id: &str,
264 ) -> DeviceResult<PlatformBenchmarkResult> {
265 let config = self
266 .config
267 .read()
268 .unwrap_or_else(|e| e.into_inner())
269 .clone();
270
271 let device_info = self.get_device_info(platform).await?;
273
274 let gate_level_results = self
276 .run_gate_level_benchmarks(platform, &config.benchmark_suite.gate_benchmarks)
277 .await?;
278 let circuit_level_results = self
279 .run_circuit_level_benchmarks(platform, &config.benchmark_suite.circuit_benchmarks)
280 .await?;
281 let algorithm_level_results = self
282 .run_algorithm_level_benchmarks(platform, &config.benchmark_suite.algorithm_benchmarks)
283 .await?;
284 let system_level_results = self
285 .run_system_level_benchmarks(platform, &config.benchmark_suite.system_benchmarks)
286 .await?;
287
288 let performance_metrics = self
290 .calculate_platform_performance_metrics(
291 &gate_level_results,
292 &circuit_level_results,
293 &algorithm_level_results,
294 &system_level_results,
295 )
296 .await?;
297
298 let reliability_metrics = self
299 .calculate_reliability_metrics(
300 &gate_level_results,
301 &circuit_level_results,
302 &algorithm_level_results,
303 )
304 .await?;
305
306 let cost_metrics = self
307 .calculate_cost_metrics(
308 &gate_level_results,
309 &circuit_level_results,
310 &algorithm_level_results,
311 )
312 .await?;
313
314 Ok(PlatformBenchmarkResult {
315 platform: platform.clone(),
316 device_info,
317 gate_level_results,
318 circuit_level_results,
319 algorithm_level_results,
320 system_level_results,
321 performance_metrics,
322 reliability_metrics,
323 cost_metrics,
324 })
325 }
326
327 fn generate_execution_id(&self) -> String {
329 format!(
330 "unified_benchmark_{}",
331 SystemTime::now()
332 .duration_since(UNIX_EPOCH)
333 .unwrap_or(Duration::ZERO)
334 .as_millis()
335 )
336 }
337
338 async fn get_device_info(&self, platform: &QuantumPlatform) -> DeviceResult<DeviceInfo> {
340 let (provider, technology) = match platform {
341 QuantumPlatform::IBMQuantum { .. } => {
342 ("IBM".to_string(), QuantumTechnology::Superconducting)
343 }
344 QuantumPlatform::AWSBraket { .. } => {
345 ("AWS".to_string(), QuantumTechnology::Superconducting)
346 }
347 QuantumPlatform::AzureQuantum { .. } => {
348 ("Microsoft".to_string(), QuantumTechnology::TrappedIon)
349 }
350 QuantumPlatform::IonQ { .. } => ("IonQ".to_string(), QuantumTechnology::TrappedIon),
351 QuantumPlatform::Rigetti { .. } => {
352 ("Rigetti".to_string(), QuantumTechnology::Superconducting)
353 }
354 QuantumPlatform::GoogleQuantumAI { .. } => {
355 ("Google".to_string(), QuantumTechnology::Superconducting)
356 }
357 QuantumPlatform::Custom { .. } => (
358 "Custom".to_string(),
359 QuantumTechnology::Other("Custom".to_string()),
360 ),
361 };
362
363 Ok(DeviceInfo {
364 device_id: format!("{platform:?}"),
365 provider,
366 technology,
367 specifications: DeviceSpecifications {
368 num_qubits: 20,
369 connectivity: ConnectivityInfo {
370 topology_type: TopologyType::Heavy,
371 coupling_map: vec![(0, 1), (1, 2), (2, 3)],
372 connectivity_matrix: Array2::eye(20),
373 },
374 gate_set: vec![
375 "X".to_string(),
376 "Y".to_string(),
377 "Z".to_string(),
378 "H".to_string(),
379 "CNOT".to_string(),
380 ],
381 coherence_times: CoherenceTimes {
382 t1: (0..20).map(|i| (i, Duration::from_micros(100))).collect(),
383 t2: (0..20).map(|i| (i, Duration::from_micros(50))).collect(),
384 t2_echo: (0..20).map(|i| (i, Duration::from_micros(80))).collect(),
385 },
386 gate_times: [
387 ("X".to_string(), Duration::from_nanos(20)),
388 ("CNOT".to_string(), Duration::from_nanos(100)),
389 ]
390 .iter()
391 .cloned()
392 .collect(),
393 error_rates: [
394 ("single_qubit".to_string(), 0.001),
395 ("two_qubit".to_string(), 0.01),
396 ]
397 .iter()
398 .cloned()
399 .collect(),
400 },
401 current_status: DeviceStatus::Online,
402 calibration_date: Some(SystemTime::now()),
403 })
404 }
405
406 async fn run_gate_level_benchmarks(
408 &self,
409 _platform: &QuantumPlatform,
410 _config: &GateBenchmarkConfig,
411 ) -> DeviceResult<GateLevelResults> {
412 Ok(default_gate_level_results())
416 }
417
418 async fn run_circuit_level_benchmarks(
419 &self,
420 _platform: &QuantumPlatform,
421 _config: &CircuitBenchmarkConfig,
422 ) -> DeviceResult<CircuitLevelResults> {
423 Ok(default_circuit_level_results())
426 }
427
428 async fn run_algorithm_level_benchmarks(
429 &self,
430 _platform: &QuantumPlatform,
431 _config: &AlgorithmBenchmarkConfig,
432 ) -> DeviceResult<AlgorithmLevelResults> {
433 Ok(default_algorithm_level_results())
436 }
437
438 async fn run_system_level_benchmarks(
439 &self,
440 platform: &QuantumPlatform,
441 _config: &SystemBenchmarkConfig,
442 ) -> DeviceResult<SystemLevelResults> {
443 Ok(default_system_level_results(platform))
444 }
445
446 async fn perform_cross_platform_analysis(
448 &self,
449 platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
450 ) -> DeviceResult<CrossPlatformAnalysis> {
451 Ok(compute_cross_platform_analysis(platform_results))
452 }
453
454 async fn perform_scirs2_analysis(
455 &self,
456 _platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
457 ) -> DeviceResult<SciRS2AnalysisResult> {
458 Ok(default_scirs2_analysis())
462 }
463
464 async fn perform_resource_analysis(
465 &self,
466 platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
467 ) -> DeviceResult<ResourceAnalysisResult> {
468 Ok(compute_resource_analysis(platform_results))
469 }
470
471 async fn perform_cost_analysis(
472 &self,
473 platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
474 ) -> DeviceResult<CostAnalysisResult> {
475 Ok(compute_cost_analysis(platform_results))
476 }
477
478 async fn calculate_platform_performance_metrics(
480 &self,
481 gate_results: &GateLevelResults,
482 circuit_results: &CircuitLevelResults,
483 algorithm_results: &AlgorithmLevelResults,
484 system_results: &SystemLevelResults,
485 ) -> DeviceResult<PlatformPerformanceMetrics> {
486 Ok(compute_performance_metrics(
487 gate_results,
488 circuit_results,
489 algorithm_results,
490 system_results,
491 ))
492 }
493
494 async fn calculate_reliability_metrics(
495 &self,
496 gate_results: &GateLevelResults,
497 circuit_results: &CircuitLevelResults,
498 algorithm_results: &AlgorithmLevelResults,
499 ) -> DeviceResult<ReliabilityMetrics> {
500 Ok(compute_reliability_metrics(
501 gate_results,
502 circuit_results,
503 algorithm_results,
504 ))
505 }
506
507 async fn calculate_cost_metrics(
508 &self,
509 gate_results: &GateLevelResults,
510 circuit_results: &CircuitLevelResults,
511 algorithm_results: &AlgorithmLevelResults,
512 ) -> DeviceResult<CostMetrics> {
513 Ok(compute_cost_metrics(
514 gate_results,
515 circuit_results,
516 algorithm_results,
517 ))
518 }
519
520 async fn generate_optimization_recommendations(
522 &self,
523 platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
524 cross_platform_analysis: &CrossPlatformAnalysis,
525 _scirs2_analysis: &SciRS2AnalysisResult,
526 ) -> DeviceResult<Vec<OptimizationRecommendation>> {
527 Ok(generate_recommendations_from_metrics(
528 platform_results,
529 cross_platform_analysis,
530 ))
531 }
532
533 async fn perform_historical_comparison(
534 &self,
535 platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
536 ) -> DeviceResult<Option<HistoricalComparisonResult>> {
537 let historical_data = self
544 .historical_data
545 .read()
546 .unwrap_or_else(|e| e.into_inner());
547
548 let baseline = historical_data.iter().next_back();
550 let baseline = match baseline {
551 Some(b) => b,
552 None => return Ok(None),
553 };
554
555 let mut baseline_comparison: Vec<super::results::MetricComparison> = Vec::new();
556 let mut trend_analysis: HashMap<String, super::results::TrendAnalysisResult> =
557 HashMap::new();
558
559 for (platform, current) in platform_results {
560 let prev = match baseline.platform_results.get(platform) {
561 Some(p) => p,
562 None => continue,
563 };
564
565 let pairs: [(&str, f64, f64); 4] = [
567 (
568 "overall_fidelity",
569 current.performance_metrics.overall_fidelity,
570 prev.performance_metrics.overall_fidelity,
571 ),
572 (
573 "error_rate",
574 current.performance_metrics.error_rate,
575 prev.performance_metrics.error_rate,
576 ),
577 (
578 "throughput",
579 current.performance_metrics.throughput,
580 prev.performance_metrics.throughput,
581 ),
582 (
583 "availability",
584 current.performance_metrics.availability,
585 prev.performance_metrics.availability,
586 ),
587 ];
588
589 for (name, cur_val, base_val) in pairs {
590 let percentage_change = if base_val.abs() > f64::EPSILON {
591 (cur_val - base_val) / base_val * 100.0
592 } else if cur_val.abs() < f64::EPSILON {
593 0.0
594 } else {
595 100.0
596 };
597 let mag = percentage_change.abs();
600 let significance = (-mag / 50.0).exp().clamp(0.0, 1.0);
601
602 let metric_label = format!("{platform:?}.{name}");
603 baseline_comparison.push(super::results::MetricComparison {
604 metric_name: metric_label.clone(),
605 current_value: cur_val,
606 baseline_value: base_val,
607 percentage_change,
608 statistical_significance: significance,
609 });
610
611 let direction = if cur_val > base_val {
612 "increasing"
613 } else if cur_val < base_val {
614 "decreasing"
615 } else {
616 "flat"
617 };
618 trend_analysis.insert(
619 metric_label,
620 super::results::TrendAnalysisResult {
621 trend_detected: mag > 1.0,
622 trend_direction: direction.to_string(),
623 trend_strength: (mag / 100.0).clamp(0.0, 1.0),
624 trend_coefficients: vec![cur_val - base_val],
625 change_points: Vec::new(),
626 },
627 );
628 }
629 }
630
631 let mut metrics_map: HashMap<String, f64> = HashMap::new();
634 for (platform, result) in platform_results {
635 metrics_map.insert(
636 format!("{platform:?}.overall_fidelity"),
637 result.performance_metrics.overall_fidelity,
638 );
639 metrics_map.insert(
640 format!("{platform:?}.error_rate"),
641 result.performance_metrics.error_rate,
642 );
643 metrics_map.insert(
644 format!("{platform:?}.throughput"),
645 result.performance_metrics.throughput,
646 );
647 metrics_map.insert(
648 format!("{platform:?}.availability"),
649 result.performance_metrics.availability,
650 );
651 }
652
653 let snapshot = super::results::PerformanceSnapshot {
654 timestamp: SystemTime::now(),
655 metrics: metrics_map,
656 configuration: "current".to_string(),
657 };
658
659 if baseline_comparison.is_empty() {
660 return Ok(None);
661 }
662
663 Ok(Some(HistoricalComparisonResult {
664 baseline_comparison,
665 trend_analysis,
666 performance_evolution: vec![snapshot],
667 }))
668 }
669
670 async fn store_historical_result(&self, result: &UnifiedBenchmarkResult) {
671 let mut historical_data = self
672 .historical_data
673 .write()
674 .unwrap_or_else(|e| e.into_inner());
675 historical_data.push_back(result.clone());
676
677 if historical_data.len() > 10000 {
679 historical_data.pop_front();
680 }
681 }
682
683 async fn update_baselines(&self, result: &UnifiedBenchmarkResult) {
684 let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
688 let dir = format!("{home}/.cache/quantrs2-baselines");
689 if let Err(e) = std::fs::create_dir_all(&dir) {
690 eprintln!("update_baselines: could not create cache dir {dir}: {e}");
691 return;
692 }
693
694 let file_path = format!("{dir}/{}.json", result.execution_id);
695 let mut snapshot: HashMap<String, serde_json::Value> = HashMap::new();
699 for (platform, pr) in &result.platform_results {
700 let m = &pr.performance_metrics;
701 let entry = serde_json::json!({
702 "overall_fidelity": m.overall_fidelity,
703 "error_rate": m.error_rate,
704 "throughput": m.throughput,
705 "availability": m.availability,
706 "avg_exec_ms": m.average_execution_time.as_millis(),
707 });
708 snapshot.insert(format!("{platform:?}"), entry);
709 }
710
711 match serde_json::to_vec_pretty(&snapshot) {
712 Ok(bytes) => {
713 if let Err(e) = std::fs::write(&file_path, bytes) {
714 eprintln!("update_baselines: could not write {file_path}: {e}");
715 }
716 }
717 Err(e) => {
718 eprintln!("update_baselines: serialisation error: {e}");
719 }
720 }
721
722 let mut baselines = self.baselines.write().unwrap_or_else(|e| e.into_inner());
724 for (platform, pr) in &result.platform_results {
725 let m = &pr.performance_metrics;
726 let ci_half = m.error_rate * 0.05; let baseline = PerformanceBaseline {
728 platform: platform.clone(),
729 metrics: vec![
730 super::types::BaselineMetricValue {
731 metric: super::types::BaselineMetric::Fidelity,
732 value: m.overall_fidelity,
733 confidence_interval: (
734 (m.overall_fidelity - ci_half).max(0.0),
735 (m.overall_fidelity + ci_half).min(1.0),
736 ),
737 measurement_count: 1,
738 },
739 super::types::BaselineMetricValue {
740 metric: super::types::BaselineMetric::ErrorRate,
741 value: m.error_rate,
742 confidence_interval: (
743 (m.error_rate - ci_half).max(0.0),
744 m.error_rate + ci_half,
745 ),
746 measurement_count: 1,
747 },
748 super::types::BaselineMetricValue {
749 metric: super::types::BaselineMetric::Throughput,
750 value: m.throughput,
751 confidence_interval: ((m.throughput * 0.9).max(0.0), m.throughput * 1.1),
752 measurement_count: 1,
753 },
754 ],
755 last_updated: result.timestamp,
756 version: result.execution_id.clone(),
757 };
758 baselines.insert(format!("{platform:?}"), baseline);
759 }
760 }
761
762 async fn trigger_optimization(&self, result: &UnifiedBenchmarkResult) -> DeviceResult<()> {
763 let recommendations = &result.optimization_recommendations;
769 if recommendations.is_empty() {
770 return Ok(());
771 }
772
773 let mut improvements: HashMap<String, f64> = HashMap::new();
774 for r in recommendations {
775 *improvements
776 .entry(r.recommendation_type.clone())
777 .or_insert(0.0) += r.expected_improvement;
778 }
779
780 for (platform, platform_result) in &result.platform_results {
784 let metrics = &platform_result.performance_metrics;
785 if metrics.error_rate > 0.05 {
786 let _ = self.event_publisher.send(BenchmarkEvent::PerformanceAlert {
787 metric: format!("{platform:?}.error_rate"),
788 current_value: metrics.error_rate,
789 threshold: 0.05,
790 timestamp: SystemTime::now(),
791 });
792 }
793 if metrics.overall_fidelity < 0.90 {
794 let _ = self.event_publisher.send(BenchmarkEvent::PerformanceAlert {
795 metric: format!("{platform:?}.overall_fidelity"),
796 current_value: metrics.overall_fidelity,
797 threshold: 0.90,
798 timestamp: SystemTime::now(),
799 });
800 }
801 }
802
803 let _ = self
804 .event_publisher
805 .send(BenchmarkEvent::OptimizationCompleted {
806 execution_id: result.execution_id.clone(),
807 improvements,
808 timestamp: SystemTime::now(),
809 });
810
811 Ok(())
812 }
813
814 async fn generate_automated_reports(
815 &self,
816 result: &UnifiedBenchmarkResult,
817 ) -> DeviceResult<()> {
818 let payload = serde_json::to_vec_pretty(result).map_err(|err| {
824 DeviceError::APIError(format!("failed to serialize benchmark result: {err}"))
825 })?;
826
827 let config = self
828 .config
829 .read()
830 .unwrap_or_else(|e| e.into_inner())
831 .clone();
832
833 for recipient in &config.reporting_config.automated_reports.recipients {
834 if let Some(path) = recipient.strip_prefix("file://") {
835 let dir = std::path::Path::new(path);
836 if let Err(err) = std::fs::create_dir_all(dir) {
837 return Err(DeviceError::APIError(format!(
838 "failed to create report directory {dir:?}: {err}"
839 )));
840 }
841 let file = dir.join(format!("benchmark_{}.json", result.execution_id));
842 if let Err(err) = std::fs::write(&file, &payload) {
843 return Err(DeviceError::APIError(format!(
844 "failed to write report {file:?}: {err}"
845 )));
846 }
847 }
848 }
849
850 let _ = self.event_publisher.send(BenchmarkEvent::PerformanceAlert {
853 metric: "automated_report.bytes".to_string(),
854 current_value: payload.len() as f64,
855 threshold: 0.0,
856 timestamp: SystemTime::now(),
857 });
858
859 Ok(())
860 }
861
862 fn get_system_info(&self) -> super::results::SystemInfo {
863 super::results::SystemInfo {
864 hostname: "localhost".to_string(),
865 operating_system: std::env::consts::OS.to_string(),
866 cpu_info: "Unknown".to_string(),
867 memory_total: 0,
868 disk_space: 0,
869 network_info: "Unknown".to_string(),
870 }
871 }
872}
873
874pub(crate) fn generate_recommendations_from_metrics(
879 platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
880 cross_platform_analysis: &CrossPlatformAnalysis,
881) -> Vec<OptimizationRecommendation> {
882 let metrics_map: HashMap<QuantumPlatform, &PlatformPerformanceMetrics> = platform_results
883 .iter()
884 .map(|(p, r)| (p.clone(), &r.performance_metrics))
885 .collect();
886 generate_recommendations_from_perf_metrics(&metrics_map, cross_platform_analysis)
887}
888
889pub(crate) fn generate_recommendations_from_perf_metrics(
893 platform_metrics: &HashMap<QuantumPlatform, &PlatformPerformanceMetrics>,
894 cross_platform_analysis: &CrossPlatformAnalysis,
895) -> Vec<OptimizationRecommendation> {
896 let mut recommendations: Vec<OptimizationRecommendation> = Vec::new();
897
898 const ERROR_RATE_THRESHOLD: f64 = 0.05;
899 const FIDELITY_THRESHOLD: f64 = 0.90;
900 const AVAILABILITY_THRESHOLD: f64 = 0.95;
901 const EXEC_TIME_SECS_THRESHOLD: f64 = 1.0;
902 const THROUGHPUT_THRESHOLD: f64 = 1.0;
903
904 for (platform, metrics) in platform_metrics {
905 let platform_label = format!("{platform:?}");
906
907 if metrics.error_rate > ERROR_RATE_THRESHOLD {
908 recommendations.push(OptimizationRecommendation {
909 recommendation_type: "error_mitigation".to_string(),
910 description: format!(
911 "Platform {platform_label} reports an error rate of {:.4} (threshold {:.2}). Apply zero-noise extrapolation, dynamical decoupling, or readout error mitigation to reduce systematic errors.",
912 metrics.error_rate, ERROR_RATE_THRESHOLD
913 ),
914 expected_improvement: (metrics.error_rate - ERROR_RATE_THRESHOLD).max(0.0),
915 implementation_effort: "Medium".to_string(),
916 priority: 2,
917 });
918 }
919
920 if metrics.overall_fidelity < FIDELITY_THRESHOLD {
921 recommendations.push(OptimizationRecommendation {
922 recommendation_type: "calibration".to_string(),
923 description: format!(
924 "Platform {platform_label} fidelity {:.4} is below threshold {:.2}. Schedule recalibration of single- and two-qubit gates and refresh readout calibration.",
925 metrics.overall_fidelity, FIDELITY_THRESHOLD
926 ),
927 expected_improvement: (FIDELITY_THRESHOLD - metrics.overall_fidelity).max(0.0),
928 implementation_effort: "Low".to_string(),
929 priority: 1,
930 });
931 }
932
933 let avg_secs = metrics.average_execution_time.as_secs_f64();
934 if avg_secs > EXEC_TIME_SECS_THRESHOLD {
935 recommendations.push(OptimizationRecommendation {
936 recommendation_type: "circuit_reduction".to_string(),
937 description: format!(
938 "Platform {platform_label} average execution time {avg_secs:.3}s exceeds threshold {EXEC_TIME_SECS_THRESHOLD:.2}s. Apply circuit transpilation passes (gate fusion, commutation analysis, and depth-aware routing)."
939 ),
940 expected_improvement: ((avg_secs - EXEC_TIME_SECS_THRESHOLD)
941 / avg_secs.max(f64::EPSILON))
942 .clamp(0.0, 1.0),
943 implementation_effort: "Medium".to_string(),
944 priority: 3,
945 });
946 }
947
948 if metrics.availability < AVAILABILITY_THRESHOLD {
949 recommendations.push(OptimizationRecommendation {
950 recommendation_type: "platform_redundancy".to_string(),
951 description: format!(
952 "Platform {platform_label} availability {:.3} is below threshold {:.2}. Configure failover to secondary platforms and enable retry policies.",
953 metrics.availability, AVAILABILITY_THRESHOLD
954 ),
955 expected_improvement: (AVAILABILITY_THRESHOLD - metrics.availability).max(0.0),
956 implementation_effort: "Medium".to_string(),
957 priority: 2,
958 });
959 }
960
961 if metrics.throughput < THROUGHPUT_THRESHOLD && metrics.throughput > 0.0 {
962 recommendations.push(OptimizationRecommendation {
963 recommendation_type: "batching_optimization".to_string(),
964 description: format!(
965 "Platform {platform_label} throughput {:.3} ops/s is below threshold {THROUGHPUT_THRESHOLD:.2}. Batch jobs and submit in larger groups to amortize queue overhead.",
966 metrics.throughput
967 ),
968 expected_improvement: ((THROUGHPUT_THRESHOLD - metrics.throughput)
969 / THROUGHPUT_THRESHOLD)
970 .clamp(0.0, 1.0),
971 implementation_effort: "Low".to_string(),
972 priority: 4,
973 });
974 }
975 }
976
977 if platform_metrics.len() > 1 {
978 if let Some(best_for_fidelity) = cross_platform_analysis
979 .best_platform_per_metric
980 .get("fidelity")
981 {
982 recommendations.push(OptimizationRecommendation {
983 recommendation_type: "platform_routing".to_string(),
984 description: format!(
985 "Cross-platform analysis identifies {best_for_fidelity:?} as the best platform for fidelity. Route fidelity-critical workloads there and use other platforms for high-throughput jobs."
986 ),
987 expected_improvement: 0.05,
988 implementation_effort: "Low".to_string(),
989 priority: 5,
990 });
991 }
992 }
993
994 if recommendations.is_empty() {
995 recommendations.push(OptimizationRecommendation {
996 recommendation_type: "monitoring".to_string(),
997 description: "All platform metrics are within configured thresholds. Continue periodic benchmarking to detect drift early.".to_string(),
998 expected_improvement: 0.0,
999 implementation_effort: "Low".to_string(),
1000 priority: 9,
1001 });
1002 }
1003
1004 recommendations.sort_by_key(|r| r.priority);
1005 recommendations
1006}
1007
1008#[cfg(test)]
1009mod tests {
1010 use super::*;
1011 use std::time::Duration;
1012
1013 fn perf(
1014 fidelity: f64,
1015 error_rate: f64,
1016 availability: f64,
1017 avg_exec_secs: u64,
1018 throughput: f64,
1019 ) -> PlatformPerformanceMetrics {
1020 PlatformPerformanceMetrics {
1021 overall_fidelity: fidelity,
1022 average_execution_time: Duration::from_secs(avg_exec_secs),
1023 throughput,
1024 error_rate,
1025 availability,
1026 }
1027 }
1028
1029 #[test]
1030 fn test_recommendations_within_thresholds() {
1031 let metrics = perf(0.99, 0.001, 0.99, 0, 100.0);
1033 let mut platforms: HashMap<QuantumPlatform, &PlatformPerformanceMetrics> = HashMap::new();
1034 platforms.insert(
1035 QuantumPlatform::IBMQuantum {
1036 device_name: "test".to_string(),
1037 hub: None,
1038 },
1039 &metrics,
1040 );
1041 let cpa = CrossPlatformAnalysis {
1042 platform_comparison: HashMap::new(),
1043 best_platform_per_metric: HashMap::new(),
1044 statistical_significance_tests: HashMap::new(),
1045 };
1046 let recs = generate_recommendations_from_perf_metrics(&platforms, &cpa);
1047 assert_eq!(recs.len(), 1, "expected single info entry, got {recs:?}");
1048 assert_eq!(recs[0].recommendation_type, "monitoring");
1049 }
1050
1051 #[test]
1052 fn test_recommendations_breach_thresholds() {
1053 let metrics = perf(0.50, 0.20, 0.50, 5, 0.1);
1055 let mut platforms: HashMap<QuantumPlatform, &PlatformPerformanceMetrics> = HashMap::new();
1056 platforms.insert(
1057 QuantumPlatform::IBMQuantum {
1058 device_name: "test".to_string(),
1059 hub: None,
1060 },
1061 &metrics,
1062 );
1063 let cpa = CrossPlatformAnalysis {
1064 platform_comparison: HashMap::new(),
1065 best_platform_per_metric: HashMap::new(),
1066 statistical_significance_tests: HashMap::new(),
1067 };
1068 let recs = generate_recommendations_from_perf_metrics(&platforms, &cpa);
1069 assert!(
1070 recs.len() >= 5,
1071 "expected >=5 recommendations, got {}: {recs:?}",
1072 recs.len()
1073 );
1074 assert!(recs.iter().all(|r| r.recommendation_type != "monitoring"));
1075 for w in recs.windows(2) {
1076 assert!(w[0].priority <= w[1].priority, "not sorted: {recs:?}");
1077 }
1078 }
1079}