1use crate::{CircuitExecutor, CircuitResult, DeviceError, DeviceResult, QuantumDevice};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::sync::Arc;
11use std::time::Duration;
12use tokio::sync::RwLock;
13
14pub mod circuit_simulation;
15pub mod classical_integration;
16pub mod gradients;
17pub mod hardware_acceleration;
18pub mod inference;
19pub mod optimization;
20pub mod quantum_neural_networks;
21pub mod training;
22pub mod variational_algorithms;
23
24pub use classical_integration::*;
25pub use gradients::*;
26pub use hardware_acceleration::*;
27pub use inference::*;
28pub use optimization::*;
29pub use quantum_neural_networks::*;
30pub use training::*;
31pub use variational_algorithms::*;
32
33pub struct QMLAccelerator {
35 pub device: Arc<RwLock<dyn QuantumDevice + Send + Sync>>,
37 pub config: QMLConfig,
39 pub training_history: Vec<TrainingEpoch>,
41 pub model_registry: ModelRegistry,
43 pub hardware_manager: HardwareAccelerationManager,
45 pub is_connected: bool,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct QMLConfig {
52 pub max_qubits: usize,
54 pub optimizer: OptimizerType,
56 pub learning_rate: f64,
58 pub max_epochs: usize,
60 pub convergence_tolerance: f64,
62 pub batch_size: usize,
64 pub enable_hardware_acceleration: bool,
66 pub gradient_method: GradientMethod,
68 pub noise_resilience: NoiseResilienceLevel,
70 pub max_circuit_depth: usize,
72 pub parameter_update_frequency: usize,
74}
75
76impl Default for QMLConfig {
77 fn default() -> Self {
78 Self {
79 max_qubits: 20,
80 optimizer: OptimizerType::Adam,
81 learning_rate: 0.01,
82 max_epochs: 1000,
83 convergence_tolerance: 1e-6,
84 batch_size: 32,
85 enable_hardware_acceleration: true,
86 gradient_method: GradientMethod::ParameterShift,
87 noise_resilience: NoiseResilienceLevel::Medium,
88 max_circuit_depth: 100,
89 parameter_update_frequency: 10,
90 }
91 }
92}
93
94#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
96pub enum OptimizerType {
97 GradientDescent,
99 Adam,
101 AdaGrad,
103 RMSprop,
105 SPSA,
107 QuantumNaturalGradient,
109 NelderMead,
111 COBYLA,
113}
114
115#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
117pub enum GradientMethod {
118 ParameterShift,
120 FiniteDifference,
122 LinearCombination,
124 QuantumNaturalGradient,
126 Adjoint,
128}
129
130#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
132pub enum NoiseResilienceLevel {
133 Low,
134 Medium,
135 High,
136 Adaptive,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct TrainingEpoch {
142 pub epoch: usize,
143 pub loss: f64,
144 pub accuracy: Option<f64>,
145 pub parameters: Vec<f64>,
146 pub gradient_norm: f64,
147 pub learning_rate: f64,
148 pub execution_time: Duration,
149 pub quantum_fidelity: Option<f64>,
150 pub classical_preprocessing_time: Duration,
151 pub quantum_execution_time: Duration,
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
156pub enum QMLModelType {
157 VQC,
159 QNN,
161 QAOA,
163 VQE,
165 QGAN,
167 QCNN,
169 HybridNetwork,
171}
172
173impl QMLAccelerator {
174 pub fn new(
176 device: Arc<RwLock<dyn QuantumDevice + Send + Sync>>,
177 config: QMLConfig,
178 ) -> DeviceResult<Self> {
179 let model_registry = ModelRegistry::new();
180 let hardware_manager = HardwareAccelerationManager::new(&config)?;
181
182 Ok(Self {
183 device,
184 config,
185 training_history: Vec::new(),
186 model_registry,
187 hardware_manager,
188 is_connected: false,
189 })
190 }
191
192 pub async fn connect(&mut self) -> DeviceResult<()> {
194 let device = self.device.read().await;
195 #[cfg(feature = "_async_device")]
196 let is_available = device.is_available().await?;
197 #[cfg(not(feature = "_async_device"))]
198 let is_available = device.is_available()?;
199
200 if !is_available {
201 return Err(DeviceError::DeviceNotInitialized(
202 "Quantum device not available".to_string(),
203 ));
204 }
205
206 self.hardware_manager.initialize().await?;
207 self.is_connected = true;
208 Ok(())
209 }
210
211 pub async fn disconnect(&mut self) -> DeviceResult<()> {
213 self.hardware_manager.shutdown().await?;
214 self.is_connected = false;
215 Ok(())
216 }
217
218 pub async fn train_model(
220 &mut self,
221 model_type: QMLModelType,
222 training_data: training::TrainingData,
223 validation_data: Option<training::TrainingData>,
224 ) -> DeviceResult<training::TrainingResult> {
225 if !self.is_connected {
226 return Err(DeviceError::DeviceNotInitialized(
227 "QML accelerator not connected".to_string(),
228 ));
229 }
230
231 let mut trainer = QuantumTrainer::new(self.device.clone(), &self.config, model_type)?;
232
233 let result = trainer
234 .train(training_data, validation_data, &mut self.training_history)
235 .await?;
236
237 self.model_registry
239 .register_model(result.model_id.clone(), result.model.clone())?;
240
241 Ok(result)
242 }
243
244 pub async fn inference(
246 &self,
247 model_id: &str,
248 input_data: InferenceData,
249 ) -> DeviceResult<InferenceResult> {
250 if !self.is_connected {
251 return Err(DeviceError::DeviceNotInitialized(
252 "QML accelerator not connected".to_string(),
253 ));
254 }
255
256 let model = self.model_registry.get_model(model_id)?;
257 let inference_engine = QuantumInferenceEngine::new(self.device.clone(), &self.config)?;
258
259 inference_engine.inference(model, input_data).await
260 }
261
262 pub async fn optimize_parameters(
264 &mut self,
265 initial_parameters: Vec<f64>,
266 objective_function: Box<dyn ObjectiveFunction + Send + Sync>,
267 ) -> DeviceResult<OptimizationResult> {
268 let mut optimizer =
269 create_gradient_optimizer(self.device.clone(), OptimizerType::Adam, 0.01);
270
271 optimizer.optimize(initial_parameters, objective_function)
272 }
273
274 pub async fn compute_gradients(
276 &self,
277 circuit: ParameterizedQuantumCircuit,
278 parameters: Vec<f64>,
279 ) -> DeviceResult<Vec<f64>> {
280 let gradient_calculator =
281 QuantumGradientCalculator::new(self.device.clone(), GradientConfig::default())?;
282
283 gradient_calculator
284 .compute_gradients(circuit, parameters)
285 .await
286 }
287
288 pub fn get_training_statistics(&self) -> TrainingStatistics {
290 TrainingStatistics::from_history(&self.training_history)
291 }
292
293 pub async fn export_model(
295 &self,
296 model_id: &str,
297 format: ModelExportFormat,
298 ) -> DeviceResult<Vec<u8>> {
299 let model = self.model_registry.get_model(model_id)?;
300 model.export(format).await
301 }
302
303 pub async fn import_model(
305 &mut self,
306 model_data: Vec<u8>,
307 format: ModelExportFormat,
308 ) -> DeviceResult<String> {
309 let model = QMLModel::import(model_data, format).await?;
310 let model_id = format!("imported_model_{}", uuid::Uuid::new_v4());
311
312 self.model_registry
313 .register_model(model_id.clone(), model)?;
314 Ok(model_id)
315 }
316
317 pub async fn get_acceleration_metrics(&self) -> HardwareAccelerationMetrics {
319 self.hardware_manager.get_metrics().await
320 }
321
322 pub async fn benchmark_performance(
324 &self,
325 model_type: QMLModelType,
326 problem_size: usize,
327 ) -> DeviceResult<PerformanceBenchmark> {
328 let benchmark_engine = PerformanceBenchmarkEngine::new(self.device.clone(), &self.config)?;
329
330 benchmark_engine.benchmark(model_type, problem_size).await
331 }
332
333 pub async fn get_diagnostics(&self) -> QMLDiagnostics {
335 let device = self.device.read().await;
336 #[cfg(feature = "_async_device")]
337 let device_props = device.properties().await.unwrap_or_default();
338 #[cfg(not(feature = "_async_device"))]
339 let device_props = device.properties().unwrap_or_default();
340
341 QMLDiagnostics {
342 is_connected: self.is_connected,
343 total_models: self.model_registry.model_count(),
344 training_epochs_completed: self.training_history.len(),
345 hardware_acceleration_enabled: self.config.enable_hardware_acceleration,
346 active_model_count: self.model_registry.active_model_count(),
347 average_training_time: self.calculate_average_training_time(),
348 quantum_advantage_ratio: self.hardware_manager.get_quantum_advantage_ratio().await,
349 device_properties: device_props,
350 }
351 }
352
353 fn calculate_average_training_time(&self) -> Duration {
354 if self.training_history.is_empty() {
355 return Duration::from_secs(0);
356 }
357
358 let total_time: Duration = self
359 .training_history
360 .iter()
361 .map(|epoch| epoch.execution_time)
362 .sum();
363
364 total_time / self.training_history.len() as u32
365 }
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize)]
370pub struct InferenceData {
371 pub features: Vec<f64>,
372 pub metadata: HashMap<String, String>,
373}
374
375#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct InferenceResult {
378 pub prediction: f64,
379 pub confidence: Option<f64>,
380 pub quantum_fidelity: Option<f64>,
381 pub execution_time: Duration,
382 pub metadata: HashMap<String, String>,
383}
384
385#[derive(Debug, Clone, Serialize, Deserialize)]
387pub struct QMLModel {
388 pub model_type: QMLModelType,
389 pub parameters: Vec<f64>,
390 pub circuit_structure: CircuitStructure,
391 pub training_metadata: HashMap<String, String>,
392 pub performance_metrics: HashMap<String, f64>,
393}
394
395impl QMLModel {
396 pub async fn export(&self, format: ModelExportFormat) -> DeviceResult<Vec<u8>> {
397 match format {
398 ModelExportFormat::JSON => serde_json::to_vec(self)
399 .map_err(|e| DeviceError::InvalidInput(format!("JSON export error: {e}"))),
400 ModelExportFormat::Binary => {
401 oxicode::serde::encode_to_vec(self, oxicode::config::standard())
402 .map_err(|e| DeviceError::InvalidInput(format!("Binary export error: {e:?}")))
403 }
404 ModelExportFormat::ONNX => {
405 Err(DeviceError::InvalidInput(
407 "ONNX export not yet implemented".to_string(),
408 ))
409 }
410 }
411 }
412
413 pub async fn import(data: Vec<u8>, format: ModelExportFormat) -> DeviceResult<Self> {
414 match format {
415 ModelExportFormat::JSON => serde_json::from_slice(&data)
416 .map_err(|e| DeviceError::InvalidInput(format!("JSON import error: {e}"))),
417 ModelExportFormat::Binary => {
418 oxicode::serde::decode_from_slice(&data, oxicode::config::standard())
419 .map(|(v, _consumed)| v)
420 .map_err(|e| DeviceError::InvalidInput(format!("Binary import error: {e:?}")))
421 }
422 ModelExportFormat::ONNX => Err(DeviceError::InvalidInput(
423 "ONNX import not yet implemented".to_string(),
424 )),
425 }
426 }
427}
428
429#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
431pub enum ModelExportFormat {
432 JSON,
433 Binary,
434 ONNX,
435}
436
437#[derive(Debug, Clone, Serialize, Deserialize)]
439pub struct CircuitStructure {
440 pub num_qubits: usize,
441 pub depth: usize,
442 pub gate_types: Vec<String>,
443 pub parameter_count: usize,
444 pub entangling_gates: usize,
445}
446
447#[derive(Debug, Clone, Serialize, Deserialize)]
449pub struct TrainingStatistics {
450 pub total_epochs: usize,
451 pub final_loss: f64,
452 pub best_loss: f64,
453 pub average_loss: f64,
454 pub convergence_epoch: Option<usize>,
455 pub total_training_time: Duration,
456 pub average_epoch_time: Duration,
457}
458
459impl TrainingStatistics {
460 pub fn from_history(history: &[TrainingEpoch]) -> Self {
461 if history.is_empty() {
462 return Self {
463 total_epochs: 0,
464 final_loss: 0.0,
465 best_loss: f64::INFINITY,
466 average_loss: 0.0,
467 convergence_epoch: None,
468 total_training_time: Duration::from_secs(0),
469 average_epoch_time: Duration::from_secs(0),
470 };
471 }
472
473 let total_epochs = history.len();
474 let final_loss = history
476 .last()
477 .expect("history should not be empty after early return check")
478 .loss;
479 let best_loss = history.iter().map(|e| e.loss).fold(f64::INFINITY, f64::min);
480 let average_loss = history.iter().map(|e| e.loss).sum::<f64>() / total_epochs as f64;
481 let total_training_time = history.iter().map(|e| e.execution_time).sum();
482 let average_epoch_time = total_training_time / total_epochs as u32;
483
484 Self {
485 total_epochs,
486 final_loss,
487 best_loss,
488 average_loss,
489 convergence_epoch: None, total_training_time,
491 average_epoch_time,
492 }
493 }
494}
495
496#[derive(Debug, Clone, Serialize, Deserialize)]
498pub struct QMLDiagnostics {
499 pub is_connected: bool,
500 pub total_models: usize,
501 pub training_epochs_completed: usize,
502 pub hardware_acceleration_enabled: bool,
503 pub active_model_count: usize,
504 pub average_training_time: Duration,
505 pub quantum_advantage_ratio: f64,
506 pub device_properties: HashMap<String, String>,
507}
508
509pub struct ModelRegistry {
511 models: HashMap<String, QMLModel>,
512 active_models: HashMap<String, bool>,
513}
514
515impl Default for ModelRegistry {
516 fn default() -> Self {
517 Self::new()
518 }
519}
520
521impl ModelRegistry {
522 pub fn new() -> Self {
523 Self {
524 models: HashMap::new(),
525 active_models: HashMap::new(),
526 }
527 }
528
529 pub fn register_model(&mut self, id: String, model: QMLModel) -> DeviceResult<()> {
530 self.models.insert(id.clone(), model);
531 self.active_models.insert(id, true);
532 Ok(())
533 }
534
535 pub fn get_model(&self, id: &str) -> DeviceResult<&QMLModel> {
536 self.models
537 .get(id)
538 .ok_or_else(|| DeviceError::InvalidInput(format!("Model {id} not found")))
539 }
540
541 pub fn model_count(&self) -> usize {
542 self.models.len()
543 }
544
545 pub fn active_model_count(&self) -> usize {
546 self.active_models
547 .values()
548 .filter(|&&active| active)
549 .count()
550 }
551
552 pub fn deactivate_model(&mut self, id: &str) -> DeviceResult<()> {
553 if self.active_models.contains_key(id) {
554 self.active_models.insert(id.to_string(), false);
555 Ok(())
556 } else {
557 Err(DeviceError::InvalidInput(format!("Model {id} not found")))
558 }
559 }
560}
561
562pub fn create_vqc_accelerator(
564 device: Arc<RwLock<dyn QuantumDevice + Send + Sync>>,
565 num_qubits: usize,
566) -> DeviceResult<QMLAccelerator> {
567 let config = QMLConfig {
568 max_qubits: num_qubits,
569 optimizer: OptimizerType::Adam,
570 gradient_method: GradientMethod::ParameterShift,
571 ..Default::default()
572 };
573
574 QMLAccelerator::new(device, config)
575}
576
577pub fn create_qaoa_accelerator(
579 device: Arc<RwLock<dyn QuantumDevice + Send + Sync>>,
580 problem_size: usize,
581) -> DeviceResult<QMLAccelerator> {
582 let config = QMLConfig {
583 max_qubits: problem_size,
584 optimizer: OptimizerType::COBYLA,
585 gradient_method: GradientMethod::FiniteDifference,
586 max_circuit_depth: 50,
587 ..Default::default()
588 };
589
590 QMLAccelerator::new(device, config)
591}
592
593#[cfg(test)]
594mod tests {
595 use super::*;
596 use crate::test_utils::*;
597
598 #[tokio::test]
599 async fn test_qml_accelerator_creation() {
600 let device = create_mock_quantum_device();
601 let accelerator = QMLAccelerator::new(device, QMLConfig::default())
602 .expect("QML accelerator creation should succeed with mock device");
603
604 assert_eq!(accelerator.config.max_qubits, 20);
605 assert!(!accelerator.is_connected);
606 }
607
608 #[tokio::test]
609 async fn test_model_registry() {
610 let mut registry = ModelRegistry::new();
611 assert_eq!(registry.model_count(), 0);
612
613 let model = QMLModel {
614 model_type: QMLModelType::VQC,
615 parameters: vec![0.1, 0.2, 0.3],
616 circuit_structure: CircuitStructure {
617 num_qubits: 4,
618 depth: 10,
619 gate_types: vec!["RY".to_string(), "CNOT".to_string()],
620 parameter_count: 8,
621 entangling_gates: 4,
622 },
623 training_metadata: HashMap::new(),
624 performance_metrics: HashMap::new(),
625 };
626
627 registry
628 .register_model("test_model".to_string(), model)
629 .expect("registering model should succeed");
630 assert_eq!(registry.model_count(), 1);
631 assert_eq!(registry.active_model_count(), 1);
632
633 let retrieved = registry
634 .get_model("test_model")
635 .expect("retrieving registered model should succeed");
636 assert_eq!(retrieved.model_type, QMLModelType::VQC);
637 }
638
639 #[test]
640 fn test_training_statistics() {
641 let history = vec![
642 TrainingEpoch {
643 epoch: 0,
644 loss: 1.0,
645 accuracy: Some(0.5),
646 parameters: vec![0.1],
647 gradient_norm: 0.5,
648 learning_rate: 0.01,
649 execution_time: Duration::from_millis(100),
650 quantum_fidelity: Some(0.95),
651 classical_preprocessing_time: Duration::from_millis(10),
652 quantum_execution_time: Duration::from_millis(90),
653 },
654 TrainingEpoch {
655 epoch: 1,
656 loss: 0.5,
657 accuracy: Some(0.7),
658 parameters: vec![0.2],
659 gradient_norm: 0.3,
660 learning_rate: 0.01,
661 execution_time: Duration::from_millis(120),
662 quantum_fidelity: Some(0.96),
663 classical_preprocessing_time: Duration::from_millis(15),
664 quantum_execution_time: Duration::from_millis(105),
665 },
666 ];
667
668 let stats = TrainingStatistics::from_history(&history);
669 assert_eq!(stats.total_epochs, 2);
670 assert_eq!(stats.final_loss, 0.5);
671 assert_eq!(stats.best_loss, 0.5);
672 assert_eq!(stats.average_loss, 0.75);
673 }
674}