1use std::collections::HashMap;
7use std::time::{Duration, Instant};
8
9use super::compilation::CompilationResult;
10use super::config::{OptimizationLevel, ResourceAllocationStrategy, SchedulingPriority};
11use super::platform::QuantumPlatform;
12
13#[derive(Debug, Clone)]
15pub struct UniversalExecutionResult {
16 pub problem_id: String,
18 pub optimal_platform: QuantumPlatform,
20 pub compilation_results: HashMap<QuantumPlatform, CompilationResult>,
22 pub performance_predictions: HashMap<QuantumPlatform, PlatformPerformancePrediction>,
24 pub execution_result: PlatformExecutionResult,
26 pub total_time: Duration,
28 pub metadata: UniversalExecutionMetadata,
30}
31
32#[derive(Debug, Clone)]
34pub struct PlatformPerformancePrediction {
35 pub platform: QuantumPlatform,
37 pub predicted_performance: PredictedPerformance,
39 pub confidence_score: f64,
41 pub prediction_metadata: PredictionMetadata,
43}
44
45#[derive(Debug, Clone)]
47pub struct PredictedPerformance {
48 pub execution_time: Duration,
50 pub solution_quality: f64,
52 pub success_probability: f64,
54 pub cost: f64,
56 pub reliability_score: f64,
58}
59
60#[derive(Debug, Clone)]
62pub struct PredictionMetadata {
63 pub model_version: String,
65 pub prediction_timestamp: Instant,
67 pub features_used: Vec<String>,
69 pub model_accuracy: f64,
71}
72
73#[derive(Debug, Clone)]
75pub struct OptimalPlatformSelection {
76 pub platform: QuantumPlatform,
78 pub selection_score: f64,
80 pub selection_rationale: String,
82 pub alternatives: Vec<QuantumPlatform>,
84 pub selection_metadata: SelectionMetadata,
86}
87
88#[derive(Debug, Clone)]
90pub struct SelectionMetadata {
91 pub selection_timestamp: Instant,
93 pub strategy_used: ResourceAllocationStrategy,
95 pub confidence: f64,
97}
98
99#[derive(Debug, Clone)]
101pub struct ExecutionPlan {
102 pub platform: QuantumPlatform,
104 pub scheduled_start_time: Instant,
106 pub estimated_duration: Duration,
108 pub resource_allocation: PlatformResourceAllocation,
110 pub execution_parameters: ExecutionParameters,
112}
113
114#[derive(Debug, Clone)]
116pub struct PlatformResourceAllocation {
117 pub qubits: Vec<usize>,
119 pub execution_priority: SchedulingPriority,
121 pub resource_reservation: ResourceReservationInfo,
123}
124
125#[derive(Debug, Clone)]
127pub struct ResourceReservationInfo {
128 pub reservation_id: String,
130 pub reserved_until: Instant,
132}
133
134#[derive(Debug, Clone)]
136pub struct ExecutionParameters {
137 pub shots: usize,
139 pub optimization_level: OptimizationLevel,
141 pub error_mitigation: bool,
143}
144
145#[derive(Debug, Clone)]
147pub struct PlatformExecutionResult {
148 pub platform: QuantumPlatform,
150 pub execution_id: String,
152 pub solution: Vec<i32>,
154 pub objective_value: f64,
156 pub execution_time: Duration,
158 pub success: bool,
160 pub quality_metrics: ExecutionQualityMetrics,
162 pub resource_usage: ExecutionResourceUsage,
164 pub metadata: ExecutionMetadata,
166}
167
168#[derive(Debug, Clone)]
170pub struct ExecutionQualityMetrics {
171 pub solution_quality: f64,
173 pub fidelity: f64,
175 pub success_probability: f64,
177}
178
179#[derive(Debug, Clone)]
181pub struct ExecutionResourceUsage {
182 pub qubits_used: usize,
184 pub shots_executed: usize,
186 pub classical_compute_time: Duration,
188 pub cost_incurred: f64,
190}
191
192#[derive(Debug, Clone)]
194pub struct ExecutionMetadata {
195 pub execution_timestamp: Instant,
197 pub platform_version: String,
199 pub execution_environment: String,
201}
202
203#[derive(Debug, Clone)]
205pub struct UniversalExecutionMetadata {
206 pub compiler_version: String,
208 pub platforms_considered: usize,
210 pub optimization_level: OptimizationLevel,
212 pub cost_savings: f64,
214 pub performance_improvement: f64,
216}
217
218#[derive(Debug, Default)]
234pub struct PerformancePredictor {
235 history: HashMap<QuantumPlatform, Vec<PlatformExecutionResult>>,
237}
238
239impl PerformancePredictor {
240 #[must_use]
242 pub fn new() -> Self {
243 Self {
244 history: HashMap::new(),
245 }
246 }
247
248 pub fn record_result(&mut self, result: &PlatformExecutionResult) {
250 self.history
251 .entry(result.platform.clone())
252 .or_default()
253 .push(result.clone());
254 }
255
256 #[must_use]
258 pub fn sample_count(&self, platform: &QuantumPlatform) -> usize {
259 self.history.get(platform).map_or(0, Vec::len)
260 }
261
262 #[must_use]
265 pub fn predict(&self, platform: &QuantumPlatform) -> Option<PredictedPerformance> {
266 let results = self.history.get(platform)?;
267 if results.is_empty() {
268 return None;
269 }
270 let n = results.len() as f64;
271
272 let mean_time_secs = results
273 .iter()
274 .map(|r| r.execution_time.as_secs_f64())
275 .sum::<f64>()
276 / n;
277 let mean_quality = results
278 .iter()
279 .map(|r| r.quality_metrics.solution_quality)
280 .sum::<f64>()
281 / n;
282 let mean_success_probability = results
283 .iter()
284 .map(|r| r.quality_metrics.success_probability)
285 .sum::<f64>()
286 / n;
287 let mean_cost = results
288 .iter()
289 .map(|r| r.resource_usage.cost_incurred)
290 .sum::<f64>()
291 / n;
292 let success_rate = results.iter().filter(|r| r.success).count() as f64 / n;
293
294 Some(PredictedPerformance {
295 execution_time: Duration::from_secs_f64(mean_time_secs.max(0.0)),
296 solution_quality: mean_quality,
297 success_probability: mean_success_probability,
298 cost: mean_cost,
299 reliability_score: success_rate,
300 })
301 }
302
303 #[must_use]
309 pub fn model_accuracy(&self, platform: &QuantumPlatform) -> f64 {
310 let Some(results) = self.history.get(platform) else {
311 return 0.0;
312 };
313 if results.len() < 2 {
314 return 0.0;
315 }
316 let n = results.len() as f64;
317 let mean = results
318 .iter()
319 .map(|r| r.quality_metrics.solution_quality)
320 .sum::<f64>()
321 / n;
322 if mean.abs() < 1e-12 {
323 return 0.0;
324 }
325 let variance = results
326 .iter()
327 .map(|r| (r.quality_metrics.solution_quality - mean).powi(2))
328 .sum::<f64>()
329 / n;
330 let coefficient_of_variation = variance.sqrt() / mean.abs();
331 (1.0 - coefficient_of_variation).clamp(0.0, 1.0)
332 }
333
334 #[must_use]
338 pub fn confidence_score(&self, platform: &QuantumPlatform) -> f64 {
339 let n = self.sample_count(platform) as f64;
340 n / (n + 5.0)
341 }
342}
343
344#[derive(Debug, Default)]
347pub struct CostOptimizer {
348 cost_history: HashMap<QuantumPlatform, Vec<f64>>,
350}
351
352impl CostOptimizer {
353 #[must_use]
355 pub fn new() -> Self {
356 Self {
357 cost_history: HashMap::new(),
358 }
359 }
360
361 pub fn record_cost(&mut self, platform: QuantumPlatform, cost: f64) {
363 self.cost_history.entry(platform).or_default().push(cost);
364 }
365
366 #[must_use]
369 pub fn estimate_cost(&self, platform: &QuantumPlatform) -> Option<f64> {
370 let costs = self.cost_history.get(platform)?;
371 if costs.is_empty() {
372 return None;
373 }
374 Some(costs.iter().sum::<f64>() / costs.len() as f64)
375 }
376
377 #[must_use]
382 pub fn recommend_cheapest<'a>(
383 &self,
384 candidates: &'a [QuantumPlatform],
385 ) -> Option<&'a QuantumPlatform> {
386 candidates
387 .iter()
388 .filter_map(|platform| self.estimate_cost(platform).map(|cost| (platform, cost)))
389 .min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
390 .map(|(platform, _)| platform)
391 }
392}
393
394#[cfg(test)]
395mod tests {
396 use super::*;
397
398 fn make_result(
399 platform: QuantumPlatform,
400 quality: f64,
401 cost: f64,
402 success: bool,
403 ) -> PlatformExecutionResult {
404 PlatformExecutionResult {
405 platform,
406 execution_id: "test".to_string(),
407 solution: vec![1, 0, 1],
408 objective_value: -1.0,
409 execution_time: Duration::from_millis(100),
410 success,
411 quality_metrics: ExecutionQualityMetrics {
412 solution_quality: quality,
413 fidelity: 0.95,
414 success_probability: if success { 0.9 } else { 0.1 },
415 },
416 resource_usage: ExecutionResourceUsage {
417 qubits_used: 4,
418 shots_executed: 100,
419 classical_compute_time: Duration::from_millis(10),
420 cost_incurred: cost,
421 },
422 metadata: ExecutionMetadata {
423 execution_timestamp: Instant::now(),
424 platform_version: "1.0".to_string(),
425 execution_environment: "test".to_string(),
426 },
427 }
428 }
429
430 #[test]
431 fn performance_predictor_has_no_prediction_without_real_history() {
432 let predictor = PerformancePredictor::new();
433 assert!(predictor.predict(&QuantumPlatform::DWave).is_none());
434 assert_eq!(predictor.model_accuracy(&QuantumPlatform::DWave), 0.0);
435 assert_eq!(predictor.confidence_score(&QuantumPlatform::DWave), 0.0);
436 }
437
438 #[test]
439 fn performance_predictor_derives_real_predictions_from_recorded_history() {
440 let mut predictor = PerformancePredictor::new();
441 predictor.record_result(&make_result(QuantumPlatform::DWave, 0.8, 1.0, true));
442 predictor.record_result(&make_result(QuantumPlatform::DWave, 0.9, 2.0, true));
443 predictor.record_result(&make_result(QuantumPlatform::DWave, 0.7, 3.0, false));
444
445 let prediction = predictor
446 .predict(&QuantumPlatform::DWave)
447 .expect("prediction should exist once history has been recorded");
448
449 assert!((prediction.solution_quality - 0.8).abs() < 1e-9);
450 assert!((prediction.cost - 2.0).abs() < 1e-9);
451 assert!((prediction.reliability_score - (2.0 / 3.0)).abs() < 1e-9);
453
454 let confidence_after_3 = predictor.confidence_score(&QuantumPlatform::DWave);
456 predictor.record_result(&make_result(QuantumPlatform::DWave, 0.85, 1.5, true));
457 let confidence_after_4 = predictor.confidence_score(&QuantumPlatform::DWave);
458 assert!(confidence_after_4 > confidence_after_3);
459 }
460
461 #[test]
462 fn performance_predictor_accuracy_reflects_real_outcome_consistency() {
463 let mut consistent = PerformancePredictor::new();
464 consistent.record_result(&make_result(QuantumPlatform::IBM, 0.9, 1.0, true));
465 consistent.record_result(&make_result(QuantumPlatform::IBM, 0.91, 1.0, true));
466 consistent.record_result(&make_result(QuantumPlatform::IBM, 0.89, 1.0, true));
467
468 let mut erratic = PerformancePredictor::new();
469 erratic.record_result(&make_result(QuantumPlatform::IBM, 0.1, 1.0, true));
470 erratic.record_result(&make_result(QuantumPlatform::IBM, 0.9, 1.0, true));
471 erratic.record_result(&make_result(QuantumPlatform::IBM, 0.2, 1.0, false));
472
473 let consistent_accuracy = consistent.model_accuracy(&QuantumPlatform::IBM);
474 let erratic_accuracy = erratic.model_accuracy(&QuantumPlatform::IBM);
475
476 assert!(
477 consistent_accuracy > erratic_accuracy,
478 "a platform with consistent real outcomes must score higher accuracy than an erratic one \
479 (consistent={consistent_accuracy}, erratic={erratic_accuracy})"
480 );
481 }
482
483 #[test]
484 fn cost_optimizer_recommends_the_real_cheapest_platform() {
485 let mut optimizer = CostOptimizer::new();
486 optimizer.record_cost(QuantumPlatform::DWave, 5.0);
487 optimizer.record_cost(QuantumPlatform::DWave, 7.0);
488 optimizer.record_cost(QuantumPlatform::IBM, 1.0);
489 optimizer.record_cost(QuantumPlatform::IBM, 2.0);
490
491 assert!((optimizer.estimate_cost(&QuantumPlatform::DWave).unwrap() - 6.0).abs() < 1e-9);
492 assert!((optimizer.estimate_cost(&QuantumPlatform::IBM).unwrap() - 1.5).abs() < 1e-9);
493
494 let candidates = vec![QuantumPlatform::DWave, QuantumPlatform::IBM];
495 let cheapest = optimizer
496 .recommend_cheapest(&candidates)
497 .expect("a cheapest platform should be found");
498 assert_eq!(*cheapest, QuantumPlatform::IBM);
499 }
500
501 #[test]
502 fn cost_optimizer_skips_platforms_with_no_recorded_history() {
503 let mut optimizer = CostOptimizer::new();
504 optimizer.record_cost(QuantumPlatform::IBM, 3.0);
505
506 assert!(optimizer.estimate_cost(&QuantumPlatform::DWave).is_none());
507
508 let candidates = vec![QuantumPlatform::DWave, QuantumPlatform::IBM];
509 let cheapest = optimizer
510 .recommend_cheapest(&candidates)
511 .expect("should still find the one platform with real history");
512 assert_eq!(*cheapest, QuantumPlatform::IBM);
513 }
514}