Skip to main content

oxirs_samm/analytics/
modelanalytics_compute_kendall_correlations_group.rs

1//! # ModelAnalytics - compute_kendall_correlations_group Methods
2//!
3//! This module contains method implementations for `ModelAnalytics`.
4//!
5//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
6
7use super::modelanalytics_type::ModelAnalytics;
8use crate::analytics::{
9    CorrelationDirection, CorrelationInsight, CorrelationStrength, PropertyCorrelationMatrix,
10};
11use scirs2_core::ndarray_ext::Array1;
12use std::collections::{HashMap, HashSet};
13
14fn generate_correlation_interpretation(feat1: &str, feat2: &str, coef: f64) -> String {
15    let direction = if coef > 0.0 { "increases" } else { "decreases" };
16    let strength = if coef.abs() > 0.7 {
17        "strongly"
18    } else if coef.abs() > 0.5 {
19        "moderately"
20    } else {
21        "weakly"
22    };
23    format!(
24        "As {} increases, {} {} {}",
25        feat1, feat2, strength, direction
26    )
27}
28
29impl ModelAnalytics {
30    /// Compute Kendall tau correlations between model properties
31    ///
32    /// Kendall tau is a non-parametric measure of ordinal association.
33    /// It measures the similarity of orderings when ranked by each variable.
34    /// More robust to errors and discrepancies in data than other methods.
35    ///
36    /// # Returns
37    ///
38    /// A correlation matrix with Kendall tau correlation coefficients and insights
39    ///
40    /// # Example
41    ///
42    /// ```rust,ignore
43    /// use oxirs_samm::analytics::ModelAnalytics;
44    /// use oxirs_samm::metamodel::Aspect;
45    ///
46    /// # fn example(aspect: &Aspect) -> Result<(), Box<dyn std::error::Error>> {
47    /// let analytics = ModelAnalytics::from_aspect(aspect)?;
48    /// let kendall = analytics.compute_kendall_correlations();
49    ///
50    /// println!("Kendall tau correlation matrix computed");
51    /// println!("Features analyzed: {:?}", kendall.feature_names);
52    /// for insight in &kendall.insights {
53    ///     println!("  {} <-> {}: {:.3}", insight.feature1, insight.feature2, insight.coefficient);
54    /// }
55    /// # Ok(())
56    /// # }
57    /// ```
58    pub fn compute_kendall_correlations(&self) -> PropertyCorrelationMatrix {
59        use scirs2_stats::{CorrelationBuilder, CorrelationMethod};
60        let features = [
61            (
62                "property_count",
63                self.distributions.property_distribution.mean,
64            ),
65            (
66                "structural_complexity",
67                self.complexity_assessment.structural,
68            ),
69            ("cognitive_complexity", self.complexity_assessment.cognitive),
70            ("coupling", self.complexity_assessment.coupling * 100.0),
71            ("quality_score", self.quality_score),
72        ];
73        let n = features.len();
74        let mut matrix = vec![vec![0.0; n]; n];
75        let mut insights = Vec::new();
76        for i in 0..n {
77            for j in 0..n {
78                if i == j {
79                    matrix[i][j] = 1.0;
80                    continue;
81                }
82                if i > j {
83                    matrix[i][j] = matrix[j][i];
84                    continue;
85                }
86                let x = Array1::from_vec(vec![features[i].1]);
87                let y = Array1::from_vec(vec![features[j].1]);
88                let corr_result = CorrelationBuilder::new()
89                    .method(CorrelationMethod::Kendall)
90                    .compute(x.view(), y.view());
91                let coefficient: f64 = match corr_result {
92                    Ok(result) => result.value.correlation,
93                    Err(_) => 0.0,
94                };
95                matrix[i][j] = coefficient;
96                let abs_coef = coefficient.abs();
97                if abs_coef > 0.3 && i != j {
98                    let strength = if abs_coef > 0.7 {
99                        CorrelationStrength::Strong
100                    } else if abs_coef > 0.5 {
101                        CorrelationStrength::Moderate
102                    } else {
103                        CorrelationStrength::Weak
104                    };
105                    let direction = if coefficient > 0.0 {
106                        CorrelationDirection::Positive
107                    } else {
108                        CorrelationDirection::Negative
109                    };
110                    insights.push(CorrelationInsight {
111                        feature1: features[i].0.to_string(),
112                        feature2: features[j].0.to_string(),
113                        coefficient,
114                        strength,
115                        direction,
116                        interpretation: generate_correlation_interpretation(
117                            features[i].0,
118                            features[j].0,
119                            coefficient,
120                        ),
121                    });
122                }
123            }
124        }
125        PropertyCorrelationMatrix {
126            feature_names: features.iter().map(|(name, _)| name.to_string()).collect(),
127            correlation_matrix: matrix,
128            insights,
129            method: "Kendall".to_string(),
130        }
131    }
132}