rustorch 0.6.29

Production-ready PyTorch-compatible deep learning library in Rust with special mathematical functions (gamma, Bessel, error functions), statistical distributions, Fourier transforms (FFT/RFFT), matrix decomposition (SVD/QR/LU/eigenvalue), automatic differentiation, neural networks, computer vision transforms, complete GPU acceleration (CUDA/Metal/OpenCL), SIMD optimizations, parallel processing, WebAssembly browser support, comprehensive distributed learning support, and performance validation
Documentation
//! Anomaly Detection System
//! 異常検出システム

use crate::error::{RusTorchError, RusTorchResult};
use std::collections::HashMap;
use std::fmt;

/// Anomaly detector for statistical outlier detection
/// 統計的外れ値検出のための異常検出器
#[derive(Debug)]
pub struct AnomalyDetector {
    /// Configuration settings
    /// 設定
    config: AnomalyConfiguration,
    /// Detection statistics
    /// 検出統計
    stats: AnomalyStatistics,
}

/// Anomaly detection configuration
/// 異常検出設定
#[derive(Debug, Clone)]
pub struct AnomalyConfiguration {
    /// Statistical methods to use
    /// 使用する統計手法
    pub methods: Vec<StatisticalMethod>,
    /// Sensitivity threshold (0.0-1.0)
    /// 感度閾値(0.0-1.0)
    pub sensitivity: f64,
    /// Minimum anomaly score to report
    /// レポートする最小異常スコア
    pub min_score_threshold: f64,
}

impl Default for AnomalyConfiguration {
    fn default() -> Self {
        Self {
            methods: vec![StatisticalMethod::ZScore, StatisticalMethod::IQR],
            sensitivity: 0.05, // 5% significance level
            min_score_threshold: 0.8,
        }
    }
}

/// Statistical methods for anomaly detection
/// 異常検出の統計手法
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StatisticalMethod {
    /// Z-Score method
    /// Zスコア法
    ZScore,
    /// Interquartile Range method
    /// 四分位範囲法
    IQR,
    /// Modified Z-Score method
    /// 修正Zスコア法
    ModifiedZScore,
    /// Isolation Forest
    /// 分離フォレスト
    IsolationForest,
    /// Local Outlier Factor
    /// 局所外れ値因子
    LOF,
}

/// Anomaly detection result
/// 異常検出結果
#[derive(Debug, Clone)]
pub struct AnomalyResult {
    /// Number of anomalies found
    /// 発見された異常数
    pub anomalies_found: usize,
    /// Detailed anomaly information
    /// 詳細異常情報
    pub anomalies: Vec<AnomalyInfo>,
    /// Overall anomaly score
    /// 総合異常スコア
    pub overall_score: f64,
    /// Methods used for detection
    /// 検出に使用された手法
    pub methods_used: Vec<StatisticalMethod>,
}

/// Individual anomaly information
/// 個別異常情報
#[derive(Debug, Clone)]
pub struct AnomalyInfo {
    /// Anomaly type
    /// 異常タイプ
    pub anomaly_type: AnomalyType,
    /// Confidence score (0.0-1.0)
    /// 信頼スコア(0.0-1.0)
    pub confidence: f64,
    /// Statistical score
    /// 統計スコア
    pub score: f64,
    /// Location in data
    /// データ内の位置
    pub location: Option<Vec<usize>>,
    /// Description
    /// 説明
    pub description: String,
}

/// Types of anomalies
/// 異常のタイプ
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AnomalyType {
    /// Statistical outlier
    /// 統計的外れ値
    StatisticalOutlier,
    /// Extreme value
    /// 極端値
    ExtremeValue,
    /// Pattern anomaly
    /// パターン異常
    PatternAnomaly,
    /// Contextual anomaly
    /// コンテキスト異常
    ContextualAnomaly,
}

/// Outlier detection methods
/// 外れ値検出手法
pub struct OutlierDetection;

