use super::{executor::VQAResult, objectives::ObjectiveResult};
use crate::DeviceResult;
use std::collections::HashMap;
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct AnalysisConfig {
pub benchmark_classical: bool,
pub landscape_analysis: bool,
pub statistical_tests: bool,
}
impl Default for AnalysisConfig {
fn default() -> Self {
Self {
benchmark_classical: true,
landscape_analysis: false,
statistical_tests: true,
}
}
}
#[derive(Debug, Clone)]
pub struct AnalysisResult {
pub performance: PerformanceMetrics,
pub convergence: ConvergenceAnalysis,
pub landscape: Option<LandscapeAnalysis>,
pub classical_comparison: Option<ClassicalComparison>,
}
#[derive(Debug, Clone)]
pub struct PerformanceMetrics {
pub convergence_rate: f64,
pub time_to_convergence: Option<Duration>,
pub final_accuracy: f64,
pub resource_efficiency: f64,
}
#[derive(Debug, Clone)]
pub struct ConvergenceAnalysis {
pub converged: bool,
pub pattern: ConvergencePattern,
pub stability: f64,
}
#[derive(Debug, Clone)]
pub enum ConvergencePattern {
Monotonic,
Oscillatory,
Plateau,
Divergent,
}
#[derive(Debug, Clone)]
pub struct LandscapeAnalysis {
pub local_minima: Vec<Vec<f64>>,
pub roughness: f64,
pub barriers: Vec<f64>,
}
#[derive(Debug, Clone)]
pub struct ClassicalComparison {
pub classical_best: f64,
pub quantum_advantage: f64,
pub resource_ratio: f64,
}
#[derive(Debug)]
pub struct PerformanceAnalyzer {
pub config: AnalysisConfig,
}
impl PerformanceAnalyzer {
pub const fn new(config: AnalysisConfig) -> Self {
Self { config }
}
pub fn analyze(&self, result: &VQAResult) -> DeviceResult<AnalysisResult> {
let performance = self.analyze_performance(result)?;
let convergence = self.analyze_convergence(result)?;
let landscape = if self.config.landscape_analysis {
Some(self.analyze_landscape(result)?)
} else {
None
};
let classical_comparison = if self.config.benchmark_classical {
Some(self.benchmark_classical(result)?)
} else {
None
};
Ok(AnalysisResult {
performance,
convergence,
landscape,
classical_comparison,
})
}
fn analyze_performance(&self, result: &VQAResult) -> DeviceResult<PerformanceMetrics> {
let convergence_rate = if result.history.len() > 1 {
let initial = result.history[0];
let final_val = result.history[result.history.len() - 1];
(initial - final_val) / result.history.len() as f64
} else {
0.0
};
let time_to_convergence = if result.converged {
Some(result.execution_time)
} else {
None
};
Ok(PerformanceMetrics {
convergence_rate,
time_to_convergence,
final_accuracy: 1.0 - result.best_value.abs(),
resource_efficiency: 1.0 / result.iterations as f64,
})
}
fn analyze_convergence(&self, result: &VQAResult) -> DeviceResult<ConvergenceAnalysis> {
let pattern = if result.history.len() < 2 {
ConvergencePattern::Plateau
} else {
let is_decreasing = result.history.windows(2).all(|w| w[1] <= w[0]);
if is_decreasing {
ConvergencePattern::Monotonic
} else {
ConvergencePattern::Oscillatory
}
};
let stability = if result.history.len() > 10 {
let last_10: Vec<f64> = result.history.iter().rev().take(10).copied().collect();
let mean = last_10.iter().sum::<f64>() / last_10.len() as f64;
let variance =
last_10.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / last_10.len() as f64;
1.0 / (1.0 + variance.sqrt())
} else {
0.5
};
Ok(ConvergenceAnalysis {
converged: result.converged,
pattern,
stability,
})
}
const fn analyze_landscape(&self, _result: &VQAResult) -> DeviceResult<LandscapeAnalysis> {
Ok(LandscapeAnalysis {
local_minima: vec![],
roughness: 0.5,
barriers: vec![],
})
}
fn benchmark_classical(&self, result: &VQAResult) -> DeviceResult<ClassicalComparison> {
let classical_best = result.best_value * 1.1; let quantum_advantage = classical_best / result.best_value;
Ok(ClassicalComparison {
classical_best,
quantum_advantage,
resource_ratio: 1.0,
})
}
}