quantrs2_device/performance_analytics_dashboard/
analytics.rs

1//! Analytics Engines for Performance Dashboard
2//!
3//! This module contains the analytics engines that power the dashboard's
4//! statistical analysis, trend detection, anomaly detection, and performance prediction.
5
6use super::config::{AnalyticsConfig, PredictionConfig};
7use super::data::{
8    AnomalyDetectionResults, PerformancePredictions, RealtimeMetrics, StatisticalAnalysisResults,
9    TrendAnalysisResults, TrendDirection,
10};
11use crate::DeviceResult;
12use scirs2_core::ndarray::{Array1, Array2};
13use serde::{Deserialize, Serialize};
14use std::collections::{HashMap, VecDeque};
15use std::time::{Duration, SystemTime};
16
17/// Statistical analyzer for metrics
18pub struct StatisticalAnalyzer {
19    config: AnalyticsConfig,
20    analysis_cache: HashMap<String, CachedAnalysis>,
21    computation_history: VecDeque<AnalysisRecord>,
22}
23
24/// Trend analyzer for performance trends
25pub struct TrendAnalyzer {
26    config: AnalyticsConfig,
27    trend_models: HashMap<String, TrendModel>,
28    forecast_accuracy: HashMap<String, f64>,
29}
30
31/// Anomaly detector for performance anomalies
32pub struct AnomalyDetector {
33    config: AnalyticsConfig,
34    detection_models: HashMap<String, AnomalyDetectionModel>,
35    baseline_statistics: HashMap<String, BaselineStatistics>,
36    anomaly_history: VecDeque<HistoricalAnomaly>,
37}
38
39/// Performance predictor for forecasting
40pub struct PerformancePredictor {
41    config: PredictionConfig,
42    prediction_models: HashMap<String, PredictionModelInstance>,
43    feature_engineering: FeatureEngineeringPipeline,
44    model_registry: ModelRegistry,
45}
46
47/// Cached analysis result
48#[derive(Debug, Clone)]
49pub struct CachedAnalysis {
50    pub timestamp: SystemTime,
51    pub analysis_type: String,
52    pub results: HashMap<String, f64>,
53    pub validity_period: Duration,
54}
55
56/// Analysis record for history tracking
57#[derive(Debug, Clone)]
58pub struct AnalysisRecord {
59    pub timestamp: SystemTime,
60    pub analysis_type: String,
61    pub computation_time: Duration,
62    pub data_points: usize,
63    pub success: bool,
64}
65
66/// Trend model for time series analysis
67#[derive(Debug, Clone)]
68pub struct TrendModel {
69    pub model_type: TrendModelType,
70    pub parameters: Vec<f64>,
71    pub last_update: SystemTime,
72    pub accuracy: f64,
73    pub trend_direction: TrendDirection,
74}
75
76/// Trend model types
77#[derive(Debug, Clone, PartialEq)]
78pub enum TrendModelType {
79    Linear,
80    Exponential,
81    Polynomial { degree: usize },
82    MovingAverage { window: usize },
83    ExponentialSmoothing { alpha: f64 },
84    ARIMA { p: usize, d: usize, q: usize },
85    Custom(String),
86}
87
88/// Anomaly detection model
89#[derive(Debug, Clone)]
90pub struct AnomalyDetectionModel {
91    pub model_type: AnomalyModelType,
92    pub sensitivity: f64,
93    pub baseline: BaselineStatistics,
94    pub detection_threshold: f64,
95    pub last_training: SystemTime,
96}
97
98/// Anomaly detection model types
99#[derive(Debug, Clone, PartialEq)]
100pub enum AnomalyModelType {
101    StatisticalOutlier,
102    IsolationForest,
103    LocalOutlierFactor,
104    OneClassSVM,
105    AutoEncoder,
106    LSTM,
107    Custom(String),
108}
109
110/// Baseline statistics for anomaly detection
111#[derive(Debug, Clone)]
112pub struct BaselineStatistics {
113    pub mean: f64,
114    pub std_dev: f64,
115    pub percentiles: HashMap<String, f64>,
116    pub distribution_type: String,
117    pub seasonal_patterns: Vec<f64>,
118}
119
120/// Historical anomaly record
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct HistoricalAnomaly {
123    pub timestamp: SystemTime,
124    pub metric_name: String,
125    pub anomaly_type: AnomalyType,
126    pub severity: AnomalySeverity,
127    pub value: f64,
128    pub expected_value: f64,
129    pub deviation: f64,
130    pub resolution: Option<AnomalyResolution>,
131}
132
133/// Anomaly types
134#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
135pub enum AnomalyType {
136    Outlier,
137    Drift,
138    Spike,
139    Drop,
140    PatternChange,
141    SeasonalDeviation,
142    Custom(String),
143}
144
145/// Anomaly severity levels
146#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
147pub enum AnomalySeverity {
148    Low,
149    Medium,
150    High,
151    Critical,
152}
153
154/// Anomaly resolution information
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct AnomalyResolution {
157    pub resolution_time: SystemTime,
158    pub resolution_method: String,
159    pub root_cause: Option<String>,
160    pub corrective_action: Option<String>,
161}
162
163/// Current anomaly
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct Anomaly {
166    pub id: String,
167    pub timestamp: SystemTime,
168    pub metric_name: String,
169    pub anomaly_type: AnomalyType,
170    pub severity: AnomalySeverity,
171    pub current_value: f64,
172    pub expected_value: f64,
173    pub confidence: f64,
174    pub impact_assessment: ImpactAssessment,
175}
176
177/// Impact assessment for anomalies
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct ImpactAssessment {
180    pub affected_systems: Vec<String>,
181    pub impact_severity: String,
182    pub estimated_duration: Option<Duration>,
183    pub business_impact: Option<String>,
184}
185
186/// Prediction model instance
187#[derive(Debug, Clone)]
188pub struct PredictionModelInstance {
189    pub model_id: String,
190    pub model_type: String,
191    pub model_parameters: HashMap<String, f64>,
192    pub training_data_size: usize,
193    pub last_training: SystemTime,
194    pub prediction_accuracy: f64,
195    pub feature_importance: HashMap<String, f64>,
196}
197
198/// Feature engineering pipeline
199#[derive(Debug, Clone)]
200pub struct FeatureEngineeringPipeline {
201    pub transformations: Vec<FeatureTransformation>,
202    pub feature_selection: FeatureSelectionMethod,
203    pub preprocessing_steps: Vec<PreprocessingStep>,
204}
205
206/// Feature transformation types
207#[derive(Debug, Clone)]
208pub enum FeatureTransformation {
209    Normalization,
210    Standardization,
211    LogTransform,
212    PolynomialFeatures { degree: usize },
213    InteractionFeatures,
214    TemporalFeatures,
215    Custom(String),
216}
217
218/// Feature selection methods
219#[derive(Debug, Clone)]
220pub enum FeatureSelectionMethod {
221    VarianceThreshold { threshold: f64 },
222    UnivariateSelection { k: usize },
223    RecursiveFeatureElimination { n_features: usize },
224    LassoRegularization { alpha: f64 },
225    MutualInformation,
226    Custom(String),
227}
228
229/// Preprocessing steps
230#[derive(Debug, Clone)]
231pub enum PreprocessingStep {
232    MissingValueImputation { method: String },
233    OutlierRemoval { method: String },
234    DataSmoothing { window_size: usize },
235    Detrending,
236    SeasonalDecomposition,
237    Custom(String),
238}
239
240/// Model registry for managing prediction models
241#[derive(Debug, Clone)]
242pub struct ModelRegistry {
243    pub registered_models: HashMap<String, ModelMetadata>,
244    pub active_models: Vec<String>,
245    pub model_performance_history: HashMap<String, Vec<ModelPerformanceRecord>>,
246}
247
248/// Model metadata
249#[derive(Debug, Clone)]
250pub struct ModelMetadata {
251    pub model_id: String,
252    pub model_name: String,
253    pub model_type: String,
254    pub version: String,
255    pub created_at: SystemTime,
256    pub last_updated: SystemTime,
257    pub performance_metrics: HashMap<String, f64>,
258    pub hyperparameters: HashMap<String, f64>,
259}
260
261/// Model performance record
262#[derive(Debug, Clone)]
263pub struct ModelPerformanceRecord {
264    pub timestamp: SystemTime,
265    pub accuracy: f64,
266    pub precision: f64,
267    pub recall: f64,
268    pub f1_score: f64,
269    pub custom_metrics: HashMap<String, f64>,
270}
271
272/// Anomaly patterns
273#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct AnomalyPatterns {
275    pub recurring_patterns: Vec<RecurringPattern>,
276    pub correlation_patterns: Vec<CorrelationPattern>,
277    pub temporal_patterns: Vec<TemporalPattern>,
278}
279
280/// Recurring anomaly pattern
281#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct RecurringPattern {
283    pub pattern_id: String,
284    pub frequency: String,
285    pub affected_metrics: Vec<String>,
286    pub pattern_strength: f64,
287    pub next_predicted_occurrence: Option<SystemTime>,
288}
289
290/// Correlation pattern between anomalies
291#[derive(Debug, Clone, Serialize, Deserialize)]
292pub struct CorrelationPattern {
293    pub pattern_id: String,
294    pub primary_metric: String,
295    pub correlated_metrics: Vec<String>,
296    pub correlation_strength: f64,
297    pub time_lag: Option<Duration>,
298}
299
300/// Temporal pattern in anomalies
301#[derive(Debug, Clone, Serialize, Deserialize)]
302pub struct TemporalPattern {
303    pub pattern_id: String,
304    pub time_of_day: Option<String>,
305    pub day_of_week: Option<String>,
306    pub seasonal_component: Option<String>,
307    pub pattern_confidence: f64,
308}
309
310/// Root cause analysis results
311#[derive(Debug, Clone, Serialize, Deserialize)]
312pub struct RootCauseAnalysis {
313    pub probable_causes: Vec<ProbableCause>,
314    pub causal_chains: Vec<CausalChain>,
315    pub correlation_analysis: CorrelationAnalysisResult,
316    pub recommendation_score: f64,
317}
318
319/// Probable cause of anomalies
320#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct ProbableCause {
322    pub cause_id: String,
323    pub cause_description: String,
324    pub confidence: f64,
325    pub supporting_evidence: Vec<String>,
326    pub recommended_actions: Vec<String>,
327}
328
329/// Causal chain analysis
330#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct CausalChain {
332    pub chain_id: String,
333    pub events: Vec<CausalEvent>,
334    pub chain_probability: f64,
335}
336
337/// Causal event in a chain
338#[derive(Debug, Clone, Serialize, Deserialize)]
339pub struct CausalEvent {
340    pub event_id: String,
341    pub event_description: String,
342    pub timestamp: SystemTime,
343    pub event_impact: f64,
344}
345
346/// Correlation analysis result
347#[derive(Debug, Clone, Serialize, Deserialize)]
348pub struct CorrelationAnalysisResult {
349    pub metric_correlations: HashMap<String, f64>,
350    pub time_lag_correlations: HashMap<String, (Duration, f64)>,
351    pub cross_correlations: HashMap<String, Vec<f64>>,
352}
353
354/// Seasonal patterns
355#[derive(Debug, Clone, Serialize, Deserialize)]
356pub struct SeasonalPatterns {
357    pub daily_patterns: HashMap<String, Vec<f64>>,
358    pub weekly_patterns: HashMap<String, Vec<f64>>,
359    pub monthly_patterns: HashMap<String, Vec<f64>>,
360    pub seasonal_strength: HashMap<String, f64>,
361}
362
363/// Change point detection
364#[derive(Debug, Clone, Serialize, Deserialize)]
365pub struct ChangePointDetection {
366    pub change_points: Vec<ChangePoint>,
367    pub change_point_probabilities: Vec<f64>,
368    pub structural_breaks: Vec<StructuralBreak>,
369}
370
371/// Change point
372#[derive(Debug, Clone, Serialize, Deserialize)]
373pub struct ChangePoint {
374    pub timestamp: SystemTime,
375    pub metric_name: String,
376    pub change_magnitude: f64,
377    pub confidence: f64,
378    pub change_type: String,
379}
380
381/// Structural break
382#[derive(Debug, Clone, Serialize, Deserialize)]
383pub struct StructuralBreak {
384    pub breakpoint_time: SystemTime,
385    pub variable_name: String,
386    pub magnitude: f64,
387    pub confidence_level: f64,
388    pub break_type: String,
389}
390
391/// Forecasting results
392#[derive(Debug, Clone, Serialize, Deserialize)]
393pub struct ForecastingResults {
394    pub forecasts: HashMap<String, Forecast>,
395    pub forecast_accuracy: HashMap<String, ForecastAccuracy>,
396    pub uncertainty_bounds: HashMap<String, (Vec<f64>, Vec<f64>)>,
397}
398
399/// Forecast data
400#[derive(Debug, Clone, Serialize, Deserialize)]
401pub struct Forecast {
402    pub predicted_values: Vec<f64>,
403    pub prediction_timestamps: Vec<SystemTime>,
404    pub confidence_intervals: Vec<(f64, f64)>,
405    pub model_used: String,
406}
407
408/// Forecast accuracy metrics
409#[derive(Debug, Clone, Serialize, Deserialize)]
410pub struct ForecastAccuracy {
411    pub mae: f64,   // Mean Absolute Error
412    pub mse: f64,   // Mean Squared Error
413    pub rmse: f64,  // Root Mean Squared Error
414    pub mape: f64,  // Mean Absolute Percentage Error
415    pub smape: f64, // Symmetric Mean Absolute Percentage Error
416}
417
418impl StatisticalAnalyzer {
419    pub fn new(config: AnalyticsConfig) -> Self {
420        Self {
421            config,
422            analysis_cache: HashMap::new(),
423            computation_history: VecDeque::new(),
424        }
425    }
426
427    pub async fn analyze_metrics(
428        &mut self,
429        metrics: &RealtimeMetrics,
430    ) -> DeviceResult<StatisticalAnalysisResults> {
431        // Check cache first
432        if let Some(cached) = self.get_cached_analysis("descriptive_stats") {
433            if self.is_cache_valid(&cached) {
434                return Ok(self.build_results_from_cache(&cached));
435            }
436        }
437
438        // Perform new analysis
439        let start_time = SystemTime::now();
440        let results = self.perform_statistical_analysis(metrics).await?;
441        let computation_time = start_time.elapsed().unwrap_or(Duration::from_secs(0));
442
443        // Cache results
444        self.cache_analysis("descriptive_stats", &results, computation_time);
445
446        // Record computation history
447        self.record_analysis("descriptive_stats", computation_time, 1, true);
448
449        Ok(results)
450    }
451
452    async fn perform_statistical_analysis(
453        &self,
454        metrics: &RealtimeMetrics,
455    ) -> DeviceResult<StatisticalAnalysisResults> {
456        // Simplified implementation - real implementation would use SciRS2
457        Ok(StatisticalAnalysisResults::default())
458    }
459
460    fn get_cached_analysis(&self, analysis_type: &str) -> Option<&CachedAnalysis> {
461        self.analysis_cache.get(analysis_type)
462    }
463
464    fn is_cache_valid(&self, cached: &CachedAnalysis) -> bool {
465        SystemTime::now()
466            .duration_since(cached.timestamp)
467            .unwrap_or(Duration::from_secs(0))
468            < cached.validity_period
469    }
470
471    fn build_results_from_cache(&self, _cached: &CachedAnalysis) -> StatisticalAnalysisResults {
472        StatisticalAnalysisResults::default()
473    }
474
475    fn cache_analysis(
476        &mut self,
477        analysis_type: &str,
478        _results: &StatisticalAnalysisResults,
479        _computation_time: Duration,
480    ) {
481        let cached = CachedAnalysis {
482            timestamp: SystemTime::now(),
483            analysis_type: analysis_type.to_string(),
484            results: HashMap::new(),
485            validity_period: Duration::from_secs(300), // 5 minutes
486        };
487        self.analysis_cache
488            .insert(analysis_type.to_string(), cached);
489    }
490
491    fn record_analysis(
492        &mut self,
493        analysis_type: &str,
494        computation_time: Duration,
495        data_points: usize,
496        success: bool,
497    ) {
498        let record = AnalysisRecord {
499            timestamp: SystemTime::now(),
500            analysis_type: analysis_type.to_string(),
501            computation_time,
502            data_points,
503            success,
504        };
505
506        self.computation_history.push_back(record);
507
508        // Keep only last 1000 records
509        if self.computation_history.len() > 1000 {
510            self.computation_history.pop_front();
511        }
512    }
513}
514
515impl TrendAnalyzer {
516    pub fn new(config: AnalyticsConfig) -> Self {
517        Self {
518            config,
519            trend_models: HashMap::new(),
520            forecast_accuracy: HashMap::new(),
521        }
522    }
523
524    pub async fn analyze_trends(
525        &mut self,
526        historical_data: &HashMap<String, Vec<f64>>,
527    ) -> DeviceResult<TrendAnalysisResults> {
528        let mut trend_directions = HashMap::new();
529        let mut trend_strengths = HashMap::new();
530
531        for (metric_name, values) in historical_data {
532            if values.len() < self.config.trend_window_size {
533                continue;
534            }
535
536            let (direction, strength) = self.calculate_trend(values)?;
537            trend_directions.insert(metric_name.clone(), direction);
538            trend_strengths.insert(metric_name.clone(), strength);
539        }
540
541        Ok(TrendAnalysisResults {
542            trend_directions,
543            trend_strengths,
544            seasonal_patterns:
545                crate::performance_analytics_dashboard::data::SeasonalPatterns::default(),
546            change_points:
547                crate::performance_analytics_dashboard::data::ChangePointDetection::default(),
548            forecasts: crate::performance_analytics_dashboard::data::ForecastingResults::default(),
549        })
550    }
551
552    fn calculate_trend(&self, values: &[f64]) -> DeviceResult<(TrendDirection, f64)> {
553        if values.len() < 2 {
554            return Ok((TrendDirection::Stable, 0.0));
555        }
556
557        // Simple linear trend calculation
558        let n = values.len() as f64;
559        let x_mean = (n - 1.0) / 2.0;
560        let y_mean = values.iter().sum::<f64>() / n;
561
562        let mut numerator = 0.0;
563        let mut denominator = 0.0;
564
565        for (i, &y) in values.iter().enumerate() {
566            let x = i as f64;
567            numerator += (x - x_mean) * (y - y_mean);
568            denominator += (x - x_mean).powi(2);
569        }
570
571        if denominator == 0.0 {
572            return Ok((TrendDirection::Stable, 0.0));
573        }
574
575        let slope = numerator / denominator;
576        let strength = slope.abs();
577
578        let direction = if slope > 0.01 {
579            TrendDirection::Increasing
580        } else if slope < -0.01 {
581            TrendDirection::Decreasing
582        } else {
583            TrendDirection::Stable
584        };
585
586        Ok((direction, strength))
587    }
588}
589
590impl AnomalyDetector {
591    pub fn new(config: AnalyticsConfig) -> Self {
592        Self {
593            config,
594            detection_models: HashMap::new(),
595            baseline_statistics: HashMap::new(),
596            anomaly_history: VecDeque::new(),
597        }
598    }
599
600    pub async fn detect_anomalies(
601        &mut self,
602        metrics: &RealtimeMetrics,
603    ) -> DeviceResult<AnomalyDetectionResults> {
604        let mut current_anomalies = Vec::new();
605
606        // Check device metrics for anomalies
607        if let Some(anomaly) = self
608            .check_metric_anomaly("fidelity", metrics.device_metrics.fidelity)
609            .await?
610        {
611            current_anomalies.push(anomaly);
612        }
613
614        if let Some(anomaly) = self
615            .check_metric_anomaly("error_rate", metrics.device_metrics.error_rate)
616            .await?
617        {
618            current_anomalies.push(anomaly);
619        }
620
621        Ok(AnomalyDetectionResults {
622            current_anomalies: current_anomalies
623                .into_iter()
624                .map(|a| crate::performance_analytics_dashboard::data::Anomaly {
625                    timestamp: a
626                        .timestamp
627                        .duration_since(std::time::UNIX_EPOCH)
628                        .unwrap_or_default()
629                        .as_secs(),
630                    metric_name: a.metric_name,
631                    anomaly_score: a.confidence,
632                    anomaly_type: format!("{:?}", a.anomaly_type),
633                    description: format!("Anomaly detected with confidence {:.2}", a.confidence),
634                })
635                .collect(),
636            anomaly_history: vec![], // Simplified conversion
637            anomaly_patterns:
638                crate::performance_analytics_dashboard::data::AnomalyPatterns::default(),
639            root_cause_analysis:
640                crate::performance_analytics_dashboard::data::RootCauseAnalysis::default(),
641        })
642    }
643
644    async fn check_metric_anomaly(
645        &mut self,
646        metric_name: &str,
647        value: f64,
648    ) -> DeviceResult<Option<Anomaly>> {
649        // Get or create baseline for this metric
650        let baseline = if let Some(baseline) = self.baseline_statistics.get(metric_name) {
651            baseline.clone()
652        } else {
653            let new_baseline = self.create_baseline(metric_name);
654            self.baseline_statistics
655                .insert(metric_name.to_string(), new_baseline.clone());
656            new_baseline
657        };
658
659        // Simple statistical anomaly detection
660        let z_score = (value - baseline.mean) / baseline.std_dev;
661        let threshold = 3.0; // 3-sigma rule
662
663        if z_score.abs() > threshold {
664            let anomaly = Anomaly {
665                id: format!(
666                    "{}-{}",
667                    metric_name,
668                    SystemTime::now()
669                        .duration_since(std::time::UNIX_EPOCH)
670                        .unwrap()
671                        .as_secs()
672                ),
673                timestamp: SystemTime::now(),
674                metric_name: metric_name.to_string(),
675                anomaly_type: if z_score > 0.0 {
676                    AnomalyType::Spike
677                } else {
678                    AnomalyType::Drop
679                },
680                severity: if z_score.abs() > 5.0 {
681                    AnomalySeverity::Critical
682                } else {
683                    AnomalySeverity::High
684                },
685                current_value: value,
686                expected_value: baseline.mean,
687                confidence: (z_score.abs() - threshold) / threshold,
688                impact_assessment: ImpactAssessment {
689                    affected_systems: vec![metric_name.to_string()],
690                    impact_severity: "Medium".to_string(),
691                    estimated_duration: Some(Duration::from_secs(15 * 60)),
692                    business_impact: Some("Performance degradation".to_string()),
693                },
694            };
695
696            Ok(Some(anomaly))
697        } else {
698            Ok(None)
699        }
700    }
701
702    fn create_baseline(&self, metric_name: &str) -> BaselineStatistics {
703        // Default baseline statistics
704        let (mean, std_dev) = match metric_name {
705            "fidelity" => (0.95, 0.02),
706            "error_rate" => (0.01, 0.005),
707            "coherence_time" => (100.0, 10.0),
708            _ => (0.0, 1.0),
709        };
710
711        BaselineStatistics {
712            mean,
713            std_dev,
714            percentiles: HashMap::new(),
715            distribution_type: "normal".to_string(),
716            seasonal_patterns: Vec::new(),
717        }
718    }
719}
720
721impl PerformancePredictor {
722    pub fn new(config: PredictionConfig) -> Self {
723        Self {
724            config,
725            prediction_models: HashMap::new(),
726            feature_engineering: FeatureEngineeringPipeline {
727                transformations: Vec::new(),
728                feature_selection: FeatureSelectionMethod::VarianceThreshold { threshold: 0.01 },
729                preprocessing_steps: Vec::new(),
730            },
731            model_registry: ModelRegistry {
732                registered_models: HashMap::new(),
733                active_models: Vec::new(),
734                model_performance_history: HashMap::new(),
735            },
736        }
737    }
738
739    pub async fn predict_performance(
740        &mut self,
741        historical_data: &HashMap<String, Vec<f64>>,
742    ) -> DeviceResult<PerformancePredictions> {
743        // Simplified prediction implementation
744        Ok(PerformancePredictions::default())
745    }
746}
747
748// Default implementations
749impl Default for SeasonalPatterns {
750    fn default() -> Self {
751        Self {
752            daily_patterns: HashMap::new(),
753            weekly_patterns: HashMap::new(),
754            monthly_patterns: HashMap::new(),
755            seasonal_strength: HashMap::new(),
756        }
757    }
758}
759
760impl Default for ChangePointDetection {
761    fn default() -> Self {
762        Self {
763            change_points: Vec::new(),
764            change_point_probabilities: Vec::new(),
765            structural_breaks: Vec::new(),
766        }
767    }
768}
769
770impl Default for ForecastingResults {
771    fn default() -> Self {
772        Self {
773            forecasts: HashMap::new(),
774            forecast_accuracy: HashMap::new(),
775            uncertainty_bounds: HashMap::new(),
776        }
777    }
778}
779
780impl Default for AnomalyPatterns {
781    fn default() -> Self {
782        Self {
783            recurring_patterns: Vec::new(),
784            correlation_patterns: Vec::new(),
785            temporal_patterns: Vec::new(),
786        }
787    }
788}
789
790impl Default for RootCauseAnalysis {
791    fn default() -> Self {
792        Self {
793            probable_causes: Vec::new(),
794            causal_chains: Vec::new(),
795            correlation_analysis: CorrelationAnalysisResult {
796                metric_correlations: HashMap::new(),
797                time_lag_correlations: HashMap::new(),
798                cross_correlations: HashMap::new(),
799            },
800            recommendation_score: 0.0,
801        }
802    }
803}