sc_neurocore_engine/neurons/trivial/
klif.rs1#[derive(Clone, Debug)]
11pub struct KLIFNeuron {
12 pub v: f64,
13 pub k: f64,
14 pub alpha: f64,
15 pub v_threshold: f64,
16 pub v_reset: f64,
17}
18
19impl KLIFNeuron {
20 pub fn new(tau: f64, k: f64, dt: f64) -> Self {
21 Self {
22 v: 0.0,
23 k,
24 alpha: (-dt / tau).exp(),
25 v_threshold: 1.0,
26 v_reset: 0.0,
27 }
28 }
29
30 pub fn step(&mut self, current: f64) -> i32 {
31 self.v = self.alpha * self.v + self.k * current;
32 if self.v >= self.v_threshold {
33 self.v = self.v_reset;
34 1
35 } else {
36 0
37 }
38 }
39
40 pub fn reset(&mut self) {
41 self.v = 0.0;
42 }
43}
44
45impl Default for KLIFNeuron {
46 fn default() -> Self {
47 Self::new(10.0, 1.0, 1.0)
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn klif_fires() {
57 let mut n = KLIFNeuron::default();
58 let total: i32 = (0..50).map(|_| n.step(0.5)).sum();
59 assert!(total > 0);
60 }
61 #[test]
62 fn klif_silent_without_input() {
63 let mut n = KLIFNeuron::default();
64 let t: i32 = (0..100).map(|_| n.step(0.0)).sum();
65 assert_eq!(t, 0);
66 }
67 #[test]
68 fn klif_reset_clears_state() {
69 let mut n = KLIFNeuron::default();
70 for _ in 0..20 {
71 n.step(0.5);
72 }
73 n.reset();
74 assert!((n.v - 0.0).abs() < 1e-10);
75 }
76 #[test]
77 fn klif_bounded() {
78 let mut n = KLIFNeuron::default();
79 for _ in 0..1000 {
80 n.step(100.0);
81 }
82 assert!(n.v.is_finite());
83 }
84 #[test]
85 fn klif_nan_no_panic() {
86 KLIFNeuron::default().step(f64::NAN);
87 }
88}