1use scirs2_core::ndarray::{s, Array1, Array2, Array3, ArrayView1, ArrayView2, Axis};
28use scirs2_core::parallel_ops::{IndexedParallelIterator, ParallelIterator};
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 #[must_use]
552 pub fn new(num_qubits: usize, memory_capacity: usize) -> Self {
553 let state_size = 1 << num_qubits;
554 let mut state_vector = Array1::zeros(state_size);
555 state_vector[0] = Complex64::new(1.0, 0.0); Self {
558 state_vector,
559 state_history: VecDeque::with_capacity(memory_capacity),
560 observables: HashMap::new(),
561 correlations: Array2::zeros((num_qubits, num_qubits)),
562 higher_order_correlations: HashMap::new(),
563 entanglement_measures: HashMap::new(),
564 memory_metrics: MemoryMetrics::default(),
565 time_index: 0,
566 last_update: 0.0,
567 activity_level: 0.0,
568 performance_history: VecDeque::with_capacity(1000),
569 }
570 }
571
572 pub fn update_state(&mut self, new_state: Array1<Complex64>, timestamp: f64) {
574 self.state_history.push_back(self.state_vector.clone());
576 if self.state_history.len() > self.state_history.capacity() {
577 self.state_history.pop_front();
578 }
579
580 self.state_vector = new_state;
582 self.time_index += 1;
583 self.last_update = timestamp;
584
585 self.update_activity_level();
587 }
588
589 fn update_activity_level(&mut self) {
591 let activity = self
592 .state_vector
593 .iter()
594 .map(scirs2_core::Complex::norm_sqr)
595 .sum::<f64>()
596 / self.state_vector.len() as f64;
597
598 let alpha = 0.1;
600 self.activity_level = alpha * activity + (1.0 - alpha) * self.activity_level;
601 }
602
603 #[must_use]
605 pub fn calculate_memory_decay(&self) -> f64 {
606 if self.state_history.len() < 2 {
607 return 0.0;
608 }
609
610 let mut total_decay = 0.0;
611 let current_state = &self.state_vector;
612
613 for (i, past_state) in self.state_history.iter().enumerate() {
614 let fidelity = self.calculate_fidelity(current_state, past_state);
615 let time_diff = (self.state_history.len() - i) as f64;
616 total_decay += fidelity * (-time_diff * 0.1).exp();
617 }
618
619 total_decay / self.state_history.len() as f64
620 }
621
622 fn calculate_fidelity(&self, state1: &Array1<Complex64>, state2: &Array1<Complex64>) -> f64 {
624 let overlap = state1
625 .iter()
626 .zip(state2.iter())
627 .map(|(a, b)| a.conj() * b)
628 .sum::<Complex64>();
629 overlap.norm_sqr()
630 }
631}
632
633#[derive(Debug, Clone)]
635pub struct ReservoirTrainingData {
636 pub inputs: Vec<Array1<f64>>,
638 pub targets: Vec<Array1<f64>>,
640 pub timestamps: Vec<f64>,
642 pub features: Option<Vec<Array1<f64>>>,
644 pub labels: Option<Vec<usize>>,
646 pub sequence_lengths: Option<Vec<usize>>,
648 pub missing_mask: Option<Vec<Array1<bool>>>,
650 pub sample_weights: Option<Vec<f64>>,
652 pub metadata: Option<Vec<HashMap<String, String>>>,
654}
655
656impl ReservoirTrainingData {
657 #[must_use]
659 pub const fn new(
660 inputs: Vec<Array1<f64>>,
661 targets: Vec<Array1<f64>>,
662 timestamps: Vec<f64>,
663 ) -> Self {
664 Self {
665 inputs,
666 targets,
667 timestamps,
668 features: None,
669 labels: None,
670 sequence_lengths: None,
671 missing_mask: None,
672 sample_weights: None,
673 metadata: None,
674 }
675 }
676
677 #[must_use]
679 pub fn with_features(mut self, features: Vec<Array1<f64>>) -> Self {
680 self.features = Some(features);
681 self
682 }
683
684 #[must_use]
686 pub fn with_labels(mut self, labels: Vec<usize>) -> Self {
687 self.labels = Some(labels);
688 self
689 }
690
691 #[must_use]
693 pub fn with_weights(mut self, weights: Vec<f64>) -> Self {
694 self.sample_weights = Some(weights);
695 self
696 }
697
698 #[must_use]
700 pub fn len(&self) -> usize {
701 self.inputs.len()
702 }
703
704 #[must_use]
706 pub fn is_empty(&self) -> bool {
707 self.inputs.is_empty()
708 }
709
710 #[must_use]
712 pub fn train_test_split(&self, test_ratio: f64) -> (Self, Self) {
713 let test_size = (self.len() as f64 * test_ratio) as usize;
714 let train_size = self.len() - test_size;
715
716 let train_data = Self {
717 inputs: self.inputs[..train_size].to_vec(),
718 targets: self.targets[..train_size].to_vec(),
719 timestamps: self.timestamps[..train_size].to_vec(),
720 features: self.features.as_ref().map(|f| f[..train_size].to_vec()),
721 labels: self.labels.as_ref().map(|l| l[..train_size].to_vec()),
722 sequence_lengths: self
723 .sequence_lengths
724 .as_ref()
725 .map(|s| s[..train_size].to_vec()),
726 missing_mask: self.missing_mask.as_ref().map(|m| m[..train_size].to_vec()),
727 sample_weights: self
728 .sample_weights
729 .as_ref()
730 .map(|w| w[..train_size].to_vec()),
731 metadata: self.metadata.as_ref().map(|m| m[..train_size].to_vec()),
732 };
733
734 let test_data = Self {
735 inputs: self.inputs[train_size..].to_vec(),
736 targets: self.targets[train_size..].to_vec(),
737 timestamps: self.timestamps[train_size..].to_vec(),
738 features: self.features.as_ref().map(|f| f[train_size..].to_vec()),
739 labels: self.labels.as_ref().map(|l| l[train_size..].to_vec()),
740 sequence_lengths: self
741 .sequence_lengths
742 .as_ref()
743 .map(|s| s[train_size..].to_vec()),
744 missing_mask: self.missing_mask.as_ref().map(|m| m[train_size..].to_vec()),
745 sample_weights: self
746 .sample_weights
747 .as_ref()
748 .map(|w| w[train_size..].to_vec()),
749 metadata: self.metadata.as_ref().map(|m| m[train_size..].to_vec()),
750 };
751
752 (train_data, test_data)
753 }
754}
755
756#[derive(Debug, Clone)]
758pub struct TrainingExample {
759 pub input: Array1<f64>,
761 pub reservoir_state: Array1<f64>,
763 pub features: Array1<f64>,
765 pub target: Array1<f64>,
767 pub prediction: Array1<f64>,
769 pub error: f64,
771 pub confidence: f64,
773 pub timestamp: f64,
775 pub metadata: HashMap<String, f64>,
777}
778
779#[derive(Debug, Clone, Default, Serialize, Deserialize)]
781pub struct ReservoirMetrics {
782 pub training_examples: usize,
784 pub prediction_accuracy: f64,
786 pub memory_capacity: f64,
788 pub nonlinear_memory_capacity: f64,
790 pub processing_capacity: f64,
792 pub generalization_error: f64,
794 pub echo_state_property: f64,
796 pub avg_processing_time_ms: f64,
798 pub quantum_resource_usage: f64,
800 pub temporal_correlation_length: f64,
802 pub reservoir_efficiency: f64,
804 pub adaptation_rate: f64,
806 pub plasticity_level: f64,
808 pub hardware_utilization: f64,
810 pub error_mitigation_overhead: f64,
812 pub quantum_advantage: f64,
814 pub computational_complexity: f64,
816}
817
818pub struct QuantumReservoirComputerEnhanced {
820 config: QuantumReservoirConfig,
822 reservoir_state: QuantumReservoirState,
824 reservoir_circuit: InterfaceCircuit,
826 input_coupling_circuit: InterfaceCircuit,
828 output_weights: Array2<f64>,
830 time_series_predictor: Option<TimeSeriesPredictor>,
832 memory_analyzer: MemoryAnalyzer,
834 simulator: StateVectorSimulator,
836 circuit_interface: CircuitInterface,
838 metrics: ReservoirMetrics,
840 training_history: VecDeque<TrainingExample>,
842 backend: Option<SciRS2Backend>,
844 rng: Arc<Mutex<scirs2_core::random::CoreRandom>>,
846}
847
848#[derive(Debug, Clone, Serialize, Deserialize)]
850pub struct TimeSeriesPredictor {
851 pub arima_params: ARIMAParams,
853 pub nar_state: NARState,
855 pub kernel_weights: Array1<f64>,
857 pub trend_model: TrendModel,
859}
860
861#[derive(Debug, Clone, Serialize, Deserialize)]
863pub struct ARIMAParams {
864 pub ar_coeffs: Array1<f64>,
866 pub ma_coeffs: Array1<f64>,
868 pub diff_order: usize,
870 pub residuals: VecDeque<f64>,
872 pub variance: f64,
874}
875
876#[derive(Debug, Clone, Serialize, Deserialize)]
878pub struct NARState {
879 pub order: usize,
881 pub coeffs: Array2<f64>,
883 pub history: VecDeque<f64>,
885 pub activation: ActivationFunction,
887}
888
889#[derive(Debug, Clone, Serialize, Deserialize)]
891pub struct TrendModel {
892 pub params: Vec<f64>,
894 pub strength: f64,
896 pub direction: f64,
898}
899
900#[derive(Debug)]
902pub struct MemoryAnalyzer {
903 pub config: MemoryAnalysisConfig,
905 pub capacity_estimates: HashMap<String, f64>,
907 pub nonlinearity_measures: HashMap<usize, f64>,
909 pub temporal_correlations: Array2<f64>,
911 pub ipc_metrics: HashMap<String, f64>,
913}
914
915impl QuantumReservoirComputerEnhanced {
916 pub fn new(config: QuantumReservoirConfig) -> Result<Self> {
918 let circuit_interface = CircuitInterface::new(Default::default())?;
919 let simulator = StateVectorSimulator::new();
920
921 let reservoir_state = QuantumReservoirState::new(config.num_qubits, config.memory_capacity);
922
923 let reservoir_circuit = Self::generate_reservoir_circuit(&config)?;
925
926 let input_coupling_circuit = Self::generate_input_coupling_circuit(&config)?;
928
929 let output_size = Self::calculate_output_size(&config);
931 let feature_size = Self::calculate_feature_size(&config);
932 let mut output_weights = Array2::zeros((output_size, feature_size));
933
934 let scale = (2.0 / (output_size + feature_size) as f64).sqrt();
936 for elem in &mut output_weights {
937 *elem = (fastrand::f64() - 0.5) * 2.0 * scale;
938 }
939
940 let time_series_predictor =
942 if config.time_series_config.enable_arima || config.time_series_config.enable_nar {
943 Some(TimeSeriesPredictor::new(&config.time_series_config))
944 } else {
945 None
946 };
947
948 let memory_analyzer = MemoryAnalyzer::new(config.memory_config.clone());
950
951 Ok(Self {
952 config,
953 reservoir_state,
954 reservoir_circuit,
955 input_coupling_circuit,
956 output_weights,
957 time_series_predictor,
958 memory_analyzer,
959 simulator,
960 circuit_interface,
961 metrics: ReservoirMetrics::default(),
962 training_history: VecDeque::with_capacity(10_000),
963 backend: None,
964 rng: Arc::new(Mutex::new(thread_rng())),
965 })
966 }
967
968 fn generate_reservoir_circuit(config: &QuantumReservoirConfig) -> Result<InterfaceCircuit> {
970 let mut circuit = InterfaceCircuit::new(config.num_qubits, 0);
971
972 match config.architecture {
973 QuantumReservoirArchitecture::RandomCircuit => {
974 Self::generate_random_circuit(&mut circuit, config)?;
975 }
976 QuantumReservoirArchitecture::SpinChain => {
977 Self::generate_spin_chain_circuit(&mut circuit, config)?;
978 }
979 QuantumReservoirArchitecture::TransverseFieldIsing => {
980 Self::generate_tfim_circuit(&mut circuit, config)?;
981 }
982 QuantumReservoirArchitecture::SmallWorld => {
983 Self::generate_small_world_circuit(&mut circuit, config)?;
984 }
985 QuantumReservoirArchitecture::FullyConnected => {
986 Self::generate_fully_connected_circuit(&mut circuit, config)?;
987 }
988 QuantumReservoirArchitecture::ScaleFree => {
989 Self::generate_scale_free_circuit(&mut circuit, config)?;
990 }
991 QuantumReservoirArchitecture::HierarchicalModular => {
992 Self::generate_hierarchical_circuit(&mut circuit, config)?;
993 }
994 QuantumReservoirArchitecture::Ring => {
995 Self::generate_ring_circuit(&mut circuit, config)?;
996 }
997 QuantumReservoirArchitecture::Grid => {
998 Self::generate_grid_circuit(&mut circuit, config)?;
999 }
1000 _ => {
1001 Self::generate_random_circuit(&mut circuit, config)?;
1003 }
1004 }
1005
1006 Ok(circuit)
1007 }
1008
1009 fn generate_random_circuit(
1011 circuit: &mut InterfaceCircuit,
1012 config: &QuantumReservoirConfig,
1013 ) -> Result<()> {
1014 let depth = config.evolution_steps;
1015
1016 for _ in 0..depth {
1017 for qubit in 0..config.num_qubits {
1019 let angle = fastrand::f64() * 2.0 * PI;
1020 let gate_type = match fastrand::usize(0..3) {
1021 0 => InterfaceGateType::RX(angle),
1022 1 => InterfaceGateType::RY(angle),
1023 _ => InterfaceGateType::RZ(angle),
1024 };
1025 circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1026 }
1027
1028 for _ in 0..(config.num_qubits / 2) {
1030 let qubit1 = fastrand::usize(0..config.num_qubits);
1031 let qubit2 = fastrand::usize(0..config.num_qubits);
1032 if qubit1 != qubit2 {
1033 circuit.add_gate(InterfaceGate::new(
1034 InterfaceGateType::CNOT,
1035 vec![qubit1, qubit2],
1036 ));
1037 }
1038 }
1039 }
1040
1041 Ok(())
1042 }
1043
1044 fn generate_spin_chain_circuit(
1046 circuit: &mut InterfaceCircuit,
1047 config: &QuantumReservoirConfig,
1048 ) -> Result<()> {
1049 let coupling = config.coupling_strength;
1050
1051 for _ in 0..config.evolution_steps {
1052 for i in 0..config.num_qubits - 1 {
1054 circuit.add_gate(InterfaceGate::new(
1056 InterfaceGateType::RZ(coupling * config.time_step),
1057 vec![i],
1058 ));
1059 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1060 circuit.add_gate(InterfaceGate::new(
1061 InterfaceGateType::RZ(coupling * config.time_step),
1062 vec![i + 1],
1063 ));
1064 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1065 }
1066 }
1067
1068 Ok(())
1069 }
1070
1071 fn generate_tfim_circuit(
1073 circuit: &mut InterfaceCircuit,
1074 config: &QuantumReservoirConfig,
1075 ) -> Result<()> {
1076 let coupling = config.coupling_strength;
1077 let field = coupling * 0.5; for _ in 0..config.evolution_steps {
1080 for qubit in 0..config.num_qubits {
1082 circuit.add_gate(InterfaceGate::new(
1083 InterfaceGateType::RX(field * config.time_step),
1084 vec![qubit],
1085 ));
1086 }
1087
1088 for i in 0..config.num_qubits - 1 {
1090 circuit.add_gate(InterfaceGate::new(
1091 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1092 vec![i],
1093 ));
1094 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1095 circuit.add_gate(InterfaceGate::new(
1096 InterfaceGateType::RZ(coupling * config.time_step),
1097 vec![i + 1],
1098 ));
1099 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, i + 1]));
1100 circuit.add_gate(InterfaceGate::new(
1101 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1102 vec![i],
1103 ));
1104 }
1105 }
1106
1107 Ok(())
1108 }
1109
1110 fn generate_small_world_circuit(
1112 circuit: &mut InterfaceCircuit,
1113 config: &QuantumReservoirConfig,
1114 ) -> Result<()> {
1115 let coupling = config.coupling_strength;
1116 let rewiring_prob = 0.1; for _ in 0..config.evolution_steps {
1119 for i in 0..config.num_qubits {
1121 let next = (i + 1) % config.num_qubits;
1122
1123 let target = if fastrand::f64() < rewiring_prob {
1125 fastrand::usize(0..config.num_qubits)
1126 } else {
1127 next
1128 };
1129
1130 if target != i {
1131 circuit.add_gate(InterfaceGate::new(
1132 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1133 vec![i],
1134 ));
1135 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, target]));
1136 circuit.add_gate(InterfaceGate::new(
1137 InterfaceGateType::RZ(coupling * config.time_step),
1138 vec![target],
1139 ));
1140 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, target]));
1141 circuit.add_gate(InterfaceGate::new(
1142 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1143 vec![i],
1144 ));
1145 }
1146 }
1147 }
1148
1149 Ok(())
1150 }
1151
1152 fn generate_fully_connected_circuit(
1154 circuit: &mut InterfaceCircuit,
1155 config: &QuantumReservoirConfig,
1156 ) -> Result<()> {
1157 let coupling = config.coupling_strength / config.num_qubits as f64; for _ in 0..config.evolution_steps {
1160 for i in 0..config.num_qubits {
1162 for j in i + 1..config.num_qubits {
1163 circuit.add_gate(InterfaceGate::new(
1164 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1165 vec![i],
1166 ));
1167 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1168 circuit.add_gate(InterfaceGate::new(
1169 InterfaceGateType::RZ(coupling * config.time_step),
1170 vec![j],
1171 ));
1172 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1173 circuit.add_gate(InterfaceGate::new(
1174 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1175 vec![i],
1176 ));
1177 }
1178 }
1179 }
1180
1181 Ok(())
1182 }
1183
1184 fn generate_scale_free_circuit(
1186 circuit: &mut InterfaceCircuit,
1187 config: &QuantumReservoirConfig,
1188 ) -> Result<()> {
1189 let mut degree_dist = vec![1; config.num_qubits];
1191 let coupling = config.coupling_strength;
1192
1193 for _ in 0..config.evolution_steps {
1194 for i in 0..config.num_qubits {
1196 let total_degree: usize = degree_dist.iter().sum();
1198 let prob_threshold = degree_dist[i] as f64 / total_degree as f64;
1199
1200 if fastrand::f64() < prob_threshold {
1201 let j = fastrand::usize(0..config.num_qubits);
1202 if i != j {
1203 circuit.add_gate(InterfaceGate::new(
1205 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1206 vec![i],
1207 ));
1208 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1209 circuit.add_gate(InterfaceGate::new(
1210 InterfaceGateType::RZ(coupling * config.time_step),
1211 vec![j],
1212 ));
1213 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1214
1215 degree_dist[i] += 1;
1217 degree_dist[j] += 1;
1218 }
1219 }
1220 }
1221 }
1222
1223 Ok(())
1224 }
1225
1226 fn generate_hierarchical_circuit(
1228 circuit: &mut InterfaceCircuit,
1229 config: &QuantumReservoirConfig,
1230 ) -> Result<()> {
1231 let coupling = config.coupling_strength;
1232 let module_size = (config.num_qubits as f64).sqrt() as usize;
1233
1234 for _ in 0..config.evolution_steps {
1235 for module in 0..(config.num_qubits / module_size) {
1237 let start = module * module_size;
1238 let end = ((module + 1) * module_size).min(config.num_qubits);
1239
1240 for i in start..end {
1241 for j in (i + 1)..end {
1242 circuit.add_gate(InterfaceGate::new(
1243 InterfaceGateType::RZ(coupling * config.time_step),
1244 vec![i],
1245 ));
1246 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1247 }
1248 }
1249 }
1250
1251 for i in 0..config.num_qubits {
1253 let j = fastrand::usize(0..config.num_qubits);
1254 if i / module_size != j / module_size && i != j {
1255 circuit.add_gate(InterfaceGate::new(
1256 InterfaceGateType::RZ(coupling * config.time_step * 0.3),
1257 vec![i],
1258 ));
1259 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1260 }
1261 }
1262 }
1263
1264 Ok(())
1265 }
1266
1267 fn generate_ring_circuit(
1269 circuit: &mut InterfaceCircuit,
1270 config: &QuantumReservoirConfig,
1271 ) -> Result<()> {
1272 let coupling = config.coupling_strength;
1273
1274 for _ in 0..config.evolution_steps {
1275 for i in 0..config.num_qubits {
1277 let j = (i + 1) % config.num_qubits;
1278
1279 circuit.add_gate(InterfaceGate::new(
1280 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1281 vec![i],
1282 ));
1283 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1284 circuit.add_gate(InterfaceGate::new(
1285 InterfaceGateType::RZ(coupling * config.time_step),
1286 vec![j],
1287 ));
1288 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1289 }
1290
1291 if fastrand::f64() < 0.1 {
1293 let i = fastrand::usize(0..config.num_qubits);
1294 let j = fastrand::usize(0..config.num_qubits);
1295 if i != j && (i as i32 - j as i32).abs() > 2 {
1296 circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![i, j]));
1297 }
1298 }
1299 }
1300
1301 Ok(())
1302 }
1303
1304 fn generate_grid_circuit(
1306 circuit: &mut InterfaceCircuit,
1307 config: &QuantumReservoirConfig,
1308 ) -> Result<()> {
1309 let coupling = config.coupling_strength;
1310 let grid_size = (config.num_qubits as f64).sqrt() as usize;
1311
1312 for _ in 0..config.evolution_steps {
1313 for i in 0..grid_size {
1315 for j in 0..grid_size {
1316 let current = i * grid_size + j;
1317 if current >= config.num_qubits {
1318 break;
1319 }
1320
1321 if j + 1 < grid_size {
1323 let neighbor = i * grid_size + j + 1;
1324 if neighbor < config.num_qubits {
1325 circuit.add_gate(InterfaceGate::new(
1326 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1327 vec![current],
1328 ));
1329 circuit.add_gate(InterfaceGate::new(
1330 InterfaceGateType::CNOT,
1331 vec![current, neighbor],
1332 ));
1333 }
1334 }
1335
1336 if i + 1 < grid_size {
1338 let neighbor = (i + 1) * grid_size + j;
1339 if neighbor < config.num_qubits {
1340 circuit.add_gate(InterfaceGate::new(
1341 InterfaceGateType::RZ(coupling * config.time_step / 2.0),
1342 vec![current],
1343 ));
1344 circuit.add_gate(InterfaceGate::new(
1345 InterfaceGateType::CNOT,
1346 vec![current, neighbor],
1347 ));
1348 }
1349 }
1350 }
1351 }
1352 }
1353
1354 Ok(())
1355 }
1356
1357 fn generate_input_coupling_circuit(
1359 config: &QuantumReservoirConfig,
1360 ) -> Result<InterfaceCircuit> {
1361 let mut circuit = InterfaceCircuit::new(config.num_qubits, 0);
1362
1363 match config.input_encoding {
1364 InputEncoding::Amplitude => {
1365 for qubit in 0..config.num_qubits {
1367 circuit.add_gate(InterfaceGate::new(
1368 InterfaceGateType::RY(0.0), vec![qubit],
1370 ));
1371 }
1372 }
1373 InputEncoding::Phase => {
1374 for qubit in 0..config.num_qubits {
1376 circuit.add_gate(InterfaceGate::new(
1377 InterfaceGateType::RZ(0.0), vec![qubit],
1379 ));
1380 }
1381 }
1382 InputEncoding::BasisState => {
1383 for qubit in 0..config.num_qubits {
1385 circuit.add_gate(InterfaceGate::new(InterfaceGateType::X, vec![qubit]));
1386 }
1387 }
1388 InputEncoding::Angle => {
1389 for qubit in 0..config.num_qubits {
1391 circuit.add_gate(InterfaceGate::new(InterfaceGateType::RX(0.0), vec![qubit]));
1392 circuit.add_gate(InterfaceGate::new(InterfaceGateType::RY(0.0), vec![qubit]));
1393 }
1394 }
1395 _ => {
1396 for qubit in 0..config.num_qubits {
1398 circuit.add_gate(InterfaceGate::new(InterfaceGateType::RY(0.0), vec![qubit]));
1399 }
1400 }
1401 }
1402
1403 Ok(circuit)
1404 }
1405
1406 const fn calculate_output_size(config: &QuantumReservoirConfig) -> usize {
1408 1
1410 }
1411
1412 fn calculate_feature_size(config: &QuantumReservoirConfig) -> usize {
1414 match config.output_measurement {
1415 OutputMeasurement::PauliExpectation => config.num_qubits * 3,
1416 OutputMeasurement::Probability => 1 << config.num_qubits.min(10), OutputMeasurement::Correlations => config.num_qubits * config.num_qubits,
1418 OutputMeasurement::Entanglement => config.num_qubits,
1419 OutputMeasurement::Fidelity => 1,
1420 OutputMeasurement::QuantumFisherInformation => config.num_qubits,
1421 OutputMeasurement::Variance => config.num_qubits * 3,
1422 OutputMeasurement::HigherOrderMoments => config.num_qubits * 6, OutputMeasurement::SpectralProperties => config.num_qubits,
1424 OutputMeasurement::QuantumCoherence => config.num_qubits,
1425 OutputMeasurement::Purity => 1,
1426 OutputMeasurement::QuantumMutualInformation => config.num_qubits * config.num_qubits,
1427 OutputMeasurement::ProcessTomography => config.num_qubits * config.num_qubits * 4,
1428 OutputMeasurement::TemporalCorrelations => config.memory_capacity,
1429 OutputMeasurement::NonLinearReadout => config.num_qubits * 2,
1430 }
1431 }
1432
1433 pub fn process_input(&mut self, input: &Array1<f64>) -> Result<Array1<f64>> {
1435 let start_time = std::time::Instant::now();
1436
1437 self.encode_input(input)?;
1439
1440 self.evolve_reservoir()?;
1442
1443 let features = self.extract_features()?;
1445
1446 let timestamp = start_time.elapsed().as_secs_f64();
1448 self.reservoir_state
1449 .update_state(self.reservoir_state.state_vector.clone(), timestamp);
1450
1451 let processing_time = start_time.elapsed().as_secs_f64() * 1000.0;
1453 self.update_processing_time(processing_time);
1454
1455 Ok(features)
1456 }
1457
1458 fn encode_input(&mut self, input: &Array1<f64>) -> Result<()> {
1460 match self.config.input_encoding {
1461 InputEncoding::Amplitude => {
1462 self.encode_amplitude(input)?;
1463 }
1464 InputEncoding::Phase => {
1465 self.encode_phase(input)?;
1466 }
1467 InputEncoding::BasisState => {
1468 self.encode_basis_state(input)?;
1469 }
1470 InputEncoding::Angle => {
1471 self.encode_angle(input)?;
1472 }
1473 _ => {
1474 self.encode_amplitude(input)?;
1475 }
1476 }
1477 Ok(())
1478 }
1479
1480 fn encode_amplitude(&mut self, input: &Array1<f64>) -> Result<()> {
1482 let num_inputs = input.len().min(self.config.num_qubits);
1483
1484 for i in 0..num_inputs {
1485 let angle = input[i] * PI; self.apply_single_qubit_rotation(i, InterfaceGateType::RY(angle))?;
1487 }
1488
1489 Ok(())
1490 }
1491
1492 fn encode_phase(&mut self, input: &Array1<f64>) -> Result<()> {
1494 let num_inputs = input.len().min(self.config.num_qubits);
1495
1496 for i in 0..num_inputs {
1497 let angle = input[i] * 2.0 * PI; self.apply_single_qubit_rotation(i, InterfaceGateType::RZ(angle))?;
1499 }
1500
1501 Ok(())
1502 }
1503
1504 fn encode_basis_state(&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 if input[i] > 0.5 {
1510 self.apply_single_qubit_gate(i, InterfaceGateType::X)?;
1511 }
1512 }
1513
1514 Ok(())
1515 }
1516
1517 fn encode_angle(&mut self, input: &Array1<f64>) -> Result<()> {
1519 let num_inputs = input.len().min(self.config.num_qubits);
1520
1521 for i in 0..num_inputs {
1522 let angle_x = input[i] * PI;
1523 let angle_y = if i + 1 < input.len() {
1524 input[i + 1] * PI
1525 } else {
1526 0.0
1527 };
1528
1529 self.apply_single_qubit_rotation(i, InterfaceGateType::RX(angle_x))?;
1530 self.apply_single_qubit_rotation(i, InterfaceGateType::RY(angle_y))?;
1531 }
1532
1533 Ok(())
1534 }
1535
1536 fn apply_single_qubit_rotation(
1538 &mut self,
1539 qubit: usize,
1540 gate_type: InterfaceGateType,
1541 ) -> Result<()> {
1542 let mut temp_circuit = InterfaceCircuit::new(self.config.num_qubits, 0);
1543 temp_circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1544
1545 self.simulator.apply_interface_circuit(&temp_circuit)?;
1546
1547 Ok(())
1548 }
1549
1550 fn apply_single_qubit_gate(
1552 &mut self,
1553 qubit: usize,
1554 gate_type: InterfaceGateType,
1555 ) -> Result<()> {
1556 let mut temp_circuit = InterfaceCircuit::new(self.config.num_qubits, 0);
1557 temp_circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1558
1559 self.simulator.apply_interface_circuit(&temp_circuit)?;
1560
1561 Ok(())
1562 }
1563
1564 fn evolve_reservoir(&mut self) -> Result<()> {
1566 match self.config.dynamics {
1567 ReservoirDynamics::Unitary => {
1568 self.evolve_unitary()?;
1569 }
1570 ReservoirDynamics::Open => {
1571 self.evolve_open_system()?;
1572 }
1573 ReservoirDynamics::NISQ => {
1574 self.evolve_nisq()?;
1575 }
1576 ReservoirDynamics::Adiabatic => {
1577 self.evolve_adiabatic()?;
1578 }
1579 ReservoirDynamics::Floquet => {
1580 self.evolve_floquet()?;
1581 }
1582 _ => {
1583 self.evolve_unitary()?;
1585 }
1586 }
1587 Ok(())
1588 }
1589
1590 fn evolve_unitary(&mut self) -> Result<()> {
1592 self.simulator
1593 .apply_interface_circuit(&self.reservoir_circuit)?;
1594 Ok(())
1595 }
1596
1597 fn evolve_open_system(&mut self) -> Result<()> {
1599 self.evolve_unitary()?;
1601
1602 self.apply_decoherence()?;
1604
1605 Ok(())
1606 }
1607
1608 fn evolve_nisq(&mut self) -> Result<()> {
1610 self.evolve_unitary()?;
1612
1613 self.apply_gate_errors()?;
1615
1616 self.apply_measurement_errors()?;
1618
1619 Ok(())
1620 }
1621
1622 fn evolve_adiabatic(&mut self) -> Result<()> {
1624 self.evolve_unitary()?;
1627 Ok(())
1628 }
1629
1630 fn evolve_floquet(&mut self) -> Result<()> {
1632 let drive_frequency = 1.0;
1634 let time = self.reservoir_state.time_index as f64 * self.config.time_step;
1635 let drive_strength = (drive_frequency * time).sin();
1636
1637 for qubit in 0..self.config.num_qubits {
1639 let angle = drive_strength * self.config.time_step;
1640 self.apply_single_qubit_rotation(qubit, InterfaceGateType::RX(angle))?;
1641 }
1642
1643 self.evolve_unitary()?;
1645
1646 Ok(())
1647 }
1648
1649 fn apply_decoherence(&mut self) -> Result<()> {
1651 let decoherence_rate = self.config.noise_level;
1652
1653 for amplitude in &mut self.reservoir_state.state_vector {
1654 let phase_noise = (fastrand::f64() - 0.5) * decoherence_rate * 2.0 * PI;
1656 *amplitude *= Complex64::new(0.0, phase_noise).exp();
1657
1658 let damping = (1.0 - decoherence_rate).sqrt();
1660 *amplitude *= damping;
1661 }
1662
1663 let norm: f64 = self
1665 .reservoir_state
1666 .state_vector
1667 .iter()
1668 .map(scirs2_core::Complex::norm_sqr)
1669 .sum::<f64>()
1670 .sqrt();
1671
1672 if norm > 1e-15 {
1673 self.reservoir_state.state_vector.mapv_inplace(|x| x / norm);
1674 }
1675
1676 Ok(())
1677 }
1678
1679 fn apply_gate_errors(&mut self) -> Result<()> {
1681 let error_rate = self.config.noise_level;
1682
1683 for qubit in 0..self.config.num_qubits {
1684 if fastrand::f64() < error_rate {
1685 let error_type = fastrand::usize(0..3);
1686 let gate_type = match error_type {
1687 0 => InterfaceGateType::X,
1688 1 => InterfaceGateType::PauliY,
1689 _ => InterfaceGateType::PauliZ,
1690 };
1691 self.apply_single_qubit_gate(qubit, gate_type)?;
1692 }
1693 }
1694
1695 Ok(())
1696 }
1697
1698 fn apply_measurement_errors(&mut self) -> Result<()> {
1700 let error_rate = self.config.noise_level * 0.1; if fastrand::f64() < error_rate {
1703 let qubit = fastrand::usize(0..self.config.num_qubits);
1704 self.apply_single_qubit_gate(qubit, InterfaceGateType::X)?;
1705 }
1706
1707 Ok(())
1708 }
1709
1710 fn extract_features(&mut self) -> Result<Array1<f64>> {
1712 match self.config.output_measurement {
1713 OutputMeasurement::PauliExpectation => self.measure_pauli_expectations(),
1714 OutputMeasurement::Probability => self.measure_probabilities(),
1715 OutputMeasurement::Correlations => self.measure_correlations(),
1716 OutputMeasurement::Entanglement => self.measure_entanglement(),
1717 OutputMeasurement::Fidelity => self.measure_fidelity(),
1718 OutputMeasurement::QuantumFisherInformation => {
1719 self.measure_quantum_fisher_information()
1720 }
1721 OutputMeasurement::Variance => self.measure_variance(),
1722 OutputMeasurement::HigherOrderMoments => self.measure_higher_order_moments(),
1723 OutputMeasurement::QuantumCoherence => self.measure_quantum_coherence(),
1724 OutputMeasurement::Purity => self.measure_purity(),
1725 OutputMeasurement::TemporalCorrelations => self.measure_temporal_correlations(),
1726 _ => {
1727 self.measure_pauli_expectations()
1729 }
1730 }
1731 }
1732
1733 fn measure_pauli_expectations(&self) -> Result<Array1<f64>> {
1735 let mut expectations = Vec::new();
1736
1737 for qubit in 0..self.config.num_qubits {
1738 let x_exp = self.calculate_single_qubit_expectation(
1740 qubit,
1741 &[
1742 Complex64::new(0.0, 0.0),
1743 Complex64::new(1.0, 0.0),
1744 Complex64::new(1.0, 0.0),
1745 Complex64::new(0.0, 0.0),
1746 ],
1747 )?;
1748 expectations.push(x_exp);
1749
1750 let y_exp = self.calculate_single_qubit_expectation(
1752 qubit,
1753 &[
1754 Complex64::new(0.0, 0.0),
1755 Complex64::new(0.0, -1.0),
1756 Complex64::new(0.0, 1.0),
1757 Complex64::new(0.0, 0.0),
1758 ],
1759 )?;
1760 expectations.push(y_exp);
1761
1762 let z_exp = self.calculate_single_qubit_expectation(
1764 qubit,
1765 &[
1766 Complex64::new(1.0, 0.0),
1767 Complex64::new(0.0, 0.0),
1768 Complex64::new(0.0, 0.0),
1769 Complex64::new(-1.0, 0.0),
1770 ],
1771 )?;
1772 expectations.push(z_exp);
1773 }
1774
1775 Ok(Array1::from_vec(expectations))
1776 }
1777
1778 fn calculate_single_qubit_expectation(
1780 &self,
1781 qubit: usize,
1782 pauli_matrix: &[Complex64; 4],
1783 ) -> Result<f64> {
1784 let state = &self.reservoir_state.state_vector;
1785 let mut expectation = 0.0;
1786
1787 for i in 0..state.len() {
1788 for j in 0..state.len() {
1789 let i_bit = (i >> qubit) & 1;
1790 let j_bit = (j >> qubit) & 1;
1791 let matrix_element = pauli_matrix[i_bit * 2 + j_bit];
1792
1793 expectation += (state[i].conj() * matrix_element * state[j]).re;
1794 }
1795 }
1796
1797 Ok(expectation)
1798 }
1799
1800 fn measure_probabilities(&self) -> Result<Array1<f64>> {
1802 let probabilities: Vec<f64> = self
1803 .reservoir_state
1804 .state_vector
1805 .iter()
1806 .map(scirs2_core::Complex::norm_sqr)
1807 .collect();
1808
1809 let max_size = 1 << 10; if probabilities.len() > max_size {
1812 let mut sampled = Vec::with_capacity(max_size);
1814 for _ in 0..max_size {
1815 let idx = fastrand::usize(0..probabilities.len());
1816 sampled.push(probabilities[idx]);
1817 }
1818 Ok(Array1::from_vec(sampled))
1819 } else {
1820 Ok(Array1::from_vec(probabilities))
1821 }
1822 }
1823
1824 fn measure_correlations(&mut self) -> Result<Array1<f64>> {
1826 let mut correlations = Vec::new();
1827
1828 for i in 0..self.config.num_qubits {
1829 for j in 0..self.config.num_qubits {
1830 if i == j {
1831 correlations.push(1.0); self.reservoir_state.correlations[[i, j]] = 1.0;
1833 } else {
1834 let corr = self.calculate_two_qubit_correlation(i, j)?;
1836 correlations.push(corr);
1837 self.reservoir_state.correlations[[i, j]] = corr;
1838 }
1839 }
1840 }
1841
1842 Ok(Array1::from_vec(correlations))
1843 }
1844
1845 fn calculate_two_qubit_correlation(&self, qubit1: usize, qubit2: usize) -> Result<f64> {
1847 let state = &self.reservoir_state.state_vector;
1848 let mut correlation = 0.0;
1849
1850 for i in 0..state.len() {
1851 let bit1 = (i >> qubit1) & 1;
1852 let bit2 = (i >> qubit2) & 1;
1853 let sign = if bit1 == bit2 { 1.0 } else { -1.0 };
1854 correlation += sign * state[i].norm_sqr();
1855 }
1856
1857 Ok(correlation)
1858 }
1859
1860 fn measure_entanglement(&self) -> Result<Array1<f64>> {
1862 let mut entanglement_measures = Vec::new();
1863
1864 for qubit in 0..self.config.num_qubits {
1866 let entropy = self.calculate_von_neumann_entropy(qubit)?;
1868 entanglement_measures.push(entropy);
1869 }
1870
1871 Ok(Array1::from_vec(entanglement_measures))
1872 }
1873
1874 fn calculate_von_neumann_entropy(&self, _qubit: usize) -> Result<f64> {
1876 let state = &self.reservoir_state.state_vector;
1877 let mut entropy = 0.0;
1878
1879 for amplitude in state {
1880 let prob = amplitude.norm_sqr();
1881 if prob > 1e-15 {
1882 entropy -= prob * prob.ln();
1883 }
1884 }
1885
1886 Ok(entropy / (state.len() as f64).ln()) }
1888
1889 fn measure_fidelity(&self) -> Result<Array1<f64>> {
1891 let fidelity = self.reservoir_state.state_vector[0].norm_sqr();
1893 Ok(Array1::from_vec(vec![fidelity]))
1894 }
1895
1896 fn measure_quantum_fisher_information(&self) -> Result<Array1<f64>> {
1898 let mut qfi_values = Vec::new();
1899
1900 for qubit in 0..self.config.num_qubits {
1901 let z_exp = self.calculate_single_qubit_expectation(
1903 qubit,
1904 &[
1905 Complex64::new(1.0, 0.0),
1906 Complex64::new(0.0, 0.0),
1907 Complex64::new(0.0, 0.0),
1908 Complex64::new(-1.0, 0.0),
1909 ],
1910 )?;
1911
1912 let qfi = 4.0 * (1.0 - z_exp * z_exp);
1914 qfi_values.push(qfi);
1915 }
1916
1917 Ok(Array1::from_vec(qfi_values))
1918 }
1919
1920 fn measure_variance(&self) -> Result<Array1<f64>> {
1922 let mut variances = Vec::new();
1923
1924 for qubit in 0..self.config.num_qubits {
1925 for pauli_idx in 0..3 {
1927 let pauli_matrix = match pauli_idx {
1928 0 => [
1929 Complex64::new(0.0, 0.0),
1930 Complex64::new(1.0, 0.0),
1931 Complex64::new(1.0, 0.0),
1932 Complex64::new(0.0, 0.0),
1933 ],
1934 1 => [
1935 Complex64::new(0.0, 0.0),
1936 Complex64::new(0.0, -1.0),
1937 Complex64::new(0.0, 1.0),
1938 Complex64::new(0.0, 0.0),
1939 ],
1940 _ => [
1941 Complex64::new(1.0, 0.0),
1942 Complex64::new(0.0, 0.0),
1943 Complex64::new(0.0, 0.0),
1944 Complex64::new(-1.0, 0.0),
1945 ],
1946 };
1947
1948 let expectation = self.calculate_single_qubit_expectation(qubit, &pauli_matrix)?;
1949 let variance = 1.0 - expectation * expectation; variances.push(variance);
1951 }
1952 }
1953
1954 Ok(Array1::from_vec(variances))
1955 }
1956
1957 fn measure_higher_order_moments(&self) -> Result<Array1<f64>> {
1959 let mut moments = Vec::new();
1960
1961 for qubit in 0..self.config.num_qubits {
1962 let z_exp = self.calculate_single_qubit_expectation(
1964 qubit,
1965 &[
1966 Complex64::new(1.0, 0.0),
1967 Complex64::new(0.0, 0.0),
1968 Complex64::new(0.0, 0.0),
1969 Complex64::new(-1.0, 0.0),
1970 ],
1971 )?;
1972
1973 moments.push(z_exp);
1975
1976 let variance = 1.0 - z_exp * z_exp;
1978 moments.push(variance);
1979
1980 moments.push(0.0);
1983
1984 moments.push(variance * variance);
1986
1987 moments.push(z_exp * variance);
1989
1990 moments.push(variance * variance * variance);
1992 }
1993
1994 Ok(Array1::from_vec(moments))
1995 }
1996
1997 fn measure_quantum_coherence(&self) -> Result<Array1<f64>> {
1999 let mut coherence_measures = Vec::new();
2000
2001 for qubit in 0..self.config.num_qubits {
2002 let mut coherence = 0.0;
2004 let state = &self.reservoir_state.state_vector;
2005
2006 for i in 0..state.len() {
2007 for j in 0..state.len() {
2008 if i != j {
2009 let i_bit = (i >> qubit) & 1;
2010 let j_bit = (j >> qubit) & 1;
2011 if i_bit != j_bit {
2012 coherence += (state[i].conj() * state[j]).norm();
2013 }
2014 }
2015 }
2016 }
2017
2018 coherence_measures.push(coherence);
2019 }
2020
2021 Ok(Array1::from_vec(coherence_measures))
2022 }
2023
2024 fn measure_purity(&self) -> Result<Array1<f64>> {
2026 let state = &self.reservoir_state.state_vector;
2028 let purity = state.iter().map(|x| x.norm_sqr().powi(2)).sum::<f64>();
2029
2030 Ok(Array1::from_vec(vec![purity]))
2031 }
2032
2033 fn measure_temporal_correlations(&self) -> Result<Array1<f64>> {
2035 let mut correlations = Vec::new();
2036
2037 let current_state = &self.reservoir_state.state_vector;
2039
2040 for past_state in &self.reservoir_state.state_history {
2041 let correlation = current_state
2042 .iter()
2043 .zip(past_state.iter())
2044 .map(|(a, b)| (a.conj() * b).re)
2045 .sum::<f64>();
2046 correlations.push(correlation);
2047 }
2048
2049 while correlations.len() < self.config.memory_capacity {
2051 correlations.push(0.0);
2052 }
2053
2054 Ok(Array1::from_vec(correlations))
2055 }
2056
2057 pub fn train(&mut self, training_data: &ReservoirTrainingData) -> Result<TrainingResult> {
2059 let start_time = std::time::Instant::now();
2060
2061 let mut all_features = Vec::new();
2062 let mut all_targets = Vec::new();
2063
2064 for i in 0..self.config.washout_period.min(training_data.inputs.len()) {
2066 let _ = self.process_input(&training_data.inputs[i])?;
2067 }
2068
2069 for i in self.config.washout_period..training_data.inputs.len() {
2071 let features = self.process_input(&training_data.inputs[i])?;
2072 all_features.push(features);
2073
2074 if i < training_data.targets.len() {
2075 all_targets.push(training_data.targets[i].clone());
2076 }
2077 }
2078
2079 self.train_with_learning_algorithm(&all_features, &all_targets)?;
2081
2082 if self.config.memory_config.enable_capacity_estimation {
2084 self.analyze_memory_capacity(&all_features)?;
2085 }
2086
2087 let (training_error, test_error) =
2089 self.evaluate_performance(&all_features, &all_targets)?;
2090
2091 let training_time = start_time.elapsed().as_secs_f64() * 1000.0;
2092
2093 self.metrics.training_examples += all_features.len();
2095 self.metrics.generalization_error = test_error;
2096 self.metrics.memory_capacity = self.reservoir_state.memory_metrics.total_capacity;
2097
2098 Ok(TrainingResult {
2099 training_error,
2100 test_error,
2101 training_time_ms: training_time,
2102 num_examples: all_features.len(),
2103 echo_state_property: self.estimate_echo_state_property()?,
2104 memory_capacity: self.reservoir_state.memory_metrics.total_capacity,
2105 nonlinear_capacity: self.reservoir_state.memory_metrics.nonlinear_capacity,
2106 processing_capacity: self.reservoir_state.memory_metrics.processing_capacity,
2107 })
2108 }
2109
2110 fn train_with_learning_algorithm(
2112 &mut self,
2113 features: &[Array1<f64>],
2114 targets: &[Array1<f64>],
2115 ) -> Result<()> {
2116 match self.config.learning_config.algorithm {
2117 LearningAlgorithm::Ridge => {
2118 self.train_ridge_regression(features, targets)?;
2119 }
2120 LearningAlgorithm::LASSO => {
2121 self.train_lasso_regression(features, targets)?;
2122 }
2123 LearningAlgorithm::ElasticNet => {
2124 self.train_elastic_net(features, targets)?;
2125 }
2126 LearningAlgorithm::RecursiveLeastSquares => {
2127 self.train_recursive_least_squares(features, targets)?;
2128 }
2129 LearningAlgorithm::KalmanFilter => {
2130 self.train_kalman_filter(features, targets)?;
2131 }
2132 _ => {
2133 self.train_ridge_regression(features, targets)?;
2135 }
2136 }
2137
2138 Ok(())
2139 }
2140
2141 fn train_ridge_regression(
2143 &mut self,
2144 features: &[Array1<f64>],
2145 targets: &[Array1<f64>],
2146 ) -> Result<()> {
2147 if features.is_empty() || targets.is_empty() {
2148 return Ok(());
2149 }
2150
2151 let n_samples = features.len().min(targets.len());
2152 let n_features = features[0].len();
2153 let n_outputs = targets[0].len().min(self.output_weights.nrows());
2154
2155 let mut feature_matrix = Array2::zeros((n_samples, n_features));
2157 for (i, feature_vec) in features.iter().enumerate().take(n_samples) {
2158 for (j, &val) in feature_vec.iter().enumerate().take(n_features) {
2159 feature_matrix[[i, j]] = val;
2160 }
2161 }
2162
2163 let mut target_matrix = Array2::zeros((n_samples, n_outputs));
2165 for (i, target_vec) in targets.iter().enumerate().take(n_samples) {
2166 for (j, &val) in target_vec.iter().enumerate().take(n_outputs) {
2167 target_matrix[[i, j]] = val;
2168 }
2169 }
2170
2171 let lambda = self.config.learning_config.regularization;
2173
2174 let xtx = feature_matrix.t().dot(&feature_matrix);
2176
2177 let mut xtx_reg = xtx;
2179 for i in 0..xtx_reg.nrows().min(xtx_reg.ncols()) {
2180 xtx_reg[[i, i]] += lambda;
2181 }
2182
2183 let xty = feature_matrix.t().dot(&target_matrix);
2185
2186 self.solve_linear_system(&xtx_reg, &xty)?;
2188
2189 Ok(())
2190 }
2191
2192 fn train_lasso_regression(
2194 &mut self,
2195 features: &[Array1<f64>],
2196 targets: &[Array1<f64>],
2197 ) -> Result<()> {
2198 let lambda = self.config.learning_config.regularization;
2200 let max_iter = 100;
2201
2202 for _ in 0..max_iter {
2203 for j in 0..self.output_weights.ncols().min(features[0].len()) {
2205 for i in 0..self.output_weights.nrows().min(targets[0].len()) {
2206 let old_weight = self.output_weights[[i, j]];
2208 let gradient = self.compute_lasso_gradient(features, targets, i, j)?;
2209 let update = 0.01f64.mul_add(-gradient, old_weight);
2210
2211 self.output_weights[[i, j]] = if update > lambda {
2213 update - lambda
2214 } else if update < -lambda {
2215 update + lambda
2216 } else {
2217 0.0
2218 };
2219 }
2220 }
2221 }
2222
2223 Ok(())
2224 }
2225
2226 fn compute_lasso_gradient(
2228 &self,
2229 features: &[Array1<f64>],
2230 targets: &[Array1<f64>],
2231 output_idx: usize,
2232 feature_idx: usize,
2233 ) -> Result<f64> {
2234 let mut gradient = 0.0;
2235
2236 for (feature_vec, target_vec) in features.iter().zip(targets.iter()) {
2237 if feature_idx < feature_vec.len() && output_idx < target_vec.len() {
2238 let prediction = self.predict_single_output(feature_vec, output_idx)?;
2239 let error = prediction - target_vec[output_idx];
2240 gradient += error * feature_vec[feature_idx];
2241 }
2242 }
2243
2244 gradient /= features.len() as f64;
2245 Ok(gradient)
2246 }
2247
2248 fn train_elastic_net(
2250 &mut self,
2251 features: &[Array1<f64>],
2252 targets: &[Array1<f64>],
2253 ) -> Result<()> {
2254 let l1_ratio = self.config.learning_config.l1_ratio;
2255
2256 if l1_ratio > 0.5 {
2258 self.train_lasso_regression(features, targets)?;
2260 } else {
2261 self.train_ridge_regression(features, targets)?;
2263 }
2264
2265 Ok(())
2266 }
2267
2268 fn train_recursive_least_squares(
2270 &mut self,
2271 features: &[Array1<f64>],
2272 targets: &[Array1<f64>],
2273 ) -> Result<()> {
2274 let forgetting_factor = self.config.learning_config.forgetting_factor;
2275 let n_features = features[0].len().min(self.output_weights.ncols());
2276 let n_outputs = targets[0].len().min(self.output_weights.nrows());
2277
2278 let mut p_matrix = Array2::eye(n_features) * 1000.0; for (feature_vec, target_vec) in features.iter().zip(targets.iter()) {
2283 let x = feature_vec.slice(s![..n_features]).to_owned();
2284 let y = target_vec.slice(s![..n_outputs]).to_owned();
2285
2286 let px = p_matrix.dot(&x);
2288 let denominator = forgetting_factor + x.dot(&px);
2289
2290 if denominator > 1e-15 {
2291 let k = &px / denominator;
2292
2293 for output_idx in 0..n_outputs {
2295 let prediction = self.predict_single_output(feature_vec, output_idx)?;
2296 let error = y[output_idx] - prediction;
2297
2298 for feature_idx in 0..n_features {
2300 self.output_weights[[output_idx, feature_idx]] += k[feature_idx] * error;
2301 }
2302 }
2303
2304 let outer_product = k
2306 .view()
2307 .insert_axis(Axis(1))
2308 .dot(&x.view().insert_axis(Axis(0)));
2309 p_matrix = (p_matrix - outer_product) / forgetting_factor;
2310 }
2311 }
2312
2313 Ok(())
2314 }
2315
2316 fn train_kalman_filter(
2318 &mut self,
2319 features: &[Array1<f64>],
2320 targets: &[Array1<f64>],
2321 ) -> Result<()> {
2322 let process_noise = self.config.learning_config.process_noise;
2323 let measurement_noise = self.config.learning_config.measurement_noise;
2324
2325 let n_features = features[0].len().min(self.output_weights.ncols());
2326 let n_outputs = targets[0].len().min(self.output_weights.nrows());
2327
2328 let mut state_covariance = Array2::eye(n_features) * 1.0;
2330 let process_noise_matrix: Array2<f64> = Array2::eye(n_features) * process_noise;
2331 let measurement_noise_scalar = measurement_noise;
2332
2333 for (feature_vec, target_vec) in features.iter().zip(targets.iter()) {
2335 let x = feature_vec.slice(s![..n_features]).to_owned();
2336 let y = target_vec.slice(s![..n_outputs]).to_owned();
2337
2338 let predicted_covariance = &state_covariance + &process_noise_matrix;
2340
2341 for output_idx in 0..n_outputs {
2343 let measurement = y[output_idx];
2344 let prediction = self.predict_single_output(feature_vec, output_idx)?;
2345
2346 let s = x.dot(&predicted_covariance.dot(&x)) + measurement_noise_scalar;
2348 if s > 1e-15 {
2349 let k = predicted_covariance.dot(&x) / s;
2350
2351 let innovation = measurement - prediction;
2353 for feature_idx in 0..n_features {
2354 self.output_weights[[output_idx, feature_idx]] +=
2355 k[feature_idx] * innovation;
2356 }
2357
2358 let kh = k
2360 .view()
2361 .insert_axis(Axis(1))
2362 .dot(&x.view().insert_axis(Axis(0)));
2363 state_covariance = &predicted_covariance - &kh.dot(&predicted_covariance);
2364 }
2365 }
2366 }
2367
2368 Ok(())
2369 }
2370
2371 fn predict_single_output(&self, features: &Array1<f64>, output_idx: usize) -> Result<f64> {
2373 let feature_size = features.len().min(self.output_weights.ncols());
2374 let mut output = 0.0;
2375
2376 for j in 0..feature_size {
2377 output += self.output_weights[[output_idx, j]] * features[j];
2378 }
2379
2380 Ok(output)
2381 }
2382
2383 fn analyze_memory_capacity(&mut self, features: &[Array1<f64>]) -> Result<()> {
2385 let linear_capacity = self.estimate_linear_memory_capacity(features)?;
2387 self.reservoir_state.memory_metrics.linear_capacity = linear_capacity;
2388
2389 if self.config.memory_config.enable_nonlinear {
2391 let nonlinear_capacity = self.estimate_nonlinear_memory_capacity(features)?;
2392 self.reservoir_state.memory_metrics.nonlinear_capacity = nonlinear_capacity;
2393 }
2394
2395 self.reservoir_state.memory_metrics.total_capacity =
2397 self.reservoir_state.memory_metrics.linear_capacity
2398 + self.reservoir_state.memory_metrics.nonlinear_capacity;
2399
2400 if self.config.memory_config.enable_ipc {
2402 let ipc = self.estimate_information_processing_capacity(features)?;
2403 self.reservoir_state.memory_metrics.processing_capacity = ipc;
2404 }
2405
2406 self.memory_analyzer.capacity_estimates.insert(
2408 "linear".to_string(),
2409 self.reservoir_state.memory_metrics.linear_capacity,
2410 );
2411 self.memory_analyzer.capacity_estimates.insert(
2412 "nonlinear".to_string(),
2413 self.reservoir_state.memory_metrics.nonlinear_capacity,
2414 );
2415 self.memory_analyzer.capacity_estimates.insert(
2416 "total".to_string(),
2417 self.reservoir_state.memory_metrics.total_capacity,
2418 );
2419
2420 Ok(())
2421 }
2422
2423 fn estimate_linear_memory_capacity(&self, features: &[Array1<f64>]) -> Result<f64> {
2425 let mut capacity = 0.0;
2427
2428 for lag in 1..=20 {
2429 if lag < features.len() {
2430 let mut correlation = 0.0;
2431 let mut count = 0;
2432
2433 for i in lag..features.len() {
2434 for j in 0..features[i].len().min(features[i - lag].len()) {
2435 correlation += features[i][j] * features[i - lag][j];
2436 count += 1;
2437 }
2438 }
2439
2440 if count > 0 {
2441 correlation /= f64::from(count);
2442 capacity += correlation.abs();
2443 }
2444 }
2445 }
2446
2447 Ok(capacity)
2448 }
2449
2450 fn estimate_nonlinear_memory_capacity(&self, features: &[Array1<f64>]) -> Result<f64> {
2452 let mut nonlinear_capacity = 0.0;
2453
2454 for order in &self.config.memory_config.nonlinearity_orders {
2456 let capacity_order = self.test_nonlinear_order(*order, features)?;
2457 nonlinear_capacity += capacity_order;
2458 }
2459
2460 Ok(nonlinear_capacity)
2461 }
2462
2463 fn test_nonlinear_order(&self, order: usize, features: &[Array1<f64>]) -> Result<f64> {
2465 let mut capacity = 0.0;
2466
2467 for lag in 1..=10 {
2469 if lag < features.len() {
2470 let mut correlation = 0.0;
2471 let mut count = 0;
2472
2473 for i in lag..features.len() {
2474 for j in 0..features[i].len().min(features[i - lag].len()) {
2475 let current = features[i][j];
2477 let past = features[i - lag][j];
2478 let nonlinear_target = past.powi(order as i32);
2479
2480 correlation += current * nonlinear_target;
2481 count += 1;
2482 }
2483 }
2484
2485 if count > 0 {
2486 correlation /= f64::from(count);
2487 capacity += correlation.abs() / order as f64; }
2489 }
2490 }
2491
2492 Ok(capacity)
2493 }
2494
2495 fn estimate_information_processing_capacity(&self, features: &[Array1<f64>]) -> Result<f64> {
2497 let mut ipc = 0.0;
2498
2499 for ipc_function in &self.config.memory_config.ipc_functions {
2500 let capacity_func = self.test_ipc_function(*ipc_function, features)?;
2501 ipc += capacity_func;
2502 }
2503
2504 Ok(ipc)
2505 }
2506
2507 fn test_ipc_function(&self, function: IPCFunction, features: &[Array1<f64>]) -> Result<f64> {
2509 let mut capacity = 0.0;
2510
2511 for lag in 1..=10 {
2512 if lag < features.len() {
2513 let mut correlation = 0.0;
2514 let mut count = 0;
2515
2516 for i in lag..features.len() {
2517 for j in 0..features[i].len().min(features[i - lag].len()) {
2518 let current = features[i][j];
2519 let past = features[i - lag][j];
2520
2521 let target = match function {
2522 IPCFunction::Linear => past,
2523 IPCFunction::Quadratic => past * past,
2524 IPCFunction::Cubic => past * past * past,
2525 IPCFunction::Sine => past.sin(),
2526 IPCFunction::Product => {
2527 if j > 0 && j - 1 < features[i - lag].len() {
2528 past * features[i - lag][j - 1]
2529 } else {
2530 past
2531 }
2532 }
2533 IPCFunction::XOR => {
2534 if past > 0.0 {
2535 1.0
2536 } else {
2537 -1.0
2538 }
2539 }
2540 };
2541
2542 correlation += current * target;
2543 count += 1;
2544 }
2545 }
2546
2547 if count > 0 {
2548 correlation /= f64::from(count);
2549 capacity += correlation.abs();
2550 }
2551 }
2552 }
2553
2554 Ok(capacity)
2555 }
2556
2557 fn solve_linear_system(&mut self, a: &Array2<f64>, b: &Array2<f64>) -> Result<()> {
2559 let min_dim = a.nrows().min(a.ncols()).min(b.nrows());
2560
2561 for i in 0..min_dim.min(self.output_weights.nrows()) {
2562 for j in 0..b.ncols().min(self.output_weights.ncols()) {
2563 if a[[i, i]].abs() > 1e-15 {
2564 self.output_weights[[i, j]] = b[[i, j]] / a[[i, i]];
2565 }
2566 }
2567 }
2568
2569 Ok(())
2570 }
2571
2572 fn evaluate_performance(
2574 &self,
2575 features: &[Array1<f64>],
2576 targets: &[Array1<f64>],
2577 ) -> Result<(f64, f64)> {
2578 if features.is_empty() || targets.is_empty() {
2579 return Ok((0.0, 0.0));
2580 }
2581
2582 let mut total_error = 0.0;
2583 let n_samples = features.len().min(targets.len());
2584
2585 for i in 0..n_samples {
2586 let prediction = self.predict_output(&features[i])?;
2587 let error = self.calculate_prediction_error(&prediction, &targets[i]);
2588 total_error += error;
2589 }
2590
2591 let training_error = total_error / n_samples as f64;
2592
2593 let test_error = training_error;
2595
2596 Ok((training_error, test_error))
2597 }
2598
2599 fn predict_output(&self, features: &Array1<f64>) -> Result<Array1<f64>> {
2601 let feature_size = features.len().min(self.output_weights.ncols());
2602 let output_size = self.output_weights.nrows();
2603
2604 let mut output = Array1::zeros(output_size);
2605
2606 for i in 0..output_size {
2607 for j in 0..feature_size {
2608 output[i] += self.output_weights[[i, j]] * features[j];
2609 }
2610 }
2611
2612 Ok(output)
2613 }
2614
2615 fn calculate_prediction_error(&self, prediction: &Array1<f64>, target: &Array1<f64>) -> f64 {
2617 let min_len = prediction.len().min(target.len());
2618 let mut error = 0.0;
2619
2620 for i in 0..min_len {
2621 let diff = prediction[i] - target[i];
2622 error += diff * diff;
2623 }
2624
2625 (error / min_len as f64).sqrt() }
2627
2628 fn estimate_echo_state_property(&self) -> Result<f64> {
2630 let coupling = self.config.coupling_strength;
2631 let estimated_spectral_radius = coupling.tanh(); Ok(if estimated_spectral_radius < 1.0 {
2635 1.0
2636 } else {
2637 1.0 / estimated_spectral_radius
2638 })
2639 }
2640
2641 fn update_processing_time(&mut self, time_ms: f64) {
2643 let count = self.metrics.training_examples as f64;
2644 self.metrics.avg_processing_time_ms =
2645 self.metrics.avg_processing_time_ms.mul_add(count, time_ms) / (count + 1.0);
2646 }
2647
2648 pub const fn get_metrics(&self) -> &ReservoirMetrics {
2650 &self.metrics
2651 }
2652
2653 pub const fn get_memory_analysis(&self) -> &MemoryAnalyzer {
2655 &self.memory_analyzer
2656 }
2657
2658 pub fn reset(&mut self) -> Result<()> {
2660 self.reservoir_state =
2661 QuantumReservoirState::new(self.config.num_qubits, self.config.memory_capacity);
2662 self.metrics = ReservoirMetrics::default();
2663 self.training_history.clear();
2664 Ok(())
2665 }
2666}
2667
2668impl TimeSeriesPredictor {
2669 #[must_use]
2671 pub fn new(config: &TimeSeriesConfig) -> Self {
2672 Self {
2673 arima_params: ARIMAParams {
2674 ar_coeffs: Array1::zeros(config.ar_order),
2675 ma_coeffs: Array1::zeros(config.ma_order),
2676 diff_order: config.diff_order,
2677 residuals: VecDeque::with_capacity(config.ma_order),
2678 variance: 1.0,
2679 },
2680 nar_state: NARState {
2681 order: config.nar_order,
2682 coeffs: Array2::zeros((config.nar_order, config.nar_order)),
2683 history: VecDeque::with_capacity(config.nar_order),
2684 activation: ActivationFunction::Tanh,
2685 },
2686 kernel_weights: Array1::from_vec(config.kernel_params.clone()),
2687 trend_model: TrendModel {
2688 params: vec![0.0, 0.0], strength: 0.0,
2690 direction: 0.0,
2691 },
2692 }
2693 }
2694}
2695
2696impl MemoryAnalyzer {
2697 #[must_use]
2699 pub fn new(config: MemoryAnalysisConfig) -> Self {
2700 Self {
2701 config,
2702 capacity_estimates: HashMap::new(),
2703 nonlinearity_measures: HashMap::new(),
2704 temporal_correlations: Array2::zeros((0, 0)),
2705 ipc_metrics: HashMap::new(),
2706 }
2707 }
2708}
2709
2710#[derive(Debug, Clone, Serialize, Deserialize)]
2712pub struct TrainingResult {
2713 pub training_error: f64,
2715 pub test_error: f64,
2717 pub training_time_ms: f64,
2719 pub num_examples: usize,
2721 pub echo_state_property: f64,
2723 pub memory_capacity: f64,
2725 pub nonlinear_capacity: f64,
2727 pub processing_capacity: f64,
2729}
2730
2731pub fn benchmark_enhanced_quantum_reservoir_computing() -> Result<HashMap<String, f64>> {
2733 let mut results = HashMap::new();
2734
2735 let configs = vec![
2737 QuantumReservoirConfig {
2738 num_qubits: 6,
2739 architecture: QuantumReservoirArchitecture::RandomCircuit,
2740 learning_config: AdvancedLearningConfig {
2741 algorithm: LearningAlgorithm::Ridge,
2742 ..Default::default()
2743 },
2744 ..Default::default()
2745 },
2746 QuantumReservoirConfig {
2747 num_qubits: 8,
2748 architecture: QuantumReservoirArchitecture::ScaleFree,
2749 learning_config: AdvancedLearningConfig {
2750 algorithm: LearningAlgorithm::LASSO,
2751 ..Default::default()
2752 },
2753 ..Default::default()
2754 },
2755 QuantumReservoirConfig {
2756 num_qubits: 6,
2757 architecture: QuantumReservoirArchitecture::HierarchicalModular,
2758 learning_config: AdvancedLearningConfig {
2759 algorithm: LearningAlgorithm::RecursiveLeastSquares,
2760 ..Default::default()
2761 },
2762 memory_config: MemoryAnalysisConfig {
2763 enable_capacity_estimation: true,
2764 enable_nonlinear: true,
2765 ..Default::default()
2766 },
2767 ..Default::default()
2768 },
2769 QuantumReservoirConfig {
2770 num_qubits: 8,
2771 architecture: QuantumReservoirArchitecture::Grid,
2772 dynamics: ReservoirDynamics::Floquet,
2773 input_encoding: InputEncoding::Angle,
2774 output_measurement: OutputMeasurement::TemporalCorrelations,
2775 ..Default::default()
2776 },
2777 ];
2778
2779 for (i, config) in configs.into_iter().enumerate() {
2780 let start = std::time::Instant::now();
2781
2782 let mut qrc = QuantumReservoirComputerEnhanced::new(config)?;
2783
2784 let training_data = ReservoirTrainingData::new(
2786 (0..200)
2787 .map(|i| {
2788 Array1::from_vec(vec![
2789 (f64::from(i) * 0.1).sin(),
2790 (f64::from(i) * 0.1).cos(),
2791 (f64::from(i) * 0.05).sin() * (f64::from(i) * 0.2).cos(),
2792 ])
2793 })
2794 .collect(),
2795 (0..200)
2796 .map(|i| Array1::from_vec(vec![f64::from(i).mul_add(0.1, 1.0).sin()]))
2797 .collect(),
2798 (0..200).map(|i| f64::from(i) * 0.1).collect(),
2799 );
2800
2801 let training_result = qrc.train(&training_data)?;
2803
2804 let time = start.elapsed().as_secs_f64() * 1000.0;
2805 results.insert(format!("enhanced_config_{i}"), time);
2806
2807 let metrics = qrc.get_metrics();
2809 results.insert(
2810 format!("enhanced_config_{i}_accuracy"),
2811 metrics.prediction_accuracy,
2812 );
2813 results.insert(
2814 format!("enhanced_config_{i}_memory_capacity"),
2815 training_result.memory_capacity,
2816 );
2817 results.insert(
2818 format!("enhanced_config_{i}_nonlinear_capacity"),
2819 training_result.nonlinear_capacity,
2820 );
2821 results.insert(
2822 format!("enhanced_config_{i}_processing_capacity"),
2823 training_result.processing_capacity,
2824 );
2825 results.insert(
2826 format!("enhanced_config_{i}_quantum_advantage"),
2827 metrics.quantum_advantage,
2828 );
2829 results.insert(
2830 format!("enhanced_config_{i}_efficiency"),
2831 metrics.reservoir_efficiency,
2832 );
2833
2834 let memory_analyzer = qrc.get_memory_analysis();
2836 if let Some(&linear_capacity) = memory_analyzer.capacity_estimates.get("linear") {
2837 results.insert(
2838 format!("enhanced_config_{i}_linear_memory"),
2839 linear_capacity,
2840 );
2841 }
2842 if let Some(&total_capacity) = memory_analyzer.capacity_estimates.get("total") {
2843 results.insert(format!("enhanced_config_{i}_total_memory"), total_capacity);
2844 }
2845 }
2846
2847 Ok(results)
2848}
2849
2850#[cfg(test)]
2851mod tests {
2852 use super::*;
2853 use approx::assert_abs_diff_eq;
2854
2855 #[test]
2856 fn test_enhanced_quantum_reservoir_creation() {
2857 let config = QuantumReservoirConfig::default();
2858 let qrc = QuantumReservoirComputerEnhanced::new(config);
2859 assert!(qrc.is_ok());
2860 }
2861
2862 #[test]
2863 fn test_enhanced_reservoir_state_creation() {
2864 let state = QuantumReservoirState::new(3, 10);
2865 assert_eq!(state.state_vector.len(), 8); assert_eq!(state.state_history.capacity(), 10);
2867 assert_eq!(state.time_index, 0);
2868 assert!(state.memory_metrics.total_capacity >= 0.0);
2869 }
2870
2871 #[test]
2872 fn test_enhanced_input_processing() {
2873 let config = QuantumReservoirConfig {
2874 num_qubits: 3,
2875 evolution_steps: 2,
2876 ..Default::default()
2877 };
2878 let mut qrc = QuantumReservoirComputerEnhanced::new(config).expect("Failed to create QRC");
2879
2880 let input = Array1::from_vec(vec![0.5, 0.3, 0.8]);
2881 let result = qrc.process_input(&input);
2882 assert!(result.is_ok());
2883
2884 let features = result.expect("Failed to process input");
2885 assert!(!features.is_empty());
2886 }
2887
2888 #[test]
2889 fn test_enhanced_architectures() {
2890 let architectures = vec![
2891 QuantumReservoirArchitecture::RandomCircuit,
2892 QuantumReservoirArchitecture::SpinChain,
2893 QuantumReservoirArchitecture::ScaleFree,
2894 QuantumReservoirArchitecture::HierarchicalModular,
2895 QuantumReservoirArchitecture::Ring,
2896 QuantumReservoirArchitecture::Grid,
2897 ];
2898
2899 for arch in architectures {
2900 let config = QuantumReservoirConfig {
2901 num_qubits: 4,
2902 architecture: arch,
2903 evolution_steps: 2,
2904 ..Default::default()
2905 };
2906
2907 let qrc = QuantumReservoirComputerEnhanced::new(config);
2908 assert!(qrc.is_ok(), "Failed for architecture: {arch:?}");
2909 }
2910 }
2911
2912 #[test]
2913 fn test_advanced_learning_algorithms() {
2914 let algorithms = vec![
2915 LearningAlgorithm::Ridge,
2916 LearningAlgorithm::LASSO,
2917 LearningAlgorithm::ElasticNet,
2918 LearningAlgorithm::RecursiveLeastSquares,
2919 ];
2920
2921 for algorithm in algorithms {
2922 let config = QuantumReservoirConfig {
2923 num_qubits: 3,
2924 learning_config: AdvancedLearningConfig {
2925 algorithm,
2926 ..Default::default()
2927 },
2928 ..Default::default()
2929 };
2930
2931 let qrc = QuantumReservoirComputerEnhanced::new(config);
2932 assert!(qrc.is_ok(), "Failed for algorithm: {algorithm:?}");
2933 }
2934 }
2935
2936 #[test]
2937 fn test_enhanced_encoding_methods() {
2938 let encodings = vec![
2939 InputEncoding::Amplitude,
2940 InputEncoding::Phase,
2941 InputEncoding::BasisState,
2942 InputEncoding::Angle,
2943 ];
2944
2945 for encoding in encodings {
2946 let config = QuantumReservoirConfig {
2947 num_qubits: 3,
2948 input_encoding: encoding,
2949 ..Default::default()
2950 };
2951 let mut qrc =
2952 QuantumReservoirComputerEnhanced::new(config).expect("Failed to create QRC");
2953
2954 let input = Array1::from_vec(vec![0.5, 0.3]);
2955 let result = qrc.encode_input(&input);
2956 assert!(result.is_ok(), "Failed for encoding: {encoding:?}");
2957 }
2958 }
2959
2960 #[test]
2961 fn test_enhanced_measurement_strategies() {
2962 let measurements = vec![
2963 OutputMeasurement::PauliExpectation,
2964 OutputMeasurement::Probability,
2965 OutputMeasurement::Correlations,
2966 OutputMeasurement::Entanglement,
2967 OutputMeasurement::QuantumFisherInformation,
2968 OutputMeasurement::Variance,
2969 OutputMeasurement::QuantumCoherence,
2970 OutputMeasurement::Purity,
2971 OutputMeasurement::TemporalCorrelations,
2972 ];
2973
2974 for measurement in measurements {
2975 let config = QuantumReservoirConfig {
2976 num_qubits: 3,
2977 output_measurement: measurement,
2978 ..Default::default()
2979 };
2980
2981 let qrc = QuantumReservoirComputerEnhanced::new(config);
2982 assert!(qrc.is_ok(), "Failed for measurement: {measurement:?}");
2983 }
2984 }
2985
2986 #[test]
2987 fn test_enhanced_reservoir_dynamics() {
2988 let dynamics = vec![
2989 ReservoirDynamics::Unitary,
2990 ReservoirDynamics::Open,
2991 ReservoirDynamics::NISQ,
2992 ReservoirDynamics::Floquet,
2993 ];
2994
2995 for dynamic in dynamics {
2996 let config = QuantumReservoirConfig {
2997 num_qubits: 3,
2998 dynamics: dynamic,
2999 evolution_steps: 1,
3000 ..Default::default()
3001 };
3002
3003 let mut qrc =
3004 QuantumReservoirComputerEnhanced::new(config).expect("Failed to create QRC");
3005 let result = qrc.evolve_reservoir();
3006 assert!(result.is_ok(), "Failed for dynamics: {dynamic:?}");
3007 }
3008 }
3009
3010 #[test]
3011 fn test_memory_analysis() {
3012 let config = QuantumReservoirConfig {
3013 num_qubits: 4,
3014 memory_config: MemoryAnalysisConfig {
3015 enable_capacity_estimation: true,
3016 enable_nonlinear: true,
3017 enable_ipc: true,
3018 ..Default::default()
3019 },
3020 ..Default::default()
3021 };
3022
3023 let qrc = QuantumReservoirComputerEnhanced::new(config).expect("Failed to create QRC");
3024 let memory_analyzer = qrc.get_memory_analysis();
3025
3026 assert!(memory_analyzer.config.enable_capacity_estimation);
3027 assert!(memory_analyzer.config.enable_nonlinear);
3028 assert!(memory_analyzer.config.enable_ipc);
3029 }
3030
3031 #[test]
3032 fn test_enhanced_training_data() {
3033 let training_data = ReservoirTrainingData::new(
3034 vec![
3035 Array1::from_vec(vec![0.1, 0.2]),
3036 Array1::from_vec(vec![0.3, 0.4]),
3037 ],
3038 vec![Array1::from_vec(vec![0.5]), Array1::from_vec(vec![0.6])],
3039 vec![0.0, 1.0],
3040 )
3041 .with_features(vec![
3042 Array1::from_vec(vec![0.7, 0.8]),
3043 Array1::from_vec(vec![0.9, 1.0]),
3044 ])
3045 .with_labels(vec![0, 1])
3046 .with_weights(vec![1.0, 1.0]);
3047
3048 assert_eq!(training_data.len(), 2);
3049 assert!(training_data.features.is_some());
3050 assert!(training_data.labels.is_some());
3051 assert!(training_data.sample_weights.is_some());
3052
3053 let (train, test) = training_data.train_test_split(0.5);
3054 assert_eq!(train.len(), 1);
3055 assert_eq!(test.len(), 1);
3056 }
3057
3058 #[test]
3059 fn test_time_series_predictor() {
3060 let config = TimeSeriesConfig::default();
3061 let predictor = TimeSeriesPredictor::new(&config);
3062
3063 assert_eq!(predictor.arima_params.ar_coeffs.len(), config.ar_order);
3064 assert_eq!(predictor.arima_params.ma_coeffs.len(), config.ma_order);
3065 assert_eq!(predictor.nar_state.order, config.nar_order);
3066 }
3067
3068 #[test]
3069 fn test_enhanced_metrics_tracking() {
3070 let config = QuantumReservoirConfig::default();
3071 let qrc = QuantumReservoirComputerEnhanced::new(config).expect("Failed to create QRC");
3072
3073 let metrics = qrc.get_metrics();
3074 assert_eq!(metrics.training_examples, 0);
3075 assert_eq!(metrics.prediction_accuracy, 0.0);
3076 assert_eq!(metrics.memory_capacity, 0.0);
3077 assert_eq!(metrics.nonlinear_memory_capacity, 0.0);
3078 assert_eq!(metrics.quantum_advantage, 0.0);
3079 }
3080
3081 #[test]
3082 fn test_enhanced_feature_sizes() {
3083 let measurements = vec![
3084 (OutputMeasurement::PauliExpectation, 24), (OutputMeasurement::QuantumFisherInformation, 8), (OutputMeasurement::Variance, 24), (OutputMeasurement::Purity, 1), ];
3089
3090 for (measurement, expected_size) in measurements {
3091 let config = QuantumReservoirConfig {
3092 num_qubits: 8,
3093 output_measurement: measurement,
3094 ..Default::default()
3095 };
3096
3097 let feature_size = QuantumReservoirComputerEnhanced::calculate_feature_size(&config);
3098 assert_eq!(
3099 feature_size, expected_size,
3100 "Feature size mismatch for {measurement:?}"
3101 );
3102 }
3103 }
3104}