sc_neurocore_engine/neurons/trivial/
gated_lif.rs1#[derive(Clone, Debug)]
11pub struct GatedLIFNeuron {
12 pub v: f64,
13 pub gate_v: f64,
14 pub gate_i: f64,
15 pub v_threshold: f64,
16 pub dt: f64,
17}
18
19impl GatedLIFNeuron {
20 pub fn new(gate_v: f64, gate_i: f64, v_threshold: f64) -> Self {
21 Self {
22 v: 0.0,
23 gate_v,
24 gate_i,
25 v_threshold,
26 dt: 1.0,
27 }
28 }
29
30 pub fn step(&mut self, current: f64) -> i32 {
31 self.v = self.gate_v * self.v + self.gate_i * current;
32 if self.v >= self.v_threshold {
33 self.v -= self.v_threshold;
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 GatedLIFNeuron {
46 fn default() -> Self {
47 Self::new(0.9, 1.0, 1.0)
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn gated_lif_fires() {
57 let mut n = GatedLIFNeuron::default();
58 let total: i32 = (0..20).map(|_| n.step(0.5)).sum();
59 assert!(total > 0);
60 }
61 #[test]
62 fn gated_lif_silent_without_input() {
63 let mut n = GatedLIFNeuron::default();
64 let t: i32 = (0..100).map(|_| n.step(0.0)).sum();
65 assert_eq!(t, 0);
66 }
67 #[test]
68 fn gated_lif_reset_clears_state() {
69 let mut n = GatedLIFNeuron::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 gated_lif_bounded() {
78 let mut n = GatedLIFNeuron::default();
79 for _ in 0..1000 {
80 n.step(100.0);
81 }
82 assert!(n.v.is_finite());
83 }
84 #[test]
85 fn gated_lif_nan_no_panic() {
86 GatedLIFNeuron::default().step(f64::NAN);
87 }
88}