impl OutlierDetection {
    /// Z-Score based outlier detection
    /// Zスコアベース外れ値検出
    pub fn z_score_method(data: &[f64], threshold: f64) -> Vec<usize> {
        if data.len() < 2 {
            return Vec::new();
        }

        let mean = data.iter().sum::<f64>() / data.len() as f64;
        let variance = data.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / data.len() as f64;
        let std_dev = variance.sqrt();

        if std_dev == 0.0 {
            return Vec::new();
        }

        data.iter()
            .enumerate()
            .filter_map(|(i, &value)| {
                let z_score = (value - mean).abs() / std_dev;
                if z_score > threshold {
                    Some(i)
                } else {
                    None
                }
            })
            .collect()
    }

    /// IQR based outlier detection
    /// IQRベース外れ値検出
    pub fn iqr_method(data: &[f64]) -> Vec<usize> {
        if data.len() < 4 {
            return Vec::new();
        }

        let mut sorted_data = data.to_vec();
        sorted_data.sort_by(|a, b| a.partial_cmp(b).unwrap());

        let q1_idx = sorted_data.len() / 4;
        let q3_idx = 3 * sorted_data.len() / 4;
        let q1 = sorted_data[q1_idx];
        let q3 = sorted_data[q3_idx];
        let iqr = q3 - q1;

        let lower_bound = q1 - 1.5 * iqr;
        let upper_bound = q3 + 1.5 * iqr;

        data.iter()
            .enumerate()
            .filter_map(|(i, &value)| {
                if value < lower_bound || value > upper_bound {
                    Some(i)
                } else {
                    None
                }
            })
            .collect()
    }
}

/// Anomaly detection statistics
/// 異常検出統計
#[derive(Debug, Default)]
pub struct AnomalyStatistics {
    /// Total detections performed
    /// 実行された総検出数
    pub total_detections: usize,
    /// Total anomalies found
    /// 発見された総異常数
    pub total_anomalies: usize,
    /// Anomalies by type
    /// タイプ別異常
    pub anomalies_by_type: HashMap<AnomalyType, usize>,
}

impl AnomalyDetector {
    /// Create new anomaly detector
    /// 新しい異常検出器を作成
    pub fn new(config: AnomalyConfiguration) -> Self {
        Self {
            config,
            stats: AnomalyStatistics::default(),
        }
    }

    /// Detect anomalies in tensor data
    /// テンソルデータの異常を検出
    pub fn detect_anomalies<T>(
        &mut self,
        _tensor: &crate::tensor::Tensor<T>,
    ) -> RusTorchResult<AnomalyResult>
    where
        T: num_traits::Float + std::fmt::Debug + Clone + Send + Sync + 'static,
    {
        // Placeholder implementation - would extract actual values and analyze
        let dummy_data = vec![1.0, 2.0, 3.0, 100.0, 4.0, 5.0]; // Simulated data with outlier

        let mut all_anomalies = Vec::new();
        let mut methods_used = Vec::new();

        for method in &self.config.methods {
            let outliers = match method {
                StatisticalMethod::ZScore => {
                    methods_used.push(method.clone());
                    OutlierDetection::z_score_method(&dummy_data, 2.0)
                }
                StatisticalMethod::IQR => {
                    methods_used.push(method.clone());
                    OutlierDetection::iqr_method(&dummy_data)
                }
                _ => Vec::new(), // Placeholder for other methods
            };

            for outlier_idx in outliers {
                all_anomalies.push(AnomalyInfo {
                    anomaly_type: AnomalyType::StatisticalOutlier,
                    confidence: 0.9,
                    score: 0.95,
                    location: Some(vec![outlier_idx]),
                    description: format!("Statistical outlier detected using {:?}", method),
                });
            }
        }

        self.stats.total_detections += 1;
        self.stats.total_anomalies += all_anomalies.len();

        Ok(AnomalyResult {
            anomalies_found: all_anomalies.len(),
            anomalies: all_anomalies.clone(),
            overall_score: if all_anomalies.is_empty() { 0.0 } else { 0.8 },
            methods_used,
        })
    }

    /// Get anomaly count
    /// 異常数を取得
    pub fn get_anomaly_count(&self) -> usize {
        self.stats.total_anomalies
    }
}