use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DecisionTrigger {
EnergyThreshold {
threshold: f32,
upward: bool,
},
DendriticCoincidence {
active_synapses: usize,
threshold: usize,
},
HysteresisChange {
from_state: HysteresisState,
to_state: HysteresisState,
},
OscillatorSync {
coherence: f32,
},
WorkspaceBroadcast {
significance: f32,
},
Manual,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum HysteresisState {
Low,
Transition,
High,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct DecisionConfidence {
pub overall: f32,
pub energy_confidence: f32,
pub dendritic_confidence: f32,
pub oscillator_confidence: f32,
pub supporting_evidence: usize,
}
impl DecisionConfidence {
pub fn new(
energy_confidence: f32,
dendritic_confidence: f32,
oscillator_confidence: f32,
supporting_evidence: usize,
) -> Self {
let overall = (energy_confidence * 0.4
+ dendritic_confidence * 0.3
+ oscillator_confidence * 0.3)
.clamp(0.0, 1.0);
Self {
overall,
energy_confidence,
dendritic_confidence,
oscillator_confidence,
supporting_evidence,
}
}
pub fn low() -> Self {
Self {
overall: 0.3,
energy_confidence: 0.3,
dendritic_confidence: 0.3,
oscillator_confidence: 0.3,
supporting_evidence: 0,
}
}
pub fn high() -> Self {
Self {
overall: 0.95,
energy_confidence: 0.95,
dendritic_confidence: 0.95,
oscillator_confidence: 0.95,
supporting_evidence: 5,
}
}
pub fn is_trustworthy(&self) -> bool {
self.overall >= 0.7 && self.supporting_evidence >= 2
}
}
impl Default for DecisionConfidence {
fn default() -> Self {
Self::low()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NeuralDecision {
pub allow: bool,
pub confidence: DecisionConfidence,
pub hysteresis_state: HysteresisState,
pub trigger: DecisionTrigger,
pub energy: f32,
pub smoothed_energy: f32,
pub timestamp_ms: u64,
pub should_broadcast: bool,
}
impl NeuralDecision {
pub fn new(
allow: bool,
energy: f32,
smoothed_energy: f32,
hysteresis_state: HysteresisState,
trigger: DecisionTrigger,
confidence: DecisionConfidence,
) -> Self {
let should_broadcast = !allow || confidence.overall > 0.9;
Self {
allow,
confidence,
hysteresis_state,
trigger,
energy,
smoothed_energy,
timestamp_ms: current_time_ms(),
should_broadcast,
}
}
pub fn allow(energy: f32) -> Self {
Self::new(
true,
energy,
energy,
HysteresisState::Low,
DecisionTrigger::Manual,
DecisionConfidence::high(),
)
}
pub fn deny(energy: f32, reason: DecisionTrigger) -> Self {
Self::new(
false,
energy,
energy,
HysteresisState::High,
reason,
DecisionConfidence::high(),
)
}
pub fn is_significant(&self) -> bool {
!self.allow || self.confidence.overall > 0.8 || self.should_broadcast
}
pub fn description(&self) -> String {
let action = if self.allow { "ALLOW" } else { "DENY" };
let state = match self.hysteresis_state {
HysteresisState::Low => "coherent",
HysteresisState::Transition => "uncertain",
HysteresisState::High => "incoherent",
};
format!(
"{} (energy={:.3}, state={}, confidence={:.2})",
action, self.energy, state, self.confidence.overall
)
}
}
fn current_time_ms() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_millis() as u64)
.unwrap_or(0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_decision_confidence() {
let low = DecisionConfidence::low();
assert!(!low.is_trustworthy());
let high = DecisionConfidence::high();
assert!(high.is_trustworthy());
let mixed = DecisionConfidence::new(0.8, 0.7, 0.6, 3);
assert!(mixed.is_trustworthy());
}
#[test]
fn test_neural_decision() {
let allow = NeuralDecision::allow(0.1);
assert!(allow.allow);
assert_eq!(allow.hysteresis_state, HysteresisState::Low);
let deny = NeuralDecision::deny(0.9, DecisionTrigger::Manual);
assert!(!deny.allow);
assert!(deny.is_significant());
}
}