1use scirs2_core::ndarray::{s, Array1, Array2, Array3, ArrayView1, ArrayView2, Axis};
28use scirs2_core::parallel_ops::*;
29use scirs2_core::random::{thread_rng, Rng};
30use scirs2_core::Complex64;
31use serde::{Deserialize, Serialize};
32use std::collections::{HashMap, VecDeque};
33use std::f64::consts::PI;
34use std::sync::{Arc, Mutex};
35
36use crate::circuit_interfaces::{
37 CircuitInterface, InterfaceCircuit, InterfaceGate, InterfaceGateType,
38};
39use crate::error::Result;
40use crate::scirs2_integration::SciRS2Backend;
41use crate::statevector::StateVectorSimulator;
42use scirs2_core::random::prelude::*;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46pub enum QuantumReservoirArchitecture {
47 RandomCircuit,
49 SpinChain,
51 TransverseFieldIsing,
53 SmallWorld,
55 FullyConnected,
57 ScaleFree,
59 HierarchicalModular,
61 AdaptiveTopology,
63 QuantumCellularAutomaton,
65 Ring,
67 Grid,
69 Tree,
71 Hypergraph,
73 TensorNetwork,
75 Custom,
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
81pub enum ReservoirDynamics {
82 Unitary,
84 Open,
86 NISQ,
88 Adiabatic,
90 Floquet,
92 QuantumWalk,
94 ContinuousTime,
96 DigitalQuantum,
98 Variational,
100 HamiltonianLearning,
102 ManyBodyLocalized,
104 QuantumChaotic,
106}
107
108#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
110pub enum InputEncoding {
111 Amplitude,
113 Phase,
115 BasisState,
117 Coherent,
119 Squeezed,
121 Angle,
123 IQP,
125 DataReUploading,
127 QuantumFeatureMap,
129 VariationalEncoding,
131 TemporalEncoding,
133 FourierEncoding,
135 WaveletEncoding,
137 HaarRandom,
139 GraphEncoding,
141}
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
145pub enum OutputMeasurement {
146 PauliExpectation,
148 Probability,
150 Correlations,
152 Entanglement,
154 Fidelity,
156 QuantumFisherInformation,
158 Variance,
160 HigherOrderMoments,
162 SpectralProperties,
164 QuantumCoherence,
166 Purity,
168 QuantumMutualInformation,
170 ProcessTomography,
172 TemporalCorrelations,
174 NonLinearReadout,
176}
177
178#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
180pub enum LearningAlgorithm {
181 Ridge,
183 LASSO,
185 ElasticNet,
187 RecursiveLeastSquares,
189 KalmanFilter,
191 ExtendedKalmanFilter,
193 NeuralNetwork,
195 SupportVectorRegression,
197 GaussianProcess,
199 RandomForest,
201 GradientBoosting,
203 OnlineGradientDescent,
205 Adam,
207 MetaLearning,
209}
210
211#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
213pub enum ActivationFunction {
214 ReLU,
216 LeakyReLU,
218 ELU,
220 Sigmoid,
222 Tanh,
224 Swish,
226 GELU,
228 Linear,
230}
231
232#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
234pub enum MemoryKernel {
235 Exponential,
237 PowerLaw,
239 Gaussian,
241 Polynomial,
243 Rational,
245 Sinusoidal,
247 Custom,
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct QuantumReservoirConfig {
254 pub num_qubits: usize,
256 pub architecture: QuantumReservoirArchitecture,
258 pub dynamics: ReservoirDynamics,
260 pub input_encoding: InputEncoding,
262 pub output_measurement: OutputMeasurement,
264 pub learning_config: AdvancedLearningConfig,
266 pub time_series_config: TimeSeriesConfig,
268 pub memory_config: MemoryAnalysisConfig,
270 pub time_step: f64,
272 pub evolution_steps: usize,
274 pub coupling_strength: f64,
276 pub noise_level: f64,
278 pub memory_capacity: usize,
280 pub adaptive_learning: bool,
282 pub learning_rate: f64,
284 pub washout_period: usize,
286 pub random_seed: Option<u64>,
288 pub enable_qec: bool,
290 pub precision: f64,
292}
293
294impl Default for QuantumReservoirConfig {
295 fn default() -> Self {
296 Self {
297 num_qubits: 8,
298 architecture: QuantumReservoirArchitecture::RandomCircuit,
299 dynamics: ReservoirDynamics::Unitary,
300 input_encoding: InputEncoding::Amplitude,
301 output_measurement: OutputMeasurement::PauliExpectation,
302 learning_config: AdvancedLearningConfig::default(),
303 time_series_config: TimeSeriesConfig::default(),
304 memory_config: MemoryAnalysisConfig::default(),
305 time_step: 0.1,
306 evolution_steps: 10,
307 coupling_strength: 1.0,
308 noise_level: 0.01,
309 memory_capacity: 100,
310 adaptive_learning: true,
311 learning_rate: 0.01,
312 washout_period: 50,
313 random_seed: None,
314 enable_qec: false,
315 precision: 1e-8,
316 }
317 }
318}
319
320#[derive(Debug, Clone, Serialize, Deserialize)]
322pub struct AdvancedLearningConfig {
323 pub algorithm: LearningAlgorithm,
325 pub regularization: f64,
327 pub l1_ratio: f64,
329 pub forgetting_factor: f64,
331 pub process_noise: f64,
333 pub measurement_noise: f64,
335 pub nn_architecture: Vec<usize>,
337 pub nn_activation: ActivationFunction,
339 pub epochs: usize,
341 pub batch_size: usize,
343 pub early_stopping_patience: usize,
345 pub cv_folds: usize,
347 pub enable_ensemble: bool,
349 pub ensemble_size: usize,
351}
352
353impl Default for AdvancedLearningConfig {
354 fn default() -> Self {
355 Self {
356 algorithm: LearningAlgorithm::Ridge,
357 regularization: 1e-6,
358 l1_ratio: 0.5,
359 forgetting_factor: 0.99,
360 process_noise: 1e-4,
361 measurement_noise: 1e-3,
362 nn_architecture: vec![64, 32, 16],
363 nn_activation: ActivationFunction::ReLU,
364 epochs: 100,
365 batch_size: 32,
366 early_stopping_patience: 10,
367 cv_folds: 5,
368 enable_ensemble: false,
369 ensemble_size: 5,
370 }
371 }
372}
373
374#[derive(Debug, Clone, Serialize, Deserialize)]
376pub struct TimeSeriesConfig {
377 pub enable_arima: bool,
379 pub ar_order: usize,
381 pub ma_order: usize,
383 pub diff_order: usize,
385 pub enable_nar: bool,
387 pub nar_order: usize,
389 pub memory_kernel: MemoryKernel,
391 pub kernel_params: Vec<f64>,
393 pub enable_seasonal: bool,
395 pub seasonal_period: usize,
397 pub enable_changepoint: bool,
399 pub anomaly_threshold: f64,
401}
402
403impl Default for TimeSeriesConfig {
404 fn default() -> Self {
405 Self {
406 enable_arima: true,
407 ar_order: 2,
408 ma_order: 1,
409 diff_order: 1,
410 enable_nar: true,
411 nar_order: 3,
412 memory_kernel: MemoryKernel::Exponential,
413 kernel_params: vec![0.9, 0.1],
414 enable_seasonal: false,
415 seasonal_period: 12,
416 enable_changepoint: false,
417 anomaly_threshold: 2.0,
418 }
419 }
420}
421
422#[derive(Debug, Clone, Serialize, Deserialize)]
424pub struct MemoryAnalysisConfig {
425 pub enable_capacity_estimation: bool,
427 pub capacity_tasks: Vec<MemoryTask>,
429 pub enable_nonlinear: bool,
431 pub nonlinearity_orders: Vec<usize>,
433 pub enable_temporal_correlation: bool,
435 pub correlation_lags: Vec<usize>,
437 pub enable_ipc: bool,
439 pub ipc_functions: Vec<IPCFunction>,
441 pub enable_entropy: bool,
443}
444
445impl Default for MemoryAnalysisConfig {
446 fn default() -> Self {
447 Self {
448 enable_capacity_estimation: true,
449 capacity_tasks: vec![
450 MemoryTask::DelayLine,
451 MemoryTask::TemporalXOR,
452 MemoryTask::Parity,
453 ],
454 enable_nonlinear: true,
455 nonlinearity_orders: vec![2, 3, 4],
456 enable_temporal_correlation: true,
457 correlation_lags: (1..=20).collect(),
458 enable_ipc: true,
459 ipc_functions: vec![
460 IPCFunction::Linear,
461 IPCFunction::Quadratic,
462 IPCFunction::Cubic,
463 ],
464 enable_entropy: true,
465 }
466 }
467}
468
469#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
471pub enum MemoryTask {
472 DelayLine,
474 TemporalXOR,
476 Parity,
478 SequencePrediction,
480 PatternCompletion,
482 TemporalIntegration,
484}
485
486#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
488pub enum IPCFunction {
489 Linear,
491 Quadratic,
493 Cubic,
495 Sine,
497 Product,
499 XOR,
501}
502
503#[derive(Debug, Clone)]
505pub struct QuantumReservoirState {
506 pub state_vector: Array1<Complex64>,
508 pub state_history: VecDeque<Array1<Complex64>>,
510 pub observables: HashMap<String, f64>,
512 pub correlations: Array2<f64>,
514 pub higher_order_correlations: HashMap<String, f64>,
516 pub entanglement_measures: HashMap<String, f64>,
518 pub memory_metrics: MemoryMetrics,
520 pub time_index: usize,
522 pub last_update: f64,
524 pub activity_level: f64,
526 pub performance_history: VecDeque<f64>,
528}
529
530#[derive(Debug, Clone, Default, Serialize, Deserialize)]
532pub struct MemoryMetrics {
533 pub linear_capacity: f64,
535 pub nonlinear_capacity: f64,
537 pub total_capacity: f64,
539 pub processing_capacity: f64,
541 pub correlation_length: f64,
543 pub decay_rate: f64,
545 pub efficiency: f64,
547}
548
549impl QuantumReservoirState {
550 pub fn new(num_qubits: usize, memory_capacity: usize) -> Self {
552 let state_size = 1 << num_qubits;
553 let mut state_vector = Array1::zeros(state_size);
554 state_vector[0] = Complex64::new(1.0, 0.0); Self {
557 state_vector,
558 state_history: VecDeque::with_capacity(memory_capacity),
559 observables: HashMap::new(),
560 correlations: Array2::zeros((num_qubits, num_qubits)),
561 higher_order_correlations: HashMap::new(),
562 entanglement_measures: HashMap::new(),
563 memory_metrics: MemoryMetrics::default(),
564 time_index: 0,
565 last_update: 0.0,
566 activity_level: 0.0,
567 performance_history: VecDeque::with_capacity(1000),
568 }
569 }
570
571 pub fn update_state(&mut self, new_state: Array1<Complex64>, timestamp: f64) {
573 self.state_history.push_back(self.state_vector.clone());
575 if self.state_history.len() > self.state_history.capacity() {
576 self.state_history.pop_front();
577 }
578
579 self.state_vector = new_state;
581 self.time_index += 1;
582 self.last_update = timestamp;
583
584 self.update_activity_level();
586 }
587
588 fn update_activity_level(&mut self) {
590 let activity = self.state_vector.iter().map(|x| x.norm_sqr()).sum::<f64>()
591 / self.state_vector.len() as f64;
592
593 let alpha = 0.1;
595 self.activity_level = alpha * activity + (1.0 - alpha) * self.activity_level;
596 }
597
598 pub fn calculate_memory_decay(&self) -> f64 {
600 if self.state_history.len() < 2 {
601 return 0.0;
602 }
603
604 let mut total_decay = 0.0;
605 let current_state = &self.state_vector;
606
607 for (i, past_state) in self.state_history.iter().enumerate() {
608 let fidelity = self.calculate_fidelity(current_state, past_state);
609 let time_diff = (self.state_history.len() - i) as f64;
610 total_decay += fidelity * (-time_diff * 0.1).exp();
611 }
612
613 total_decay / self.state_history.len() as f64
614 }
615
616 fn calculate_fidelity(&self, state1: &Array1<Complex64>, state2: &Array1<Complex64>) -> f64 {
618 let overlap = state1
619 .iter()
620 .zip(state2.iter())
621 .map(|(a, b)| a.conj() * b)
622 .sum::<Complex64>();
623 overlap.norm_sqr()
624 }
625}
626
627#[derive(Debug, Clone)]
629pub struct ReservoirTrainingData {
630 pub inputs: Vec<Array1<f64>>,
632 pub targets: Vec<Array1<f64>>,
634 pub timestamps: Vec<f64>,
636 pub features: Option<Vec<Array1<f64>>>,
638 pub labels: Option<Vec<usize>>,
640 pub sequence_lengths: Option<Vec<usize>>,
642 pub missing_mask: Option<Vec<Array1<bool>>>,
644 pub sample_weights: Option<Vec<f64>>,
646 pub metadata: Option<Vec<HashMap<String, String>>>,
648}
649
650impl ReservoirTrainingData {
651 pub const fn new(
653 inputs: Vec<Array1<f64>>,
654 targets: Vec<Array1<f64>>,
655 timestamps: Vec<f64>,
656 ) -> Self {
657 Self {
658 inputs,
659 targets,
660 timestamps,
661 features: None,
662 labels: None,
663 sequence_lengths: None,
664 missing_mask: None,
665 sample_weights: None,
666 metadata: None,
667 }
668 }
669
670 pub fn with_features(mut self, features: Vec<Array1<f64>>) -> Self {
672 self.features = Some(features);
673 self
674 }
675
676 pub fn with_labels(mut self, labels: Vec<usize>) -> Self {
678 self.labels = Some(labels);
679 self
680 }
681
682 pub fn with_weights(mut self, weights: Vec<f64>) -> Self {
684 self.sample_weights = Some(weights);
685 self
686 }
687
688 pub fn len(&self) -> usize {
690 self.inputs.len()
691 }
692
693 pub fn is_empty(&self) -> bool {
695 self.inputs.is_empty()
696 }
697
698 pub fn train_test_split(&self, test_ratio: f64) -> (Self, Self) {
700 let test_size = (self.len() as f64 * test_ratio) as usize;
701 let train_size = self.len() - test_size;
702
703 let train_data = Self {
704 inputs: self.inputs[..train_size].to_vec(),
705 targets: self.targets[..train_size].to_vec(),
706 timestamps: self.timestamps[..train_size].to_vec(),
707 features: self.features.as_ref().map(|f| f[..train_size].to_vec()),
708 labels: self.labels.as_ref().map(|l| l[..train_size].to_vec()),
709 sequence_lengths: self
710 .sequence_lengths
711 .as_ref()
712 .map(|s| s[..train_size].to_vec()),
713 missing_mask: self.missing_mask.as_ref().map(|m| m[..train_size].to_vec()),
714 sample_weights: self
715 .sample_weights
716 .as_ref()
717 .map(|w| w[..train_size].to_vec()),
718 metadata: self.metadata.as_ref().map(|m| m[..train_size].to_vec()),
719 };
720
721 let test_data = Self {
722 inputs: self.inputs[train_size..].to_vec(),
723 targets: self.targets[train_size..].to_vec(),
724 timestamps: self.timestamps[train_size..].to_vec(),
725 features: self.features.as_ref().map(|f| f[train_size..].to_vec()),
726 labels: self.labels.as_ref().map(|l| l[train_size..].to_vec()),
727 sequence_lengths: self
728 .sequence_lengths
729 .as_ref()
730 .map(|s| s[train_size..].to_vec()),
731 missing_mask: self.missing_mask.as_ref().map(|m| m[train_size..].to_vec()),
732 sample_weights: self
733 .sample_weights
734 .as_ref()
735 .map(|w| w[train_size..].to_vec()),
736 metadata: self.metadata.as_ref().map(|m| m[train_size..].to_vec()),
737 };
738
739 (train_data, test_data)
740 }
741}
742
743#[derive(Debug, Clone)]
745pub struct TrainingExample {
746 pub input: Array1<f64>,
748 pub reservoir_state: Array1<f64>,
750 pub features: Array1<f64>,
752 pub target: Array1<f64>,
754 pub prediction: Array1<f64>,
756 pub error: f64,
758 pub confidence: f64,
760 pub timestamp: f64,
762 pub metadata: HashMap<String, f64>,
764}
765
766#[derive(Debug, Clone, Default, Serialize, Deserialize)]
768pub struct ReservoirMetrics {
769 pub training_examples: usize,
771 pub prediction_accuracy: f64,
773 pub memory_capacity: f64,
775 pub nonlinear_memory_capacity: f64,
777 pub processing_capacity: f64,
779 pub generalization_error: f64,
781 pub echo_state_property: f64,
783 pub avg_processing_time_ms: f64,
785 pub quantum_resource_usage: f64,
787 pub temporal_correlation_length: f64,
789 pub reservoir_efficiency: f64,
791 pub adaptation_rate: f64,
793 pub plasticity_level: f64,
795 pub hardware_utilization: f64,
797 pub error_mitigation_overhead: f64,
799 pub quantum_advantage: f64,
801 pub computational_complexity: f64,
803}
804
805pub struct QuantumReservoirComputerEnhanced {
807 config: QuantumReservoirConfig,
809 reservoir_state: QuantumReservoirState,
811 reservoir_circuit: InterfaceCircuit,
813 input_coupling_circuit: InterfaceCircuit,
815 output_weights: Array2<f64>,
817 time_series_predictor: Option<TimeSeriesPredictor>,
819 memory_analyzer: MemoryAnalyzer,
821 simulator: StateVectorSimulator,
823 circuit_interface: CircuitInterface,
825 metrics: ReservoirMetrics,
827 training_history: VecDeque<TrainingExample>,
829 backend: Option<SciRS2Backend>,
831 rng: Arc<Mutex<scirs2_core::random::CoreRandom>>,
833}
834
835#[derive(Debug, Clone, Serialize, Deserialize)]
837pub struct TimeSeriesPredictor {
838 pub arima_params: ARIMAParams,
840 pub nar_state: NARState,
842 pub kernel_weights: Array1<f64>,
844 pub trend_model: TrendModel,
846}
847
848#[derive(Debug, Clone, Serialize, Deserialize)]
850pub struct ARIMAParams {
851 pub ar_coeffs: Array1<f64>,
853 pub ma_coeffs: Array1<f64>,
855 pub diff_order: usize,
857 pub residuals: VecDeque<f64>,
859 pub variance: f64,
861}
862
863#[derive(Debug, Clone, Serialize, Deserialize)]
865pub struct NARState {
866 pub order: usize,
868 pub coeffs: Array2<f64>,
870 pub history: VecDeque<f64>,
872 pub activation: ActivationFunction,
874}
875
876#[derive(Debug, Clone, Serialize, Deserialize)]
878pub struct TrendModel {
879 pub params: Vec<f64>,
881 pub strength: f64,
883 pub direction: f64,
885}
886
887#[derive(Debug)]
889pub struct MemoryAnalyzer {
890 pub config: MemoryAnalysisConfig,
892 pub capacity_estimates: HashMap<String, f64>,
894 pub nonlinearity_measures: HashMap<usize, f64>,
896 pub temporal_correlations: Array2<f64>,
898 pub ipc_metrics: HashMap<String, f64>,
900}
901
902impl QuantumReservoirComputerEnhanced {
903 pub fn new(config: QuantumReservoirConfig) -> Result<Self> {
905 let circuit_interface = CircuitInterface::new(Default::default())?;
906 let simulator = StateVectorSimulator::new();
907
908 let reservoir_state = QuantumReservoirState::new(config.num_qubits, config.memory_capacity);
909
910 let reservoir_circuit = Self::generate_reservoir_circuit(&config)?;
912
913 let input_coupling_circuit = Self::generate_input_coupling_circuit(&config)?;
915
916 let output_size = Self::calculate_output_size(&config);
918 let feature_size = Self::calculate_feature_size(&config);
919 let mut output_weights = Array2::zeros((output_size, feature_size));
920
921 let scale = (2.0 / (output_size + feature_size) as f64).sqrt();
923 for elem in &mut output_weights {
924 *elem = (fastrand::f64() - 0.5) * 2.0 * scale;
925 }
926
927 let time_series_predictor =
929 if config.time_series_config.enable_arima || config.time_series_config.enable_nar {
930 Some(TimeSeriesPredictor::new(&config.time_series_config))
931 } else {
932 None
933 };
934
935 let memory_analyzer = MemoryAnalyzer::new(config.memory_config.clone());
937
938 Ok(Self {
939 config,
940 reservoir_state,
941 reservoir_circuit,
942 input_coupling_circuit,
943 output_weights,
944 time_series_predictor,
945 memory_analyzer,
946 simulator,
947 circuit_interface,
948 metrics: ReservoirMetrics::default(),
949 training_history: VecDeque::with_capacity(10000),
950 backend: None,
951 rng: Arc::new(Mutex::new(thread_rng())),
952 })
953 }
954
955 fn generate_reservoir_circuit(config: &QuantumReservoirConfig) -> Result<InterfaceCircuit> {
957 let mut circuit = InterfaceCircuit::new(config.num_qubits, 0);
958
959 match config.architecture {
960 QuantumReservoirArchitecture::RandomCircuit => {
961 Self::generate_random_circuit(&mut circuit, config)?;
962 }
963 QuantumReservoirArchitecture::SpinChain => {
964 Self::generate_spin_chain_circuit(&mut circuit, config)?;
965 }
966 QuantumReservoirArchitecture::TransverseFieldIsing => {
967 Self::generate_tfim_circuit(&mut circuit, config)?;
968 }
969 QuantumReservoirArchitecture::SmallWorld => {
970 Self::generate_small_world_circuit(&mut circuit, config)?;
971 }
972 QuantumReservoirArchitecture::FullyConnected => {
973 Self::generate_fully_connected_circuit(&mut circuit, config)?;
974 }
975 QuantumReservoirArchitecture::ScaleFree => {
976 Self::generate_scale_free_circuit(&mut circuit, config)?;
977 }
978 QuantumReservoirArchitecture::HierarchicalModular => {
979 Self::generate_hierarchical_circuit(&mut circuit, config)?;
980 }
981 QuantumReservoirArchitecture::Ring => {
982 Self::generate_ring_circuit(&mut circuit, config)?;
983 }
984 QuantumReservoirArchitecture::Grid => {
985 Self::generate_grid_circuit(&mut circuit, config)?;
986 }
987 _ => {
988 Self::generate_random_circuit(&mut circuit, config)?;
990 }
991 }
992
993 Ok(circuit)
994 }
995
996 fn generate_random_circuit(
998 circuit: &mut InterfaceCircuit,
999 config: &QuantumReservoirConfig,
1000 ) -> Result<()> {
1001 let depth = config.evolution_steps;
1002
1003 for _ in 0..depth {
1004 for qubit in 0..config.num_qubits {
1006 let angle = fastrand::f64() * 2.0 * PI;
1007 let gate_type = match fastrand::usize(0..3) {
1008 0 => InterfaceGateType::RX(angle),
1009 1 => InterfaceGateType::RY(angle),
1010 _ => InterfaceGateType::RZ(angle),
1011 };
1012 circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1013 }
1014
1015 for _ in 0..(config.num_qubits / 2) {
1017 let qubit1 = fastrand::usize(0..config.num_qubits);
1018 let qubit2 = fastrand::usize(0..config.num_qubits);
1019 if qubit1 != qubit2 {
1020 circuit.add_gate(InterfaceGate::new(
1021 InterfaceGateType::CNOT,
1022 vec![qubit1, qubit2],
1023 ));
1024 }
1025 }
1026 }
1027
1028 Ok(())
1029 }
1030
1031 fn generate_spin_chain_circuit(
1033 circuit: &mut InterfaceCircuit,
1034 config: &QuantumReservoirConfig,
1035 ) -> Result<()> {
1036 let coupling = config.coupling_strength;
1037
1038 for _ in 0..config.evolution_steps {
1039 for i in 0..config.num_qubits - 1 {
1041 circuit.add_gate(InterfaceGate::new(
1043 InterfaceGateType::RZ(coupling * config.time_step),
1044 vec![i],
1045 ));
1046 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1047 circuit.add_gate(InterfaceGate::new(
1048 InterfaceGateType::RZ(coupling * config.time_step),
1049 vec![i + 1],
1050 ));
1051 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1052 }
1053 }
1054
1055 Ok(())
1056 }
1057
1058 fn generate_tfim_circuit(
1060 circuit: &mut InterfaceCircuit,
1061 config: &QuantumReservoirConfig,
1062 ) -> Result<()> {
1063 let coupling = config.coupling_strength;
1064 let field = coupling * 0.5; for _ in 0..config.evolution_steps {
1067 for qubit in 0..config.num_qubits {
1069 circuit.add_gate(InterfaceGate::new(
1070 InterfaceGateType::RX(field * config.time_step),
1071 vec![qubit],
1072 ));
1073 }
1074
1075 for i in 0..config.num_qubits - 1 {
1077 circuit.add_gate(InterfaceGate::new(
1078 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1079 vec![i],
1080 ));
1081 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1082 circuit.add_gate(InterfaceGate::new(
1083 InterfaceGateType::RZ(coupling * config.time_step),
1084 vec![i + 1],
1085 ));
1086 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1087 circuit.add_gate(InterfaceGate::new(
1088 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1089 vec![i],
1090 ));
1091 }
1092 }
1093
1094 Ok(())
1095 }
1096
1097 fn generate_small_world_circuit(
1099 circuit: &mut InterfaceCircuit,
1100 config: &QuantumReservoirConfig,
1101 ) -> Result<()> {
1102 let coupling = config.coupling_strength;
1103 let rewiring_prob = 0.1; for _ in 0..config.evolution_steps {
1106 for i in 0..config.num_qubits {
1108 let next = (i + 1) % config.num_qubits;
1109
1110 let target = if fastrand::f64() < rewiring_prob {
1112 fastrand::usize(0..config.num_qubits)
1113 } else {
1114 next
1115 };
1116
1117 if target != i {
1118 circuit.add_gate(InterfaceGate::new(
1119 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1120 vec![i],
1121 ));
1122 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, target]));
1123 circuit.add_gate(InterfaceGate::new(
1124 InterfaceGateType::RZ(coupling * config.time_step),
1125 vec![target],
1126 ));
1127 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, target]));
1128 circuit.add_gate(InterfaceGate::new(
1129 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1130 vec![i],
1131 ));
1132 }
1133 }
1134 }
1135
1136 Ok(())
1137 }
1138
1139 fn generate_fully_connected_circuit(
1141 circuit: &mut InterfaceCircuit,
1142 config: &QuantumReservoirConfig,
1143 ) -> Result<()> {
1144 let coupling = config.coupling_strength / config.num_qubits as f64; for _ in 0..config.evolution_steps {
1147 for i in 0..config.num_qubits {
1149 for j in i + 1..config.num_qubits {
1150 circuit.add_gate(InterfaceGate::new(
1151 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1152 vec![i],
1153 ));
1154 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1155 circuit.add_gate(InterfaceGate::new(
1156 InterfaceGateType::RZ(coupling * config.time_step),
1157 vec![j],
1158 ));
1159 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1160 circuit.add_gate(InterfaceGate::new(
1161 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1162 vec![i],
1163 ));
1164 }
1165 }
1166 }
1167
1168 Ok(())
1169 }
1170
1171 fn generate_scale_free_circuit(
1173 circuit: &mut InterfaceCircuit,
1174 config: &QuantumReservoirConfig,
1175 ) -> Result<()> {
1176 let mut degree_dist = vec![1; config.num_qubits];
1178 let coupling = config.coupling_strength;
1179
1180 for _ in 0..config.evolution_steps {
1181 for i in 0..config.num_qubits {
1183 let total_degree: usize = degree_dist.iter().sum();
1185 let prob_threshold = degree_dist[i] as f64 / total_degree as f64;
1186
1187 if fastrand::f64() < prob_threshold {
1188 let j = fastrand::usize(0..config.num_qubits);
1189 if i != j {
1190 circuit.add_gate(InterfaceGate::new(
1192 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1193 vec![i],
1194 ));
1195 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1196 circuit.add_gate(InterfaceGate::new(
1197 InterfaceGateType::RZ(coupling * config.time_step),
1198 vec![j],
1199 ));
1200 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1201
1202 degree_dist[i] += 1;
1204 degree_dist[j] += 1;
1205 }
1206 }
1207 }
1208 }
1209
1210 Ok(())
1211 }
1212
1213 fn generate_hierarchical_circuit(
1215 circuit: &mut InterfaceCircuit,
1216 config: &QuantumReservoirConfig,
1217 ) -> Result<()> {
1218 let coupling = config.coupling_strength;
1219 let module_size = (config.num_qubits as f64).sqrt() as usize;
1220
1221 for _ in 0..config.evolution_steps {
1222 for module in 0..(config.num_qubits / module_size) {
1224 let start = module * module_size;
1225 let end = ((module + 1) * module_size).min(config.num_qubits);
1226
1227 for i in start..end {
1228 for j in (i + 1)..end {
1229 circuit.add_gate(InterfaceGate::new(
1230 InterfaceGateType::RZ(coupling * config.time_step),
1231 vec![i],
1232 ));
1233 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1234 }
1235 }
1236 }
1237
1238 for i in 0..config.num_qubits {
1240 let j = fastrand::usize(0..config.num_qubits);
1241 if i / module_size != j / module_size && i != j {
1242 circuit.add_gate(InterfaceGate::new(
1243 InterfaceGateType::RZ(coupling * config.time_step * 0.3),
1244 vec![i],
1245 ));
1246 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1247 }
1248 }
1249 }
1250
1251 Ok(())
1252 }
1253
1254 fn generate_ring_circuit(
1256 circuit: &mut InterfaceCircuit,
1257 config: &QuantumReservoirConfig,
1258 ) -> Result<()> {
1259 let coupling = config.coupling_strength;
1260
1261 for _ in 0..config.evolution_steps {
1262 for i in 0..config.num_qubits {
1264 let j = (i + 1) % config.num_qubits;
1265
1266 circuit.add_gate(InterfaceGate::new(
1267 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1268 vec![i],
1269 ));
1270 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1271 circuit.add_gate(InterfaceGate::new(
1272 InterfaceGateType::RZ(coupling * config.time_step),
1273 vec![j],
1274 ));
1275 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1276 }
1277
1278 if fastrand::f64() < 0.1 {
1280 let i = fastrand::usize(0..config.num_qubits);
1281 let j = fastrand::usize(0..config.num_qubits);
1282 if i != j && (i as i32 - j as i32).abs() > 2 {
1283 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1284 }
1285 }
1286 }
1287
1288 Ok(())
1289 }
1290
1291 fn generate_grid_circuit(
1293 circuit: &mut InterfaceCircuit,
1294 config: &QuantumReservoirConfig,
1295 ) -> Result<()> {
1296 let coupling = config.coupling_strength;
1297 let grid_size = (config.num_qubits as f64).sqrt() as usize;
1298
1299 for _ in 0..config.evolution_steps {
1300 for i in 0..grid_size {
1302 for j in 0..grid_size {
1303 let current = i * grid_size + j;
1304 if current >= config.num_qubits {
1305 break;
1306 }
1307
1308 if j + 1 < grid_size {
1310 let neighbor = i * grid_size + j + 1;
1311 if neighbor < config.num_qubits {
1312 circuit.add_gate(InterfaceGate::new(
1313 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1314 vec![current],
1315 ));
1316 circuit.add_gate(InterfaceGate::new(
1317 InterfaceGateType::CNOT,
1318 vec![current, neighbor],
1319 ));
1320 }
1321 }
1322
1323 if i + 1 < grid_size {
1325 let neighbor = (i + 1) * grid_size + j;
1326 if neighbor < config.num_qubits {
1327 circuit.add_gate(InterfaceGate::new(
1328 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1329 vec![current],
1330 ));
1331 circuit.add_gate(InterfaceGate::new(
1332 InterfaceGateType::CNOT,
1333 vec![current, neighbor],
1334 ));
1335 }
1336 }
1337 }
1338 }
1339 }
1340
1341 Ok(())
1342 }
1343
1344 fn generate_input_coupling_circuit(
1346 config: &QuantumReservoirConfig,
1347 ) -> Result<InterfaceCircuit> {
1348 let mut circuit = InterfaceCircuit::new(config.num_qubits, 0);
1349
1350 match config.input_encoding {
1351 InputEncoding::Amplitude => {
1352 for qubit in 0..config.num_qubits {
1354 circuit.add_gate(InterfaceGate::new(
1355 InterfaceGateType::RY(0.0), vec![qubit],
1357 ));
1358 }
1359 }
1360 InputEncoding::Phase => {
1361 for qubit in 0..config.num_qubits {
1363 circuit.add_gate(InterfaceGate::new(
1364 InterfaceGateType::RZ(0.0), vec![qubit],
1366 ));
1367 }
1368 }
1369 InputEncoding::BasisState => {
1370 for qubit in 0..config.num_qubits {
1372 circuit.add_gate(InterfaceGate::new(InterfaceGateType::X, vec![qubit]));
1373 }
1374 }
1375 InputEncoding::Angle => {
1376 for qubit in 0..config.num_qubits {
1378 circuit.add_gate(InterfaceGate::new(InterfaceGateType::RX(0.0), vec![qubit]));
1379 circuit.add_gate(InterfaceGate::new(InterfaceGateType::RY(0.0), vec![qubit]));
1380 }
1381 }
1382 _ => {
1383 for qubit in 0..config.num_qubits {
1385 circuit.add_gate(InterfaceGate::new(InterfaceGateType::RY(0.0), vec![qubit]));
1386 }
1387 }
1388 }
1389
1390 Ok(circuit)
1391 }
1392
1393 const fn calculate_output_size(config: &QuantumReservoirConfig) -> usize {
1395 1
1397 }
1398
1399 fn calculate_feature_size(config: &QuantumReservoirConfig) -> usize {
1401 match config.output_measurement {
1402 OutputMeasurement::PauliExpectation => config.num_qubits * 3,
1403 OutputMeasurement::Probability => 1 << config.num_qubits.min(10), OutputMeasurement::Correlations => config.num_qubits * config.num_qubits,
1405 OutputMeasurement::Entanglement => config.num_qubits,
1406 OutputMeasurement::Fidelity => 1,
1407 OutputMeasurement::QuantumFisherInformation => config.num_qubits,
1408 OutputMeasurement::Variance => config.num_qubits * 3,
1409 OutputMeasurement::HigherOrderMoments => config.num_qubits * 6, OutputMeasurement::SpectralProperties => config.num_qubits,
1411 OutputMeasurement::QuantumCoherence => config.num_qubits,
1412 OutputMeasurement::Purity => 1,
1413 OutputMeasurement::QuantumMutualInformation => config.num_qubits * config.num_qubits,
1414 OutputMeasurement::ProcessTomography => config.num_qubits * config.num_qubits * 4,
1415 OutputMeasurement::TemporalCorrelations => config.memory_capacity,
1416 OutputMeasurement::NonLinearReadout => config.num_qubits * 2,
1417 }
1418 }
1419
1420 pub fn process_input(&mut self, input: &Array1<f64>) -> Result<Array1<f64>> {
1422 let start_time = std::time::Instant::now();
1423
1424 self.encode_input(input)?;
1426
1427 self.evolve_reservoir()?;
1429
1430 let features = self.extract_features()?;
1432
1433 let timestamp = start_time.elapsed().as_secs_f64();
1435 self.reservoir_state
1436 .update_state(self.reservoir_state.state_vector.clone(), timestamp);
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 InputEncoding::Angle => {
1458 self.encode_angle(input)?;
1459 }
1460 _ => {
1461 self.encode_amplitude(input)?;
1462 }
1463 }
1464 Ok(())
1465 }
1466
1467 fn encode_amplitude(&mut self, input: &Array1<f64>) -> Result<()> {
1469 let num_inputs = input.len().min(self.config.num_qubits);
1470
1471 for i in 0..num_inputs {
1472 let angle = input[i] * PI; self.apply_single_qubit_rotation(i, InterfaceGateType::RY(angle))?;
1474 }
1475
1476 Ok(())
1477 }
1478
1479 fn encode_phase(&mut self, input: &Array1<f64>) -> Result<()> {
1481 let num_inputs = input.len().min(self.config.num_qubits);
1482
1483 for i in 0..num_inputs {
1484 let angle = input[i] * 2.0 * PI; self.apply_single_qubit_rotation(i, InterfaceGateType::RZ(angle))?;
1486 }
1487
1488 Ok(())
1489 }
1490
1491 fn encode_basis_state(&mut self, input: &Array1<f64>) -> Result<()> {
1493 let num_inputs = input.len().min(self.config.num_qubits);
1494
1495 for i in 0..num_inputs {
1496 if input[i] > 0.5 {
1497 self.apply_single_qubit_gate(i, InterfaceGateType::X)?;
1498 }
1499 }
1500
1501 Ok(())
1502 }
1503
1504 fn encode_angle(&mut self, input: &Array1<f64>) -> Result<()> {
1506 let num_inputs = input.len().min(self.config.num_qubits);
1507
1508 for i in 0..num_inputs {
1509 let angle_x = input[i] * PI;
1510 let angle_y = if i + 1 < input.len() {
1511 input[i + 1] * PI
1512 } else {
1513 0.0
1514 };
1515
1516 self.apply_single_qubit_rotation(i, InterfaceGateType::RX(angle_x))?;
1517 self.apply_single_qubit_rotation(i, InterfaceGateType::RY(angle_y))?;
1518 }
1519
1520 Ok(())
1521 }
1522
1523 fn apply_single_qubit_rotation(
1525 &mut self,
1526 qubit: usize,
1527 gate_type: InterfaceGateType,
1528 ) -> Result<()> {
1529 let mut temp_circuit = InterfaceCircuit::new(self.config.num_qubits, 0);
1530 temp_circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1531
1532 self.simulator.apply_interface_circuit(&temp_circuit)?;
1533
1534 Ok(())
1535 }
1536
1537 fn apply_single_qubit_gate(
1539 &mut self,
1540 qubit: usize,
1541 gate_type: InterfaceGateType,
1542 ) -> Result<()> {
1543 let mut temp_circuit = InterfaceCircuit::new(self.config.num_qubits, 0);
1544 temp_circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1545
1546 self.simulator.apply_interface_circuit(&temp_circuit)?;
1547
1548 Ok(())
1549 }
1550
1551 fn evolve_reservoir(&mut self) -> Result<()> {
1553 match self.config.dynamics {
1554 ReservoirDynamics::Unitary => {
1555 self.evolve_unitary()?;
1556 }
1557 ReservoirDynamics::Open => {
1558 self.evolve_open_system()?;
1559 }
1560 ReservoirDynamics::NISQ => {
1561 self.evolve_nisq()?;
1562 }
1563 ReservoirDynamics::Adiabatic => {
1564 self.evolve_adiabatic()?;
1565 }
1566 ReservoirDynamics::Floquet => {
1567 self.evolve_floquet()?;
1568 }
1569 _ => {
1570 self.evolve_unitary()?;
1572 }
1573 }
1574 Ok(())
1575 }
1576
1577 fn evolve_unitary(&mut self) -> Result<()> {
1579 self.simulator
1580 .apply_interface_circuit(&self.reservoir_circuit)?;
1581 Ok(())
1582 }
1583
1584 fn evolve_open_system(&mut self) -> Result<()> {
1586 self.evolve_unitary()?;
1588
1589 self.apply_decoherence()?;
1591
1592 Ok(())
1593 }
1594
1595 fn evolve_nisq(&mut self) -> Result<()> {
1597 self.evolve_unitary()?;
1599
1600 self.apply_gate_errors()?;
1602
1603 self.apply_measurement_errors()?;
1605
1606 Ok(())
1607 }
1608
1609 fn evolve_adiabatic(&mut self) -> Result<()> {
1611 self.evolve_unitary()?;
1614 Ok(())
1615 }
1616
1617 fn evolve_floquet(&mut self) -> Result<()> {
1619 let drive_frequency = 1.0;
1621 let time = self.reservoir_state.time_index as f64 * self.config.time_step;
1622 let drive_strength = (drive_frequency * time).sin();
1623
1624 for qubit in 0..self.config.num_qubits {
1626 let angle = drive_strength * self.config.time_step;
1627 self.apply_single_qubit_rotation(qubit, InterfaceGateType::RX(angle))?;
1628 }
1629
1630 self.evolve_unitary()?;
1632
1633 Ok(())
1634 }
1635
1636 fn apply_decoherence(&mut self) -> Result<()> {
1638 let decoherence_rate = self.config.noise_level;
1639
1640 for amplitude in &mut self.reservoir_state.state_vector {
1641 let phase_noise = (fastrand::f64() - 0.5) * decoherence_rate * 2.0 * PI;
1643 *amplitude *= Complex64::new(0.0, phase_noise).exp();
1644
1645 let damping = (1.0 - decoherence_rate).sqrt();
1647 *amplitude *= damping;
1648 }
1649
1650 let norm: f64 = self
1652 .reservoir_state
1653 .state_vector
1654 .iter()
1655 .map(|x| x.norm_sqr())
1656 .sum::<f64>()
1657 .sqrt();
1658
1659 if norm > 1e-15 {
1660 self.reservoir_state.state_vector.mapv_inplace(|x| x / norm);
1661 }
1662
1663 Ok(())
1664 }
1665
1666 fn apply_gate_errors(&mut self) -> Result<()> {
1668 let error_rate = self.config.noise_level;
1669
1670 for qubit in 0..self.config.num_qubits {
1671 if fastrand::f64() < error_rate {
1672 let error_type = fastrand::usize(0..3);
1673 let gate_type = match error_type {
1674 0 => InterfaceGateType::X,
1675 1 => InterfaceGateType::PauliY,
1676 _ => InterfaceGateType::PauliZ,
1677 };
1678 self.apply_single_qubit_gate(qubit, gate_type)?;
1679 }
1680 }
1681
1682 Ok(())
1683 }
1684
1685 fn apply_measurement_errors(&mut self) -> Result<()> {
1687 let error_rate = self.config.noise_level * 0.1; if fastrand::f64() < error_rate {
1690 let qubit = fastrand::usize(0..self.config.num_qubits);
1691 self.apply_single_qubit_gate(qubit, InterfaceGateType::X)?;
1692 }
1693
1694 Ok(())
1695 }
1696
1697 fn extract_features(&mut self) -> Result<Array1<f64>> {
1699 match self.config.output_measurement {
1700 OutputMeasurement::PauliExpectation => self.measure_pauli_expectations(),
1701 OutputMeasurement::Probability => self.measure_probabilities(),
1702 OutputMeasurement::Correlations => self.measure_correlations(),
1703 OutputMeasurement::Entanglement => self.measure_entanglement(),
1704 OutputMeasurement::Fidelity => self.measure_fidelity(),
1705 OutputMeasurement::QuantumFisherInformation => {
1706 self.measure_quantum_fisher_information()
1707 }
1708 OutputMeasurement::Variance => self.measure_variance(),
1709 OutputMeasurement::HigherOrderMoments => self.measure_higher_order_moments(),
1710 OutputMeasurement::QuantumCoherence => self.measure_quantum_coherence(),
1711 OutputMeasurement::Purity => self.measure_purity(),
1712 OutputMeasurement::TemporalCorrelations => self.measure_temporal_correlations(),
1713 _ => {
1714 self.measure_pauli_expectations()
1716 }
1717 }
1718 }
1719
1720 fn measure_pauli_expectations(&self) -> Result<Array1<f64>> {
1722 let mut expectations = Vec::new();
1723
1724 for qubit in 0..self.config.num_qubits {
1725 let x_exp = self.calculate_single_qubit_expectation(
1727 qubit,
1728 &[
1729 Complex64::new(0.0, 0.0),
1730 Complex64::new(1.0, 0.0),
1731 Complex64::new(1.0, 0.0),
1732 Complex64::new(0.0, 0.0),
1733 ],
1734 )?;
1735 expectations.push(x_exp);
1736
1737 let y_exp = self.calculate_single_qubit_expectation(
1739 qubit,
1740 &[
1741 Complex64::new(0.0, 0.0),
1742 Complex64::new(0.0, -1.0),
1743 Complex64::new(0.0, 1.0),
1744 Complex64::new(0.0, 0.0),
1745 ],
1746 )?;
1747 expectations.push(y_exp);
1748
1749 let z_exp = self.calculate_single_qubit_expectation(
1751 qubit,
1752 &[
1753 Complex64::new(1.0, 0.0),
1754 Complex64::new(0.0, 0.0),
1755 Complex64::new(0.0, 0.0),
1756 Complex64::new(-1.0, 0.0),
1757 ],
1758 )?;
1759 expectations.push(z_exp);
1760 }
1761
1762 Ok(Array1::from_vec(expectations))
1763 }
1764
1765 fn calculate_single_qubit_expectation(
1767 &self,
1768 qubit: usize,
1769 pauli_matrix: &[Complex64; 4],
1770 ) -> Result<f64> {
1771 let state = &self.reservoir_state.state_vector;
1772 let mut expectation = 0.0;
1773
1774 for i in 0..state.len() {
1775 for j in 0..state.len() {
1776 let i_bit = (i >> qubit) & 1;
1777 let j_bit = (j >> qubit) & 1;
1778 let matrix_element = pauli_matrix[i_bit * 2 + j_bit];
1779
1780 expectation += (state[i].conj() * matrix_element * state[j]).re;
1781 }
1782 }
1783
1784 Ok(expectation)
1785 }
1786
1787 fn measure_probabilities(&self) -> Result<Array1<f64>> {
1789 let probabilities: Vec<f64> = self
1790 .reservoir_state
1791 .state_vector
1792 .iter()
1793 .map(|x| x.norm_sqr())
1794 .collect();
1795
1796 let max_size = 1 << 10; if probabilities.len() > max_size {
1799 let mut sampled = Vec::with_capacity(max_size);
1801 for _ in 0..max_size {
1802 let idx = fastrand::usize(0..probabilities.len());
1803 sampled.push(probabilities[idx]);
1804 }
1805 Ok(Array1::from_vec(sampled))
1806 } else {
1807 Ok(Array1::from_vec(probabilities))
1808 }
1809 }
1810
1811 fn measure_correlations(&mut self) -> Result<Array1<f64>> {
1813 let mut correlations = Vec::new();
1814
1815 for i in 0..self.config.num_qubits {
1816 for j in 0..self.config.num_qubits {
1817 if i == j {
1818 correlations.push(1.0); self.reservoir_state.correlations[[i, j]] = 1.0;
1820 } else {
1821 let corr = self.calculate_two_qubit_correlation(i, j)?;
1823 correlations.push(corr);
1824 self.reservoir_state.correlations[[i, j]] = corr;
1825 }
1826 }
1827 }
1828
1829 Ok(Array1::from_vec(correlations))
1830 }
1831
1832 fn calculate_two_qubit_correlation(&self, qubit1: usize, qubit2: usize) -> Result<f64> {
1834 let state = &self.reservoir_state.state_vector;
1835 let mut correlation = 0.0;
1836
1837 for i in 0..state.len() {
1838 let bit1 = (i >> qubit1) & 1;
1839 let bit2 = (i >> qubit2) & 1;
1840 let sign = if bit1 == bit2 { 1.0 } else { -1.0 };
1841 correlation += sign * state[i].norm_sqr();
1842 }
1843
1844 Ok(correlation)
1845 }
1846
1847 fn measure_entanglement(&self) -> Result<Array1<f64>> {
1849 let mut entanglement_measures = Vec::new();
1850
1851 for qubit in 0..self.config.num_qubits {
1853 let entropy = self.calculate_von_neumann_entropy(qubit)?;
1855 entanglement_measures.push(entropy);
1856 }
1857
1858 Ok(Array1::from_vec(entanglement_measures))
1859 }
1860
1861 fn calculate_von_neumann_entropy(&self, _qubit: usize) -> Result<f64> {
1863 let state = &self.reservoir_state.state_vector;
1864 let mut entropy = 0.0;
1865
1866 for amplitude in state {
1867 let prob = amplitude.norm_sqr();
1868 if prob > 1e-15 {
1869 entropy -= prob * prob.ln();
1870 }
1871 }
1872
1873 Ok(entropy / (state.len() as f64).ln()) }
1875
1876 fn measure_fidelity(&self) -> Result<Array1<f64>> {
1878 let fidelity = self.reservoir_state.state_vector[0].norm_sqr();
1880 Ok(Array1::from_vec(vec![fidelity]))
1881 }
1882
1883 fn measure_quantum_fisher_information(&self) -> Result<Array1<f64>> {
1885 let mut qfi_values = Vec::new();
1886
1887 for qubit in 0..self.config.num_qubits {
1888 let z_exp = self.calculate_single_qubit_expectation(
1890 qubit,
1891 &[
1892 Complex64::new(1.0, 0.0),
1893 Complex64::new(0.0, 0.0),
1894 Complex64::new(0.0, 0.0),
1895 Complex64::new(-1.0, 0.0),
1896 ],
1897 )?;
1898
1899 let qfi = 4.0 * (1.0 - z_exp * z_exp);
1901 qfi_values.push(qfi);
1902 }
1903
1904 Ok(Array1::from_vec(qfi_values))
1905 }
1906
1907 fn measure_variance(&self) -> Result<Array1<f64>> {
1909 let mut variances = Vec::new();
1910
1911 for qubit in 0..self.config.num_qubits {
1912 for pauli_idx in 0..3 {
1914 let pauli_matrix = match pauli_idx {
1915 0 => [
1916 Complex64::new(0.0, 0.0),
1917 Complex64::new(1.0, 0.0),
1918 Complex64::new(1.0, 0.0),
1919 Complex64::new(0.0, 0.0),
1920 ],
1921 1 => [
1922 Complex64::new(0.0, 0.0),
1923 Complex64::new(0.0, -1.0),
1924 Complex64::new(0.0, 1.0),
1925 Complex64::new(0.0, 0.0),
1926 ],
1927 _ => [
1928 Complex64::new(1.0, 0.0),
1929 Complex64::new(0.0, 0.0),
1930 Complex64::new(0.0, 0.0),
1931 Complex64::new(-1.0, 0.0),
1932 ],
1933 };
1934
1935 let expectation = self.calculate_single_qubit_expectation(qubit, &pauli_matrix)?;
1936 let variance = 1.0 - expectation * expectation; variances.push(variance);
1938 }
1939 }
1940
1941 Ok(Array1::from_vec(variances))
1942 }
1943
1944 fn measure_higher_order_moments(&self) -> Result<Array1<f64>> {
1946 let mut moments = Vec::new();
1947
1948 for qubit in 0..self.config.num_qubits {
1949 let z_exp = self.calculate_single_qubit_expectation(
1951 qubit,
1952 &[
1953 Complex64::new(1.0, 0.0),
1954 Complex64::new(0.0, 0.0),
1955 Complex64::new(0.0, 0.0),
1956 Complex64::new(-1.0, 0.0),
1957 ],
1958 )?;
1959
1960 moments.push(z_exp);
1962
1963 let variance = 1.0 - z_exp * z_exp;
1965 moments.push(variance);
1966
1967 moments.push(0.0);
1970
1971 moments.push(variance * variance);
1973
1974 moments.push(z_exp * variance);
1976
1977 moments.push(variance * variance * variance);
1979 }
1980
1981 Ok(Array1::from_vec(moments))
1982 }
1983
1984 fn measure_quantum_coherence(&self) -> Result<Array1<f64>> {
1986 let mut coherence_measures = Vec::new();
1987
1988 for qubit in 0..self.config.num_qubits {
1989 let mut coherence = 0.0;
1991 let state = &self.reservoir_state.state_vector;
1992
1993 for i in 0..state.len() {
1994 for j in 0..state.len() {
1995 if i != j {
1996 let i_bit = (i >> qubit) & 1;
1997 let j_bit = (j >> qubit) & 1;
1998 if i_bit != j_bit {
1999 coherence += (state[i].conj() * state[j]).norm();
2000 }
2001 }
2002 }
2003 }
2004
2005 coherence_measures.push(coherence);
2006 }
2007
2008 Ok(Array1::from_vec(coherence_measures))
2009 }
2010
2011 fn measure_purity(&self) -> Result<Array1<f64>> {
2013 let state = &self.reservoir_state.state_vector;
2015 let purity = state.iter().map(|x| x.norm_sqr().powi(2)).sum::<f64>();
2016
2017 Ok(Array1::from_vec(vec![purity]))
2018 }
2019
2020 fn measure_temporal_correlations(&self) -> Result<Array1<f64>> {
2022 let mut correlations = Vec::new();
2023
2024 let current_state = &self.reservoir_state.state_vector;
2026
2027 for past_state in &self.reservoir_state.state_history {
2028 let correlation = current_state
2029 .iter()
2030 .zip(past_state.iter())
2031 .map(|(a, b)| (a.conj() * b).re)
2032 .sum::<f64>();
2033 correlations.push(correlation);
2034 }
2035
2036 while correlations.len() < self.config.memory_capacity {
2038 correlations.push(0.0);
2039 }
2040
2041 Ok(Array1::from_vec(correlations))
2042 }
2043
2044 pub fn train(&mut self, training_data: &ReservoirTrainingData) -> Result<TrainingResult> {
2046 let start_time = std::time::Instant::now();
2047
2048 let mut all_features = Vec::new();
2049 let mut all_targets = Vec::new();
2050
2051 for i in 0..self.config.washout_period.min(training_data.inputs.len()) {
2053 let _ = self.process_input(&training_data.inputs[i])?;
2054 }
2055
2056 for i in self.config.washout_period..training_data.inputs.len() {
2058 let features = self.process_input(&training_data.inputs[i])?;
2059 all_features.push(features);
2060
2061 if i < training_data.targets.len() {
2062 all_targets.push(training_data.targets[i].clone());
2063 }
2064 }
2065
2066 self.train_with_learning_algorithm(&all_features, &all_targets)?;
2068
2069 if self.config.memory_config.enable_capacity_estimation {
2071 self.analyze_memory_capacity(&all_features)?;
2072 }
2073
2074 let (training_error, test_error) =
2076 self.evaluate_performance(&all_features, &all_targets)?;
2077
2078 let training_time = start_time.elapsed().as_secs_f64() * 1000.0;
2079
2080 self.metrics.training_examples += all_features.len();
2082 self.metrics.generalization_error = test_error;
2083 self.metrics.memory_capacity = self.reservoir_state.memory_metrics.total_capacity;
2084
2085 Ok(TrainingResult {
2086 training_error,
2087 test_error,
2088 training_time_ms: training_time,
2089 num_examples: all_features.len(),
2090 echo_state_property: self.estimate_echo_state_property()?,
2091 memory_capacity: self.reservoir_state.memory_metrics.total_capacity,
2092 nonlinear_capacity: self.reservoir_state.memory_metrics.nonlinear_capacity,
2093 processing_capacity: self.reservoir_state.memory_metrics.processing_capacity,
2094 })
2095 }
2096
2097 fn train_with_learning_algorithm(
2099 &mut self,
2100 features: &[Array1<f64>],
2101 targets: &[Array1<f64>],
2102 ) -> Result<()> {
2103 match self.config.learning_config.algorithm {
2104 LearningAlgorithm::Ridge => {
2105 self.train_ridge_regression(features, targets)?;
2106 }
2107 LearningAlgorithm::LASSO => {
2108 self.train_lasso_regression(features, targets)?;
2109 }
2110 LearningAlgorithm::ElasticNet => {
2111 self.train_elastic_net(features, targets)?;
2112 }
2113 LearningAlgorithm::RecursiveLeastSquares => {
2114 self.train_recursive_least_squares(features, targets)?;
2115 }
2116 LearningAlgorithm::KalmanFilter => {
2117 self.train_kalman_filter(features, targets)?;
2118 }
2119 _ => {
2120 self.train_ridge_regression(features, targets)?;
2122 }
2123 }
2124
2125 Ok(())
2126 }
2127
2128 fn train_ridge_regression(
2130 &mut self,
2131 features: &[Array1<f64>],
2132 targets: &[Array1<f64>],
2133 ) -> Result<()> {
2134 if features.is_empty() || targets.is_empty() {
2135 return Ok(());
2136 }
2137
2138 let n_samples = features.len().min(targets.len());
2139 let n_features = features[0].len();
2140 let n_outputs = targets[0].len().min(self.output_weights.nrows());
2141
2142 let mut feature_matrix = Array2::zeros((n_samples, n_features));
2144 for (i, feature_vec) in features.iter().enumerate().take(n_samples) {
2145 for (j, &val) in feature_vec.iter().enumerate().take(n_features) {
2146 feature_matrix[[i, j]] = val;
2147 }
2148 }
2149
2150 let mut target_matrix = Array2::zeros((n_samples, n_outputs));
2152 for (i, target_vec) in targets.iter().enumerate().take(n_samples) {
2153 for (j, &val) in target_vec.iter().enumerate().take(n_outputs) {
2154 target_matrix[[i, j]] = val;
2155 }
2156 }
2157
2158 let lambda = self.config.learning_config.regularization;
2160
2161 let xtx = feature_matrix.t().dot(&feature_matrix);
2163
2164 let mut xtx_reg = xtx;
2166 for i in 0..xtx_reg.nrows().min(xtx_reg.ncols()) {
2167 xtx_reg[[i, i]] += lambda;
2168 }
2169
2170 let xty = feature_matrix.t().dot(&target_matrix);
2172
2173 self.solve_linear_system(&xtx_reg, &xty)?;
2175
2176 Ok(())
2177 }
2178
2179 fn train_lasso_regression(
2181 &mut self,
2182 features: &[Array1<f64>],
2183 targets: &[Array1<f64>],
2184 ) -> Result<()> {
2185 let lambda = self.config.learning_config.regularization;
2187 let max_iter = 100;
2188
2189 for _ in 0..max_iter {
2190 for j in 0..self.output_weights.ncols().min(features[0].len()) {
2192 for i in 0..self.output_weights.nrows().min(targets[0].len()) {
2193 let old_weight = self.output_weights[[i, j]];
2195 let gradient = self.compute_lasso_gradient(features, targets, i, j)?;
2196 let update = 0.01f64.mul_add(-gradient, old_weight);
2197
2198 self.output_weights[[i, j]] = if update > lambda {
2200 update - lambda
2201 } else if update < -lambda {
2202 update + lambda
2203 } else {
2204 0.0
2205 };
2206 }
2207 }
2208 }
2209
2210 Ok(())
2211 }
2212
2213 fn compute_lasso_gradient(
2215 &self,
2216 features: &[Array1<f64>],
2217 targets: &[Array1<f64>],
2218 output_idx: usize,
2219 feature_idx: usize,
2220 ) -> Result<f64> {
2221 let mut gradient = 0.0;
2222
2223 for (feature_vec, target_vec) in features.iter().zip(targets.iter()) {
2224 if feature_idx < feature_vec.len() && output_idx < target_vec.len() {
2225 let prediction = self.predict_single_output(feature_vec, output_idx)?;
2226 let error = prediction - target_vec[output_idx];
2227 gradient += error * feature_vec[feature_idx];
2228 }
2229 }
2230
2231 gradient /= features.len() as f64;
2232 Ok(gradient)
2233 }
2234
2235 fn train_elastic_net(
2237 &mut self,
2238 features: &[Array1<f64>],
2239 targets: &[Array1<f64>],
2240 ) -> Result<()> {
2241 let l1_ratio = self.config.learning_config.l1_ratio;
2242
2243 if l1_ratio > 0.5 {
2245 self.train_lasso_regression(features, targets)?;
2247 } else {
2248 self.train_ridge_regression(features, targets)?;
2250 }
2251
2252 Ok(())
2253 }
2254
2255 fn train_recursive_least_squares(
2257 &mut self,
2258 features: &[Array1<f64>],
2259 targets: &[Array1<f64>],
2260 ) -> Result<()> {
2261 let forgetting_factor = self.config.learning_config.forgetting_factor;
2262 let n_features = features[0].len().min(self.output_weights.ncols());
2263 let n_outputs = targets[0].len().min(self.output_weights.nrows());
2264
2265 let mut p_matrix = Array2::eye(n_features) * 1000.0; for (feature_vec, target_vec) in features.iter().zip(targets.iter()) {
2270 let x = feature_vec.slice(s![..n_features]).to_owned();
2271 let y = target_vec.slice(s![..n_outputs]).to_owned();
2272
2273 let px = p_matrix.dot(&x);
2275 let denominator = forgetting_factor + x.dot(&px);
2276
2277 if denominator > 1e-15 {
2278 let k = &px / denominator;
2279
2280 for output_idx in 0..n_outputs {
2282 let prediction = self.predict_single_output(feature_vec, output_idx)?;
2283 let error = y[output_idx] - prediction;
2284
2285 for feature_idx in 0..n_features {
2287 self.output_weights[[output_idx, feature_idx]] += k[feature_idx] * error;
2288 }
2289 }
2290
2291 let outer_product = k
2293 .view()
2294 .insert_axis(Axis(1))
2295 .dot(&x.view().insert_axis(Axis(0)));
2296 p_matrix = (p_matrix - outer_product) / forgetting_factor;
2297 }
2298 }
2299
2300 Ok(())
2301 }
2302
2303 fn train_kalman_filter(
2305 &mut self,
2306 features: &[Array1<f64>],
2307 targets: &[Array1<f64>],
2308 ) -> Result<()> {
2309 let process_noise = self.config.learning_config.process_noise;
2310 let measurement_noise = self.config.learning_config.measurement_noise;
2311
2312 let n_features = features[0].len().min(self.output_weights.ncols());
2313 let n_outputs = targets[0].len().min(self.output_weights.nrows());
2314
2315 let mut state_covariance = Array2::eye(n_features) * 1.0;
2317 let process_noise_matrix: Array2<f64> = Array2::eye(n_features) * process_noise;
2318 let measurement_noise_scalar = measurement_noise;
2319
2320 for (feature_vec, target_vec) in features.iter().zip(targets.iter()) {
2322 let x = feature_vec.slice(s![..n_features]).to_owned();
2323 let y = target_vec.slice(s![..n_outputs]).to_owned();
2324
2325 let predicted_covariance = &state_covariance + &process_noise_matrix;
2327
2328 for output_idx in 0..n_outputs {
2330 let measurement = y[output_idx];
2331 let prediction = self.predict_single_output(feature_vec, output_idx)?;
2332
2333 let s = x.dot(&predicted_covariance.dot(&x)) + measurement_noise_scalar;
2335 if s > 1e-15 {
2336 let k = predicted_covariance.dot(&x) / s;
2337
2338 let innovation = measurement - prediction;
2340 for feature_idx in 0..n_features {
2341 self.output_weights[[output_idx, feature_idx]] +=
2342 k[feature_idx] * innovation;
2343 }
2344
2345 let kh = k
2347 .view()
2348 .insert_axis(Axis(1))
2349 .dot(&x.view().insert_axis(Axis(0)));
2350 state_covariance = &predicted_covariance - &kh.dot(&predicted_covariance);
2351 }
2352 }
2353 }
2354
2355 Ok(())
2356 }
2357
2358 fn predict_single_output(&self, features: &Array1<f64>, output_idx: usize) -> Result<f64> {
2360 let feature_size = features.len().min(self.output_weights.ncols());
2361 let mut output = 0.0;
2362
2363 for j in 0..feature_size {
2364 output += self.output_weights[[output_idx, j]] * features[j];
2365 }
2366
2367 Ok(output)
2368 }
2369
2370 fn analyze_memory_capacity(&mut self, features: &[Array1<f64>]) -> Result<()> {
2372 let linear_capacity = self.estimate_linear_memory_capacity(features)?;
2374 self.reservoir_state.memory_metrics.linear_capacity = linear_capacity;
2375
2376 if self.config.memory_config.enable_nonlinear {
2378 let nonlinear_capacity = self.estimate_nonlinear_memory_capacity(features)?;
2379 self.reservoir_state.memory_metrics.nonlinear_capacity = nonlinear_capacity;
2380 }
2381
2382 self.reservoir_state.memory_metrics.total_capacity =
2384 self.reservoir_state.memory_metrics.linear_capacity
2385 + self.reservoir_state.memory_metrics.nonlinear_capacity;
2386
2387 if self.config.memory_config.enable_ipc {
2389 let ipc = self.estimate_information_processing_capacity(features)?;
2390 self.reservoir_state.memory_metrics.processing_capacity = ipc;
2391 }
2392
2393 self.memory_analyzer.capacity_estimates.insert(
2395 "linear".to_string(),
2396 self.reservoir_state.memory_metrics.linear_capacity,
2397 );
2398 self.memory_analyzer.capacity_estimates.insert(
2399 "nonlinear".to_string(),
2400 self.reservoir_state.memory_metrics.nonlinear_capacity,
2401 );
2402 self.memory_analyzer.capacity_estimates.insert(
2403 "total".to_string(),
2404 self.reservoir_state.memory_metrics.total_capacity,
2405 );
2406
2407 Ok(())
2408 }
2409
2410 fn estimate_linear_memory_capacity(&self, features: &[Array1<f64>]) -> Result<f64> {
2412 let mut capacity = 0.0;
2414
2415 for lag in 1..=20 {
2416 if lag < features.len() {
2417 let mut correlation = 0.0;
2418 let mut count = 0;
2419
2420 for i in lag..features.len() {
2421 for j in 0..features[i].len().min(features[i - lag].len()) {
2422 correlation += features[i][j] * features[i - lag][j];
2423 count += 1;
2424 }
2425 }
2426
2427 if count > 0 {
2428 correlation /= count as f64;
2429 capacity += correlation.abs();
2430 }
2431 }
2432 }
2433
2434 Ok(capacity)
2435 }
2436
2437 fn estimate_nonlinear_memory_capacity(&self, features: &[Array1<f64>]) -> Result<f64> {
2439 let mut nonlinear_capacity = 0.0;
2440
2441 for order in &self.config.memory_config.nonlinearity_orders {
2443 let capacity_order = self.test_nonlinear_order(*order, features)?;
2444 nonlinear_capacity += capacity_order;
2445 }
2446
2447 Ok(nonlinear_capacity)
2448 }
2449
2450 fn test_nonlinear_order(&self, order: usize, features: &[Array1<f64>]) -> Result<f64> {
2452 let mut capacity = 0.0;
2453
2454 for lag in 1..=10 {
2456 if lag < features.len() {
2457 let mut correlation = 0.0;
2458 let mut count = 0;
2459
2460 for i in lag..features.len() {
2461 for j in 0..features[i].len().min(features[i - lag].len()) {
2462 let current = features[i][j];
2464 let past = features[i - lag][j];
2465 let nonlinear_target = past.powi(order as i32);
2466
2467 correlation += current * nonlinear_target;
2468 count += 1;
2469 }
2470 }
2471
2472 if count > 0 {
2473 correlation /= count as f64;
2474 capacity += correlation.abs() / order as f64; }
2476 }
2477 }
2478
2479 Ok(capacity)
2480 }
2481
2482 fn estimate_information_processing_capacity(&self, features: &[Array1<f64>]) -> Result<f64> {
2484 let mut ipc = 0.0;
2485
2486 for ipc_function in &self.config.memory_config.ipc_functions {
2487 let capacity_func = self.test_ipc_function(*ipc_function, features)?;
2488 ipc += capacity_func;
2489 }
2490
2491 Ok(ipc)
2492 }
2493
2494 fn test_ipc_function(&self, function: IPCFunction, features: &[Array1<f64>]) -> Result<f64> {
2496 let mut capacity = 0.0;
2497
2498 for lag in 1..=10 {
2499 if lag < features.len() {
2500 let mut correlation = 0.0;
2501 let mut count = 0;
2502
2503 for i in lag..features.len() {
2504 for j in 0..features[i].len().min(features[i - lag].len()) {
2505 let current = features[i][j];
2506 let past = features[i - lag][j];
2507
2508 let target = match function {
2509 IPCFunction::Linear => past,
2510 IPCFunction::Quadratic => past * past,
2511 IPCFunction::Cubic => past * past * past,
2512 IPCFunction::Sine => past.sin(),
2513 IPCFunction::Product => {
2514 if j > 0 && j - 1 < features[i - lag].len() {
2515 past * features[i - lag][j - 1]
2516 } else {
2517 past
2518 }
2519 }
2520 IPCFunction::XOR => {
2521 if past > 0.0 {
2522 1.0
2523 } else {
2524 -1.0
2525 }
2526 }
2527 };
2528
2529 correlation += current * target;
2530 count += 1;
2531 }
2532 }
2533
2534 if count > 0 {
2535 correlation /= count as f64;
2536 capacity += correlation.abs();
2537 }
2538 }
2539 }
2540
2541 Ok(capacity)
2542 }
2543
2544 fn solve_linear_system(&mut self, a: &Array2<f64>, b: &Array2<f64>) -> Result<()> {
2546 let min_dim = a.nrows().min(a.ncols()).min(b.nrows());
2547
2548 for i in 0..min_dim.min(self.output_weights.nrows()) {
2549 for j in 0..b.ncols().min(self.output_weights.ncols()) {
2550 if a[[i, i]].abs() > 1e-15 {
2551 self.output_weights[[i, j]] = b[[i, j]] / a[[i, i]];
2552 }
2553 }
2554 }
2555
2556 Ok(())
2557 }
2558
2559 fn evaluate_performance(
2561 &self,
2562 features: &[Array1<f64>],
2563 targets: &[Array1<f64>],
2564 ) -> Result<(f64, f64)> {
2565 if features.is_empty() || targets.is_empty() {
2566 return Ok((0.0, 0.0));
2567 }
2568
2569 let mut total_error = 0.0;
2570 let n_samples = features.len().min(targets.len());
2571
2572 for i in 0..n_samples {
2573 let prediction = self.predict_output(&features[i])?;
2574 let error = self.calculate_prediction_error(&prediction, &targets[i]);
2575 total_error += error;
2576 }
2577
2578 let training_error = total_error / n_samples as f64;
2579
2580 let test_error = training_error;
2582
2583 Ok((training_error, test_error))
2584 }
2585
2586 fn predict_output(&self, features: &Array1<f64>) -> Result<Array1<f64>> {
2588 let feature_size = features.len().min(self.output_weights.ncols());
2589 let output_size = self.output_weights.nrows();
2590
2591 let mut output = Array1::zeros(output_size);
2592
2593 for i in 0..output_size {
2594 for j in 0..feature_size {
2595 output[i] += self.output_weights[[i, j]] * features[j];
2596 }
2597 }
2598
2599 Ok(output)
2600 }
2601
2602 fn calculate_prediction_error(&self, prediction: &Array1<f64>, target: &Array1<f64>) -> f64 {
2604 let min_len = prediction.len().min(target.len());
2605 let mut error = 0.0;
2606
2607 for i in 0..min_len {
2608 let diff = prediction[i] - target[i];
2609 error += diff * diff;
2610 }
2611
2612 (error / min_len as f64).sqrt() }
2614
2615 fn estimate_echo_state_property(&self) -> Result<f64> {
2617 let coupling = self.config.coupling_strength;
2618 let estimated_spectral_radius = coupling.tanh(); Ok(if estimated_spectral_radius < 1.0 {
2622 1.0
2623 } else {
2624 1.0 / estimated_spectral_radius
2625 })
2626 }
2627
2628 fn update_processing_time(&mut self, time_ms: f64) {
2630 let count = self.metrics.training_examples as f64;
2631 self.metrics.avg_processing_time_ms =
2632 self.metrics.avg_processing_time_ms.mul_add(count, time_ms) / (count + 1.0);
2633 }
2634
2635 pub const fn get_metrics(&self) -> &ReservoirMetrics {
2637 &self.metrics
2638 }
2639
2640 pub const fn get_memory_analysis(&self) -> &MemoryAnalyzer {
2642 &self.memory_analyzer
2643 }
2644
2645 pub fn reset(&mut self) -> Result<()> {
2647 self.reservoir_state =
2648 QuantumReservoirState::new(self.config.num_qubits, self.config.memory_capacity);
2649 self.metrics = ReservoirMetrics::default();
2650 self.training_history.clear();
2651 Ok(())
2652 }
2653}
2654
2655impl TimeSeriesPredictor {
2656 pub fn new(config: &TimeSeriesConfig) -> Self {
2658 Self {
2659 arima_params: ARIMAParams {
2660 ar_coeffs: Array1::zeros(config.ar_order),
2661 ma_coeffs: Array1::zeros(config.ma_order),
2662 diff_order: config.diff_order,
2663 residuals: VecDeque::with_capacity(config.ma_order),
2664 variance: 1.0,
2665 },
2666 nar_state: NARState {
2667 order: config.nar_order,
2668 coeffs: Array2::zeros((config.nar_order, config.nar_order)),
2669 history: VecDeque::with_capacity(config.nar_order),
2670 activation: ActivationFunction::Tanh,
2671 },
2672 kernel_weights: Array1::from_vec(config.kernel_params.clone()),
2673 trend_model: TrendModel {
2674 params: vec![0.0, 0.0], strength: 0.0,
2676 direction: 0.0,
2677 },
2678 }
2679 }
2680}
2681
2682impl MemoryAnalyzer {
2683 pub fn new(config: MemoryAnalysisConfig) -> Self {
2685 Self {
2686 config,
2687 capacity_estimates: HashMap::new(),
2688 nonlinearity_measures: HashMap::new(),
2689 temporal_correlations: Array2::zeros((0, 0)),
2690 ipc_metrics: HashMap::new(),
2691 }
2692 }
2693}
2694
2695#[derive(Debug, Clone, Serialize, Deserialize)]
2697pub struct TrainingResult {
2698 pub training_error: f64,
2700 pub test_error: f64,
2702 pub training_time_ms: f64,
2704 pub num_examples: usize,
2706 pub echo_state_property: f64,
2708 pub memory_capacity: f64,
2710 pub nonlinear_capacity: f64,
2712 pub processing_capacity: f64,
2714}
2715
2716pub fn benchmark_enhanced_quantum_reservoir_computing() -> Result<HashMap<String, f64>> {
2718 let mut results = HashMap::new();
2719
2720 let configs = vec![
2722 QuantumReservoirConfig {
2723 num_qubits: 6,
2724 architecture: QuantumReservoirArchitecture::RandomCircuit,
2725 learning_config: AdvancedLearningConfig {
2726 algorithm: LearningAlgorithm::Ridge,
2727 ..Default::default()
2728 },
2729 ..Default::default()
2730 },
2731 QuantumReservoirConfig {
2732 num_qubits: 8,
2733 architecture: QuantumReservoirArchitecture::ScaleFree,
2734 learning_config: AdvancedLearningConfig {
2735 algorithm: LearningAlgorithm::LASSO,
2736 ..Default::default()
2737 },
2738 ..Default::default()
2739 },
2740 QuantumReservoirConfig {
2741 num_qubits: 6,
2742 architecture: QuantumReservoirArchitecture::HierarchicalModular,
2743 learning_config: AdvancedLearningConfig {
2744 algorithm: LearningAlgorithm::RecursiveLeastSquares,
2745 ..Default::default()
2746 },
2747 memory_config: MemoryAnalysisConfig {
2748 enable_capacity_estimation: true,
2749 enable_nonlinear: true,
2750 ..Default::default()
2751 },
2752 ..Default::default()
2753 },
2754 QuantumReservoirConfig {
2755 num_qubits: 8,
2756 architecture: QuantumReservoirArchitecture::Grid,
2757 dynamics: ReservoirDynamics::Floquet,
2758 input_encoding: InputEncoding::Angle,
2759 output_measurement: OutputMeasurement::TemporalCorrelations,
2760 ..Default::default()
2761 },
2762 ];
2763
2764 for (i, config) in configs.into_iter().enumerate() {
2765 let start = std::time::Instant::now();
2766
2767 let mut qrc = QuantumReservoirComputerEnhanced::new(config)?;
2768
2769 let training_data = ReservoirTrainingData::new(
2771 (0..200)
2772 .map(|i| {
2773 Array1::from_vec(vec![
2774 (i as f64 * 0.1).sin(),
2775 (i as f64 * 0.1).cos(),
2776 (i as f64 * 0.05).sin() * (i as f64 * 0.2).cos(),
2777 ])
2778 })
2779 .collect(),
2780 (0..200)
2781 .map(|i| Array1::from_vec(vec![(i as f64).mul_add(0.1, 1.0).sin()]))
2782 .collect(),
2783 (0..200).map(|i| i as f64 * 0.1).collect(),
2784 );
2785
2786 let training_result = qrc.train(&training_data)?;
2788
2789 let time = start.elapsed().as_secs_f64() * 1000.0;
2790 results.insert(format!("enhanced_config_{i}"), time);
2791
2792 let metrics = qrc.get_metrics();
2794 results.insert(
2795 format!("enhanced_config_{i}_accuracy"),
2796 metrics.prediction_accuracy,
2797 );
2798 results.insert(
2799 format!("enhanced_config_{i}_memory_capacity"),
2800 training_result.memory_capacity,
2801 );
2802 results.insert(
2803 format!("enhanced_config_{i}_nonlinear_capacity"),
2804 training_result.nonlinear_capacity,
2805 );
2806 results.insert(
2807 format!("enhanced_config_{i}_processing_capacity"),
2808 training_result.processing_capacity,
2809 );
2810 results.insert(
2811 format!("enhanced_config_{i}_quantum_advantage"),
2812 metrics.quantum_advantage,
2813 );
2814 results.insert(
2815 format!("enhanced_config_{i}_efficiency"),
2816 metrics.reservoir_efficiency,
2817 );
2818
2819 let memory_analyzer = qrc.get_memory_analysis();
2821 if let Some(&linear_capacity) = memory_analyzer.capacity_estimates.get("linear") {
2822 results.insert(
2823 format!("enhanced_config_{i}_linear_memory"),
2824 linear_capacity,
2825 );
2826 }
2827 if let Some(&total_capacity) = memory_analyzer.capacity_estimates.get("total") {
2828 results.insert(format!("enhanced_config_{i}_total_memory"), total_capacity);
2829 }
2830 }
2831
2832 Ok(results)
2833}
2834
2835#[cfg(test)]
2836mod tests {
2837 use super::*;
2838 use approx::assert_abs_diff_eq;
2839
2840 #[test]
2841 fn test_enhanced_quantum_reservoir_creation() {
2842 let config = QuantumReservoirConfig::default();
2843 let qrc = QuantumReservoirComputerEnhanced::new(config);
2844 assert!(qrc.is_ok());
2845 }
2846
2847 #[test]
2848 fn test_enhanced_reservoir_state_creation() {
2849 let state = QuantumReservoirState::new(3, 10);
2850 assert_eq!(state.state_vector.len(), 8); assert_eq!(state.state_history.capacity(), 10);
2852 assert_eq!(state.time_index, 0);
2853 assert!(state.memory_metrics.total_capacity >= 0.0);
2854 }
2855
2856 #[test]
2857 fn test_enhanced_input_processing() {
2858 let config = QuantumReservoirConfig {
2859 num_qubits: 3,
2860 evolution_steps: 2,
2861 ..Default::default()
2862 };
2863 let mut qrc = QuantumReservoirComputerEnhanced::new(config).unwrap();
2864
2865 let input = Array1::from_vec(vec![0.5, 0.3, 0.8]);
2866 let result = qrc.process_input(&input);
2867 assert!(result.is_ok());
2868
2869 let features = result.unwrap();
2870 assert!(!features.is_empty());
2871 }
2872
2873 #[test]
2874 fn test_enhanced_architectures() {
2875 let architectures = vec![
2876 QuantumReservoirArchitecture::RandomCircuit,
2877 QuantumReservoirArchitecture::SpinChain,
2878 QuantumReservoirArchitecture::ScaleFree,
2879 QuantumReservoirArchitecture::HierarchicalModular,
2880 QuantumReservoirArchitecture::Ring,
2881 QuantumReservoirArchitecture::Grid,
2882 ];
2883
2884 for arch in architectures {
2885 let config = QuantumReservoirConfig {
2886 num_qubits: 4,
2887 architecture: arch,
2888 evolution_steps: 2,
2889 ..Default::default()
2890 };
2891
2892 let qrc = QuantumReservoirComputerEnhanced::new(config);
2893 assert!(qrc.is_ok(), "Failed for architecture: {arch:?}");
2894 }
2895 }
2896
2897 #[test]
2898 fn test_advanced_learning_algorithms() {
2899 let algorithms = vec![
2900 LearningAlgorithm::Ridge,
2901 LearningAlgorithm::LASSO,
2902 LearningAlgorithm::ElasticNet,
2903 LearningAlgorithm::RecursiveLeastSquares,
2904 ];
2905
2906 for algorithm in algorithms {
2907 let config = QuantumReservoirConfig {
2908 num_qubits: 3,
2909 learning_config: AdvancedLearningConfig {
2910 algorithm,
2911 ..Default::default()
2912 },
2913 ..Default::default()
2914 };
2915
2916 let qrc = QuantumReservoirComputerEnhanced::new(config);
2917 assert!(qrc.is_ok(), "Failed for algorithm: {algorithm:?}");
2918 }
2919 }
2920
2921 #[test]
2922 fn test_enhanced_encoding_methods() {
2923 let encodings = vec![
2924 InputEncoding::Amplitude,
2925 InputEncoding::Phase,
2926 InputEncoding::BasisState,
2927 InputEncoding::Angle,
2928 ];
2929
2930 for encoding in encodings {
2931 let config = QuantumReservoirConfig {
2932 num_qubits: 3,
2933 input_encoding: encoding,
2934 ..Default::default()
2935 };
2936 let mut qrc = QuantumReservoirComputerEnhanced::new(config).unwrap();
2937
2938 let input = Array1::from_vec(vec![0.5, 0.3]);
2939 let result = qrc.encode_input(&input);
2940 assert!(result.is_ok(), "Failed for encoding: {encoding:?}");
2941 }
2942 }
2943
2944 #[test]
2945 fn test_enhanced_measurement_strategies() {
2946 let measurements = vec![
2947 OutputMeasurement::PauliExpectation,
2948 OutputMeasurement::Probability,
2949 OutputMeasurement::Correlations,
2950 OutputMeasurement::Entanglement,
2951 OutputMeasurement::QuantumFisherInformation,
2952 OutputMeasurement::Variance,
2953 OutputMeasurement::QuantumCoherence,
2954 OutputMeasurement::Purity,
2955 OutputMeasurement::TemporalCorrelations,
2956 ];
2957
2958 for measurement in measurements {
2959 let config = QuantumReservoirConfig {
2960 num_qubits: 3,
2961 output_measurement: measurement,
2962 ..Default::default()
2963 };
2964
2965 let qrc = QuantumReservoirComputerEnhanced::new(config);
2966 assert!(qrc.is_ok(), "Failed for measurement: {measurement:?}");
2967 }
2968 }
2969
2970 #[test]
2971 fn test_enhanced_reservoir_dynamics() {
2972 let dynamics = vec![
2973 ReservoirDynamics::Unitary,
2974 ReservoirDynamics::Open,
2975 ReservoirDynamics::NISQ,
2976 ReservoirDynamics::Floquet,
2977 ];
2978
2979 for dynamic in dynamics {
2980 let config = QuantumReservoirConfig {
2981 num_qubits: 3,
2982 dynamics: dynamic,
2983 evolution_steps: 1,
2984 ..Default::default()
2985 };
2986
2987 let mut qrc = QuantumReservoirComputerEnhanced::new(config).unwrap();
2988 let result = qrc.evolve_reservoir();
2989 assert!(result.is_ok(), "Failed for dynamics: {dynamic:?}");
2990 }
2991 }
2992
2993 #[test]
2994 fn test_memory_analysis() {
2995 let config = QuantumReservoirConfig {
2996 num_qubits: 4,
2997 memory_config: MemoryAnalysisConfig {
2998 enable_capacity_estimation: true,
2999 enable_nonlinear: true,
3000 enable_ipc: true,
3001 ..Default::default()
3002 },
3003 ..Default::default()
3004 };
3005
3006 let qrc = QuantumReservoirComputerEnhanced::new(config).unwrap();
3007 let memory_analyzer = qrc.get_memory_analysis();
3008
3009 assert!(memory_analyzer.config.enable_capacity_estimation);
3010 assert!(memory_analyzer.config.enable_nonlinear);
3011 assert!(memory_analyzer.config.enable_ipc);
3012 }
3013
3014 #[test]
3015 fn test_enhanced_training_data() {
3016 let training_data = ReservoirTrainingData::new(
3017 vec![
3018 Array1::from_vec(vec![0.1, 0.2]),
3019 Array1::from_vec(vec![0.3, 0.4]),
3020 ],
3021 vec![Array1::from_vec(vec![0.5]), Array1::from_vec(vec![0.6])],
3022 vec![0.0, 1.0],
3023 )
3024 .with_features(vec![
3025 Array1::from_vec(vec![0.7, 0.8]),
3026 Array1::from_vec(vec![0.9, 1.0]),
3027 ])
3028 .with_labels(vec![0, 1])
3029 .with_weights(vec![1.0, 1.0]);
3030
3031 assert_eq!(training_data.len(), 2);
3032 assert!(training_data.features.is_some());
3033 assert!(training_data.labels.is_some());
3034 assert!(training_data.sample_weights.is_some());
3035
3036 let (train, test) = training_data.train_test_split(0.5);
3037 assert_eq!(train.len(), 1);
3038 assert_eq!(test.len(), 1);
3039 }
3040
3041 #[test]
3042 fn test_time_series_predictor() {
3043 let config = TimeSeriesConfig::default();
3044 let predictor = TimeSeriesPredictor::new(&config);
3045
3046 assert_eq!(predictor.arima_params.ar_coeffs.len(), config.ar_order);
3047 assert_eq!(predictor.arima_params.ma_coeffs.len(), config.ma_order);
3048 assert_eq!(predictor.nar_state.order, config.nar_order);
3049 }
3050
3051 #[test]
3052 fn test_enhanced_metrics_tracking() {
3053 let config = QuantumReservoirConfig::default();
3054 let qrc = QuantumReservoirComputerEnhanced::new(config).unwrap();
3055
3056 let metrics = qrc.get_metrics();
3057 assert_eq!(metrics.training_examples, 0);
3058 assert_eq!(metrics.prediction_accuracy, 0.0);
3059 assert_eq!(metrics.memory_capacity, 0.0);
3060 assert_eq!(metrics.nonlinear_memory_capacity, 0.0);
3061 assert_eq!(metrics.quantum_advantage, 0.0);
3062 }
3063
3064 #[test]
3065 fn test_enhanced_feature_sizes() {
3066 let measurements = vec![
3067 (OutputMeasurement::PauliExpectation, 24), (OutputMeasurement::QuantumFisherInformation, 8), (OutputMeasurement::Variance, 24), (OutputMeasurement::Purity, 1), ];
3072
3073 for (measurement, expected_size) in measurements {
3074 let config = QuantumReservoirConfig {
3075 num_qubits: 8,
3076 output_measurement: measurement,
3077 ..Default::default()
3078 };
3079
3080 let feature_size = QuantumReservoirComputerEnhanced::calculate_feature_size(&config);
3081 assert_eq!(
3082 feature_size, expected_size,
3083 "Feature size mismatch for {measurement:?}"
3084 );
3085 }
3086 }
3087}