quantrs2_device/vqa_support/
analysis.rs1use super::{executor::VQAResult, objectives::ObjectiveResult};
7use crate::DeviceResult;
8use std::collections::HashMap;
9use std::time::Duration;
10
11#[derive(Debug, Clone)]
13pub struct AnalysisConfig {
14 pub benchmark_classical: bool,
16 pub landscape_analysis: bool,
18 pub statistical_tests: bool,
20}
21
22impl Default for AnalysisConfig {
23 fn default() -> Self {
24 Self {
25 benchmark_classical: true,
26 landscape_analysis: false,
27 statistical_tests: true,
28 }
29 }
30}
31
32#[derive(Debug, Clone)]
34pub struct AnalysisResult {
35 pub performance: PerformanceMetrics,
37 pub convergence: ConvergenceAnalysis,
39 pub landscape: Option<LandscapeAnalysis>,
41 pub classical_comparison: Option<ClassicalComparison>,
43}
44
45#[derive(Debug, Clone)]
47pub struct PerformanceMetrics {
48 pub convergence_rate: f64,
50 pub time_to_convergence: Option<Duration>,
52 pub final_accuracy: f64,
54 pub resource_efficiency: f64,
56}
57
58#[derive(Debug, Clone)]
60pub struct ConvergenceAnalysis {
61 pub converged: bool,
63 pub pattern: ConvergencePattern,
65 pub stability: f64,
67}
68
69#[derive(Debug, Clone)]
71pub enum ConvergencePattern {
72 Monotonic,
74 Oscillatory,
76 Plateau,
78 Divergent,
80}
81
82#[derive(Debug, Clone)]
84pub struct LandscapeAnalysis {
85 pub local_minima: Vec<Vec<f64>>,
87 pub roughness: f64,
89 pub barriers: Vec<f64>,
91}
92
93#[derive(Debug, Clone)]
95pub struct ClassicalComparison {
96 pub classical_best: f64,
98 pub quantum_advantage: f64,
100 pub resource_ratio: f64,
102}
103
104#[derive(Debug)]
106pub struct PerformanceAnalyzer {
107 pub config: AnalysisConfig,
109}
110
111impl PerformanceAnalyzer {
112 pub const fn new(config: AnalysisConfig) -> Self {
114 Self { config }
115 }
116
117 pub fn analyze(&self, result: &VQAResult) -> DeviceResult<AnalysisResult> {
119 let performance = self.analyze_performance(result)?;
120 let convergence = self.analyze_convergence(result)?;
121
122 let landscape = if self.config.landscape_analysis {
123 Some(self.analyze_landscape(result)?)
124 } else {
125 None
126 };
127
128 let classical_comparison = if self.config.benchmark_classical {
129 Some(self.benchmark_classical(result)?)
130 } else {
131 None
132 };
133
134 Ok(AnalysisResult {
135 performance,
136 convergence,
137 landscape,
138 classical_comparison,
139 })
140 }
141
142 fn analyze_performance(&self, result: &VQAResult) -> DeviceResult<PerformanceMetrics> {
144 let convergence_rate = if result.history.len() > 1 {
145 let initial = result.history[0];
146 let final_val = result.history[result.history.len() - 1];
147 (initial - final_val) / result.history.len() as f64
148 } else {
149 0.0
150 };
151
152 let time_to_convergence = if result.converged {
153 Some(result.execution_time)
154 } else {
155 None
156 };
157
158 Ok(PerformanceMetrics {
159 convergence_rate,
160 time_to_convergence,
161 final_accuracy: 1.0 - result.best_value.abs(),
162 resource_efficiency: 1.0 / result.iterations as f64,
163 })
164 }
165
166 fn analyze_convergence(&self, result: &VQAResult) -> DeviceResult<ConvergenceAnalysis> {
168 let pattern = if result.history.len() < 2 {
169 ConvergencePattern::Plateau
170 } else {
171 let is_decreasing = result.history.windows(2).all(|w| w[1] <= w[0]);
173
174 if is_decreasing {
175 ConvergencePattern::Monotonic
176 } else {
177 ConvergencePattern::Oscillatory
178 }
179 };
180
181 let stability = if result.history.len() > 10 {
182 let last_10: Vec<f64> = result.history.iter().rev().take(10).copied().collect();
183 let mean = last_10.iter().sum::<f64>() / last_10.len() as f64;
184 let variance =
185 last_10.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / last_10.len() as f64;
186 1.0 / (1.0 + variance.sqrt())
187 } else {
188 0.5
189 };
190
191 Ok(ConvergenceAnalysis {
192 converged: result.converged,
193 pattern,
194 stability,
195 })
196 }
197
198 const fn analyze_landscape(&self, _result: &VQAResult) -> DeviceResult<LandscapeAnalysis> {
200 Ok(LandscapeAnalysis {
202 local_minima: vec![],
203 roughness: 0.5,
204 barriers: vec![],
205 })
206 }
207
208 fn benchmark_classical(&self, result: &VQAResult) -> DeviceResult<ClassicalComparison> {
210 let classical_best = result.best_value * 1.1; let quantum_advantage = classical_best / result.best_value;
213
214 Ok(ClassicalComparison {
215 classical_best,
216 quantum_advantage,
217 resource_ratio: 1.0,
218 })
219 }
220}