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