use burn::tensor::backend::Backend;
use burn::tensor::Tensor;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ResetMode {
#[default]
Subtract,
Zero,
None,
}
pub fn apply_reset<B: Backend>(
mem_new: Tensor<B, 2>,
spike_hard: &Tensor<B, 2>,
threshold: f32,
mode: ResetMode,
) -> Tensor<B, 2> {
match mode {
ResetMode::Subtract => mem_new - spike_hard.clone().mul_scalar(threshold),
ResetMode::Zero => mem_new.clone() * (spike_hard.clone().mul_scalar(-1.0).add_scalar(1.0)),
ResetMode::None => mem_new,
}
}
#[derive(Debug, Clone)]
pub struct NeuronState<B: Backend> {
pub mem: Tensor<B, 2>,
pub syn: Option<Tensor<B, 2>>,
}
impl<B: Backend> NeuronState<B> {
pub fn zeros(device: &B::Device, batch_size: usize, units: usize) -> Self {
let mem = Tensor::zeros([batch_size, units], device);
let syn = Tensor::zeros([batch_size, units], device);
Self {
mem,
syn: Some(syn),
}
}
pub fn zeros_mem_only(device: &B::Device, batch_size: usize, units: usize) -> Self {
let mem = Tensor::zeros([batch_size, units], device);
Self { mem, syn: None }
}
pub fn new(mem: Tensor<B, 2>, syn: Option<Tensor<B, 2>>) -> Self {
Self { mem, syn }
}
}
#[derive(Debug, Clone)]
pub struct LayerState<B: Backend> {
pub trace: Tensor<B, 2>,
pub mem: Tensor<B, 2>,
pub last_trace: Option<Tensor<B, 2>>,
pub last_output: Option<Tensor<B, 2>>,
}
impl<B: Backend> LayerState<B> {
pub fn zeros(
device: &B::Device,
batch_size: usize,
in_features: usize,
out_features: usize,
with_kan_cache: bool,
) -> Self {
let trace = Tensor::zeros([batch_size, in_features], device);
let mem = Tensor::zeros([batch_size, out_features], device);
let (last_trace, last_output) = if with_kan_cache {
(
Some(Tensor::zeros([batch_size, in_features], device)),
Some(Tensor::zeros([batch_size, out_features], device)),
)
} else {
(None, None)
};
Self {
trace,
mem,
last_trace,
last_output,
}
}
}