1use std::collections::HashMap;
8use std::time::Duration;
9
10use scirs2_core::ndarray::Array2;
11
12use super::results::{
13 AccuracyComparison, AlgorithmLevelResults, AnomalyDetectionResults, BarrenPlateauAnalysis,
14 BreakEvenAnalysis, CapacityPlanningResult, CapacityRecommendation, CentralityAnalysisResult,
15 CircuitLevelResults, ClassicalComparisonResult, ClassificationResults, ClusteringResults,
16 CommunityDetectionResult, ConnectivityAnalysisResult, ConvergenceAnalysis,
17 CorrelationAnalysisResult, CostAnalysisResult, CostMetrics, CostOptimizationAnalysisResult,
18 CrossEntropyResult, CrossPlatformAnalysis, CrossPlatformComparison, CrossValidationResult,
19 DepthScalingResult, EnsembleResult, ExponentialFit, FailurePattern, FeatureImportanceResults,
20 ForecastingResults, GateLevelResults, GraphAnalysisResult, HeavyOutputResult,
21 HypothesisTestResult, LinearRegressionResult, MLAnalysisResult, MLModelResult,
22 MLRegressionResults, ModelComparisonResult, NISQPerformanceResult, NonlinearRegressionResult,
23 OptimizationAnalysisResult, OptimizationResult, ParameterSensitivityAnalysis,
24 ParetoAnalysisResult, PerturbationResult, PlatformBenchmarkResult, PlatformPerformanceMetrics,
25 PlatformRanking, PolynomialFit, QuantumAdvantageResult, ROIAnalysis, ROIAnalysisResult,
26 RandomizedBenchmarkingResult, RegressionAnalysisResult, ReliabilityMetrics,
27 ResourceAnalysisResult, ResourceUtilizationMetrics, RobustnessAnalysisResult,
28 ScalabilityAnalysis, ScalingMetric, SciRS2AnalysisResult, SeasonalityAnalysisResult,
29 SensitivityAnalysisResult, StabilityAnalysis, StationarityTestResults,
30 StatisticalAnalysisResult, StatisticalSummary, SystemCostEfficiency, SystemLevelResults,
31 SystemReliabilityAnalysis, SystemResourceUtilization, SystemScalabilityAnalysis,
32 TimeSeriesAnalysisResult, TopologyOptimizationResult, TrendAnalysisResult,
33 UncertaintyPropagation, VariationalAlgorithmResult, VolumeBenchmarkResult, WidthScalingResult,
34};
35use super::types::QuantumPlatform;
36
37pub fn zero_statistical_summary() -> StatisticalSummary {
41 StatisticalSummary {
42 mean: 0.0,
43 std_dev: 0.0,
44 median: 0.0,
45 min: 0.0,
46 max: 0.0,
47 percentiles: HashMap::new(),
48 confidence_interval: (0.0, 0.0),
49 }
50}
51
52pub fn statistical_summary_from_slice(values: &[f64]) -> StatisticalSummary {
55 if values.is_empty() {
56 return zero_statistical_summary();
57 }
58 let n = values.len() as f64;
59 let mean = values.iter().sum::<f64>() / n;
60 let variance = values.iter().map(|&x| (x - mean).powi(2)).sum::<f64>() / n;
61 let std_dev = variance.sqrt();
62 let mut sorted = values.to_vec();
63 sorted.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
64 let min = sorted[0];
65 let max = *sorted.last().unwrap_or(&0.0);
66 let median = if sorted.len() % 2 == 0 {
67 (sorted[sorted.len() / 2 - 1] + sorted[sorted.len() / 2]) / 2.0
68 } else {
69 sorted[sorted.len() / 2]
70 };
71 let p95_idx = ((sorted.len() as f64 * 0.95) as usize).min(sorted.len() - 1);
72 let p50_idx = ((sorted.len() as f64 * 0.50) as usize).min(sorted.len() - 1);
73 let mut percentiles = HashMap::new();
74 percentiles.insert(50u8, sorted[p50_idx]);
75 percentiles.insert(95u8, sorted[p95_idx]);
76 let ci_half = 1.96 * std_dev / n.sqrt();
78 StatisticalSummary {
79 mean,
80 std_dev,
81 median,
82 min,
83 max,
84 percentiles,
85 confidence_interval: (mean - ci_half, mean + ci_half),
86 }
87}
88
89pub fn default_gate_level_results() -> GateLevelResults {
94 GateLevelResults {
95 single_qubit_results: HashMap::new(),
96 two_qubit_results: HashMap::new(),
97 multi_qubit_results: HashMap::new(),
98 randomized_benchmarking: RandomizedBenchmarkingResult {
99 clifford_fidelity: 0.99,
100 decay_parameter: 0.001,
101 confidence_interval: (0.985, 0.995),
102 sequence_lengths: vec![1, 2, 4, 8, 16],
103 survival_probabilities: vec![1.0, 0.998, 0.992, 0.984, 0.968],
104 },
105 process_tomography: None,
106 }
107}
108
109pub fn default_circuit_level_results() -> CircuitLevelResults {
111 CircuitLevelResults {
112 depth_scaling: DepthScalingResult {
113 depth_vs_fidelity: vec![(1, 0.99), (10, 0.90), (50, 0.70)],
114 depth_vs_execution_time: vec![
115 (1, Duration::from_micros(50)),
116 (10, Duration::from_micros(500)),
117 (50, Duration::from_millis(3)),
118 ],
119 scaling_exponent: 1.2,
120 coherence_limited_depth: 100,
121 },
122 width_scaling: WidthScalingResult {
123 width_vs_fidelity: vec![(1, 0.99), (5, 0.95), (20, 0.80)],
124 width_vs_execution_time: vec![
125 (1, Duration::from_micros(50)),
126 (5, Duration::from_micros(150)),
127 (20, Duration::from_millis(1)),
128 ],
129 scaling_exponent: 0.8,
130 connectivity_limited_width: 50,
131 },
132 circuit_type_results: HashMap::new(),
133 parametric_results: HashMap::new(),
134 volume_benchmarks: VolumeBenchmarkResult {
135 heavy_output: HeavyOutputResult {
136 heavy_output_probability: 0.66,
137 theoretical_threshold: 0.5,
138 statistical_significance: 0.95,
139 },
140 cross_entropy: CrossEntropyResult {
141 cross_entropy_benchmarking_fidelity: 0.95,
142 linear_xeb_fidelity: 0.94,
143 log_xeb_fidelity: 0.93,
144 },
145 quantum_volume: 32,
146 },
147 }
148}
149
150pub fn default_algorithm_level_results() -> AlgorithmLevelResults {
152 AlgorithmLevelResults {
153 algorithm_results: HashMap::new(),
154 nisq_performance: NISQPerformanceResult {
155 noise_resilience: 0.85,
156 error_mitigation_effectiveness: 0.70,
157 depth_limited_performance: {
158 let mut m = HashMap::new();
159 m.insert(10_usize, 0.95_f64);
160 m.insert(50, 0.80);
161 m.insert(100, 0.60);
162 m
163 },
164 variational_optimization_convergence: ConvergenceAnalysis {
165 convergence_achieved: true,
166 iterations_to_convergence: Some(150),
167 final_cost: -1.0,
168 cost_history: vec![-0.1, -0.5, -0.8, -1.0],
169 gradient_norms: vec![0.5, 0.2, 0.05, 0.001],
170 },
171 },
172 quantum_advantage: QuantumAdvantageResult {
173 advantage_demonstrated: false,
174 speedup_factor: None,
175 confidence_level: 0.0,
176 problem_instances_tested: 0,
177 },
178 classical_comparison: ClassicalComparisonResult {
179 classical_runtime: Duration::from_secs(1),
180 quantum_runtime: Duration::from_millis(100),
181 speedup_ratio: 10.0,
182 accuracy_comparison: AccuracyComparison {
183 classical_accuracy: 1.0,
184 quantum_accuracy: 0.95,
185 relative_error: 0.05,
186 },
187 },
188 variational_algorithm_performance: VariationalAlgorithmResult {
189 optimization_landscapes: HashMap::new(),
190 convergence_analysis: ConvergenceAnalysis {
191 convergence_achieved: true,
192 iterations_to_convergence: Some(200),
193 final_cost: -0.9,
194 cost_history: vec![-0.1, -0.5, -0.8, -0.9],
195 gradient_norms: vec![0.5, 0.2, 0.05, 0.01],
196 },
197 parameter_sensitivity: ParameterSensitivityAnalysis {
198 sensitivity_matrix: Array2::eye(2),
199 most_sensitive_parameters: vec![0],
200 robustness_score: 0.75,
201 },
202 barren_plateau_analysis: BarrenPlateauAnalysis {
203 plateau_detected: false,
204 gradient_variance: 0.1,
205 effective_dimension: 4.0,
206 mitigation_strategies: vec![],
207 },
208 },
209 }
210}
211
212pub fn default_system_level_results(platform: &QuantumPlatform) -> SystemLevelResults {
214 SystemLevelResults {
215 cross_platform_comparison: CrossPlatformComparison {
216 platform_rankings: vec![PlatformRanking {
217 platform: platform.clone(),
218 overall_score: 0.85,
219 category_scores: {
220 let mut m = HashMap::new();
221 m.insert("fidelity".to_string(), 0.90);
222 m.insert("speed".to_string(), 0.80);
223 m
224 },
225 rank: 1,
226 }],
227 relative_performance: {
228 let mut m = HashMap::new();
229 m.insert(format!("{platform:?}"), 1.0);
230 m
231 },
232 statistical_significance: HashMap::new(),
233 },
234 resource_utilization: SystemResourceUtilization {
235 average_queue_time: Duration::from_secs(60),
236 throughput: 10.0,
237 utilization_rate: 0.75,
238 peak_usage_times: vec![],
239 },
240 reliability_analysis: SystemReliabilityAnalysis {
241 uptime: 0.995,
242 error_frequency: 0.001,
243 recovery_time: Duration::from_secs(300),
244 failure_patterns: vec![],
245 },
246 scalability_analysis: SystemScalabilityAnalysis {
247 max_supported_qubits: 127,
248 max_circuit_depth: 1000,
249 performance_scaling: HashMap::new(),
250 },
251 cost_efficiency: SystemCostEfficiency {
252 cost_per_shot: 0.0001,
253 cost_per_gate: 0.000001,
254 cost_efficiency_score: 0.80,
255 roi_analysis: ROIAnalysis {
256 investment_cost: 1000.0,
257 operational_cost: 100.0,
258 performance_benefit: 5000.0,
259 roi_ratio: 4.5,
260 },
261 },
262 }
263}
264
265pub fn compute_performance_metrics(
269 gate: &GateLevelResults,
270 circuit: &CircuitLevelResults,
271 algo: &AlgorithmLevelResults,
272 system: &SystemLevelResults,
273) -> PlatformPerformanceMetrics {
274 let rb_fidelity = gate.randomized_benchmarking.clifford_fidelity;
276
277 let error_rate = (1.0 - rb_fidelity).max(0.0);
279
280 let throughput = system.resource_utilization.throughput;
282
283 let availability = system.reliability_analysis.uptime.clamp(0.0, 1.0);
285
286 let avg_execution_time = circuit
288 .depth_scaling
289 .depth_vs_execution_time
290 .first()
291 .map(|(_, d)| *d)
292 .unwrap_or(Duration::from_millis(100));
293
294 let fidelity = if !algo.nisq_performance.depth_limited_performance.is_empty() {
296 let vals: Vec<f64> = algo
297 .nisq_performance
298 .depth_limited_performance
299 .values()
300 .copied()
301 .collect();
302 let algo_fidelity = vals.iter().sum::<f64>() / vals.len() as f64;
303 (rb_fidelity + algo_fidelity) / 2.0
304 } else {
305 rb_fidelity
306 };
307
308 PlatformPerformanceMetrics {
309 overall_fidelity: fidelity.clamp(0.0, 1.0),
310 average_execution_time: avg_execution_time,
311 throughput,
312 error_rate,
313 availability,
314 }
315}
316
317pub fn compute_reliability_metrics(
319 gate: &GateLevelResults,
320 _circuit: &CircuitLevelResults,
321 _algo: &AlgorithmLevelResults,
322) -> ReliabilityMetrics {
323 let error_rate = (1.0 - gate.randomized_benchmarking.clifford_fidelity).max(0.0);
324 let mtbf_hours = if error_rate > 1e-9 {
326 (1.0 / error_rate).min(876_000.0) } else {
328 876_000.0
329 };
330 let mtbf = Duration::from_secs_f64(mtbf_hours * 3600.0);
331 ReliabilityMetrics {
332 uptime: (1.0 - error_rate).clamp(0.0, 1.0),
333 mtbf,
334 mttr: Duration::from_secs(300), availability: (1.0 - error_rate).clamp(0.0, 1.0),
336 }
337}
338
339pub fn compute_cost_metrics(
341 _gate: &GateLevelResults,
342 circuit: &CircuitLevelResults,
343 _algo: &AlgorithmLevelResults,
344) -> CostMetrics {
345 let qv = circuit.volume_benchmarks.quantum_volume as f64;
348 let cost_per_shot = (0.0001 * qv / 32.0).max(0.00001);
349 let cost_per_hour = cost_per_shot * 3600.0;
350 let total_cost = cost_per_hour; let mut breakdown = HashMap::new();
352 breakdown.insert("gate_operations".to_string(), total_cost * 0.6);
353 breakdown.insert("readout".to_string(), total_cost * 0.2);
354 breakdown.insert("qubit_time".to_string(), total_cost * 0.2);
355 CostMetrics {
356 total_cost,
357 cost_per_shot,
358 cost_per_hour,
359 cost_breakdown: breakdown,
360 }
361}
362
363pub fn compute_cross_platform_analysis(
367 platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
368) -> CrossPlatformAnalysis {
369 if platform_results.is_empty() {
370 return CrossPlatformAnalysis {
371 platform_comparison: HashMap::new(),
372 best_platform_per_metric: HashMap::new(),
373 statistical_significance_tests: HashMap::new(),
374 };
375 }
376
377 let mut platform_comparison: HashMap<String, f64> = HashMap::new();
378 let mut fidelity_scores: Vec<(QuantumPlatform, f64)> = Vec::new();
379 let mut error_scores: Vec<(QuantumPlatform, f64)> = Vec::new();
380 let mut throughput_scores: Vec<(QuantumPlatform, f64)> = Vec::new();
381
382 for (platform, result) in platform_results {
383 let m = &result.performance_metrics;
384 let label = format!("{platform:?}");
385 let composite = m.overall_fidelity * 0.5
387 + (1.0 - m.error_rate).clamp(0.0, 1.0) * 0.3
388 + (m.throughput / 100.0).clamp(0.0, 1.0) * 0.2;
389 platform_comparison.insert(label, composite);
390 fidelity_scores.push((platform.clone(), m.overall_fidelity));
391 error_scores.push((platform.clone(), m.error_rate));
392 throughput_scores.push((platform.clone(), m.throughput));
393 }
394
395 let best_fidelity = fidelity_scores
396 .iter()
397 .max_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal))
398 .map(|(p, _)| p.clone());
399
400 let best_error = error_scores
401 .iter()
402 .min_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal))
403 .map(|(p, _)| p.clone());
404
405 let best_throughput = throughput_scores
406 .iter()
407 .max_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal))
408 .map(|(p, _)| p.clone());
409
410 let mut best_platform_per_metric: HashMap<String, QuantumPlatform> = HashMap::new();
411 if let Some(p) = best_fidelity {
412 best_platform_per_metric.insert("fidelity".to_string(), p);
413 }
414 if let Some(p) = best_error {
415 best_platform_per_metric.insert("error_rate".to_string(), p);
416 }
417 if let Some(p) = best_throughput {
418 best_platform_per_metric.insert("throughput".to_string(), p);
419 }
420
421 let scores: Vec<f64> = platform_comparison.values().copied().collect();
433 let n = scores.len();
434 let statistical_significance_tests: HashMap<String, f64> = if n < 2 {
435 platform_comparison
438 .keys()
439 .map(|k| (k.clone(), 1.0))
440 .collect()
441 } else {
442 let mean = scores.iter().sum::<f64>() / n as f64;
443 let variance = scores.iter().map(|s| (s - mean).powi(2)).sum::<f64>() / n as f64;
444 let std_dev = variance.sqrt();
445 platform_comparison
446 .iter()
447 .map(|(label, &score)| {
448 let p_value = if std_dev > f64::EPSILON {
449 let z = (score - mean) / std_dev;
450 two_tailed_normal_p_value(z)
451 } else {
452 1.0
455 };
456 (label.clone(), p_value)
457 })
458 .collect()
459 };
460
461 CrossPlatformAnalysis {
462 platform_comparison,
463 best_platform_per_metric,
464 statistical_significance_tests,
465 }
466}
467
468fn two_tailed_normal_p_value(z: f64) -> f64 {
474 let survival = 0.5 * erfc(z.abs() / std::f64::consts::SQRT_2);
475 (2.0 * survival).clamp(0.0, 1.0)
476}
477
478fn erfc(x: f64) -> f64 {
481 let sign = if x < 0.0 { -1.0 } else { 1.0 };
482 let x = x.abs();
483 const A1: f64 = 0.254_829_592;
484 const A2: f64 = -0.284_496_736;
485 const A3: f64 = 1.421_413_741;
486 const A4: f64 = -1.453_152_027;
487 const A5: f64 = 1.061_405_429;
488 const P: f64 = 0.3275911;
489 let t = 1.0 / P.mul_add(x, 1.0);
490 let poly = ((((A5 * t + A4) * t + A3) * t + A2) * t + A1) * t;
491 let erf = 1.0 - poly * (-x * x).exp();
492 1.0 - sign * erf
493}
494
495pub fn default_scirs2_analysis() -> SciRS2AnalysisResult {
501 let hypothesis_test = HypothesisTestResult {
502 test_name: "baseline_t_test".to_string(),
503 p_value: 1.0,
504 statistic: 0.0,
505 critical_value: 1.96,
506 significant: false,
507 effect_size: 0.0,
508 };
509
510 let stationarity_test = HypothesisTestResult {
511 test_name: "adf".to_string(),
512 p_value: 0.5,
513 statistic: -1.0,
514 critical_value: -2.86,
515 significant: false,
516 effect_size: 0.0,
517 };
518
519 SciRS2AnalysisResult {
520 statistical_analysis: StatisticalAnalysisResult {
521 hypothesis_tests: vec![hypothesis_test],
522 correlation_analysis: CorrelationAnalysisResult {
523 correlationmatrix: Array2::eye(1),
524 significant_correlations: vec![],
525 partial_correlations: Array2::eye(1),
526 },
527 regression_analysis: RegressionAnalysisResult {
528 linear_regression: LinearRegressionResult {
529 coefficients: vec![0.0],
530 r_squared: 0.0,
531 adjusted_r_squared: 0.0,
532 p_values: vec![1.0],
533 residuals: vec![],
534 },
535 nonlinear_regression: NonlinearRegressionResult {
536 model_type: "none".to_string(),
537 parameters: vec![],
538 r_squared: 0.0,
539 mse: 0.0,
540 convergence_achieved: false,
541 },
542 model_comparison: ModelComparisonResult {
543 aic_scores: HashMap::new(),
544 bic_scores: HashMap::new(),
545 cross_validation_scores: HashMap::new(),
546 best_model: "none".to_string(),
547 },
548 },
549 time_series_analysis: TimeSeriesAnalysisResult {
550 trend_analysis: TrendAnalysisResult {
551 trend_detected: false,
552 trend_direction: "flat".to_string(),
553 trend_strength: 0.0,
554 trend_coefficients: vec![0.0],
555 change_points: vec![],
556 },
557 seasonality_analysis: SeasonalityAnalysisResult {
558 seasonal_components: vec![],
559 seasonal_period: 0,
560 seasonal_strength: 0.0,
561 },
562 stationarity_tests: StationarityTestResults {
563 adf_test: stationarity_test.clone(),
564 kpss_test: stationarity_test,
565 is_stationary: true,
566 },
567 forecasting: ForecastingResults {
568 forecasts: vec![],
569 confidence_intervals: vec![],
570 forecast_horizon: 0,
571 model_performance: HashMap::new(),
572 },
573 },
574 },
575 ml_analysis: MLAnalysisResult {
576 clustering_results: ClusteringResults {
577 cluster_assignments: vec![],
578 cluster_centers: Array2::zeros((0, 0)),
579 silhouette_score: 0.0,
580 inertia: 0.0,
581 optimal_clusters: 1,
582 },
583 classification_results: ClassificationResults {
584 model_accuracy: 0.0,
585 precision: vec![],
586 recall: vec![],
587 f1_score: vec![],
588 confusion_matrix: Array2::zeros((0, 0)),
589 feature_importance: vec![],
590 },
591 regression_results: MLRegressionResults {
592 models: vec![],
593 ensemble_result: EnsembleResult {
594 ensemble_mse: 0.0,
595 ensemble_mae: 0.0,
596 ensemble_r_squared: 0.0,
597 model_weights: vec![],
598 },
599 cross_validation: CrossValidationResult {
600 cv_scores: vec![],
601 mean_cv_score: 0.0,
602 std_cv_score: 0.0,
603 },
604 },
605 anomaly_detection: AnomalyDetectionResults {
606 anomaly_scores: vec![],
607 anomaly_labels: vec![],
608 anomaly_count: 0,
609 feature_importance: FeatureImportanceResults {
610 importance_scores: vec![],
611 feature_names: vec![],
612 ranked_features: vec![],
613 },
614 },
615 },
616 optimization_analysis: OptimizationAnalysisResult {
617 optimization_results: vec![],
618 pareto_analysis: ParetoAnalysisResult {
619 pareto_front: vec![],
620 pareto_solutions: vec![],
621 hypervolume: 0.0,
622 spread_metric: 0.0,
623 },
624 sensitivity_analysis: SensitivityAnalysisResult {
625 sensitivity_indices: vec![],
626 total_sensitivity_indices: vec![],
627 interaction_effects: Array2::zeros((0, 0)),
628 },
629 robustness_analysis: RobustnessAnalysisResult {
630 robustness_score: 0.0,
631 stability_analysis: StabilityAnalysis {
632 stability_score: 0.0,
633 perturbation_analysis: vec![],
634 },
635 uncertainty_propagation: UncertaintyPropagation {
636 input_uncertainties: vec![],
637 output_uncertainty: 0.0,
638 uncertainty_contributions: vec![],
639 },
640 },
641 },
642 graph_analysis: GraphAnalysisResult {
643 connectivity_analysis: ConnectivityAnalysisResult {
644 connectivity_matrix: Array2::zeros((0, 0)),
645 path_lengths: Array2::zeros((0, 0)),
646 clustering_coefficient: 0.0,
647 graph_density: 0.0,
648 },
649 centrality_analysis: CentralityAnalysisResult {
650 betweenness_centrality: vec![],
651 closeness_centrality: vec![],
652 eigenvector_centrality: vec![],
653 pagerank: vec![],
654 },
655 community_detection: CommunityDetectionResult {
656 community_assignments: vec![],
657 modularity: 0.0,
658 num_communities: 0,
659 community_sizes: vec![],
660 },
661 topology_optimization: TopologyOptimizationResult {
662 optimal_topology: Array2::zeros((0, 0)),
663 optimization_objective: 0.0,
664 improvement_factor: 1.0,
665 },
666 },
667 }
668}
669
670pub fn compute_resource_analysis(
674 platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
675) -> ResourceAnalysisResult {
676 let throughputs: Vec<f64> = platform_results
677 .values()
678 .map(|r| r.performance_metrics.throughput)
679 .collect();
680 let utilizations: Vec<f64> = platform_results
681 .values()
682 .map(|r| r.performance_metrics.availability)
683 .collect();
684
685 let avg_throughput = if throughputs.is_empty() {
686 0.0
687 } else {
688 throughputs.iter().sum::<f64>() / throughputs.len() as f64
689 };
690 let avg_utilization = if utilizations.is_empty() {
691 0.0
692 } else {
693 utilizations.iter().sum::<f64>() / utilizations.len() as f64
694 };
695 let peak_utilization = utilizations.iter().cloned().fold(0.0_f64, f64::max);
696
697 let util_metric = |avg: f64, peak: f64| ResourceUtilizationMetrics {
698 average_utilization: avg,
699 peak_utilization: peak,
700 utilization_distribution: vec![avg],
701 efficiency_score: if peak > 0.0 { avg / peak } else { 1.0 },
702 };
703
704 ResourceAnalysisResult {
705 cpu_utilization: util_metric(avg_utilization * 0.6, peak_utilization * 0.7),
706 memory_utilization: util_metric(avg_utilization * 0.4, peak_utilization * 0.5),
707 network_utilization: util_metric(avg_throughput / 100.0, avg_throughput / 50.0),
708 storage_utilization: util_metric(0.2, 0.4),
709 capacity_planning: CapacityPlanningResult {
710 current_capacity: avg_throughput,
711 projected_demand: vec![avg_throughput * 1.1, avg_throughput * 1.2],
712 capacity_recommendations: vec![CapacityRecommendation {
713 resource_type: "qubit_count".to_string(),
714 recommended_capacity: 256.0,
715 timeline: Duration::from_secs(7_776_000), cost_estimate: 50_000.0,
717 }],
718 scaling_timeline: vec![],
719 },
720 }
721}
722
723pub fn compute_cost_analysis(
725 platform_results: &HashMap<QuantumPlatform, PlatformBenchmarkResult>,
726) -> CostAnalysisResult {
727 let total_cost: f64 = platform_results
728 .values()
729 .map(|r| r.cost_metrics.total_cost)
730 .sum();
731
732 let mut cost_breakdown: HashMap<String, f64> = HashMap::new();
733 let mut cost_per_metric: HashMap<String, f64> = HashMap::new();
734 for (platform, result) in platform_results {
735 let label = format!("{platform:?}");
736 cost_breakdown.insert(label.clone(), result.cost_metrics.total_cost);
737 cost_per_metric.insert(
738 format!("{label}.cost_per_shot"),
739 result.cost_metrics.cost_per_shot,
740 );
741 }
742
743 let potential_savings = total_cost * 0.15; CostAnalysisResult {
745 total_cost,
746 cost_breakdown,
747 cost_per_metric,
748 cost_optimization: CostOptimizationAnalysisResult {
749 potential_savings,
750 optimization_strategies: vec![],
751 implementation_roadmap: vec![],
752 },
753 roi_analysis: ROIAnalysisResult {
754 roi_percentage: 250.0,
755 payback_period: Duration::from_secs(365 * 24 * 3600),
756 net_present_value: total_cost * 2.5,
757 break_even_analysis: BreakEvenAnalysis {
758 break_even_point: Duration::from_secs(180 * 24 * 3600),
759 break_even_volume: total_cost,
760 sensitivity_analysis: vec![],
761 },
762 },
763 }
764}
765
766#[derive(Debug, Clone)]
770pub struct FidelityStats {
771 pub mean: f64,
772 pub median: f64,
773 pub p95: f64,
774 pub std_dev: f64,
775 pub n: usize,
776}
777
778pub fn compute_fidelity_statistics(results: &[f64]) -> Option<FidelityStats> {
782 if results.is_empty() {
783 return None;
784 }
785 let summary = statistical_summary_from_slice(results);
786 let p95 = *summary.percentiles.get(&95u8).unwrap_or(&summary.max);
787 Some(FidelityStats {
788 mean: summary.mean,
789 median: summary.median,
790 p95,
791 std_dev: summary.std_dev,
792 n: results.len(),
793 })
794}
795
796#[cfg(test)]
799mod tests {
800 use super::super::results::{
801 CoherenceTimes, ConnectivityInfo, DeviceInfo, DeviceSpecifications, DeviceStatus,
802 QuantumTechnology, TopologyType,
803 };
804 use super::*;
805
806 #[test]
807 fn test_statistical_summary_from_slice() {
808 let values = vec![1.0, 2.0, 3.0, 4.0, 5.0];
809 let s = statistical_summary_from_slice(&values);
810 assert!((s.mean - 3.0).abs() < 1e-9);
811 assert_eq!(s.min, 1.0);
812 assert_eq!(s.max, 5.0);
813 }
814
815 #[test]
816 fn test_statistical_summary_empty() {
817 let s = statistical_summary_from_slice(&[]);
818 assert_eq!(s.mean, 0.0);
819 }
820
821 #[test]
822 fn test_compute_fidelity_statistics() {
823 let values = vec![0.99, 0.98, 0.97, 0.96, 0.95];
824 let stats = compute_fidelity_statistics(&values).expect("should have stats");
825 assert!(stats.mean > 0.96 && stats.mean < 0.99);
826 assert_eq!(stats.n, 5);
827 }
828
829 #[test]
830 fn test_compute_fidelity_statistics_empty() {
831 assert!(compute_fidelity_statistics(&[]).is_none());
832 }
833
834 #[test]
835 fn test_default_gate_level_results() {
836 let g = default_gate_level_results();
837 assert!(g.randomized_benchmarking.clifford_fidelity > 0.9);
838 }
839
840 #[test]
841 fn test_default_scirs2_analysis_is_valid() {
842 let a = default_scirs2_analysis();
843 assert!(!a.statistical_analysis.hypothesis_tests.is_empty());
844 }
845
846 #[test]
847 fn test_cross_platform_analysis_empty() {
848 let cpa = compute_cross_platform_analysis(&HashMap::new());
849 assert!(cpa.platform_comparison.is_empty());
850 }
851
852 #[test]
853 fn test_two_tailed_normal_p_value_is_real_not_fixed() {
854 assert!((two_tailed_normal_p_value(0.0) - 1.0).abs() < 1e-9);
857 let p1 = two_tailed_normal_p_value(1.0);
861 let p2 = two_tailed_normal_p_value(2.0);
862 let p3 = two_tailed_normal_p_value(3.0);
863 assert!(p1 > p2 && p2 > p3);
864 let p_1_96 = two_tailed_normal_p_value(1.96);
867 assert!((p_1_96 - 0.05).abs() < 0.002, "p(1.96) = {p_1_96}");
868 assert!((two_tailed_normal_p_value(-2.0) - p2).abs() < 1e-12);
870 }
871
872 fn make_test_platform_result(
873 platform: QuantumPlatform,
874 overall_fidelity: f64,
875 error_rate: f64,
876 throughput: f64,
877 ) -> PlatformBenchmarkResult {
878 let gate = default_gate_level_results();
879 let circuit = default_circuit_level_results();
880 let algo = default_algorithm_level_results();
881 let system = default_system_level_results(&platform);
882 let reliability_metrics = compute_reliability_metrics(&gate, &circuit, &algo);
883 let cost_metrics = compute_cost_metrics(&gate, &circuit, &algo);
884 PlatformBenchmarkResult {
885 platform: platform.clone(),
886 device_info: DeviceInfo {
887 device_id: "test-device".to_string(),
888 provider: "test-provider".to_string(),
889 technology: QuantumTechnology::Superconducting,
890 specifications: DeviceSpecifications {
891 num_qubits: 5,
892 connectivity: ConnectivityInfo {
893 topology_type: TopologyType::Linear,
894 coupling_map: vec![(0, 1), (1, 2)],
895 connectivity_matrix: Array2::zeros((5, 5)),
896 },
897 gate_set: vec!["H".to_string(), "CNOT".to_string()],
898 coherence_times: CoherenceTimes {
899 t1: HashMap::new(),
900 t2: HashMap::new(),
901 t2_echo: HashMap::new(),
902 },
903 gate_times: HashMap::new(),
904 error_rates: HashMap::new(),
905 },
906 current_status: DeviceStatus::Online,
907 calibration_date: None,
908 },
909 gate_level_results: gate,
910 circuit_level_results: circuit,
911 algorithm_level_results: algo,
912 system_level_results: system,
913 performance_metrics: PlatformPerformanceMetrics {
914 overall_fidelity,
915 average_execution_time: Duration::from_millis(10),
916 throughput,
917 error_rate,
918 availability: 0.99,
919 },
920 reliability_metrics,
921 cost_metrics,
922 }
923 }
924
925 #[test]
926 fn test_cross_platform_significance_varies_with_real_scores_not_fixed_005() {
927 let mut platforms = HashMap::new();
928 platforms.insert(
929 QuantumPlatform::IonQ {
930 device_name: "clearly_best".to_string(),
931 },
932 make_test_platform_result(
933 QuantumPlatform::IonQ {
934 device_name: "clearly_best".to_string(),
935 },
936 0.999,
937 0.0001,
938 100.0,
939 ),
940 );
941 platforms.insert(
942 QuantumPlatform::IonQ {
943 device_name: "clearly_worst".to_string(),
944 },
945 make_test_platform_result(
946 QuantumPlatform::IonQ {
947 device_name: "clearly_worst".to_string(),
948 },
949 0.5,
950 0.4,
951 1.0,
952 ),
953 );
954 platforms.insert(
955 QuantumPlatform::IonQ {
956 device_name: "middling".to_string(),
957 },
958 make_test_platform_result(
959 QuantumPlatform::IonQ {
960 device_name: "middling".to_string(),
961 },
962 0.9,
963 0.05,
964 50.0,
965 ),
966 );
967
968 let cpa = compute_cross_platform_analysis(&platforms);
969 assert_eq!(cpa.statistical_significance_tests.len(), 3);
970
971 let values: Vec<f64> = cpa
974 .statistical_significance_tests
975 .values()
976 .copied()
977 .collect();
978 assert!(
979 values.iter().any(|&v| (v - 0.05).abs() > 1e-6),
980 "all significance values were exactly 0.05: {values:?}"
981 );
982 for v in &values {
984 assert!((0.0..=1.0).contains(v));
985 }
986 }
987}