optirs_core/streaming/adaptive_streaming/
performance.rs

1// Performance tracking and prediction for streaming optimization
2//
3// This module provides comprehensive performance monitoring, trend analysis,
4// and prediction capabilities for streaming optimization scenarios, including
5// real-time metrics collection, statistical analysis, and predictive modeling.
6
7use super::config::*;
8use super::optimizer::{Adaptation, AdaptationPriority, AdaptationType, StreamingDataPoint};
9use super::resource_management::ResourceUsage;
10
11use scirs2_core::numeric::Float;
12use serde::{Deserialize, Serialize};
13use std::collections::{HashMap, VecDeque};
14use std::iter::Sum;
15use std::time::{Duration, Instant};
16
17/// Performance snapshot representing metrics at a specific point in time
18#[derive(Debug, Clone)]
19pub struct PerformanceSnapshot<A: Float + Send + Sync> {
20    /// Timestamp when snapshot was taken
21    pub timestamp: Instant,
22    /// Primary loss metric
23    pub loss: A,
24    /// Accuracy metric (if applicable)
25    pub accuracy: Option<A>,
26    /// Convergence rate
27    pub convergence_rate: Option<A>,
28    /// Gradient norm
29    pub gradient_norm: Option<A>,
30    /// Parameter update magnitude
31    pub parameter_update_magnitude: Option<A>,
32    /// Data quality statistics
33    pub data_statistics: DataStatistics<A>,
34    /// Resource usage at snapshot time
35    pub resource_usage: ResourceUsage,
36    /// Custom performance metrics
37    pub custom_metrics: HashMap<String, A>,
38}
39
40/// Data quality and distribution statistics
41#[derive(Debug, Clone)]
42pub struct DataStatistics<A: Float + Send + Sync> {
43    /// Number of samples in this batch
44    pub sample_count: usize,
45    /// Feature-wise means
46    pub feature_means: scirs2_core::ndarray::Array1<A>,
47    /// Feature-wise standard deviations
48    pub feature_stds: scirs2_core::ndarray::Array1<A>,
49    /// Average data quality score
50    pub average_quality: A,
51    /// Timestamp of statistics computation
52    pub timestamp: Instant,
53}
54
55impl<A: Float + Send + Sync> Default for DataStatistics<A> {
56    fn default() -> Self {
57        Self {
58            sample_count: 0,
59            feature_means: scirs2_core::ndarray::Array1::zeros(0),
60            feature_stds: scirs2_core::ndarray::Array1::zeros(0),
61            average_quality: A::zero(),
62            timestamp: Instant::now(),
63        }
64    }
65}
66
67/// Performance metrics for tracking and analysis
68#[derive(Debug, Clone)]
69pub enum PerformanceMetric<A: Float + Send + Sync> {
70    /// Loss function value
71    Loss(A),
72    /// Classification/regression accuracy
73    Accuracy(A),
74    /// Rate of convergence
75    ConvergenceRate(A),
76    /// Gradient magnitude
77    GradientNorm(A),
78    /// Learning rate effectiveness
79    LearningRateEffectiveness(A),
80    /// Resource utilization efficiency
81    ResourceEfficiency(A),
82    /// Data quality score
83    DataQuality(A),
84    /// Custom metric with name and value
85    Custom(String, A),
86}
87
88/// Context information for performance evaluation
89#[derive(Debug, Clone)]
90pub struct PerformanceContext<A: Float + Send + Sync> {
91    /// Current learning rate
92    pub learning_rate: A,
93    /// Current batch size
94    pub batch_size: usize,
95    /// Current buffer size
96    pub buffer_size: usize,
97    /// Recent drift detection status
98    pub drift_detected: bool,
99    /// Resource constraints
100    pub resource_constraints: ResourceUsage,
101    /// Time since last adaptation
102    pub time_since_adaptation: Duration,
103}
104
105/// Performance tracker for streaming optimization
106pub struct PerformanceTracker<A: Float + Send + Sync + std::iter::Sum> {
107    /// Configuration for performance tracking
108    config: PerformanceConfig,
109    /// Performance history
110    performance_history: VecDeque<PerformanceSnapshot<A>>,
111    /// Trend analyzer
112    trend_analyzer: PerformanceTrendAnalyzer<A>,
113    /// Performance predictor
114    predictor: PerformancePredictor<A>,
115    /// Performance baseline
116    baseline: Option<PerformanceSnapshot<A>>,
117    /// Current performance context
118    current_context: Option<PerformanceContext<A>>,
119    /// Performance improvement tracker
120    improvement_tracker: PerformanceImprovementTracker<A>,
121    /// Anomaly detector for performance
122    performance_anomaly_detector: PerformanceAnomalyDetector<A>,
123}
124
125/// Trend analysis for performance metrics
126pub struct PerformanceTrendAnalyzer<A: Float + Send + Sync> {
127    /// Window size for trend analysis
128    window_size: usize,
129    /// Current trends for different metrics
130    trends: HashMap<String, TrendData<A>>,
131    /// Trend computation methods
132    trend_methods: Vec<TrendMethod>,
133}
134
135/// Trend data for a specific metric
136#[derive(Debug, Clone)]
137pub struct TrendData<A: Float + Send + Sync> {
138    /// Linear trend slope
139    pub slope: A,
140    /// Trend correlation coefficient
141    pub correlation: A,
142    /// Trend volatility
143    pub volatility: A,
144    /// Trend confidence
145    pub confidence: A,
146    /// Recent values used for trend calculation
147    pub recent_values: VecDeque<A>,
148    /// Last update timestamp
149    pub last_update: Instant,
150}
151
152/// Methods for trend calculation
153#[derive(Debug, Clone)]
154pub enum TrendMethod {
155    /// Linear regression
156    LinearRegression,
157    /// Moving average
158    MovingAverage { window: usize },
159    /// Exponential smoothing
160    ExponentialSmoothing { alpha: f64 },
161    /// Seasonal decomposition
162    SeasonalDecomposition,
163}
164
165/// Performance predictor using various forecasting methods
166pub struct PerformancePredictor<A: Float + Send + Sync> {
167    /// Prediction methods to use
168    prediction_methods: Vec<PredictionMethod>,
169    /// Historical predictions for accuracy tracking
170    prediction_history: VecDeque<PredictionResult<A>>,
171    /// Model accuracy scores
172    model_accuracies: HashMap<String, A>,
173    /// Ensemble weights for combining predictions
174    ensemble_weights: HashMap<String, A>,
175}
176
177/// Prediction methods for performance forecasting
178#[derive(Debug, Clone)]
179pub enum PredictionMethod {
180    /// Linear extrapolation
181    Linear,
182    /// Exponential smoothing
183    Exponential { alpha: f64, beta: f64 },
184    /// ARIMA model
185    ARIMA { p: usize, d: usize, q: usize },
186    /// Neural network
187    NeuralNetwork { hidden_layers: Vec<usize> },
188    /// Ensemble of multiple methods
189    Ensemble,
190}
191
192/// Result of performance prediction
193#[derive(Debug, Clone)]
194pub struct PredictionResult<A: Float + Send + Sync> {
195    /// Predicted metric value
196    pub predicted_value: A,
197    /// Prediction confidence interval
198    pub confidence_interval: (A, A),
199    /// Prediction method used
200    pub method: String,
201    /// Steps ahead predicted
202    pub steps_ahead: usize,
203    /// Prediction timestamp
204    pub timestamp: Instant,
205    /// Actual value (filled in later for accuracy assessment)
206    pub actual_value: Option<A>,
207}
208
209/// Performance improvement tracking
210pub struct PerformanceImprovementTracker<A: Float + Send + Sync> {
211    /// Baseline performance metrics
212    baseline_metrics: HashMap<String, A>,
213    /// Current improvement rates
214    improvement_rates: HashMap<String, A>,
215    /// Improvement history
216    improvement_history: VecDeque<ImprovementEvent<A>>,
217    /// Plateau detection
218    plateau_detector: PlateauDetector<A>,
219}
220
221/// Performance improvement event
222#[derive(Debug, Clone)]
223pub struct ImprovementEvent<A: Float + Send + Sync> {
224    /// Event timestamp
225    pub timestamp: Instant,
226    /// Metric that improved
227    pub metric_name: String,
228    /// Improvement magnitude
229    pub improvement: A,
230    /// Improvement rate (per unit time)
231    pub improvement_rate: A,
232    /// Context when improvement occurred
233    pub context: String,
234}
235
236/// Plateau detection for performance metrics
237pub struct PlateauDetector<A: Float + Send + Sync> {
238    /// Window size for plateau detection
239    window_size: usize,
240    /// Plateau threshold (minimum change for non-plateau)
241    plateau_threshold: A,
242    /// Recent performance values
243    recent_values: VecDeque<A>,
244    /// Current plateau status
245    is_plateau: bool,
246    /// Plateau duration
247    plateau_duration: Duration,
248    /// Last significant change timestamp
249    last_significant_change: Option<Instant>,
250}
251
252/// Anomaly detection for performance metrics
253pub struct PerformanceAnomalyDetector<A: Float + Send + Sync> {
254    /// Anomaly detection threshold (standard deviations)
255    threshold: A,
256    /// Historical statistics for anomaly detection
257    historical_stats: HashMap<String, MetricStatistics<A>>,
258    /// Recent anomalies detected
259    recent_anomalies: VecDeque<PerformanceAnomaly<A>>,
260    /// Adaptive threshold adjustment
261    adaptive_threshold: bool,
262}
263
264/// Statistics for a performance metric
265#[derive(Debug, Clone)]
266pub struct MetricStatistics<A: Float + Send + Sync> {
267    /// Running mean
268    pub mean: A,
269    /// Running variance
270    pub variance: A,
271    /// Minimum observed value
272    pub min_value: A,
273    /// Maximum observed value
274    pub max_value: A,
275    /// Number of observations
276    pub count: usize,
277    /// Last update timestamp
278    pub last_update: Instant,
279}
280
281/// Performance anomaly event
282#[derive(Debug, Clone)]
283pub struct PerformanceAnomaly<A: Float + Send + Sync> {
284    /// Anomaly timestamp
285    pub timestamp: Instant,
286    /// Affected metric
287    pub metric_name: String,
288    /// Observed value
289    pub observed_value: A,
290    /// Expected value range
291    pub expected_range: (A, A),
292    /// Anomaly severity
293    pub severity: AnomalySeverity,
294    /// Anomaly type
295    pub anomaly_type: AnomalyType,
296}
297
298/// Severity levels for performance anomalies
299#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
300pub enum AnomalySeverity {
301    /// Minor anomaly
302    Minor,
303    /// Moderate anomaly requiring attention
304    Moderate,
305    /// Major anomaly requiring intervention
306    Major,
307    /// Critical anomaly requiring immediate action
308    Critical,
309}
310
311/// Types of performance anomalies
312#[derive(Debug, Clone, PartialEq, Eq)]
313pub enum AnomalyType {
314    /// Value significantly higher than expected
315    High,
316    /// Value significantly lower than expected
317    Low,
318    /// Sudden change in trend
319    TrendChange,
320    /// Unexpected oscillation
321    Oscillation,
322    /// Performance degradation
323    Degradation,
324    /// Performance plateau
325    Plateau,
326}
327
328impl<A: Float + Default + Clone + std::iter::Sum + Send + Sync + std::fmt::Debug>
329    PerformanceTracker<A>
330{
331    /// Creates a new performance tracker
332    pub fn new(config: &StreamingConfig) -> Result<Self, String> {
333        let performance_config = config.performance_config.clone();
334
335        let trend_analyzer = PerformanceTrendAnalyzer::new(performance_config.trend_window_size);
336        let predictor = PerformancePredictor::new();
337        let improvement_tracker = PerformanceImprovementTracker::new();
338        let performance_anomaly_detector = PerformanceAnomalyDetector::new(2.0); // 2 sigma threshold
339
340        Ok(Self {
341            config: performance_config,
342            performance_history: VecDeque::with_capacity(1000),
343            trend_analyzer,
344            predictor,
345            baseline: None,
346            current_context: None,
347            improvement_tracker,
348            performance_anomaly_detector,
349        })
350    }
351
352    /// Adds a new performance snapshot
353    pub fn add_performance(&mut self, snapshot: PerformanceSnapshot<A>) -> Result<(), String> {
354        // Store in history
355        if self.performance_history.len() >= self.config.history_size {
356            self.performance_history.pop_front();
357        }
358        self.performance_history.push_back(snapshot.clone());
359
360        // Set baseline if this is the first measurement
361        if self.baseline.is_none() {
362            self.baseline = Some(snapshot.clone());
363        }
364
365        // Update trend analysis
366        if self.config.enable_trend_analysis {
367            self.trend_analyzer.update(&snapshot)?;
368        }
369
370        // Update improvement tracking
371        self.improvement_tracker.update(&snapshot)?;
372
373        // Check for performance anomalies
374        let anomalies = self
375            .performance_anomaly_detector
376            .check_for_anomalies(&snapshot)?;
377        if !anomalies.is_empty() {
378            // Handle detected anomalies
379            self.handle_performance_anomalies(&anomalies)?;
380        }
381
382        // Update predictions if enabled
383        if self.config.enable_prediction {
384            self.predictor.update_with_actual(&snapshot)?;
385        }
386
387        Ok(())
388    }
389
390    /// Gets recent performance snapshots
391    pub fn get_recent_performance(&self, count: usize) -> Vec<PerformanceSnapshot<A>> {
392        self.performance_history
393            .iter()
394            .rev()
395            .take(count)
396            .cloned()
397            .collect()
398    }
399
400    /// Gets recent loss values for trend analysis
401    pub fn get_recent_losses(&self, count: usize) -> Vec<A> {
402        self.performance_history
403            .iter()
404            .rev()
405            .take(count)
406            .map(|snapshot| snapshot.loss)
407            .collect()
408    }
409
410    /// Predicts future performance
411    pub fn predict_performance(
412        &mut self,
413        steps_ahead: usize,
414    ) -> Result<PredictionResult<A>, String> {
415        if !self.config.enable_prediction {
416            return Err("Performance prediction is disabled".to_string());
417        }
418
419        self.predictor
420            .predict(steps_ahead, &self.performance_history)
421    }
422
423    /// Gets current performance trends
424    pub fn get_performance_trends(&self) -> HashMap<String, TrendData<A>> {
425        self.trend_analyzer.get_current_trends()
426    }
427
428    /// Computes adaptation for performance thresholds
429    pub fn apply_threshold_adaptation(&mut self, adaptation: &Adaptation<A>) -> Result<(), String> {
430        if adaptation.adaptation_type == AdaptationType::PerformanceThreshold {
431            // Adjust anomaly detection thresholds
432            let new_threshold = self.performance_anomaly_detector.threshold + adaptation.magnitude;
433            self.performance_anomaly_detector
434                .update_threshold(new_threshold);
435        }
436        Ok(())
437    }
438
439    /// Handles detected performance anomalies
440    fn handle_performance_anomalies(
441        &mut self,
442        anomalies: &[PerformanceAnomaly<A>],
443    ) -> Result<(), String> {
444        for anomaly in anomalies {
445            match anomaly.severity {
446                AnomalySeverity::Critical | AnomalySeverity::Major => {
447                    // Log critical anomalies for immediate attention
448                    println!("Critical performance anomaly detected: {:?}", anomaly);
449                }
450                _ => {
451                    // Store for analysis
452                    self.performance_anomaly_detector
453                        .recent_anomalies
454                        .push_back(anomaly.clone());
455                }
456            }
457        }
458        Ok(())
459    }
460
461    /// Resets performance tracking
462    pub fn reset(&mut self) -> Result<(), String> {
463        self.performance_history.clear();
464        self.baseline = None;
465        self.current_context = None;
466        self.trend_analyzer.reset();
467        self.predictor.reset();
468        self.improvement_tracker.reset();
469        self.performance_anomaly_detector.reset();
470        Ok(())
471    }
472
473    /// Gets diagnostic information
474    pub fn get_diagnostics(&self) -> PerformanceDiagnostics {
475        PerformanceDiagnostics {
476            history_size: self.performance_history.len(),
477            baseline_set: self.baseline.is_some(),
478            trends_available: !self.trend_analyzer.trends.is_empty(),
479            anomalies_detected: self.performance_anomaly_detector.recent_anomalies.len(),
480            plateau_detected: self.improvement_tracker.plateau_detector.is_plateau,
481            prediction_accuracy: self.predictor.get_average_accuracy(),
482        }
483    }
484}
485
486impl<A: Float + Default + Clone + Send + Sync + std::iter::Sum> PerformanceTrendAnalyzer<A> {
487    fn new(window_size: usize) -> Self {
488        Self {
489            window_size,
490            trends: HashMap::new(),
491            trend_methods: vec![
492                TrendMethod::LinearRegression,
493                TrendMethod::MovingAverage {
494                    window: window_size / 2,
495                },
496                TrendMethod::ExponentialSmoothing { alpha: 0.3 },
497            ],
498        }
499    }
500
501    fn update(&mut self, snapshot: &PerformanceSnapshot<A>) -> Result<(), String> {
502        // Update trends for different metrics
503        self.update_metric_trend("loss", snapshot.loss)?;
504
505        if let Some(accuracy) = snapshot.accuracy {
506            self.update_metric_trend("accuracy", accuracy)?;
507        }
508
509        if let Some(convergence) = snapshot.convergence_rate {
510            self.update_metric_trend("convergence", convergence)?;
511        }
512
513        self.compute_trends()?;
514        Ok(())
515    }
516
517    fn update_metric_trend(&mut self, metric_name: &str, value: A) -> Result<(), String> {
518        let trend_data = self
519            .trends
520            .entry(metric_name.to_string())
521            .or_insert_with(|| TrendData {
522                slope: A::zero(),
523                correlation: A::zero(),
524                volatility: A::zero(),
525                confidence: A::zero(),
526                recent_values: VecDeque::with_capacity(self.window_size),
527                last_update: Instant::now(),
528            });
529
530        if trend_data.recent_values.len() >= self.window_size {
531            trend_data.recent_values.pop_front();
532        }
533        trend_data.recent_values.push_back(value);
534        trend_data.last_update = Instant::now();
535
536        Ok(())
537    }
538
539    fn compute_trends(&mut self) -> Result<(), String> {
540        let keys: Vec<_> = self.trends.keys().cloned().collect();
541
542        // Collect all computed values first
543        let mut computed_values = Vec::new();
544        for metric_name in &keys {
545            if let Some(trend_data) = self.trends.get(metric_name) {
546                if trend_data.recent_values.len() >= 3 {
547                    let values = trend_data.recent_values.clone();
548                    let slope = self.compute_slope(&values)?;
549                    let correlation = self.compute_correlation(&values)?;
550                    let volatility = self.compute_volatility(&values)?;
551                    let confidence = self.compute_confidence(&values)?;
552                    computed_values.push((
553                        metric_name.clone(),
554                        slope,
555                        correlation,
556                        volatility,
557                        confidence,
558                    ));
559                }
560            }
561        }
562
563        // Now update the trend data
564        for (metric_name, slope, correlation, volatility, confidence) in computed_values {
565            if let Some(trend_data) = self.trends.get_mut(&metric_name) {
566                trend_data.slope = slope;
567                trend_data.correlation = correlation;
568                trend_data.volatility = volatility;
569                trend_data.confidence = confidence;
570            }
571        }
572
573        Ok(())
574    }
575
576    fn compute_slope(&self, values: &VecDeque<A>) -> Result<A, String> {
577        if values.len() < 2 {
578            return Ok(A::zero());
579        }
580
581        let n = A::from(values.len()).unwrap();
582        // Compute sum_x = 1 + 2 + ... + n = n*(n+1)/2
583        let sum_x = n * (n + A::one()) / A::from(2.0).unwrap();
584        let sum_y = values.iter().cloned().sum::<A>();
585        let sum_xy = values
586            .iter()
587            .enumerate()
588            .map(|(i, &y)| A::from(i + 1).unwrap() * y)
589            .sum::<A>();
590        // Compute sum_x_squared = 1^2 + 2^2 + ... + n^2 = n*(n+1)*(2n+1)/6
591        let two = A::from(2.0).unwrap();
592        let six = A::from(6.0).unwrap();
593        let sum_x_squared = n * (n + A::one()) * (two * n + A::one()) / six;
594
595        let denominator = n * sum_x_squared - sum_x * sum_x;
596        if denominator == A::zero() {
597            return Ok(A::zero());
598        }
599
600        let slope = (n * sum_xy - sum_x * sum_y) / denominator;
601        Ok(slope)
602    }
603
604    fn compute_correlation(&self, values: &VecDeque<A>) -> Result<A, String> {
605        if values.len() < 2 {
606            return Ok(A::zero());
607        }
608
609        // Simplified correlation with time index
610        let n = values.len();
611        let time_values: Vec<A> = (1..=n).map(|i| A::from(i).unwrap()).collect();
612        let value_vec: Vec<A> = values.iter().cloned().collect();
613
614        let mean_time = time_values.iter().cloned().sum::<A>() / A::from(n).unwrap();
615        let mean_value = value_vec.iter().cloned().sum::<A>() / A::from(n).unwrap();
616
617        let numerator = time_values
618            .iter()
619            .zip(value_vec.iter())
620            .map(|(&t, &v)| (t - mean_time) * (v - mean_value))
621            .sum::<A>();
622
623        let time_variance = time_values
624            .iter()
625            .map(|&t| (t - mean_time) * (t - mean_time))
626            .sum::<A>();
627
628        let value_variance = value_vec
629            .iter()
630            .map(|&v| (v - mean_value) * (v - mean_value))
631            .sum::<A>();
632
633        let denominator = (time_variance * value_variance).sqrt();
634        if denominator == A::zero() {
635            return Ok(A::zero());
636        }
637
638        Ok(numerator / denominator)
639    }
640
641    fn compute_volatility(&self, values: &VecDeque<A>) -> Result<A, String> {
642        if values.len() < 2 {
643            return Ok(A::zero());
644        }
645
646        let mean = values.iter().cloned().sum::<A>() / A::from(values.len()).unwrap();
647        let variance = values.iter().map(|&v| (v - mean) * (v - mean)).sum::<A>()
648            / A::from(values.len()).unwrap();
649
650        Ok(variance.sqrt())
651    }
652
653    fn compute_confidence(&self, values: &VecDeque<A>) -> Result<A, String> {
654        // Simple confidence based on trend consistency
655        if values.len() < 3 {
656            return Ok(A::zero());
657        }
658
659        let slope = self.compute_slope(values)?;
660        let correlation = self.compute_correlation(values)?;
661
662        // Confidence increases with stronger correlation and consistent slope direction
663        let confidence = correlation.abs() * (A::one() - (slope.abs() / (slope.abs() + A::one())));
664        Ok(confidence)
665    }
666
667    fn get_current_trends(&self) -> HashMap<String, TrendData<A>> {
668        self.trends.clone()
669    }
670
671    fn reset(&mut self) {
672        self.trends.clear();
673    }
674}
675
676impl<A: Float + Default + Clone + Send + Sync + std::iter::Sum> PerformancePredictor<A> {
677    fn new() -> Self {
678        Self {
679            prediction_methods: vec![
680                PredictionMethod::Linear,
681                PredictionMethod::Exponential {
682                    alpha: 0.3,
683                    beta: 0.1,
684                },
685            ],
686            prediction_history: VecDeque::with_capacity(1000),
687            model_accuracies: HashMap::new(),
688            ensemble_weights: HashMap::new(),
689        }
690    }
691
692    fn predict(
693        &mut self,
694        steps_ahead: usize,
695        history: &VecDeque<PerformanceSnapshot<A>>,
696    ) -> Result<PredictionResult<A>, String> {
697        if history.len() < 2 {
698            return Err("Insufficient history for prediction".to_string());
699        }
700
701        // Extract loss values for prediction
702        let loss_values: Vec<A> = history.iter().map(|s| s.loss).collect();
703
704        // Use linear prediction for simplicity
705        let predicted_value = self.linear_prediction(&loss_values, steps_ahead)?;
706
707        // Estimate confidence interval (simplified)
708        let recent_volatility = self.compute_recent_volatility(&loss_values)?;
709        let confidence_interval = (
710            predicted_value - recent_volatility,
711            predicted_value + recent_volatility,
712        );
713
714        let prediction = PredictionResult {
715            predicted_value,
716            confidence_interval,
717            method: "linear".to_string(),
718            steps_ahead,
719            timestamp: Instant::now(),
720            actual_value: None,
721        };
722
723        // Store prediction for later accuracy assessment
724        if self.prediction_history.len() >= 1000 {
725            self.prediction_history.pop_front();
726        }
727        self.prediction_history.push_back(prediction.clone());
728
729        Ok(prediction)
730    }
731
732    fn linear_prediction(&self, values: &[A], steps_ahead: usize) -> Result<A, String> {
733        if values.len() < 2 {
734            return Ok(A::zero());
735        }
736
737        // Simple linear extrapolation using last two points
738        let n = values.len();
739        let x1 = A::from(n - 1).unwrap();
740        let y1 = values[n - 1];
741        let x2 = A::from(n).unwrap();
742        let y2 = values[n - 1]; // Use same point for stability
743
744        // Use trend from last few points
745        if n >= 3 {
746            let slope = (values[n - 1] - values[n - 3]) / A::from(2).unwrap();
747            let predicted = values[n - 1] + slope * A::from(steps_ahead).unwrap();
748            Ok(predicted)
749        } else {
750            Ok(values[n - 1])
751        }
752    }
753
754    fn exponential_prediction(&self, values: &[A], steps_ahead: usize) -> Result<A, String> {
755        if values.is_empty() {
756            return Ok(A::zero());
757        }
758
759        // Simple exponential smoothing
760        let alpha = A::from(0.3).unwrap();
761        let mut forecast = values[0];
762
763        for &value in values.iter().skip(1) {
764            forecast = alpha * value + (A::one() - alpha) * forecast;
765        }
766
767        // Project forward (simplified)
768        for _ in 0..steps_ahead {
769            forecast = forecast * A::from(0.99).unwrap(); // Assume slight improvement
770        }
771
772        Ok(forecast)
773    }
774
775    fn compute_recent_volatility(&self, values: &[A]) -> Result<A, String> {
776        if values.len() < 2 {
777            return Ok(A::zero());
778        }
779
780        let recent_count = values.len().min(10);
781        let recent_values = &values[values.len() - recent_count..];
782
783        let mean = recent_values.iter().cloned().sum::<A>() / A::from(recent_count).unwrap();
784        let variance = recent_values
785            .iter()
786            .map(|&v| (v - mean) * (v - mean))
787            .sum::<A>()
788            / A::from(recent_count).unwrap();
789
790        Ok(variance.sqrt())
791    }
792
793    fn update_with_actual(&mut self, snapshot: &PerformanceSnapshot<A>) -> Result<(), String> {
794        // Update prediction accuracy by matching actual values with predictions
795        let mut updated_predictions = Vec::new();
796
797        for prediction in &mut self.prediction_history {
798            if prediction.actual_value.is_none() {
799                let time_diff = snapshot.timestamp.duration_since(prediction.timestamp);
800                let expected_duration = Duration::from_secs(prediction.steps_ahead as u64 * 10); // Assume 10s per step
801
802                if time_diff >= expected_duration {
803                    prediction.actual_value = Some(snapshot.loss);
804                    updated_predictions.push(prediction.clone());
805                }
806            }
807        }
808
809        // Update accuracy metrics for all updated predictions
810        for prediction in &updated_predictions {
811            self.update_accuracy_metrics(prediction)?;
812        }
813
814        Ok(())
815    }
816
817    fn update_accuracy_metrics(&mut self, prediction: &PredictionResult<A>) -> Result<(), String> {
818        if let Some(actual) = prediction.actual_value {
819            let error = (prediction.predicted_value - actual).abs();
820            let relative_error = error / actual.max(A::from(1e-8).unwrap());
821
822            // Update accuracy for this method
823            let accuracy = A::one() - relative_error.min(A::one());
824            let method_name = &prediction.method;
825
826            self.model_accuracies.insert(method_name.clone(), accuracy);
827        }
828
829        Ok(())
830    }
831
832    fn get_average_accuracy(&self) -> f64 {
833        if self.model_accuracies.is_empty() {
834            return 0.0;
835        }
836
837        let sum: A = self.model_accuracies.values().cloned().sum();
838        let avg = sum / A::from(self.model_accuracies.len()).unwrap();
839        avg.to_f64().unwrap_or(0.0)
840    }
841
842    fn reset(&mut self) {
843        self.prediction_history.clear();
844        self.model_accuracies.clear();
845        self.ensemble_weights.clear();
846    }
847}
848
849impl<A: Float + Default + Clone + Sum + Send + Sync + Send + Sync>
850    PerformanceImprovementTracker<A>
851{
852    fn new() -> Self {
853        Self {
854            baseline_metrics: HashMap::new(),
855            improvement_rates: HashMap::new(),
856            improvement_history: VecDeque::with_capacity(1000),
857            plateau_detector: PlateauDetector::new(50, A::from(0.01).unwrap()),
858        }
859    }
860
861    fn update(&mut self, snapshot: &PerformanceSnapshot<A>) -> Result<(), String> {
862        // Update baseline if not set
863        if self.baseline_metrics.is_empty() {
864            self.baseline_metrics
865                .insert("loss".to_string(), snapshot.loss);
866            if let Some(accuracy) = snapshot.accuracy {
867                self.baseline_metrics
868                    .insert("accuracy".to_string(), accuracy);
869            }
870        }
871
872        // Check for improvements
873        if let Some(&baseline_loss) = self.baseline_metrics.get("loss") {
874            if snapshot.loss < baseline_loss {
875                let improvement = baseline_loss - snapshot.loss;
876                let improvement_event = ImprovementEvent {
877                    timestamp: snapshot.timestamp,
878                    metric_name: "loss".to_string(),
879                    improvement,
880                    improvement_rate: improvement / A::from(1.0).unwrap(), // Simplified rate
881                    context: "optimization_step".to_string(),
882                };
883
884                if self.improvement_history.len() >= 1000 {
885                    self.improvement_history.pop_front();
886                }
887                self.improvement_history.push_back(improvement_event);
888
889                // Update baseline
890                self.baseline_metrics
891                    .insert("loss".to_string(), snapshot.loss);
892            }
893        }
894
895        // Update plateau detector
896        self.plateau_detector.update(snapshot.loss);
897
898        Ok(())
899    }
900
901    fn reset(&mut self) {
902        self.baseline_metrics.clear();
903        self.improvement_rates.clear();
904        self.improvement_history.clear();
905        self.plateau_detector.reset();
906    }
907}
908
909impl<A: Float + Default + Clone + Send + Sync + std::iter::Sum> PlateauDetector<A> {
910    fn new(window_size: usize, threshold: A) -> Self {
911        Self {
912            window_size,
913            plateau_threshold: threshold,
914            recent_values: VecDeque::with_capacity(window_size),
915            is_plateau: false,
916            plateau_duration: Duration::ZERO,
917            last_significant_change: None,
918        }
919    }
920
921    fn update(&mut self, value: A) {
922        if self.recent_values.len() >= self.window_size {
923            self.recent_values.pop_front();
924        }
925        self.recent_values.push_back(value);
926
927        if self.recent_values.len() >= self.window_size {
928            self.detect_plateau();
929        }
930    }
931
932    fn detect_plateau(&mut self) {
933        if self.recent_values.len() < 2 {
934            return;
935        }
936
937        let max_val = self.recent_values.iter().cloned().fold(A::zero(), A::max);
938        let min_val = self.recent_values.iter().cloned().fold(A::zero(), A::min);
939        let range = max_val - min_val;
940
941        let was_plateau = self.is_plateau;
942        self.is_plateau = range < self.plateau_threshold;
943
944        if self.is_plateau && !was_plateau {
945            self.plateau_duration = Duration::ZERO;
946        } else if self.is_plateau {
947            self.plateau_duration += Duration::from_secs(1); // Simplified
948        } else if !self.is_plateau {
949            self.last_significant_change = Some(Instant::now());
950            self.plateau_duration = Duration::ZERO;
951        }
952    }
953
954    fn reset(&mut self) {
955        self.recent_values.clear();
956        self.is_plateau = false;
957        self.plateau_duration = Duration::ZERO;
958        self.last_significant_change = None;
959    }
960}
961
962impl<A: Float + Default + Clone + Sum + Send + Sync + Send + Sync> PerformanceAnomalyDetector<A> {
963    fn new(threshold: f64) -> Self {
964        Self {
965            threshold: A::from(threshold).unwrap(),
966            historical_stats: HashMap::new(),
967            recent_anomalies: VecDeque::with_capacity(100),
968            adaptive_threshold: true,
969        }
970    }
971
972    fn check_for_anomalies(
973        &mut self,
974        snapshot: &PerformanceSnapshot<A>,
975    ) -> Result<Vec<PerformanceAnomaly<A>>, String> {
976        let mut anomalies = Vec::new();
977
978        // Check loss anomaly
979        let loss_anomaly = self.check_metric_anomaly("loss", snapshot.loss, snapshot.timestamp)?;
980        if let Some(anomaly) = loss_anomaly {
981            anomalies.push(anomaly);
982        }
983
984        // Check accuracy anomaly if available
985        if let Some(accuracy) = snapshot.accuracy {
986            let accuracy_anomaly =
987                self.check_metric_anomaly("accuracy", accuracy, snapshot.timestamp)?;
988            if let Some(anomaly) = accuracy_anomaly {
989                anomalies.push(anomaly);
990            }
991        }
992
993        Ok(anomalies)
994    }
995
996    fn check_metric_anomaly(
997        &mut self,
998        metric_name: &str,
999        value: A,
1000        timestamp: Instant,
1001    ) -> Result<Option<PerformanceAnomaly<A>>, String> {
1002        // Update statistics for this metric
1003        let stats = self
1004            .historical_stats
1005            .entry(metric_name.to_string())
1006            .or_insert_with(|| MetricStatistics {
1007                mean: value,
1008                variance: A::zero(),
1009                min_value: value,
1010                max_value: value,
1011                count: 0,
1012                last_update: timestamp,
1013            });
1014
1015        // Update running statistics
1016        stats.count += 1;
1017        let delta = value - stats.mean;
1018        stats.mean = stats.mean + delta / A::from(stats.count).unwrap();
1019        let delta2 = value - stats.mean;
1020        stats.variance = stats.variance + delta * delta2;
1021        stats.min_value = stats.min_value.min(value);
1022        stats.max_value = stats.max_value.max(value);
1023        stats.last_update = timestamp;
1024
1025        // Check for anomaly after sufficient samples
1026        if stats.count >= 10 {
1027            let std_dev = (stats.variance / A::from(stats.count - 1).unwrap()).sqrt();
1028            let z_score = (value - stats.mean) / std_dev.max(A::from(1e-8).unwrap());
1029
1030            if z_score.abs() > self.threshold {
1031                let severity = if z_score.abs() > A::from(3.0).unwrap() {
1032                    AnomalySeverity::Critical
1033                } else if z_score.abs() > A::from(2.5).unwrap() {
1034                    AnomalySeverity::Major
1035                } else {
1036                    AnomalySeverity::Moderate
1037                };
1038
1039                let anomaly_type = if z_score > A::zero() {
1040                    AnomalyType::High
1041                } else {
1042                    AnomalyType::Low
1043                };
1044
1045                let expected_range = (
1046                    stats.mean - self.threshold * std_dev,
1047                    stats.mean + self.threshold * std_dev,
1048                );
1049
1050                let anomaly = PerformanceAnomaly {
1051                    timestamp,
1052                    metric_name: metric_name.to_string(),
1053                    observed_value: value,
1054                    expected_range,
1055                    severity,
1056                    anomaly_type,
1057                };
1058
1059                return Ok(Some(anomaly));
1060            }
1061        }
1062
1063        Ok(None)
1064    }
1065
1066    fn update_threshold(&mut self, new_threshold: A) {
1067        self.threshold = new_threshold;
1068    }
1069
1070    fn reset(&mut self) {
1071        self.historical_stats.clear();
1072        self.recent_anomalies.clear();
1073    }
1074}
1075
1076/// Diagnostic information for performance tracking
1077#[derive(Debug, Clone)]
1078pub struct PerformanceDiagnostics {
1079    pub history_size: usize,
1080    pub baseline_set: bool,
1081    pub trends_available: bool,
1082    pub anomalies_detected: usize,
1083    pub plateau_detected: bool,
1084    pub prediction_accuracy: f64,
1085}