use crate::estimate::Estimate;
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct CognitiveSplit {
pub statistical_complexity: Estimate<f64>,
pub entropy_rate: Estimate<f64>,
}
impl CognitiveSplit {
#[must_use]
pub fn structure_noise_ratio(&self) -> Option<f64> {
if self.entropy_rate.point.abs() < f64::EPSILON {
return None; }
Some(self.statistical_complexity.point / self.entropy_rate.point)
}
#[must_use]
pub fn is_structured(&self) -> bool {
self.structure_noise_ratio().is_none_or(|r| r > 1.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::estimate::Estimate;
#[test]
fn structured_stream_ratio_gt_one() {
let g = CognitiveSplit {
statistical_complexity: Estimate::exact(4.0),
entropy_rate: Estimate::exact(1.0),
};
let r = g.structure_noise_ratio().unwrap();
assert!((r - 4.0).abs() < f64::EPSILON);
assert!(g.is_structured());
}
#[test]
fn noisy_stream_ratio_lt_one() {
let g = CognitiveSplit {
statistical_complexity: Estimate::exact(0.5),
entropy_rate: Estimate::exact(2.0),
};
assert!(!g.is_structured());
}
#[test]
fn deterministic_stream_returns_none_and_is_structured() {
let g = CognitiveSplit {
statistical_complexity: Estimate::exact(3.0),
entropy_rate: Estimate::exact(0.0),
};
assert!(g.structure_noise_ratio().is_none());
assert!(g.is_structured()); }
#[test]
fn equal_complexity_and_entropy_ratio_is_one() {
let g = CognitiveSplit {
statistical_complexity: Estimate::exact(2.0),
entropy_rate: Estimate::exact(2.0),
};
let r = g.structure_noise_ratio().unwrap();
assert!((r - 1.0).abs() < f64::EPSILON);
}
}