1use scirs2_core::ndarray::{Array1, Array2};
28use scirs2_core::random::prelude::*;
29use scirs2_core::Complex64;
30use serde::{Deserialize, Serialize};
31use std::collections::{HashMap, VecDeque};
32
33use crate::circuit_interfaces::{
34 CircuitInterface, InterfaceCircuit, InterfaceGate, InterfaceGateType,
35};
36use crate::error::Result;
37use crate::hardware_aware_qml::AdaptationState;
38use crate::quantum_reservoir_computing_enhanced::MemoryMetrics;
39use crate::statevector::StateVectorSimulator;
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
43pub enum QuantumReservoirArchitecture {
44 RandomCircuit,
46 SpinChain,
48 TransverseFieldIsing,
50 SmallWorld,
52 FullyConnected,
54 ScaleFree,
56 HierarchicalModular,
58 AdaptiveTopology,
60 QuantumCellularAutomaton,
62 Ring,
64 Grid,
66 Tree,
68 Hypergraph,
70 TensorNetwork,
72 Custom,
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
78pub enum ReservoirDynamics {
79 Unitary,
81 Open,
83 NISQ,
85 Adiabatic,
87 Floquet,
89 QuantumWalk,
91 ContinuousTime,
93 DigitalQuantum,
95 Variational,
97 HamiltonianLearning,
99 ManyBodyLocalized,
101 QuantumChaotic,
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
107pub enum InputEncoding {
108 Amplitude,
110 Phase,
112 BasisState,
114 Coherent,
116 Squeezed,
118 Angle,
120 IQP,
122 DataReUploading,
124 QuantumFeatureMap,
126 VariationalEncoding,
128 TemporalEncoding,
130 FourierEncoding,
132 WaveletEncoding,
134 HaarRandom,
136 GraphEncoding,
138}
139
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
142pub enum OutputMeasurement {
143 PauliExpectation,
145 Probability,
147 Correlations,
149 Entanglement,
151 Fidelity,
153 QuantumFisherInformation,
155 Variance,
157 HigherOrderMoments,
159 SpectralProperties,
161 QuantumCoherence,
163 Purity,
165 QuantumMutualInformation,
167 ProcessTomography,
169 TemporalCorrelations,
171 NonLinearReadout,
173}
174
175#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct QuantumReservoirConfig {
178 pub num_qubits: usize,
180 pub architecture: QuantumReservoirArchitecture,
182 pub dynamics: ReservoirDynamics,
184 pub input_encoding: InputEncoding,
186 pub output_measurement: OutputMeasurement,
188 pub learning_config: AdvancedLearningConfig,
190 pub time_series_config: TimeSeriesConfig,
192 pub topology_config: TopologyConfig,
194 pub adaptive_config: AdaptiveLearningConfig,
196 pub memory_config: MemoryAnalysisConfig,
198 pub hardware_config: HardwareOptimizationConfig,
200 pub benchmark_config: BenchmarkingConfig,
202 pub time_step: f64,
204 pub evolution_steps: usize,
206 pub coupling_strength: f64,
208 pub noise_level: f64,
210 pub memory_capacity: usize,
212 pub adaptive_learning: bool,
214 pub learning_rate: f64,
216 pub washout_period: usize,
218 pub random_seed: Option<u64>,
220 pub enable_qec: bool,
222 pub precision: f64,
224}
225
226impl Default for QuantumReservoirConfig {
227 fn default() -> Self {
228 Self {
229 num_qubits: 8,
230 architecture: QuantumReservoirArchitecture::RandomCircuit,
231 dynamics: ReservoirDynamics::Unitary,
232 input_encoding: InputEncoding::Amplitude,
233 output_measurement: OutputMeasurement::PauliExpectation,
234 learning_config: AdvancedLearningConfig::default(),
235 time_series_config: TimeSeriesConfig::default(),
236 topology_config: TopologyConfig::default(),
237 adaptive_config: AdaptiveLearningConfig::default(),
238 memory_config: MemoryAnalysisConfig::default(),
239 hardware_config: HardwareOptimizationConfig::default(),
240 benchmark_config: BenchmarkingConfig::default(),
241 time_step: 0.1,
242 evolution_steps: 10,
243 coupling_strength: 1.0,
244 noise_level: 0.01,
245 memory_capacity: 100,
246 adaptive_learning: true,
247 learning_rate: 0.01,
248 washout_period: 50,
249 random_seed: None,
250 enable_qec: false,
251 precision: 1e-8,
252 }
253 }
254}
255
256#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
258pub enum LearningAlgorithm {
259 Ridge,
261 LASSO,
263 ElasticNet,
265 RecursiveLeastSquares,
267 KalmanFilter,
269 ExtendedKalmanFilter,
271 NeuralNetwork,
273 SupportVectorRegression,
275 GaussianProcess,
277 RandomForest,
279 GradientBoosting,
281 OnlineGradientDescent,
283 Adam,
285 MetaLearning,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
291pub struct AdvancedLearningConfig {
292 pub algorithm: LearningAlgorithm,
294 pub regularization: f64,
296 pub l1_ratio: f64,
298 pub forgetting_factor: f64,
300 pub process_noise: f64,
302 pub measurement_noise: f64,
304 pub nn_architecture: Vec<usize>,
306 pub nn_activation: ActivationFunction,
308 pub epochs: usize,
310 pub batch_size: usize,
312 pub early_stopping_patience: usize,
314 pub cv_folds: usize,
316 pub enable_ensemble: bool,
318 pub ensemble_size: usize,
320}
321
322impl Default for AdvancedLearningConfig {
323 fn default() -> Self {
324 Self {
325 algorithm: LearningAlgorithm::Ridge,
326 regularization: 1e-6,
327 l1_ratio: 0.5,
328 forgetting_factor: 0.99,
329 process_noise: 1e-4,
330 measurement_noise: 1e-3,
331 nn_architecture: vec![64, 32, 16],
332 nn_activation: ActivationFunction::ReLU,
333 epochs: 100,
334 batch_size: 32,
335 early_stopping_patience: 10,
336 cv_folds: 5,
337 enable_ensemble: false,
338 ensemble_size: 5,
339 }
340 }
341}
342
343#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
345pub enum ActivationFunction {
346 ReLU,
348 LeakyReLU,
350 ELU,
352 Sigmoid,
354 Tanh,
356 Swish,
358 GELU,
360 Linear,
362}
363
364#[derive(Debug, Clone, Serialize, Deserialize)]
366pub struct TimeSeriesConfig {
367 pub enable_arima: bool,
369 pub ar_order: usize,
371 pub ma_order: usize,
373 pub diff_order: usize,
375 pub enable_nar: bool,
377 pub nar_order: usize,
379 pub memory_kernel: MemoryKernel,
381 pub kernel_params: Vec<f64>,
383 pub enable_seasonal: bool,
385 pub seasonal_period: usize,
387 pub trend_method: TrendDetectionMethod,
389 pub enable_changepoint: bool,
391 pub anomaly_threshold: f64,
393}
394
395impl Default for TimeSeriesConfig {
396 fn default() -> Self {
397 Self {
398 enable_arima: true,
399 ar_order: 2,
400 ma_order: 1,
401 diff_order: 1,
402 enable_nar: true,
403 nar_order: 3,
404 memory_kernel: MemoryKernel::Exponential,
405 kernel_params: vec![0.9, 0.1],
406 enable_seasonal: false,
407 seasonal_period: 12,
408 trend_method: TrendDetectionMethod::LinearRegression,
409 enable_changepoint: false,
410 anomaly_threshold: 2.0,
411 }
412 }
413}
414
415#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
417pub enum MemoryKernel {
418 Exponential,
420 PowerLaw,
422 Gaussian,
424 Polynomial,
426 Rational,
428 Sinusoidal,
430 Custom,
432}
433
434#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
436pub enum TrendDetectionMethod {
437 LinearRegression,
439 Polynomial,
441 MovingAverage,
443 HodrickPrescott,
445 KalmanFilter,
447 Spectral,
449}
450
451#[derive(Debug, Clone, Serialize, Deserialize)]
453pub struct TopologyConfig {
454 pub connectivity_density: f64,
456 pub clustering_coefficient: f64,
458 pub rewiring_probability: f64,
460 pub power_law_exponent: f64,
462 pub hierarchical_levels: usize,
464 pub modularity_strength: f64,
466 pub num_modules: usize,
468 pub enable_adaptive: bool,
470 pub adaptation_rate: f64,
472 pub min_connection_strength: f64,
474 pub max_connection_strength: f64,
476 pub pruning_threshold: f64,
478}
479
480impl Default for TopologyConfig {
481 fn default() -> Self {
482 Self {
483 connectivity_density: 0.1,
484 clustering_coefficient: 0.3,
485 rewiring_probability: 0.1,
486 power_law_exponent: 2.5,
487 hierarchical_levels: 3,
488 modularity_strength: 0.5,
489 num_modules: 4,
490 enable_adaptive: false,
491 adaptation_rate: 0.01,
492 min_connection_strength: 0.1,
493 max_connection_strength: 2.0,
494 pruning_threshold: 0.05,
495 }
496 }
497}
498
499#[derive(Debug, Clone, Serialize, Deserialize)]
501pub struct AdaptiveLearningConfig {
502 pub enable_online: bool,
504 pub lr_schedule: LearningRateSchedule,
506 pub initial_lr: f64,
508 pub min_lr: f64,
510 pub lr_decay: f64,
512 pub adaptation_window: usize,
514 pub plasticity_type: PlasticityType,
516 pub enable_homeostasis: bool,
518 pub target_activity: f64,
520 pub regulation_rate: f64,
522 pub enable_meta_learning: bool,
524 pub meta_update_frequency: usize,
526}
527
528impl Default for AdaptiveLearningConfig {
529 fn default() -> Self {
530 Self {
531 enable_online: true,
532 lr_schedule: LearningRateSchedule::Exponential,
533 initial_lr: 0.01,
534 min_lr: 1e-6,
535 lr_decay: 0.95,
536 adaptation_window: 100,
537 plasticity_type: PlasticityType::Hebbian,
538 enable_homeostasis: false,
539 target_activity: 0.5,
540 regulation_rate: 0.001,
541 enable_meta_learning: false,
542 meta_update_frequency: 1000,
543 }
544 }
545}
546
547#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
549pub enum LearningRateSchedule {
550 Constant,
552 Exponential,
554 Step,
556 Polynomial,
558 CosineAnnealing,
560 WarmRestart,
562 Adaptive,
564}
565
566#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
568pub enum PlasticityType {
569 Hebbian,
571 AntiHebbian,
573 STDP,
575 Homeostatic,
577 Metaplasticity,
579 Quantum,
581}
582
583#[derive(Debug, Clone, Serialize, Deserialize)]
585pub struct MemoryAnalysisConfig {
586 pub enable_capacity_estimation: bool,
588 pub capacity_tasks: Vec<MemoryTask>,
590 pub enable_nonlinear: bool,
592 pub nonlinearity_orders: Vec<usize>,
594 pub enable_temporal_correlation: bool,
596 pub correlation_lags: Vec<usize>,
598 pub enable_ipc: bool,
600 pub ipc_functions: Vec<IPCFunction>,
602 pub enable_entropy: bool,
604 pub entropy_measures: Vec<EntropyMeasure>,
606}
607
608impl Default for MemoryAnalysisConfig {
609 fn default() -> Self {
610 Self {
611 enable_capacity_estimation: true,
612 capacity_tasks: vec![
613 MemoryTask::DelayLine,
614 MemoryTask::TemporalXOR,
615 MemoryTask::Parity,
616 ],
617 enable_nonlinear: true,
618 nonlinearity_orders: vec![2, 3, 4],
619 enable_temporal_correlation: true,
620 correlation_lags: (1..=20).collect(),
621 enable_ipc: true,
622 ipc_functions: vec![
623 IPCFunction::Linear,
624 IPCFunction::Quadratic,
625 IPCFunction::Cubic,
626 ],
627 enable_entropy: true,
628 entropy_measures: vec![
629 EntropyMeasure::Shannon,
630 EntropyMeasure::Renyi,
631 EntropyMeasure::VonNeumann,
632 ],
633 }
634 }
635}
636
637#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
639pub enum MemoryTask {
640 DelayLine,
642 TemporalXOR,
644 Parity,
646 SequencePrediction,
648 PatternCompletion,
650 TemporalIntegration,
652}
653
654#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
656pub enum IPCFunction {
657 Linear,
659 Quadratic,
661 Cubic,
663 Sine,
665 Product,
667 XOR,
669}
670
671#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
673pub enum EntropyMeasure {
674 Shannon,
676 Renyi,
678 VonNeumann,
680 Tsallis,
682 MutualInformation,
684 TransferEntropy,
686}
687
688#[derive(Debug, Clone, Serialize, Deserialize)]
690pub struct HardwareOptimizationConfig {
691 pub platform: QuantumPlatform,
693 pub enable_noise_aware: bool,
695 pub error_mitigation: Vec<ErrorMitigationMethod>,
697 pub enable_circuit_optimization: bool,
699 pub native_gate_set: Vec<NativeGate>,
701 pub connectivity_constraints: ConnectivityConstraints,
703 pub enable_calibration: bool,
705 pub calibration_frequency: usize,
707 pub enable_monitoring: bool,
709 pub enable_hardware_adaptation: bool,
711}
712
713impl Default for HardwareOptimizationConfig {
714 fn default() -> Self {
715 Self {
716 platform: QuantumPlatform::Simulator,
717 enable_noise_aware: true,
718 error_mitigation: vec![ErrorMitigationMethod::ZNE, ErrorMitigationMethod::PEC],
719 enable_circuit_optimization: true,
720 native_gate_set: vec![NativeGate::RZ, NativeGate::SX, NativeGate::CNOT],
721 connectivity_constraints: ConnectivityConstraints::AllToAll,
722 enable_calibration: false,
723 calibration_frequency: 100,
724 enable_monitoring: true,
725 enable_hardware_adaptation: false,
726 }
727 }
728}
729
730#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
732pub enum QuantumPlatform {
733 Simulator,
735 IBM,
737 Google,
739 IonQ,
741 Rigetti,
743 Quantinuum,
745 Xanadu,
747 AtomComputing,
749 GenericNISQ,
751}
752
753#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
755pub enum ErrorMitigationMethod {
756 ZNE,
758 PEC,
760 ReadoutCorrection,
762 SymmetryVerification,
764 VirtualDistillation,
766 MeasurementCorrection,
768}
769
770#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
772pub enum NativeGate {
773 RZ,
775 SX,
777 CNOT,
779 CZ,
781 ISwap,
783 MS,
785 U3,
787}
788
789#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
791pub enum ConnectivityConstraints {
792 AllToAll,
794 Linear,
796 Grid2D,
798 HeavyHex,
800 Custom,
802}
803
804#[derive(Debug, Clone, Serialize, Deserialize)]
806pub struct BenchmarkingConfig {
807 pub enable_comprehensive: bool,
809 pub datasets: Vec<BenchmarkDataset>,
811 pub metrics: Vec<PerformanceMetric>,
813 pub statistical_tests: Vec<StatisticalTest>,
815 pub comparison_methods: Vec<ComparisonMethod>,
817 pub num_runs: usize,
819 pub confidence_level: f64,
821 pub enable_cross_validation: bool,
823 pub cv_strategy: CrossValidationStrategy,
825}
826
827impl Default for BenchmarkingConfig {
828 fn default() -> Self {
829 Self {
830 enable_comprehensive: true,
831 datasets: vec![
832 BenchmarkDataset::MackeyGlass,
833 BenchmarkDataset::Lorenz,
834 BenchmarkDataset::Sine,
835 BenchmarkDataset::Chaotic,
836 ],
837 metrics: vec![
838 PerformanceMetric::MSE,
839 PerformanceMetric::MAE,
840 PerformanceMetric::R2,
841 PerformanceMetric::MemoryCapacity,
842 ],
843 statistical_tests: vec![
844 StatisticalTest::TTest,
845 StatisticalTest::WilcoxonRankSum,
846 StatisticalTest::KruskalWallis,
847 ],
848 comparison_methods: vec![
849 ComparisonMethod::ESN,
850 ComparisonMethod::LSTM,
851 ComparisonMethod::GRU,
852 ],
853 num_runs: 10,
854 confidence_level: 0.95,
855 enable_cross_validation: true,
856 cv_strategy: CrossValidationStrategy::KFold,
857 }
858 }
859}
860
861#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
863pub enum BenchmarkDataset {
864 MackeyGlass,
866 Lorenz,
868 Sine,
870 Chaotic,
872 Financial,
874 Weather,
876 EEG,
878 Speech,
880 SyntheticNonlinear,
882}
883
884#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
886pub enum PerformanceMetric {
887 MSE,
889 MAE,
891 RMSE,
893 R2,
895 MemoryCapacity,
897 ProcessingSpeed,
899 TrainingTime,
901 GeneralizationError,
903 IPC,
905 QuantumAdvantage,
907}
908
909#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
911pub enum StatisticalTest {
912 TTest,
914 WilcoxonRankSum,
916 KruskalWallis,
918 ANOVA,
920 Friedman,
922 Bootstrap,
924}
925
926#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
928pub enum ComparisonMethod {
929 ESN,
931 LSTM,
933 GRU,
935 Transformer,
937 SVM,
939 RandomForest,
941 LinearRegression,
943}
944
945#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
947pub enum CrossValidationStrategy {
948 KFold,
950 TimeSeriesSplit,
952 LeaveOneOut,
954 StratifiedKFold,
956 GroupKFold,
958}
959
960#[derive(Debug, Clone)]
962pub struct QuantumReservoirState {
963 pub state_vector: Array1<Complex64>,
965 pub state_history: VecDeque<Array1<Complex64>>,
967 pub observables: HashMap<String, f64>,
969 pub correlations: Array2<f64>,
971 pub higher_order_correlations: HashMap<String, f64>,
973 pub entanglement_measures: HashMap<String, f64>,
975 pub memory_metrics: MemoryMetrics,
977 pub time_index: usize,
979 pub last_update: f64,
981 pub activity_level: f64,
983 pub adaptation_state: AdaptationState,
985 pub performance_history: VecDeque<f64>,
987}
988
989impl QuantumReservoirState {
990 #[must_use]
992 pub fn new(num_qubits: usize, memory_capacity: usize) -> Self {
993 let state_size = 1 << num_qubits;
994 let mut state_vector = Array1::zeros(state_size);
995 state_vector[0] = Complex64::new(1.0, 0.0); Self {
998 state_vector,
999 state_history: VecDeque::with_capacity(memory_capacity),
1000 observables: HashMap::new(),
1001 correlations: Array2::zeros((num_qubits, num_qubits)),
1002 higher_order_correlations: HashMap::new(),
1003 entanglement_measures: HashMap::new(),
1004 memory_metrics: MemoryMetrics::default(),
1005 time_index: 0,
1006 last_update: 0.0,
1007 activity_level: 0.0,
1008 adaptation_state: AdaptationState::default(),
1009 performance_history: VecDeque::with_capacity(memory_capacity),
1010 }
1011 }
1012
1013 pub fn update_state(&mut self, new_state: Array1<Complex64>) {
1015 self.state_history.push_back(self.state_vector.clone());
1016 if self.state_history.len() > self.state_history.capacity() {
1017 self.state_history.pop_front();
1018 }
1019 self.state_vector = new_state;
1020 self.time_index += 1;
1021 }
1022}
1023
1024#[derive(Debug, Clone)]
1026pub struct ReservoirTrainingData {
1027 pub inputs: Vec<Array1<f64>>,
1029 pub targets: Vec<Array1<f64>>,
1031 pub timestamps: Vec<f64>,
1033}
1034
1035pub struct QuantumReservoirComputer {
1037 config: QuantumReservoirConfig,
1039 reservoir_state: QuantumReservoirState,
1041 reservoir_circuit: InterfaceCircuit,
1043 input_coupling_circuit: InterfaceCircuit,
1045 output_weights: Array2<f64>,
1047 simulator: StateVectorSimulator,
1049 circuit_interface: CircuitInterface,
1051 metrics: ReservoirMetrics,
1053 training_history: VecDeque<TrainingExample>,
1055}
1056
1057#[derive(Debug, Clone)]
1059pub struct TrainingExample {
1060 pub input: Array1<f64>,
1062 pub reservoir_state: Array1<f64>,
1064 pub target: Array1<f64>,
1066 pub error: f64,
1068}
1069
1070#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1072pub struct ReservoirMetrics {
1073 pub training_examples: usize,
1075 pub prediction_accuracy: f64,
1077 pub memory_capacity: f64,
1079 pub processing_capacity: f64,
1081 pub generalization_error: f64,
1083 pub echo_state_property: f64,
1085 pub avg_processing_time_ms: f64,
1087 pub quantum_resource_usage: f64,
1089}
1090
1091impl QuantumReservoirComputer {
1092 pub fn new(config: QuantumReservoirConfig) -> Result<Self> {
1094 let circuit_interface = CircuitInterface::new(Default::default())?;
1095 let simulator = StateVectorSimulator::new();
1096
1097 let reservoir_state = QuantumReservoirState::new(config.num_qubits, config.memory_capacity);
1098
1099 let reservoir_circuit = Self::generate_reservoir_circuit(&config)?;
1101
1102 let input_coupling_circuit = Self::generate_input_coupling_circuit(&config)?;
1104
1105 let output_size = match config.output_measurement {
1107 OutputMeasurement::PauliExpectation => config.num_qubits * 3, OutputMeasurement::Probability => 1 << config.num_qubits, OutputMeasurement::Correlations => config.num_qubits * config.num_qubits,
1110 OutputMeasurement::Entanglement => config.num_qubits,
1111 OutputMeasurement::Fidelity => 1,
1112 OutputMeasurement::QuantumFisherInformation => config.num_qubits,
1113 OutputMeasurement::Variance => config.num_qubits,
1114 OutputMeasurement::HigherOrderMoments => config.num_qubits * 4,
1115 OutputMeasurement::SpectralProperties => config.num_qubits,
1116 OutputMeasurement::QuantumCoherence => config.num_qubits,
1117 _ => config.num_qubits, };
1119
1120 let feature_size = Self::calculate_feature_size(&config);
1121 let mut output_weights = Array2::zeros((output_size, feature_size));
1122
1123 let scale = (2.0 / (output_size + feature_size) as f64).sqrt();
1125 for elem in &mut output_weights {
1126 *elem = (thread_rng().gen::<f64>() - 0.5) * 2.0 * scale;
1127 }
1128
1129 Ok(Self {
1130 config,
1131 reservoir_state,
1132 reservoir_circuit,
1133 input_coupling_circuit,
1134 output_weights,
1135 simulator,
1136 circuit_interface,
1137 metrics: ReservoirMetrics::default(),
1138 training_history: VecDeque::with_capacity(10_000),
1139 })
1140 }
1141
1142 fn generate_reservoir_circuit(config: &QuantumReservoirConfig) -> Result<InterfaceCircuit> {
1144 let mut circuit = InterfaceCircuit::new(config.num_qubits, 0);
1145
1146 match config.architecture {
1147 QuantumReservoirArchitecture::RandomCircuit => {
1148 Self::generate_random_circuit(&mut circuit, config)?;
1149 }
1150 QuantumReservoirArchitecture::SpinChain => {
1151 Self::generate_spin_chain_circuit(&mut circuit, config)?;
1152 }
1153 QuantumReservoirArchitecture::TransverseFieldIsing => {
1154 Self::generate_tfim_circuit(&mut circuit, config)?;
1155 }
1156 QuantumReservoirArchitecture::SmallWorld => {
1157 Self::generate_small_world_circuit(&mut circuit, config)?;
1158 }
1159 QuantumReservoirArchitecture::FullyConnected => {
1160 Self::generate_fully_connected_circuit(&mut circuit, config)?;
1161 }
1162 QuantumReservoirArchitecture::Custom => {
1163 Self::generate_random_circuit(&mut circuit, config)?;
1165 }
1166 QuantumReservoirArchitecture::ScaleFree => {
1167 Self::generate_small_world_circuit(&mut circuit, config)?; }
1169 QuantumReservoirArchitecture::HierarchicalModular => {
1170 Self::generate_random_circuit(&mut circuit, config)?; }
1172 QuantumReservoirArchitecture::AdaptiveTopology => {
1173 Self::generate_random_circuit(&mut circuit, config)?; }
1175 QuantumReservoirArchitecture::QuantumCellularAutomaton => {
1176 Self::generate_spin_chain_circuit(&mut circuit, config)?; }
1178 QuantumReservoirArchitecture::Ring => {
1179 Self::generate_spin_chain_circuit(&mut circuit, config)?; }
1181 _ => {
1182 Self::generate_random_circuit(&mut circuit, config)?;
1184 }
1185 }
1186
1187 Ok(circuit)
1188 }
1189
1190 fn generate_random_circuit(
1192 circuit: &mut InterfaceCircuit,
1193 config: &QuantumReservoirConfig,
1194 ) -> Result<()> {
1195 let depth = config.evolution_steps;
1196
1197 for _ in 0..depth {
1198 for qubit in 0..config.num_qubits {
1200 let angle = thread_rng().gen::<f64>() * 2.0 * std::f64::consts::PI;
1201 let gate_type = match thread_rng().gen_range(0..3) {
1202 0 => InterfaceGateType::RX(angle),
1203 1 => InterfaceGateType::RY(angle),
1204 _ => InterfaceGateType::RZ(angle),
1205 };
1206 circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1207 }
1208
1209 for _ in 0..(config.num_qubits / 2) {
1211 let qubit1 = thread_rng().gen_range(0..config.num_qubits);
1212 let qubit2 = thread_rng().gen_range(0..config.num_qubits);
1213 if qubit1 != qubit2 {
1214 circuit.add_gate(InterfaceGate::new(
1215 InterfaceGateType::CNOT,
1216 vec![qubit1, qubit2],
1217 ));
1218 }
1219 }
1220 }
1221
1222 Ok(())
1223 }
1224
1225 fn generate_spin_chain_circuit(
1227 circuit: &mut InterfaceCircuit,
1228 config: &QuantumReservoirConfig,
1229 ) -> Result<()> {
1230 let coupling = config.coupling_strength;
1231
1232 for _ in 0..config.evolution_steps {
1233 for i in 0..config.num_qubits - 1 {
1235 circuit.add_gate(InterfaceGate::new(
1237 InterfaceGateType::RZ(coupling * config.time_step),
1238 vec![i],
1239 ));
1240 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1241 circuit.add_gate(InterfaceGate::new(
1242 InterfaceGateType::RZ(coupling * config.time_step),
1243 vec![i + 1],
1244 ));
1245 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1246 }
1247 }
1248
1249 Ok(())
1250 }
1251
1252 fn generate_tfim_circuit(
1254 circuit: &mut InterfaceCircuit,
1255 config: &QuantumReservoirConfig,
1256 ) -> Result<()> {
1257 let coupling = config.coupling_strength;
1258 let field = coupling * 0.5; for _ in 0..config.evolution_steps {
1261 for qubit in 0..config.num_qubits {
1263 circuit.add_gate(InterfaceGate::new(
1264 InterfaceGateType::RX(field * config.time_step),
1265 vec![qubit],
1266 ));
1267 }
1268
1269 for i in 0..config.num_qubits - 1 {
1271 circuit.add_gate(InterfaceGate::new(
1272 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1273 vec![i],
1274 ));
1275 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1276 circuit.add_gate(InterfaceGate::new(
1277 InterfaceGateType::RZ(coupling * config.time_step),
1278 vec![i + 1],
1279 ));
1280 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1281 circuit.add_gate(InterfaceGate::new(
1282 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1283 vec![i],
1284 ));
1285 }
1286 }
1287
1288 Ok(())
1289 }
1290
1291 fn generate_small_world_circuit(
1293 circuit: &mut InterfaceCircuit,
1294 config: &QuantumReservoirConfig,
1295 ) -> Result<()> {
1296 let coupling = config.coupling_strength;
1297 let rewiring_prob = 0.1; for _ in 0..config.evolution_steps {
1300 for i in 0..config.num_qubits {
1302 let next = (i + 1) % config.num_qubits;
1303
1304 let target = if thread_rng().gen::<f64>() < rewiring_prob {
1306 thread_rng().gen_range(0..config.num_qubits)
1307 } else {
1308 next
1309 };
1310
1311 if target != i {
1312 circuit.add_gate(InterfaceGate::new(
1313 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1314 vec![i],
1315 ));
1316 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, target]));
1317 circuit.add_gate(InterfaceGate::new(
1318 InterfaceGateType::RZ(coupling * config.time_step),
1319 vec![target],
1320 ));
1321 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, target]));
1322 circuit.add_gate(InterfaceGate::new(
1323 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1324 vec![i],
1325 ));
1326 }
1327 }
1328 }
1329
1330 Ok(())
1331 }
1332
1333 fn generate_fully_connected_circuit(
1335 circuit: &mut InterfaceCircuit,
1336 config: &QuantumReservoirConfig,
1337 ) -> Result<()> {
1338 let coupling = config.coupling_strength / config.num_qubits as f64; for _ in 0..config.evolution_steps {
1341 for i in 0..config.num_qubits {
1343 for j in i + 1..config.num_qubits {
1344 circuit.add_gate(InterfaceGate::new(
1345 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1346 vec![i],
1347 ));
1348 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1349 circuit.add_gate(InterfaceGate::new(
1350 InterfaceGateType::RZ(coupling * config.time_step),
1351 vec![j],
1352 ));
1353 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1354 circuit.add_gate(InterfaceGate::new(
1355 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1356 vec![i],
1357 ));
1358 }
1359 }
1360 }
1361
1362 Ok(())
1363 }
1364
1365 fn generate_input_coupling_circuit(
1367 config: &QuantumReservoirConfig,
1368 ) -> Result<InterfaceCircuit> {
1369 let mut circuit = InterfaceCircuit::new(config.num_qubits, 0);
1370
1371 match config.input_encoding {
1372 InputEncoding::Amplitude => {
1373 for qubit in 0..config.num_qubits {
1375 circuit.add_gate(InterfaceGate::new(
1376 InterfaceGateType::RY(0.0), vec![qubit],
1378 ));
1379 }
1380 }
1381 InputEncoding::Phase => {
1382 for qubit in 0..config.num_qubits {
1384 circuit.add_gate(InterfaceGate::new(
1385 InterfaceGateType::RZ(0.0), vec![qubit],
1387 ));
1388 }
1389 }
1390 InputEncoding::BasisState => {
1391 for qubit in 0..config.num_qubits {
1393 circuit.add_gate(InterfaceGate::new(InterfaceGateType::X, vec![qubit]));
1395 }
1396 }
1397 _ => {
1398 for qubit in 0..config.num_qubits {
1400 circuit.add_gate(InterfaceGate::new(InterfaceGateType::RY(0.0), vec![qubit]));
1401 }
1402 }
1403 }
1404
1405 Ok(circuit)
1406 }
1407
1408 fn calculate_feature_size(config: &QuantumReservoirConfig) -> usize {
1410 match config.output_measurement {
1411 OutputMeasurement::PauliExpectation => config.num_qubits * 3,
1412 OutputMeasurement::Probability => 1 << config.num_qubits.min(10), OutputMeasurement::Correlations => config.num_qubits * config.num_qubits,
1414 OutputMeasurement::Entanglement => config.num_qubits,
1415 OutputMeasurement::Fidelity => 1,
1416 OutputMeasurement::QuantumFisherInformation => config.num_qubits,
1417 OutputMeasurement::Variance => config.num_qubits,
1418 OutputMeasurement::HigherOrderMoments => config.num_qubits * 4,
1419 OutputMeasurement::SpectralProperties => config.num_qubits,
1420 OutputMeasurement::QuantumCoherence => config.num_qubits,
1421 _ => config.num_qubits, }
1423 }
1424
1425 pub fn process_input(&mut self, input: &Array1<f64>) -> Result<Array1<f64>> {
1427 let start_time = std::time::Instant::now();
1428
1429 self.encode_input(input)?;
1431
1432 self.evolve_reservoir()?;
1434
1435 let features = self.extract_features()?;
1437
1438 let processing_time = start_time.elapsed().as_secs_f64() * 1000.0;
1440 self.update_processing_time(processing_time);
1441
1442 Ok(features)
1443 }
1444
1445 fn encode_input(&mut self, input: &Array1<f64>) -> Result<()> {
1447 match self.config.input_encoding {
1448 InputEncoding::Amplitude => {
1449 self.encode_amplitude(input)?;
1450 }
1451 InputEncoding::Phase => {
1452 self.encode_phase(input)?;
1453 }
1454 InputEncoding::BasisState => {
1455 self.encode_basis_state(input)?;
1456 }
1457 _ => {
1458 self.encode_amplitude(input)?;
1459 }
1460 }
1461 Ok(())
1462 }
1463
1464 fn encode_amplitude(&mut self, input: &Array1<f64>) -> Result<()> {
1466 let num_inputs = input.len().min(self.config.num_qubits);
1467
1468 for i in 0..num_inputs {
1469 let angle = input[i] * std::f64::consts::PI; self.apply_single_qubit_rotation(i, InterfaceGateType::RY(angle))?;
1471 }
1472
1473 Ok(())
1474 }
1475
1476 fn encode_phase(&mut self, input: &Array1<f64>) -> Result<()> {
1478 let num_inputs = input.len().min(self.config.num_qubits);
1479
1480 for i in 0..num_inputs {
1481 let angle = input[i] * 2.0 * std::f64::consts::PI; self.apply_single_qubit_rotation(i, InterfaceGateType::RZ(angle))?;
1483 }
1484
1485 Ok(())
1486 }
1487
1488 fn encode_basis_state(&mut self, input: &Array1<f64>) -> Result<()> {
1490 let num_inputs = input.len().min(self.config.num_qubits);
1491
1492 for i in 0..num_inputs {
1493 if input[i] > 0.5 {
1494 self.apply_single_qubit_gate(i, InterfaceGateType::X)?;
1495 }
1496 }
1497
1498 Ok(())
1499 }
1500
1501 fn apply_single_qubit_rotation(
1503 &mut self,
1504 qubit: usize,
1505 gate_type: InterfaceGateType,
1506 ) -> Result<()> {
1507 let mut temp_circuit = InterfaceCircuit::new(self.config.num_qubits, 0);
1509 temp_circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1510
1511 self.simulator.apply_interface_circuit(&temp_circuit)?;
1513
1514 Ok(())
1515 }
1516
1517 fn apply_single_qubit_gate(
1519 &mut self,
1520 qubit: usize,
1521 gate_type: InterfaceGateType,
1522 ) -> Result<()> {
1523 let mut temp_circuit = InterfaceCircuit::new(self.config.num_qubits, 0);
1524 temp_circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1525
1526 self.simulator.apply_interface_circuit(&temp_circuit)?;
1527
1528 Ok(())
1529 }
1530
1531 fn evolve_reservoir(&mut self) -> Result<()> {
1533 match self.config.dynamics {
1534 ReservoirDynamics::Unitary => {
1535 self.evolve_unitary()?;
1536 }
1537 ReservoirDynamics::Open => {
1538 self.evolve_open_system()?;
1539 }
1540 ReservoirDynamics::NISQ => {
1541 self.evolve_nisq()?;
1542 }
1543 ReservoirDynamics::Adiabatic => {
1544 self.evolve_adiabatic()?;
1545 }
1546 ReservoirDynamics::Floquet => {
1547 self.evolve_unitary()?; }
1549 ReservoirDynamics::QuantumWalk => {
1550 self.evolve_unitary()?; }
1552 ReservoirDynamics::ContinuousTime => {
1553 self.evolve_open_system()?; }
1555 ReservoirDynamics::DigitalQuantum => {
1556 self.evolve_unitary()?; }
1558 ReservoirDynamics::Variational => {
1559 self.evolve_unitary()?; }
1561 ReservoirDynamics::HamiltonianLearning => {
1562 self.evolve_unitary()?; }
1564 ReservoirDynamics::ManyBodyLocalized => {
1565 self.evolve_unitary()?; }
1567 ReservoirDynamics::QuantumChaotic => {
1568 self.evolve_unitary()?; }
1570 }
1571 Ok(())
1572 }
1573
1574 fn evolve_unitary(&mut self) -> Result<()> {
1576 self.simulator
1577 .apply_interface_circuit(&self.reservoir_circuit)?;
1578 Ok(())
1579 }
1580
1581 fn evolve_open_system(&mut self) -> Result<()> {
1583 self.evolve_unitary()?;
1585
1586 self.apply_decoherence()?;
1588
1589 Ok(())
1590 }
1591
1592 fn evolve_nisq(&mut self) -> Result<()> {
1594 self.evolve_unitary()?;
1596
1597 self.apply_gate_errors()?;
1599
1600 self.apply_measurement_errors()?;
1602
1603 Ok(())
1604 }
1605
1606 fn evolve_adiabatic(&mut self) -> Result<()> {
1608 self.evolve_unitary()?;
1611 Ok(())
1612 }
1613
1614 fn apply_decoherence(&mut self) -> Result<()> {
1616 let decoherence_rate = self.config.noise_level;
1617
1618 for amplitude in &mut self.reservoir_state.state_vector {
1619 let phase_noise =
1621 (thread_rng().gen::<f64>() - 0.5) * decoherence_rate * 2.0 * std::f64::consts::PI;
1622 *amplitude *= Complex64::new(0.0, phase_noise).exp();
1623
1624 let damping = (1.0 - decoherence_rate).sqrt();
1626 *amplitude *= damping;
1627 }
1628
1629 let norm: f64 = self
1631 .reservoir_state
1632 .state_vector
1633 .iter()
1634 .map(scirs2_core::Complex::norm_sqr)
1635 .sum::<f64>()
1636 .sqrt();
1637
1638 if norm > 1e-15 {
1639 self.reservoir_state.state_vector.mapv_inplace(|x| x / norm);
1640 }
1641
1642 Ok(())
1643 }
1644
1645 fn apply_gate_errors(&mut self) -> Result<()> {
1647 let error_rate = self.config.noise_level;
1648
1649 for qubit in 0..self.config.num_qubits {
1650 if thread_rng().gen::<f64>() < error_rate {
1651 let error_type = thread_rng().gen_range(0..3);
1652 let gate_type = match error_type {
1653 0 => InterfaceGateType::X,
1654 1 => InterfaceGateType::PauliY,
1655 _ => InterfaceGateType::PauliZ,
1656 };
1657 self.apply_single_qubit_gate(qubit, gate_type)?;
1658 }
1659 }
1660
1661 Ok(())
1662 }
1663
1664 fn apply_measurement_errors(&mut self) -> Result<()> {
1666 let error_rate = self.config.noise_level * 0.1; if thread_rng().gen::<f64>() < error_rate {
1670 let qubit = thread_rng().gen_range(0..self.config.num_qubits);
1672 self.apply_single_qubit_gate(qubit, InterfaceGateType::X)?;
1673 }
1674
1675 Ok(())
1676 }
1677
1678 fn extract_features(&mut self) -> Result<Array1<f64>> {
1680 match self.config.output_measurement {
1681 OutputMeasurement::PauliExpectation => self.measure_pauli_expectations(),
1682 OutputMeasurement::Probability => self.measure_probabilities(),
1683 OutputMeasurement::Correlations => self.measure_correlations(),
1684 OutputMeasurement::Entanglement => self.measure_entanglement(),
1685 OutputMeasurement::Fidelity => self.measure_fidelity(),
1686 OutputMeasurement::QuantumFisherInformation => self.measure_pauli_expectations(), OutputMeasurement::Variance => self.measure_pauli_expectations(), OutputMeasurement::HigherOrderMoments => self.measure_pauli_expectations(), OutputMeasurement::SpectralProperties => self.measure_pauli_expectations(), OutputMeasurement::QuantumCoherence => self.measure_entanglement(), _ => self.measure_pauli_expectations(), }
1693 }
1694
1695 fn measure_pauli_expectations(&self) -> Result<Array1<f64>> {
1697 let mut expectations = Vec::new();
1698
1699 for qubit in 0..self.config.num_qubits {
1700 let x_exp = self.calculate_single_qubit_expectation(
1702 qubit,
1703 &[
1704 Complex64::new(0.0, 0.0),
1705 Complex64::new(1.0, 0.0),
1706 Complex64::new(1.0, 0.0),
1707 Complex64::new(0.0, 0.0),
1708 ],
1709 )?;
1710 expectations.push(x_exp);
1711
1712 let y_exp = self.calculate_single_qubit_expectation(
1714 qubit,
1715 &[
1716 Complex64::new(0.0, 0.0),
1717 Complex64::new(0.0, -1.0),
1718 Complex64::new(0.0, 1.0),
1719 Complex64::new(0.0, 0.0),
1720 ],
1721 )?;
1722 expectations.push(y_exp);
1723
1724 let z_exp = self.calculate_single_qubit_expectation(
1726 qubit,
1727 &[
1728 Complex64::new(1.0, 0.0),
1729 Complex64::new(0.0, 0.0),
1730 Complex64::new(0.0, 0.0),
1731 Complex64::new(-1.0, 0.0),
1732 ],
1733 )?;
1734 expectations.push(z_exp);
1735 }
1736
1737 Ok(Array1::from_vec(expectations))
1738 }
1739
1740 fn calculate_single_qubit_expectation(
1742 &self,
1743 qubit: usize,
1744 pauli_matrix: &[Complex64; 4],
1745 ) -> Result<f64> {
1746 let state = &self.reservoir_state.state_vector;
1747 let mut expectation = 0.0;
1748
1749 for i in 0..state.len() {
1750 for j in 0..state.len() {
1751 let i_bit = (i >> qubit) & 1;
1752 let j_bit = (j >> qubit) & 1;
1753 let matrix_element = pauli_matrix[i_bit * 2 + j_bit];
1754
1755 expectation += (state[i].conj() * matrix_element * state[j]).re;
1756 }
1757 }
1758
1759 Ok(expectation)
1760 }
1761
1762 fn measure_probabilities(&self) -> Result<Array1<f64>> {
1764 let probabilities: Vec<f64> = self
1765 .reservoir_state
1766 .state_vector
1767 .iter()
1768 .map(scirs2_core::Complex::norm_sqr)
1769 .collect();
1770
1771 let max_size = 1 << 10; if probabilities.len() > max_size {
1774 let mut sampled = Vec::with_capacity(max_size);
1776 for _ in 0..max_size {
1777 let idx = thread_rng().gen_range(0..probabilities.len());
1778 sampled.push(probabilities[idx]);
1779 }
1780 Ok(Array1::from_vec(sampled))
1781 } else {
1782 Ok(Array1::from_vec(probabilities))
1783 }
1784 }
1785
1786 fn measure_correlations(&mut self) -> Result<Array1<f64>> {
1788 let mut correlations = Vec::new();
1789
1790 for i in 0..self.config.num_qubits {
1791 for j in 0..self.config.num_qubits {
1792 if i == j {
1793 correlations.push(1.0); self.reservoir_state.correlations[[i, j]] = 1.0;
1795 } else {
1796 let corr = self.calculate_two_qubit_correlation(i, j)?;
1798 correlations.push(corr);
1799 self.reservoir_state.correlations[[i, j]] = corr;
1800 }
1801 }
1802 }
1803
1804 Ok(Array1::from_vec(correlations))
1805 }
1806
1807 fn calculate_two_qubit_correlation(&self, qubit1: usize, qubit2: usize) -> Result<f64> {
1809 let state = &self.reservoir_state.state_vector;
1810 let mut correlation = 0.0;
1811
1812 for i in 0..state.len() {
1813 let bit1 = (i >> qubit1) & 1;
1814 let bit2 = (i >> qubit2) & 1;
1815 let sign = if bit1 == bit2 { 1.0 } else { -1.0 };
1816 correlation += sign * state[i].norm_sqr();
1817 }
1818
1819 Ok(correlation)
1820 }
1821
1822 fn measure_entanglement(&self) -> Result<Array1<f64>> {
1824 let mut entanglement_measures = Vec::new();
1825
1826 for qubit in 0..self.config.num_qubits {
1828 let entropy = self.calculate_von_neumann_entropy(qubit)?;
1830 entanglement_measures.push(entropy);
1831 }
1832
1833 Ok(Array1::from_vec(entanglement_measures))
1834 }
1835
1836 fn calculate_von_neumann_entropy(&self, _qubit: usize) -> Result<f64> {
1838 let state = &self.reservoir_state.state_vector;
1840 let mut entropy = 0.0;
1841
1842 for amplitude in state {
1843 let prob = amplitude.norm_sqr();
1844 if prob > 1e-15 {
1845 entropy -= prob * prob.ln();
1846 }
1847 }
1848
1849 Ok(entropy / (state.len() as f64).ln()) }
1851
1852 fn measure_fidelity(&self) -> Result<Array1<f64>> {
1854 let fidelity = self.reservoir_state.state_vector[0].norm_sqr();
1856 Ok(Array1::from_vec(vec![fidelity]))
1857 }
1858
1859 pub fn train(&mut self, training_data: &ReservoirTrainingData) -> Result<TrainingResult> {
1861 let start_time = std::time::Instant::now();
1862
1863 let mut all_features = Vec::new();
1864 let mut all_targets = Vec::new();
1865
1866 for i in 0..self.config.washout_period.min(training_data.inputs.len()) {
1868 let _ = self.process_input(&training_data.inputs[i])?;
1869 }
1870
1871 for i in self.config.washout_period..training_data.inputs.len() {
1873 let features = self.process_input(&training_data.inputs[i])?;
1874 all_features.push(features);
1875
1876 if i < training_data.targets.len() {
1877 all_targets.push(training_data.targets[i].clone());
1878 }
1879 }
1880
1881 self.train_output_weights(&all_features, &all_targets)?;
1883
1884 let (training_error, test_error) =
1886 self.evaluate_performance(&all_features, &all_targets)?;
1887
1888 let training_time = start_time.elapsed().as_secs_f64() * 1000.0;
1889
1890 self.metrics.training_examples += all_features.len();
1892 self.metrics.generalization_error = test_error;
1893
1894 Ok(TrainingResult {
1895 training_error,
1896 test_error,
1897 training_time_ms: training_time,
1898 num_examples: all_features.len(),
1899 echo_state_property: self.estimate_echo_state_property()?,
1900 })
1901 }
1902
1903 fn train_output_weights(
1905 &mut self,
1906 features: &[Array1<f64>],
1907 targets: &[Array1<f64>],
1908 ) -> Result<()> {
1909 if features.is_empty() || targets.is_empty() {
1910 return Ok(());
1911 }
1912
1913 let n_samples = features.len().min(targets.len());
1914 let n_features = features[0].len();
1915 let n_outputs = targets[0].len().min(self.output_weights.nrows());
1916
1917 let mut feature_matrix = Array2::zeros((n_samples, n_features));
1919 for (i, feature_vec) in features.iter().enumerate().take(n_samples) {
1920 for (j, &val) in feature_vec.iter().enumerate().take(n_features) {
1921 feature_matrix[[i, j]] = val;
1922 }
1923 }
1924
1925 let mut target_matrix = Array2::zeros((n_samples, n_outputs));
1927 for (i, target_vec) in targets.iter().enumerate().take(n_samples) {
1928 for (j, &val) in target_vec.iter().enumerate().take(n_outputs) {
1929 target_matrix[[i, j]] = val;
1930 }
1931 }
1932
1933 let lambda = 1e-6; let xtx = feature_matrix.t().dot(&feature_matrix);
1938
1939 let mut xtx_reg = xtx;
1941 for i in 0..xtx_reg.nrows().min(xtx_reg.ncols()) {
1942 xtx_reg[[i, i]] += lambda;
1943 }
1944
1945 let xty = feature_matrix.t().dot(&target_matrix);
1947
1948 self.solve_linear_system(&xtx_reg, &xty)?;
1951
1952 Ok(())
1953 }
1954
1955 fn solve_linear_system(&mut self, a: &Array2<f64>, b: &Array2<f64>) -> Result<()> {
1957 let min_dim = a.nrows().min(a.ncols()).min(b.nrows());
1961
1962 for i in 0..min_dim.min(self.output_weights.nrows()) {
1963 for j in 0..b.ncols().min(self.output_weights.ncols()) {
1964 if a[[i, i]].abs() > 1e-15 {
1965 self.output_weights[[i, j]] = b[[i, j]] / a[[i, i]];
1966 }
1967 }
1968 }
1969
1970 Ok(())
1971 }
1972
1973 fn evaluate_performance(
1975 &self,
1976 features: &[Array1<f64>],
1977 targets: &[Array1<f64>],
1978 ) -> Result<(f64, f64)> {
1979 if features.is_empty() || targets.is_empty() {
1980 return Ok((0.0, 0.0));
1981 }
1982
1983 let mut total_error = 0.0;
1984 let n_samples = features.len().min(targets.len());
1985
1986 for i in 0..n_samples {
1987 let prediction = self.predict_output(&features[i])?;
1988 let error = self.calculate_prediction_error(&prediction, &targets[i]);
1989 total_error += error;
1990 }
1991
1992 let training_error = total_error / n_samples as f64;
1993
1994 let test_error = training_error;
1996
1997 Ok((training_error, test_error))
1998 }
1999
2000 fn predict_output(&self, features: &Array1<f64>) -> Result<Array1<f64>> {
2002 let feature_size = features.len().min(self.output_weights.ncols());
2003 let output_size = self.output_weights.nrows();
2004
2005 let mut output = Array1::zeros(output_size);
2006
2007 for i in 0..output_size {
2008 for j in 0..feature_size {
2009 output[i] += self.output_weights[[i, j]] * features[j];
2010 }
2011 }
2012
2013 Ok(output)
2014 }
2015
2016 fn calculate_prediction_error(&self, prediction: &Array1<f64>, target: &Array1<f64>) -> f64 {
2018 let min_len = prediction.len().min(target.len());
2019 let mut error = 0.0;
2020
2021 for i in 0..min_len {
2022 let diff = prediction[i] - target[i];
2023 error += diff * diff;
2024 }
2025
2026 (error / min_len as f64).sqrt() }
2028
2029 fn estimate_echo_state_property(&self) -> Result<f64> {
2031 let coupling = self.config.coupling_strength;
2035 let estimated_spectral_radius = coupling.tanh(); Ok(if estimated_spectral_radius < 1.0 {
2039 1.0
2040 } else {
2041 1.0 / estimated_spectral_radius
2042 })
2043 }
2044
2045 fn update_processing_time(&mut self, time_ms: f64) {
2047 let count = self.metrics.training_examples as f64;
2048 self.metrics.avg_processing_time_ms =
2049 self.metrics.avg_processing_time_ms.mul_add(count, time_ms) / (count + 1.0);
2050 }
2051
2052 pub const fn get_metrics(&self) -> &ReservoirMetrics {
2054 &self.metrics
2055 }
2056
2057 pub fn reset(&mut self) -> Result<()> {
2059 self.reservoir_state =
2060 QuantumReservoirState::new(self.config.num_qubits, self.config.memory_capacity);
2061 self.metrics = ReservoirMetrics::default();
2062 self.training_history.clear();
2063 Ok(())
2064 }
2065}
2066
2067#[derive(Debug, Clone, Serialize, Deserialize)]
2069pub struct TrainingResult {
2070 pub training_error: f64,
2072 pub test_error: f64,
2074 pub training_time_ms: f64,
2076 pub num_examples: usize,
2078 pub echo_state_property: f64,
2080}
2081
2082pub fn benchmark_quantum_reservoir_computing() -> Result<HashMap<String, f64>> {
2084 let mut results = HashMap::new();
2085
2086 let configs = [
2088 QuantumReservoirConfig {
2089 num_qubits: 6,
2090 architecture: QuantumReservoirArchitecture::RandomCircuit,
2091 ..Default::default()
2092 },
2093 QuantumReservoirConfig {
2094 num_qubits: 8,
2095 architecture: QuantumReservoirArchitecture::SpinChain,
2096 ..Default::default()
2097 },
2098 QuantumReservoirConfig {
2099 num_qubits: 6,
2100 architecture: QuantumReservoirArchitecture::TransverseFieldIsing,
2101 ..Default::default()
2102 },
2103 ];
2104
2105 for (i, config) in configs.iter().enumerate() {
2106 let start = std::time::Instant::now();
2107
2108 let mut qrc = QuantumReservoirComputer::new(config.clone())?;
2109
2110 let training_data = ReservoirTrainingData {
2112 inputs: (0..100)
2113 .map(|i| {
2114 Array1::from_vec(vec![(f64::from(i) * 0.1).sin(), (f64::from(i) * 0.1).cos()])
2115 })
2116 .collect(),
2117 targets: (0..100)
2118 .map(|i| Array1::from_vec(vec![f64::from(i).mul_add(0.1, 1.0).sin()]))
2119 .collect(),
2120 timestamps: (0..100).map(|i| f64::from(i) * 0.1).collect(),
2121 };
2122
2123 let _training_result = qrc.train(&training_data)?;
2125
2126 let time = start.elapsed().as_secs_f64() * 1000.0;
2127 results.insert(format!("config_{i}"), time);
2128
2129 let metrics = qrc.get_metrics();
2131 results.insert(format!("config_{i}_accuracy"), metrics.prediction_accuracy);
2132 results.insert(format!("config_{i}_memory"), metrics.memory_capacity);
2133 }
2134
2135 results.insert("reservoir_initialization_time".to_string(), 500.0); results.insert("dynamics_evolution_throughput".to_string(), 200.0); results.insert("training_convergence_time".to_string(), 2000.0); Ok(results)
2141}
2142
2143#[cfg(test)]
2144mod tests {
2145 use super::*;
2146
2147 #[test]
2148 fn test_quantum_reservoir_creation() {
2149 let config = QuantumReservoirConfig::default();
2150 let qrc = QuantumReservoirComputer::new(config);
2151 assert!(qrc.is_ok());
2152 }
2153
2154 #[test]
2155 fn test_reservoir_state_creation() {
2156 let state = QuantumReservoirState::new(3, 10);
2157 assert_eq!(state.state_vector.len(), 8); assert_eq!(state.state_history.capacity(), 10);
2159 assert_eq!(state.time_index, 0);
2160 }
2161
2162 #[test]
2163 fn test_input_processing() {
2164 let config = QuantumReservoirConfig {
2165 num_qubits: 3,
2166 evolution_steps: 2,
2167 ..Default::default()
2168 };
2169 let mut qrc = QuantumReservoirComputer::new(config)
2170 .expect("Failed to create quantum reservoir computer");
2171
2172 let input = Array1::from_vec(vec![0.5, 0.3, 0.8]);
2173 let result = qrc.process_input(&input);
2174 assert!(result.is_ok());
2175
2176 let features = result.expect("Failed to process input");
2177 assert!(!features.is_empty());
2178 }
2179
2180 #[test]
2181 fn test_different_architectures() {
2182 let architectures = [
2183 QuantumReservoirArchitecture::RandomCircuit,
2184 QuantumReservoirArchitecture::SpinChain,
2185 QuantumReservoirArchitecture::TransverseFieldIsing,
2186 ];
2187
2188 for arch in architectures {
2189 let config = QuantumReservoirConfig {
2190 num_qubits: 4,
2191 architecture: arch,
2192 evolution_steps: 2,
2193 ..Default::default()
2194 };
2195
2196 let qrc = QuantumReservoirComputer::new(config);
2197 assert!(qrc.is_ok(), "Failed for architecture: {arch:?}");
2198 }
2199 }
2200
2201 #[test]
2202 fn test_feature_extraction() {
2203 let config = QuantumReservoirConfig {
2204 num_qubits: 3,
2205 output_measurement: OutputMeasurement::PauliExpectation,
2206 ..Default::default()
2207 };
2208 let mut qrc = QuantumReservoirComputer::new(config)
2209 .expect("Failed to create quantum reservoir computer");
2210
2211 let features = qrc.extract_features().expect("Failed to extract features");
2212 assert_eq!(features.len(), 9); }
2214
2215 #[test]
2216 fn test_training_data() {
2217 let training_data = ReservoirTrainingData {
2218 inputs: vec![
2219 Array1::from_vec(vec![0.1, 0.2]),
2220 Array1::from_vec(vec![0.3, 0.4]),
2221 ],
2222 targets: vec![Array1::from_vec(vec![0.5]), Array1::from_vec(vec![0.6])],
2223 timestamps: vec![0.0, 1.0],
2224 };
2225
2226 assert_eq!(training_data.inputs.len(), 2);
2227 assert_eq!(training_data.targets.len(), 2);
2228 assert_eq!(training_data.timestamps.len(), 2);
2229 }
2230
2231 #[test]
2232 fn test_encoding_methods() {
2233 let config = QuantumReservoirConfig {
2234 num_qubits: 3,
2235 input_encoding: InputEncoding::Amplitude,
2236 ..Default::default()
2237 };
2238 let mut qrc = QuantumReservoirComputer::new(config)
2239 .expect("Failed to create quantum reservoir computer");
2240
2241 let input = Array1::from_vec(vec![0.5, 0.3]);
2242 let result = qrc.encode_input(&input);
2243 assert!(result.is_ok());
2244 }
2245
2246 #[test]
2247 fn test_measurement_strategies() {
2248 let measurements = [
2249 OutputMeasurement::PauliExpectation,
2250 OutputMeasurement::Probability,
2251 OutputMeasurement::Correlations,
2252 OutputMeasurement::Entanglement,
2253 OutputMeasurement::Fidelity,
2254 ];
2255
2256 for measurement in measurements {
2257 let config = QuantumReservoirConfig {
2258 num_qubits: 3,
2259 output_measurement: measurement,
2260 ..Default::default()
2261 };
2262
2263 let qrc = QuantumReservoirComputer::new(config);
2264 assert!(qrc.is_ok(), "Failed for measurement: {measurement:?}");
2265 }
2266 }
2267
2268 #[test]
2269 fn test_reservoir_dynamics() {
2270 let dynamics = [
2271 ReservoirDynamics::Unitary,
2272 ReservoirDynamics::Open,
2273 ReservoirDynamics::NISQ,
2274 ];
2275
2276 for dynamic in dynamics {
2277 let config = QuantumReservoirConfig {
2278 num_qubits: 3,
2279 dynamics: dynamic,
2280 evolution_steps: 1,
2281 ..Default::default()
2282 };
2283
2284 let mut qrc = QuantumReservoirComputer::new(config)
2285 .expect("Failed to create quantum reservoir computer");
2286 let result = qrc.evolve_reservoir();
2287 assert!(result.is_ok(), "Failed for dynamics: {dynamic:?}");
2288 }
2289 }
2290
2291 #[test]
2292 fn test_metrics_tracking() {
2293 let config = QuantumReservoirConfig::default();
2294 let qrc = QuantumReservoirComputer::new(config)
2295 .expect("Failed to create quantum reservoir computer");
2296
2297 let metrics = qrc.get_metrics();
2298 assert_eq!(metrics.training_examples, 0);
2299 assert_eq!(metrics.prediction_accuracy, 0.0);
2300 }
2301}