sc_neurocore_engine/neurons/
ibarz_tanaka_map.rs1#[derive(Clone, Debug)]
13pub struct IbarzTanakaMapNeuron {
14 pub v: f64,
15 pub u: f64,
16 pub alpha: f64,
17 pub mu: f64,
18 pub sigma: f64,
19}
20
21impl IbarzTanakaMapNeuron {
22 pub fn new() -> Self {
23 Self {
24 v: -1.0,
25 u: -0.1,
26 alpha: 1.0,
27 mu: 0.001,
28 sigma: 0.1,
29 }
30 }
31
32 fn parameters_are_valid(&self) -> bool {
33 self.alpha.is_finite()
34 && self.mu.is_finite()
35 && self.sigma.is_finite()
36 && self.alpha > 0.0
37 && self.mu > 0.0
38 }
39
40 fn candidate(&self, current: f64) -> Result<(f64, f64, i32), &'static str> {
41 let lower = -1.0 - self.alpha / 2.0;
42 let upper = 1.0 + current + self.u;
43 let v_next = if self.v < lower {
44 -(self.alpha * self.alpha) / 4.0 - self.alpha + current + self.u
45 } else if self.v <= 0.0 {
46 self.alpha * self.v + (self.v + 1.0) * (self.v + 1.0) + current + self.u
47 } else if self.v < upper {
48 upper
49 } else {
50 -1.0
51 };
52 let u_next = self.u - self.mu * (self.v + 1.0 - self.sigma);
53 if !v_next.is_finite() || !u_next.is_finite() {
54 return Err("invalid Ibarz-Tanaka map candidate");
55 }
56 Ok((v_next, u_next, i32::from(self.v >= upper)))
57 }
58
59 pub fn try_step(&mut self, current: f64) -> Result<i32, &'static str> {
61 if !self.v.is_finite() || !self.u.is_finite() || !self.parameters_are_valid() {
62 return Err("invalid Ibarz-Tanaka runtime state");
63 }
64 if !current.is_finite() {
65 return Err("invalid Ibarz-Tanaka current");
66 }
67 let (v_next, u_next, event) = self.candidate(current)?;
68 self.v = v_next;
69 self.u = u_next;
70 Ok(event)
71 }
72
73 pub fn step(&mut self, current: f64) -> i32 {
75 self.try_step(current).unwrap_or(0)
76 }
77
78 pub fn simulate(
80 &mut self,
81 n_steps: usize,
82 current: f64,
83 ) -> Result<(Vec<f64>, i64), &'static str> {
84 let mut trace = Vec::with_capacity(n_steps);
85 let mut events = 0_i64;
86 for _ in 0..n_steps {
87 events += i64::from(self.try_step(current)?);
88 trace.push(self.v);
89 }
90 Ok((trace, events))
91 }
92
93 pub fn reset(&mut self) {
94 self.v = -1.0;
95 self.u = -0.1;
96 }
97}
98impl Default for IbarzTanakaMapNeuron {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn ibarz_fires() {
110 let mut n = IbarzTanakaMapNeuron::new();
111 let t: i32 = (0..2000).map(|_| n.step(2.0)).sum();
112 assert!(t > 0);
113 }
114}