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}