sc_neurocore_engine/neurons/trivial/
mat.rs1#[derive(Clone, Debug)]
11pub struct MATNeuron {
12 pub v: f64,
13 pub theta1: f64,
14 pub theta2: f64,
15 pub v_rest: f64,
16 pub v_reset: f64,
17 pub v_threshold_base: f64,
18 pub tau_m: f64,
19 pub tau_1: f64,
20 pub tau_2: f64,
21 pub h1: f64,
22 pub h2: f64,
23 pub resistance: f64,
24 pub dt: f64,
25}
26
27impl MATNeuron {
28 pub fn new() -> Self {
29 Self {
30 v: -70.0,
31 theta1: 0.0,
32 theta2: 0.0,
33 v_rest: -70.0,
34 v_reset: -70.0,
35 v_threshold_base: -50.0,
36 tau_m: 10.0,
37 tau_1: 10.0,
38 tau_2: 200.0,
39 h1: 5.0,
40 h2: 3.0,
41 resistance: 1.0,
42 dt: 1.0,
43 }
44 }
45
46 pub fn step(&mut self, current: f64) -> i32 {
47 self.v += (-(self.v - self.v_rest) + self.resistance * current) / self.tau_m * self.dt;
48 self.theta1 *= (-self.dt / self.tau_1).exp();
49 self.theta2 *= (-self.dt / self.tau_2).exp();
50 let threshold = self.v_threshold_base + self.theta1 + self.theta2;
51 if self.v >= threshold {
52 self.v = self.v_reset;
53 self.theta1 += self.h1;
54 self.theta2 += self.h2;
55 1
56 } else {
57 0
58 }
59 }
60
61 pub fn reset(&mut self) {
62 self.v = self.v_rest;
63 self.theta1 = 0.0;
64 self.theta2 = 0.0;
65 }
66}
67
68impl Default for MATNeuron {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn mat_dual_threshold_adapts() {
80 let mut n = MATNeuron::new();
81 let total: i32 = (0..200).map(|_| n.step(30.0)).sum();
82 assert!(total > 0);
83 assert!(n.theta1 > 0.0 || n.theta2 > 0.0);
84 }
85 #[test]
86 fn mat_silent_without_input() {
87 let mut n = MATNeuron::new();
88 let t: i32 = (0..200).map(|_| n.step(0.0)).sum();
89 assert_eq!(t, 0);
90 }
91 #[test]
92 fn mat_reset_clears_state() {
93 let mut n = MATNeuron::new();
94 for _ in 0..100 {
95 n.step(30.0);
96 }
97 n.reset();
98 assert!((n.v - n.v_rest).abs() < 1e-10);
99 assert!((n.theta1 - 0.0).abs() < 1e-10);
100 assert!((n.theta2 - 0.0).abs() < 1e-10);
101 }
102 #[test]
103 fn mat_bounded() {
104 let mut n = MATNeuron::new();
105 for _ in 0..1000 {
106 n.step(1e4);
107 }
108 assert!(n.v.is_finite());
109 }
110 #[test]
111 fn mat_nan_no_panic() {
112 MATNeuron::new().step(f64::NAN);
113 }
114}