1#![allow(dead_code)]
8#![allow(clippy::too_many_arguments)]
9
10use crate::error::Result;
11use scirs2_core::ndarray::{Array1, Array2};
12use scirs2_core::simd_ops::SimdUnifiedOps;
13use serde::{Deserialize, Serialize};
14use statrs::statistics::Statistics;
15use std::collections::{HashMap, VecDeque};
16use std::sync::{Arc, RwLock};
17use std::time::{Duration, Instant};
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct AdamOptimizer {
22 m_weights: Array2<f32>,
24 v_weights: Array2<f32>,
26 m_bias: Array1<f32>,
28 v_bias: Array1<f32>,
30 beta1: f32,
32 beta2: f32,
34 epsilon: f32,
36 timestep: usize,
38}
39
40impl AdamOptimizer {
41 pub fn new(weight_shape: (usize, usize), bias_size: usize) -> Self {
43 Self {
44 m_weights: Array2::zeros(weight_shape),
45 v_weights: Array2::zeros(weight_shape),
46 m_bias: Array1::zeros(bias_size),
47 v_bias: Array1::zeros(bias_size),
48 beta1: 0.9,
49 beta2: 0.999,
50 epsilon: 1e-8,
51 timestep: 0,
52 }
53 }
54
55 pub fn update_weights(
57 &mut self,
58 weights: &mut Array2<f32>,
59 bias: &mut Array1<f32>,
60 weight_gradients: &Array2<f32>,
61 bias_gradients: &Array1<f32>,
62 learning_rate: f32,
63 ) {
64 self.timestep += 1;
65 let t = self.timestep as f32;
66
67 self.m_weights = self.beta1 * &self.m_weights + (1.0 - self.beta1) * weight_gradients;
69 self.m_bias = self.beta1 * &self.m_bias + (1.0 - self.beta1) * bias_gradients;
70
71 self.v_weights =
73 self.beta2 * &self.v_weights + (1.0 - self.beta2) * weight_gradients.mapv(|x| x * x);
74 self.v_bias =
75 self.beta2 * &self.v_bias + (1.0 - self.beta2) * bias_gradients.mapv(|x| x * x);
76
77 let m_weights_corrected = &self.m_weights / (1.0 - self.beta1.powf(t));
79 let m_bias_corrected = &self.m_bias / (1.0 - self.beta1.powf(t));
80
81 let v_weights_corrected = &self.v_weights / (1.0 - self.beta2.powf(t));
83 let v_bias_corrected = &self.v_bias / (1.0 - self.beta2.powf(t));
84
85 let v_weights_sqrt = v_weights_corrected.mapv(|x| x.sqrt() + self.epsilon);
87 let v_bias_sqrt = v_bias_corrected.mapv(|x| x.sqrt() + self.epsilon);
88
89 *weights = &*weights - &(learning_rate * &m_weights_corrected / &v_weights_sqrt);
90 *bias = &*bias - &(learning_rate * &m_bias_corrected / &v_bias_sqrt);
91 }
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct NeuralIoNetwork {
97 input_weights: Array2<f32>,
99 hidden_weights: Array2<f32>,
101 output_weights: Array2<f32>,
103 input_bias: Array1<f32>,
105 hidden_bias: Array1<f32>,
106 output_bias: Array1<f32>,
107 learning_rate: f32,
109 adam_optimizer: AdamOptimizer,
111 attention_weights: Array1<f32>,
113 dropout_rate: f32,
115}
116
117impl NeuralIoNetwork {
118 pub fn new(input_size: usize, hidden_size: usize, output_size: usize) -> Self {
120 let input_scale = (2.0 / input_size as f32).sqrt();
122 let hidden_scale = (2.0 / hidden_size as f32).sqrt();
123 let output_scale = (2.0 / hidden_size as f32).sqrt();
124
125 Self {
126 input_weights: Self::random_weights((hidden_size, input_size), input_scale),
127 hidden_weights: Self::random_weights((hidden_size, hidden_size), hidden_scale),
128 output_weights: Self::random_weights((output_size, hidden_size), output_scale),
129 input_bias: Array1::zeros(hidden_size),
130 hidden_bias: Array1::zeros(hidden_size),
131 output_bias: Array1::zeros(output_size),
132 learning_rate: 0.001,
133 adam_optimizer: AdamOptimizer::new((hidden_size, input_size), hidden_size),
134 attention_weights: Array1::from_elem(input_size, 1.0 / input_size as f32),
135 dropout_rate: 0.1,
136 }
137 }
138
139 pub fn forward(&self, input: &Array1<f32>) -> Result<Array1<f32>> {
141 let attended_input = self.apply_attention(input);
143
144 let hidden_input = self.input_weights.dot(&attended_input) + &self.input_bias;
146 let hidden_output = hidden_input.mapv(Self::gelu); let hidden_normalized = self.layer_normalize(&hidden_output);
150
151 let hidden_input2 = self.hidden_weights.dot(&hidden_normalized) + &self.hidden_bias;
153 let hidden_output2 = hidden_input2.mapv(Self::swish); let gate = hidden_output2.mapv(Self::sigmoid);
157 let gated_residual = &gate * &hidden_output2 + &(1.0 - &gate) * &hidden_normalized;
158
159 let output = self.output_weights.dot(&gated_residual) + &self.output_bias;
161 let final_output = output.mapv(Self::tanh); Ok(final_output)
164 }
165
166 fn apply_attention(&self, input: &Array1<f32>) -> Array1<f32> {
168 let attention_scores = input * &self.attention_weights;
170
171 let max_score = attention_scores
173 .iter()
174 .copied()
175 .fold(f32::NEG_INFINITY, f32::max);
176 let exp_scores = attention_scores.mapv(|x| (x - max_score).exp());
177 let sum_exp = exp_scores.sum();
178 let attention_probs = exp_scores / sum_exp;
179
180 input * &attention_probs
182 }
183
184 fn layer_normalize(&self, input: &Array1<f32>) -> Array1<f32> {
186 let mean = input.mean().unwrap_or(0.0);
187 let variance = input.mapv(|x| (x - mean).powi(2)).mean().unwrap_or(1.0);
188 let std_dev = (variance + 1e-6).sqrt();
189
190 input.mapv(|x| (x - mean) / std_dev)
191 }
192
193 fn relu(x: f32) -> f32 {
195 x.max(0.0)
196 }
197
198 fn gelu(x: f32) -> f32 {
200 0.5 * x * (1.0 + ((2.0 / std::f32::consts::PI).sqrt() * (x + 0.044715 * x.powi(3))).tanh())
201 }
202
203 fn swish(x: f32) -> f32 {
205 x * Self::sigmoid(x)
206 }
207
208 fn sigmoid(x: f32) -> f32 {
210 1.0 / (1.0 + (-x).exp())
211 }
212
213 fn tanh(x: f32) -> f32 {
215 x.tanh()
216 }
217
218 fn random_weights(shape: (usize, usize), scale: f32) -> Array2<f32> {
220 Array2::from_shape_fn(shape, |_| {
221 let mut state = std::ptr::addr_of!(scale) as usize;
223 state = state.wrapping_mul(1103515245).wrapping_add(12345);
224 let rand_val = ((state / 65536) % 32768) as f32 / 32768.0;
225 (rand_val - 0.5) * 2.0 * scale
226 })
227 }
228
229 pub fn update_weights(
231 &mut self,
232 input: &Array1<f32>,
233 target: &Array1<f32>,
234 prediction: &Array1<f32>,
235 ) -> Result<()> {
236 let output_error = &(2.0 * (prediction - target)) / prediction.len() as f32;
238
239 let attended_input = self.apply_attention(input);
241
242 let hidden_input = self.input_weights.dot(&attended_input) + &self.input_bias;
244 let hidden_output = hidden_input.mapv(Self::gelu);
245 let hidden_normalized = self.layer_normalize(&hidden_output);
246
247 let hidden_input2 = self.hidden_weights.dot(&hidden_normalized) + &self.hidden_bias;
248 let hidden_output2 = hidden_input2.mapv(Self::swish);
249
250 let output_bias_grad = output_error.clone();
252
253 let _output_weight_grad = output_bias_grad
255 .view()
256 .to_shape((output_bias_grad.len(), 1))
257 .unwrap()
258 .dot(
259 &hidden_output2
260 .view()
261 .to_shape((1, hidden_output2.len()))
262 .unwrap(),
263 );
264
265 let hidden_error = self.output_weights.t().dot(&output_bias_grad);
267 let mut hidden_bias_grad = hidden_error.clone();
268 for val in hidden_bias_grad.iter_mut() {
269 *val *= Self::gelu_derivative(*val);
270 }
271
272 let input_error = self.hidden_weights.t().dot(&hidden_bias_grad);
274 let mut input_bias_grad = input_error.clone();
275 for val in input_bias_grad.iter_mut() {
276 *val *= Self::gelu_derivative(*val);
277 }
278
279 let _input_weight_grad = input_bias_grad
281 .view()
282 .to_shape((input_bias_grad.len(), 1))
283 .unwrap()
284 .dot(
285 &attended_input
286 .view()
287 .to_shape((1, attended_input.len()))
288 .unwrap(),
289 );
290
291 self.update_attention_weights(&output_error, input);
293
294 {
296 let momentum = 0.9;
297 let scaled_grad = self.learning_rate * &output_bias_grad;
298 for i in 0..self.output_bias.len() {
299 self.output_bias[i] = momentum * self.output_bias[i] - scaled_grad[i];
300 }
301 }
302
303 {
304 let momentum = 0.9;
305 let scaled_grad = self.learning_rate * &hidden_bias_grad;
306 for i in 0..self.hidden_bias.len() {
307 self.hidden_bias[i] = momentum * self.hidden_bias[i] - scaled_grad[i];
308 }
309 }
310
311 {
312 let momentum = 0.9;
313 let scaled_grad = self.learning_rate * &input_bias_grad;
314 for i in 0..self.input_bias.len() {
315 self.input_bias[i] = momentum * self.input_bias[i] - scaled_grad[i];
316 }
317 }
318
319 Ok(())
320 }
321
322 fn gelu_derivative(x: f32) -> f32 {
324 let tanh_term = (2.0 / std::f32::consts::PI).sqrt() * (x + 0.044715 * x.powi(3));
325 let sech2 = 1.0 - tanh_term.tanh().powi(2);
326
327 0.5 * (1.0 + tanh_term.tanh())
328 + 0.5
329 * x
330 * sech2
331 * (2.0 / std::f32::consts::PI).sqrt()
332 * (1.0 + 3.0 * 0.044715 * x.powi(2))
333 }
334
335 fn update_attention_weights(&mut self, error: &Array1<f32>, input: &Array1<f32>) {
337 let attention_grad = error.sum() * input / input.len() as f32;
338 self.attention_weights =
339 0.9 * &self.attention_weights + 0.1 * self.learning_rate * &attention_grad;
340
341 let sum = self.attention_weights.sum();
343 if sum > 0.0 {
344 self.attention_weights /= sum;
345 }
346 }
347
348 fn update_bias_with_momentum(&mut self, bias: &mut Array1<f32>, gradient: &Array1<f32>) {
350 let momentum = 0.9;
351 let scaled_grad = self.learning_rate * gradient;
352
353 for i in 0..bias.len() {
355 bias[i] = momentum * bias[i] - scaled_grad[i];
356 }
357 }
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize)]
362pub struct SystemMetrics {
363 pub cpu_usage: f32,
365 pub memory_usage: f32,
367 pub disk_usage: f32,
369 pub network_usage: f32,
371 pub cache_hit_ratio: f32,
373 pub throughput: f32,
375 pub load_average: f32,
377 pub available_memory_ratio: f32,
379}
380
381impl SystemMetrics {
382 pub fn to_input_vector(&self) -> Array1<f32> {
384 Array1::from(vec![
385 self.cpu_usage,
386 self.memory_usage,
387 self.disk_usage,
388 self.network_usage,
389 self.cache_hit_ratio,
390 self.throughput,
391 self.load_average,
392 self.available_memory_ratio,
393 ])
394 }
395
396 pub fn mock() -> Self {
398 Self {
399 cpu_usage: 0.7,
400 memory_usage: 0.6,
401 disk_usage: 0.4,
402 network_usage: 0.3,
403 cache_hit_ratio: 0.8,
404 throughput: 0.5,
405 load_average: 0.6,
406 available_memory_ratio: 0.4,
407 }
408 }
409}
410
411#[derive(Debug, Clone, Serialize, Deserialize)]
413pub struct OptimizationDecisions {
414 pub thread_count_factor: f32,
416 pub buffer_size_factor: f32,
418 pub compression_level: f32,
420 pub cache_priority: f32,
422 pub simd_factor: f32,
424}
425
426impl OptimizationDecisions {
427 pub fn from_output_vector(output: &Array1<f32>) -> Self {
429 Self {
430 thread_count_factor: output[0].clamp(0.0, 1.0),
431 buffer_size_factor: output[1].clamp(0.0, 1.0),
432 compression_level: output[2].clamp(0.0, 1.0),
433 cache_priority: output[3].clamp(0.0, 1.0),
434 simd_factor: output[4].clamp(0.0, 1.0),
435 }
436 }
437
438 pub fn to_concrete_params(
440 &self,
441 base_thread_count: usize,
442 base_buffer_size: usize,
443 ) -> ConcreteOptimizationParams {
444 ConcreteOptimizationParams {
445 thread_count: ((self.thread_count_factor * 16.0).ceil() as usize).clamp(1, 32),
446 buffer_size: ((self.buffer_size_factor * base_buffer_size as f32) as usize).max(4096),
447 compression_level: (self.compression_level * 9.0) as u32,
448 use_cache: self.cache_priority > 0.5,
449 use_simd: self.simd_factor > 0.3,
450 }
451 }
452}
453
454#[derive(Debug, Clone)]
456pub struct ConcreteOptimizationParams {
457 pub thread_count: usize,
459 pub buffer_size: usize,
461 pub compression_level: u32,
463 pub use_cache: bool,
465 pub use_simd: bool,
467}
468
469#[derive(Debug, Clone)]
471pub struct PerformanceFeedback {
472 pub throughput_mbps: f32,
474 pub latency_ms: f32,
476 pub cpu_efficiency: f32,
478 pub memory_efficiency: f32,
480 pub error_rate: f32,
482}
483
484impl PerformanceFeedback {
485 pub fn to_target_vector(&self, baselinethroughput: f32) -> Array1<f32> {
487 let throughput_improvement = (self.throughput_mbps / baselinethroughput.max(1.0)).min(2.0);
488 let latency_score = (100.0 / (self.latency_ms + 1.0)).min(1.0);
489 let efficiency_score = (self.cpu_efficiency + self.memory_efficiency) / 2.0;
490 let reliability_score = 1.0 - self.error_rate.min(1.0);
491
492 Array1::from(vec![
493 throughput_improvement - 1.0, latency_score,
495 efficiency_score,
496 reliability_score,
497 (throughput_improvement * efficiency_score).min(1.0),
498 ])
499 }
500}
501
502pub struct NeuralAdaptiveIoController {
504 network: Arc<RwLock<NeuralIoNetwork>>,
505 performance_history:
506 Arc<RwLock<VecDeque<(SystemMetrics, OptimizationDecisions, PerformanceFeedback)>>>,
507 baseline_performance: Arc<RwLock<Option<f32>>>,
508 adaptation_interval: Duration,
509 last_adaptation: Arc<RwLock<Instant>>,
510}
511
512impl Default for NeuralAdaptiveIoController {
513 fn default() -> Self {
514 Self::new()
515 }
516}
517
518impl NeuralAdaptiveIoController {
519 pub fn new() -> Self {
521 let network = Arc::new(RwLock::new(NeuralIoNetwork::new(8, 16, 5)));
522
523 Self {
524 network,
525 performance_history: Arc::new(RwLock::new(VecDeque::with_capacity(1000))),
526 baseline_performance: Arc::new(RwLock::new(None)),
527 adaptation_interval: Duration::from_secs(30),
528 last_adaptation: Arc::new(RwLock::new(Instant::now())),
529 }
530 }
531
532 pub fn get_optimization_decisions(
534 &self,
535 metrics: &SystemMetrics,
536 ) -> Result<OptimizationDecisions> {
537 let network = self.network.read().unwrap();
538 let input = metrics.to_input_vector();
539 let output = network.forward(&input)?;
540 Ok(OptimizationDecisions::from_output_vector(&output))
541 }
542
543 pub fn record_performance(
545 &self,
546 metrics: SystemMetrics,
547 decisions: OptimizationDecisions,
548 feedback: PerformanceFeedback,
549 ) -> Result<()> {
550 {
552 let mut history = self.performance_history.write().unwrap();
553 history.push_back((metrics.clone(), decisions.clone(), feedback.clone()));
554 if history.len() > 1000 {
555 history.pop_front();
556 }
557 }
558
559 {
561 let mut baseline = self.baseline_performance.write().unwrap();
562 if baseline.is_none() {
563 *baseline = Some(feedback.throughput_mbps);
564 } else {
565 let current_baseline = baseline.as_mut().unwrap();
566 *current_baseline = 0.9 * *current_baseline + 0.1 * feedback.throughput_mbps;
567 }
568 }
569
570 let should_adapt = {
572 let last_adaptation = self.last_adaptation.read().unwrap();
573 last_adaptation.elapsed() > self.adaptation_interval
574 };
575
576 if should_adapt {
577 self.adapt_network()?;
578 let mut last_adaptation = self.last_adaptation.write().unwrap();
579 *last_adaptation = Instant::now();
580 }
581
582 Ok(())
583 }
584
585 fn adapt_network(&self) -> Result<()> {
587 let history = self.performance_history.read().unwrap();
588 let baseline = self.baseline_performance.read().unwrap();
589
590 if let Some(baseline_throughput) = *baseline {
591 let mut network = self.network.write().unwrap();
592
593 let recent_entries: Vec<_> = history.iter().rev().take(10).collect();
595
596 for (metrics, decisions, feedback) in recent_entries {
597 let input = metrics.to_input_vector();
598 let current_output = network.forward(&input).unwrap_or_else(|_| Array1::zeros(5));
599 let target = feedback.to_target_vector(baseline_throughput);
600
601 network.update_weights(&input, &target, ¤t_output)?;
602 }
603 }
604
605 Ok(())
606 }
607
608 pub fn get_adaptation_stats(&self) -> AdaptationStats {
610 let history = self.performance_history.read().unwrap();
611 let baseline = self.baseline_performance.read().unwrap();
612
613 let recent_performance: Vec<f32> = history
614 .iter()
615 .rev()
616 .take(50)
617 .map(|(_, _, feedback)| feedback.throughput_mbps)
618 .collect();
619
620 let avg_recent_performance = if !recent_performance.is_empty() {
621 recent_performance.iter().sum::<f32>() / recent_performance.len() as f32
622 } else {
623 0.0
624 };
625
626 let improvement_ratio = baseline
627 .map(|b| avg_recent_performance / b.max(1.0))
628 .unwrap_or(1.0);
629
630 AdaptationStats {
631 total_adaptations: history.len(),
632 recent_avg_throughput: avg_recent_performance,
633 baseline_throughput: baseline.unwrap_or(0.0),
634 improvement_ratio,
635 adaptation_effectiveness: (improvement_ratio - 1.0).max(0.0),
636 }
637 }
638}
639
640#[derive(Debug, Clone)]
642pub struct AdaptationStats {
643 pub total_adaptations: usize,
645 pub recent_avg_throughput: f32,
647 pub baseline_throughput: f32,
649 pub improvement_ratio: f32,
651 pub adaptation_effectiveness: f32,
653}
654
655pub struct AdvancedIoProcessor {
657 controller: NeuralAdaptiveIoController,
658 current_params: Arc<RwLock<ConcreteOptimizationParams>>,
659 performance_monitor: Arc<RwLock<PerformanceMonitor>>,
660}
661
662impl Default for AdvancedIoProcessor {
663 fn default() -> Self {
664 Self::new()
665 }
666}
667
668impl AdvancedIoProcessor {
669 pub fn new() -> Self {
671 Self {
672 controller: NeuralAdaptiveIoController::new(),
673 current_params: Arc::new(RwLock::new(ConcreteOptimizationParams {
674 thread_count: 4,
675 buffer_size: 64 * 1024,
676 compression_level: 6,
677 use_cache: true,
678 use_simd: true,
679 })),
680 performance_monitor: Arc::new(RwLock::new(PerformanceMonitor::new())),
681 }
682 }
683
684 pub fn process_data_adaptive(&mut self, data: &[u8]) -> Result<Vec<u8>> {
686 let start_time = Instant::now();
687
688 let metrics = self.get_system_metrics();
690
691 let decisions = self.controller.get_optimization_decisions(&metrics)?;
693 let concrete_params = decisions.to_concrete_params(4, 64 * 1024);
694
695 {
697 let mut params = self.current_params.write().unwrap();
698 *params = concrete_params.clone();
699 }
700
701 let result = self.process_with_params(data, &concrete_params)?;
703
704 let processing_time = start_time.elapsed();
706 let throughput =
707 (data.len() as f32) / (processing_time.as_secs_f64() as f32 * 1024.0 * 1024.0);
708
709 let feedback = PerformanceFeedback {
710 throughput_mbps: throughput,
711 latency_ms: processing_time.as_millis() as f32,
712 cpu_efficiency: 0.8, memory_efficiency: 0.7, error_rate: 0.0, };
716
717 self.controller
718 .record_performance(metrics, decisions, feedback)?;
719
720 Ok(result)
721 }
722
723 fn process_with_params(
725 &self,
726 data: &[u8],
727 params: &ConcreteOptimizationParams,
728 ) -> Result<Vec<u8>> {
729 let mut result = Vec::with_capacity(data.len());
730
731 if params.use_simd && data.len() >= 32 {
732 let simd_result = self.process_simd_optimized(data)?;
734 result.extend_from_slice(&simd_result);
735 } else {
736 result.extend_from_slice(data);
738 }
739
740 if params.compression_level > 0 {
742 result = self.compress_data(&result, params.compression_level)?;
743 }
744
745 Ok(result)
746 }
747
748 fn process_simd_optimized(&self, data: &[u8]) -> Result<Vec<u8>> {
750 let float_data: Vec<f32> = data.iter().map(|&x| x as f32).collect();
752 let array = Array1::from(float_data);
753
754 let ones_array = Array1::ones(array.len());
756 let array_view = array.view();
757 let ones_view = ones_array.view();
758 let processed = f32::simd_add(&array_view, &ones_view);
759
760 let result: Vec<u8> = processed.iter().map(|&x| x as u8).collect();
762 Ok(result)
763 }
764
765 fn compress_data(&self, data: &[u8], level: u32) -> Result<Vec<u8>> {
767 Ok(data.to_vec())
769 }
770
771 fn get_system_metrics(&self) -> SystemMetrics {
773 SystemMetrics::mock()
774 }
775
776 pub fn get_performance_stats(&self) -> AdaptationStats {
778 self.controller.get_adaptation_stats()
779 }
780}
781
782#[derive(Debug)]
784struct PerformanceMonitor {
785 operation_count: usize,
786 total_processing_time: Duration,
787 total_bytes_processed: usize,
788}
789
790impl PerformanceMonitor {
791 fn new() -> Self {
792 Self {
793 operation_count: 0,
794 total_processing_time: Duration::default(),
795 total_bytes_processed: 0,
796 }
797 }
798}
799
800#[derive(Debug, Clone)]
802pub struct ReinforcementLearningAgent {
803 q_table: HashMap<String, HashMap<String, f32>>,
805 exploration_rate: f32,
807 learning_rate: f32,
809 discount_factor: f32,
811 current_state: Option<String>,
813 action_history: VecDeque<(String, String, f32)>, }
816
817impl Default for ReinforcementLearningAgent {
818 fn default() -> Self {
819 Self::new()
820 }
821}
822
823impl ReinforcementLearningAgent {
824 pub fn new() -> Self {
826 Self {
827 q_table: HashMap::new(),
828 exploration_rate: 0.1,
829 learning_rate: 0.1,
830 discount_factor: 0.95,
831 current_state: None,
832 action_history: VecDeque::with_capacity(1000),
833 }
834 }
835
836 pub fn choose_action(&mut self, state: &str) -> String {
838 let actions = vec![
839 "increase_threads".to_string(),
840 "decrease_threads".to_string(),
841 "increase_buffer".to_string(),
842 "decrease_buffer".to_string(),
843 "enable_compression".to_string(),
844 "disable_compression".to_string(),
845 "enable_simd".to_string(),
846 "disable_simd".to_string(),
847 ];
848
849 if self.exploration_rate > 0.5 {
851 actions[0].clone()
853 } else {
854 self.get_best_action(state, &actions)
856 }
857 }
858
859 fn get_best_action(&self, state: &str, actions: &[String]) -> String {
861 if let Some(state_actions) = self.q_table.get(state) {
862 actions
863 .iter()
864 .max_by(|a, b| {
865 let value_a = state_actions.get(*a).unwrap_or(&0.0);
866 let value_b = state_actions.get(*b).unwrap_or(&0.0);
867 value_a.partial_cmp(value_b).unwrap()
868 })
869 .cloned()
870 .unwrap_or_else(|| actions[0].clone())
871 } else {
872 actions[0].clone()
873 }
874 }
875
876 pub fn update_q_value(&mut self, state: &str, action: &str, reward: f32, nextstate: &str) {
878 let max_next_q = self
880 .q_table
881 .get(nextstate)
882 .map(|actions| actions.values().copied().fold(f32::NEG_INFINITY, f32::max))
883 .unwrap_or(0.0);
884
885 let current_q = self
887 .q_table
888 .entry(state.to_string())
889 .or_default()
890 .entry(action.to_string())
891 .or_insert(0.0);
892
893 let td_target = reward + self.discount_factor * max_next_q;
894 let td_error = td_target - *current_q;
895 *current_q += self.learning_rate * td_error;
896
897 self.action_history
899 .push_back((state.to_string(), action.to_string(), reward));
900 if self.action_history.len() > 1000 {
901 self.action_history.pop_front();
902 }
903
904 self.exploration_rate = (self.exploration_rate * 0.995).max(0.01);
906 }
907
908 pub fn get_learning_stats(&self) -> ReinforcementLearningStats {
910 let avg_reward = if !self.action_history.is_empty() {
911 self.action_history.iter().map(|(_, _, r)| r).sum::<f32>()
912 / self.action_history.len() as f32
913 } else {
914 0.0
915 };
916
917 ReinforcementLearningStats {
918 total_states: self.q_table.len(),
919 total_actions: self.action_history.len(),
920 average_reward: avg_reward,
921 exploration_rate: self.exploration_rate,
922 q_table_size: self.q_table.values().map(|actions| actions.len()).sum(),
923 }
924 }
925}
926
927#[derive(Debug, Clone)]
929pub struct ReinforcementLearningStats {
930 pub total_states: usize,
932 pub total_actions: usize,
934 pub average_reward: f32,
936 pub exploration_rate: f32,
938 pub q_table_size: usize,
940}
941
942#[derive(Debug, Clone)]
944pub struct EnsembleNeuralNetwork {
945 networks: Vec<NeuralIoNetwork>,
947 ensemble_weights: Array1<f32>,
949 network_performance: Vec<f32>,
951}
952
953impl Default for EnsembleNeuralNetwork {
954 fn default() -> Self {
955 Self::new(3, 8, 16, 5)
956 }
957}
958
959impl EnsembleNeuralNetwork {
960 pub fn new(
962 num_networks: usize,
963 input_size: usize,
964 hidden_size: usize,
965 output_size: usize,
966 ) -> Self {
967 let networks = (0..num_networks)
968 .map(|_| NeuralIoNetwork::new(input_size, hidden_size, output_size))
969 .collect();
970
971 let ensemble_weights = Array1::from_elem(num_networks, 1.0 / num_networks as f32);
972 let network_performance = vec![1.0; num_networks];
973
974 Self {
975 networks,
976 ensemble_weights,
977 network_performance,
978 }
979 }
980
981 pub fn forward_ensemble(&self, input: &Array1<f32>) -> Result<Array1<f32>> {
983 let mut predictions = Vec::new();
984
985 for network in &self.networks {
986 let prediction = network.forward(input)?;
987 predictions.push(prediction);
988 }
989
990 let mut ensemble_output = Array1::zeros(predictions[0].len());
992 for (i, prediction) in predictions.iter().enumerate() {
993 ensemble_output = ensemble_output + self.ensemble_weights[i] * prediction;
994 }
995
996 Ok(ensemble_output)
997 }
998
999 pub fn update_ensemble_weights(&mut self, individual_errors: &[f32]) {
1001 for (i, &error) in individual_errors.iter().enumerate() {
1003 self.network_performance[i] =
1004 0.9 * self.network_performance[i] + 0.1 * (1.0 / (error + 0.001));
1005 }
1006
1007 let total_performance: f32 = self.network_performance.iter().sum();
1009 for (i, &performance) in self.network_performance.iter().enumerate() {
1010 self.ensemble_weights[i] = performance / total_performance;
1011 }
1012 }
1013
1014 pub fn train_ensemble(&mut self, input: &Array1<f32>, target: &Array1<f32>) -> Result<()> {
1016 let mut individual_errors = Vec::new();
1017
1018 for network in &mut self.networks {
1019 let prediction = network.forward(input)?;
1020 let error = (target - &prediction).mapv(|x| x * x).mean().unwrap_or(1.0);
1021 individual_errors.push(error);
1022
1023 network.update_weights(input, target, &prediction)?;
1024 }
1025
1026 self.update_ensemble_weights(&individual_errors);
1027 Ok(())
1028 }
1029
1030 pub fn get_ensemble_stats(&self) -> EnsembleStats {
1032 EnsembleStats {
1033 num_networks: self.networks.len(),
1034 ensemble_weights: self.ensemble_weights.clone(),
1035 network_performance: self.network_performance.clone(),
1036 weight_entropy: -self
1037 .ensemble_weights
1038 .iter()
1039 .map(|&w| if w > 0.0 { w * w.ln() } else { 0.0 })
1040 .sum::<f32>(),
1041 }
1042 }
1043}
1044
1045#[derive(Debug, Clone)]
1047pub struct EnsembleStats {
1048 pub num_networks: usize,
1050 pub ensemble_weights: Array1<f32>,
1052 pub network_performance: Vec<f32>,
1054 pub weight_entropy: f32,
1056}
1057
1058#[cfg(test)]
1059mod tests {
1060 use super::*;
1061
1062 #[test]
1063 fn test_neural_network_forward() {
1064 let network = NeuralIoNetwork::new(8, 16, 5);
1065 let input = Array1::from(vec![0.5; 8]);
1066 let output = network.forward(&input).unwrap();
1067 assert_eq!(output.len(), 5);
1068 assert!(output.iter().all(|&x| (0.0..=1.0).contains(&x)));
1069 }
1070
1071 #[test]
1072 fn test_system_metrics_conversion() {
1073 let metrics = SystemMetrics::mock();
1074 let input_vector = metrics.to_input_vector();
1075 assert_eq!(input_vector.len(), 8);
1076 }
1077
1078 #[test]
1079 fn test_optimization_decisions() {
1080 let output = Array1::from(vec![0.8, 0.6, 0.4, 0.9, 0.7]);
1081 let decisions = OptimizationDecisions::from_output_vector(&output);
1082 let params = decisions.to_concrete_params(4, 64 * 1024);
1083
1084 assert!(params.thread_count >= 1 && params.thread_count <= 32);
1085 assert!(params.buffer_size >= 4096);
1086 assert!(params.compression_level <= 9);
1087 }
1088
1089 #[test]
1090 fn test_advanced_think_processor() {
1091 let mut processor = AdvancedIoProcessor::new();
1092 let test_data = vec![1, 2, 3, 4, 5];
1093 let result = processor.process_data_adaptive(&test_data).unwrap();
1094 assert!(!result.is_empty());
1095 }
1096}