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