quantrs2_device/vqa_support/
executor.rs1use super::{
7 circuits::ParametricCircuit,
8 hardware::HardwareConfig,
9 noise::NoiseMitigationConfig,
10 objectives::{ObjectiveEvaluator, ObjectiveFunction, ObjectiveResult},
11 statistical::VQAStatistics,
12};
13use crate::DeviceResult;
14use scirs2_core::ndarray::Array1;
15use scirs2_core::random::prelude::*;
16use std::collections::HashMap;
17use std::time::{Duration, Instant};
18
19#[derive(Debug, Clone)]
21pub struct VQAExecutorConfig {
22 pub max_iterations: usize,
24 pub tolerance: f64,
26 pub hardware: HardwareConfig,
28 pub noise_mitigation: NoiseMitigationConfig,
30 pub optimizer: OptimizerConfig,
32}
33
34#[derive(Debug, Clone)]
36pub struct OptimizerConfig {
37 pub optimizer_type: OptimizerType,
39 pub learning_rate: f64,
41 pub parameters: HashMap<String, f64>,
43}
44
45#[derive(Debug, Clone)]
47pub enum OptimizerType {
48 GradientDescent,
50 Adam,
52 LBFGSB,
54 COBYLA,
56}
57
58impl Default for VQAExecutorConfig {
59 fn default() -> Self {
60 Self {
61 max_iterations: 1000,
62 tolerance: 1e-6,
63 hardware: HardwareConfig::default(),
64 noise_mitigation: NoiseMitigationConfig::default(),
65 optimizer: OptimizerConfig::default(),
66 }
67 }
68}
69
70impl Default for OptimizerConfig {
71 fn default() -> Self {
72 Self {
73 optimizer_type: OptimizerType::Adam,
74 learning_rate: 0.01,
75 parameters: HashMap::new(),
76 }
77 }
78}
79
80#[derive(Debug, Clone)]
82pub struct VQAResult {
83 pub optimal_parameters: Vec<f64>,
85 pub best_value: f64,
87 pub iterations: usize,
89 pub execution_time: Duration,
91 pub converged: bool,
93 pub statistics: VQAStatistics,
95 pub history: Vec<f64>,
97}
98
99#[derive(Debug)]
101pub struct VQAExecutor {
102 pub config: VQAExecutorConfig,
104}
105
106impl VQAExecutor {
107 pub fn new(
109 config: super::config::VQAConfig,
110 _calibration_manager: crate::calibration::CalibrationManager,
111 _device: Option<String>,
112 ) -> Self {
113 Self {
114 config: VQAExecutorConfig::default(),
115 }
116 }
117
118 pub const fn with_config(config: VQAExecutorConfig) -> Self {
120 Self { config }
121 }
122
123 pub fn execute(
125 &self,
126 circuit: &mut ParametricCircuit,
127 objective: &ObjectiveEvaluator,
128 ) -> DeviceResult<VQAResult> {
129 let start_time = Instant::now();
130 let mut best_value = f64::INFINITY;
131 let mut best_params = circuit.parameters.clone();
132 let mut history = Vec::new();
133 let mut converged = false;
134
135 for iteration in 0..self.config.max_iterations {
136 let result = objective.evaluate(&Array1::from_vec(circuit.parameters.clone()))?;
138 history.push(result.value);
139
140 if result.value < best_value {
142 best_value = result.value;
143 best_params.clone_from(&circuit.parameters);
144 }
145
146 if result.value.abs() < self.config.tolerance {
148 converged = true;
149 break;
150 }
151
152 self.update_parameters(circuit, &result)?;
154 }
155
156 let execution_time = start_time.elapsed();
157 let statistics = super::statistical::analyze_convergence(&history);
158
159 Ok(VQAResult {
160 optimal_parameters: best_params,
161 best_value,
162 iterations: history.len(),
163 execution_time,
164 converged,
165 statistics,
166 history,
167 })
168 }
169
170 fn update_parameters(
172 &self,
173 circuit: &mut ParametricCircuit,
174 _result: &ObjectiveResult,
175 ) -> DeviceResult<()> {
176 use scirs2_core::random::prelude::*;
178 let mut rng = thread_rng();
179
180 for param in &mut circuit.parameters {
181 *param += rng.gen_range(-0.1..0.1) * self.config.optimizer.learning_rate;
182 }
183
184 Ok(())
185 }
186}