Skip to main content

sc_neurocore_engine/scpn/
metrics.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Commercial license available
3// © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
4// © Code 2020–2026 Miroslav Šotek. All rights reserved.
5// ORCID: 0009-0009-3560-0851
6// Contact: www.anulum.li | protoscience@anulum.li
7// SC-NeuroCore — SCPN Metrics
8
9//! # SCPN Metrics
10//!
11//! Composite metrics computed from multi-layer SCPN outputs.
12
13/// SCPN-wide metrics computed from the 7-layer outputs.
14pub struct SCPNMetrics;
15
16impl SCPNMetrics {
17    /// Compute weighted global coherence across all layers.
18    /// weights: per-layer importance weights (7,)
19    /// metrics: per-layer global metric values (7,)
20    /// Returns: weighted average coherence ∈ [0, 1]
21    pub fn global_coherence(weights: &[f64; 7], metrics: &[f64; 7]) -> f64 {
22        let mut weighted_sum = 0.0_f64;
23        let mut weight_total = 0.0_f64;
24
25        for idx in 0..7 {
26            let weight = weights[idx].max(0.0);
27            let metric = metrics[idx].clamp(0.0, 1.0);
28            weighted_sum += weight * metric;
29            weight_total += weight;
30        }
31
32        if weight_total == 0.0 {
33            0.0
34        } else {
35            (weighted_sum / weight_total).clamp(0.0, 1.0)
36        }
37    }
38
39    /// Compute the "consciousness index" — a composite score
40    /// based on cross-layer synchronization.
41    /// phases_l4: Kuramoto phases from L4
42    /// glyph_l7: Glyph vector from L7
43    /// Returns: index ∈ [0, 1]
44    pub fn consciousness_index(phases_l4: &[f64], glyph_l7: &[f64; 6]) -> f64 {
45        let phase_sync = if phases_l4.is_empty() {
46            0.0
47        } else {
48            let n_inv = 1.0 / phases_l4.len() as f64;
49            let mean_cos = phases_l4.iter().map(|theta| theta.cos()).sum::<f64>() * n_inv;
50            let mean_sin = phases_l4.iter().map(|theta| theta.sin()).sum::<f64>() * n_inv;
51            (mean_cos * mean_cos + mean_sin * mean_sin)
52                .sqrt()
53                .clamp(0.0, 1.0)
54        };
55
56        let glyph_norm =
57            (glyph_l7.iter().map(|v| v * v).sum::<f64>().sqrt() / (6.0_f64).sqrt()).clamp(0.0, 1.0);
58
59        (0.7 * phase_sync + 0.3 * glyph_norm).clamp(0.0, 1.0)
60    }
61}