Skip to main content

sc_neurocore_engine/neurons/hardware/
akida.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Commercial license available
3// © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
4// © Code 2020–2026 Miroslav Šotek. All rights reserved.
5// ORCID: 0009-0009-3560-0851
6// Contact: www.anulum.li | protoscience@anulum.li
7// SC-NeuroCore — Akida Neuron Emulator
8
9/// Akida — BrainChip event-domain rank-order neuron.
10#[derive(Clone, Debug)]
11pub struct AkidaNeuron {
12    pub v: i32,
13    pub threshold: i32,
14    pub modulation: f64,
15    pub rank: i32,
16    pub spiked: bool,
17}
18
19impl AkidaNeuron {
20    pub fn new(threshold: i32) -> Self {
21        Self {
22            v: 0,
23            threshold,
24            modulation: 0.75,
25            rank: 0,
26            spiked: false,
27        }
28    }
29    pub fn step(&mut self, weight: f64) -> i32 {
30        if self.spiked {
31            return 0;
32        }
33        self.v += (weight * self.modulation.powi(self.rank)) as i32;
34        self.rank += 1;
35        if self.v >= self.threshold {
36            self.spiked = true;
37            1
38        } else {
39            0
40        }
41    }
42    pub fn reset(&mut self) {
43        self.v = 0;
44        self.rank = 0;
45        self.spiked = false;
46    }
47}
48impl Default for AkidaNeuron {
49    fn default() -> Self {
50        Self::new(100)
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn akida_fires() {
60        let mut n = AkidaNeuron::default();
61        let t: i32 = (0..10).map(|_| n.step(50.0)).sum();
62        assert!(t > 0);
63    }
64    #[test]
65    fn akida_silent() {
66        let mut n = AkidaNeuron::default();
67        let t: i32 = (0..100).map(|_| n.step(0.0)).sum();
68        assert_eq!(t, 0);
69    }
70    #[test]
71    fn akida_reset() {
72        let mut n = AkidaNeuron::default();
73        for _ in 0..10 {
74            n.step(50.0);
75        }
76        n.reset();
77    }
78    #[test]
79    fn akida_nan_no_panic() {
80        AkidaNeuron::default().step(f64::NAN);
81    }
82}