use rand::Rng;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PoissonEncoder {
pub num_steps: usize,
}
impl PoissonEncoder {
pub fn new(steps: usize) -> Self {
Self { num_steps: steps }
}
pub fn encode(&self, input: f32) -> Vec<u8> {
let mut rng = rand::thread_rng();
let mut spikes = Vec::with_capacity(self.num_steps);
let probability = input.clamp(0.0, 1.0);
for _ in 0..self.num_steps {
if rng.r#gen::<f32>() < probability {
spikes.push(1);
} else {
spikes.push(0);
}
}
spikes
}
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct LifNeuron {
pub membrane_potential: f32, pub decay_rate: f32, pub threshold: f32, #[serde(default)]
pub base_threshold: f32,
pub last_spike: bool, #[serde(default)]
pub weights: Vec<f32>,
#[serde(default)]
pub last_spike_time: i64,
}
impl Default for LifNeuron {
fn default() -> Self {
Self {
membrane_potential: 0.0,
decay_rate: 0.15,
threshold: 0.02, base_threshold: 0.02,
last_spike: false,
weights: Vec::new(),
last_spike_time: -1,
}
}
}
impl LifNeuron {
pub fn new() -> Self {
Self::default()
}
pub fn integrate(&mut self, stimulus: f32) {
self.membrane_potential += stimulus;
self.membrane_potential -= self.membrane_potential * self.decay_rate;
}
pub fn check_fire(&mut self) -> Option<f32> {
if self.membrane_potential >= self.threshold {
let peak = self.membrane_potential; self.membrane_potential = 0.0; return Some(peak);
}
None
}
}