Biologically grounded spiking neural network (SNN) primitives in Rust: a topology-neutral SpikingNetwork engine, generic neuromodulators, STDP building blocks, and standalone neuron models.
neuromod is a reusable core library: topology-neutral at initialization, dynamically sizable at runtime, and strict about input shape validation. Dual-licensed MIT OR Apache-2.0.
- Dynamic network sizing with
SpikingNetwork::with_dimensions(...) - Backward-compatible default constructor:
SpikingNetwork::new() - Strict step contract:
Result<Vec<usize>, StepError> - Neutral initialization (blank synaptic weights; no hardcoded domain topology)
- Generic neuromodulators: dopamine, serotonin, acetylcholine, norepinephrine
GenericRewardtrait for domain-specific reward shaping in downstream crates- Classical Hebbian STDP utilities and reward-modulated STDP types (
EligibilityTrace,RmStdpConfig)
The network engine integrates two neuron banks only:
- LIF (
LifNeuron) — primary bank sized bynum_lif - Izhikevich (
IzhikevichNeuron) — secondary bank sized bynum_izh
Default construction: 16 LIF, 5 Izhikevich, 16 input channels.
These types ship in the crate for research and composition, but are not wired as alternate banks inside SpikingNetwork:
- Lapicque (
LapicqueNeuron) - GIF — Generalized Integrate-and-Fire (
GifNeuron) - FitzHugh–Nagumo (
FitzHughNagumoNeuron) - Hodgkin–Huxley (
HodgkinHuxleyNeuron)
Use them directly; use HebbianIzhikevichNetwork for a small classical-STDP Izhikevich helper separate from SpikingNetwork.
| MSRV | Rust 1.97.1 (rust-version in Cargo.toml) |
| Edition | 2024 |
| Pin | rust-toolchain.toml (channel 1.97.1) |
| CI platforms | Linux, macOS, and Windows (GitHub Actions matrix: ubuntu-latest, macos-latest, windows-latest) |
CI installs the same toolchain on each OS. Keep Cargo.toml rust-version, rust-toolchain.toml, and the version string in .github/workflows/ci.yml identical (the CI job fails if they drift).
[dependencies]
neuromod = "0.5.2"Links: crates.io · docs.rs · repository
use neuromod::{NeuroModulators, SpikingNetwork};
fn main() {
let mut network = SpikingNetwork::new(); // default: 16 LIF, 5 Izh, 16 channels
let stimuli = [0.5_f32; 16];
let modulators = NeuroModulators::default();
let spikes = network.step(&stimuli, &modulators).unwrap();
println!("Spiking neuron indices: {spikes:?}");
}use neuromod::{NeuroModulators, SpikingNetwork};
fn main() {
let mut network = SpikingNetwork::with_dimensions(518, 5, 518);
let modulators = NeuroModulators::default();
let stimuli = vec![0.25_f32; 518];
let spikes = network.step(&stimuli, &modulators).unwrap();
println!("Spike count: {}", spikes.len());
}step validates that stimuli.len() == num_channels and returns an error on mismatch.
use neuromod::{NeuroModulators, SpikingNetwork, StepError};
fn main() {
let mut network = SpikingNetwork::with_dimensions(32, 4, 32);
let modulators = NeuroModulators::default();
let bad_stimuli = vec![0.1_f32; 31];
match network.step(&bad_stimuli, &modulators) {
Ok(_) => unreachable!("expected length mismatch"),
Err(StepError::InputLenMismatch { expected, got }) => {
println!("InputLenMismatch: expected {expected}, got {got}");
}
}
}NeuroModulators supports direct control, signal-derived initialization via SignalProfile, and generic reward shaping.
use neuromod::{
apply_neuromodulation, GenericReward, NeuroModulators, Observation, SignalProfile, UnitReward,
};
fn main() {
let profile = SignalProfile::default();
let mut mods = NeuroModulators::from_signals(&profile, 0.2, 0.1, 0.8, 0.9);
mods.add_reward(0.2);
mods.add_norepinephrine(0.1);
mods.boost_focus(0.3);
mods.add_serotonin(0.4);
mods.decay();
let reward = UnitReward;
let obs = Observation::from_slice(&[0.5, 0.7]);
mods.apply_reward(&reward, &obs);
let mut weights = vec![1.0, 0.8];
let mut thresholds = vec![0.20, 0.25];
apply_neuromodulation(&mods, &mut weights, &mut thresholds);
println!(
"dopamine={:.3}, serotonin={:.3}, ne={:.3}",
mods.dopamine, mods.serotonin, mods.norepinephrine
);
}For legacy hardware-calibrated signal mapping, use SignalProfile::hardware_calibrated().
- Engine:
SpikingNetwork,StepError(LIF + Izhikevich banks) - Neuromodulation:
NeuroModulators,SignalProfile,Observation,GenericReward,UnitReward,apply_neuromodulation - Engine neuron types:
LifNeuron,IzhikevichNeuron - Standalone neuron types:
GifNeuron,LapicqueNeuron,FitzHughNagumoNeuron,HodgkinHuxleyNeuron - Learning/plasticity:
- Classical:
apply_classical_stdp,StdpParams,HebbianIzhikevichNetwork - Reward-modulated building blocks:
EligibilityTrace,RmStdpConfig
- Classical:
neuromod is the core library layer for neuron dynamics, generic neuromodulation, and foundational plasticity primitives.
See the full planning documents:
- Org Modularization Standards — workstream index (#35–#43), cross-cutting git/build/beads standards, and audit commands.
- neuromod Boundary Matrix — runtime/deployment role, owns/does-not-own, allowed/forbidden dependencies vs. limbic-critic, brainstem-daemon, axon-encoder, synaptic-mesh, silicon-bridge, Spikenaut-Hardware, plasticity-lab, etc. (LIM-9).
- ADR 001: Shared traits live in neuromod — why traits are hosted here.
Run included examples:
cargo run --example basic
cargo run --example rstdp_democargo check
cargo test
cargo clippy --all-targets --all-features -- -D warnings
cargo fmt --check
cargo bench --no-run
# Coverage (matches CI; see codecov.yml)
cargo install cargo-llvm-cov
cargo llvm-cov --all-features --lcov --output-path lcov.info
# HTML report: cargo llvm-cov --all-features --html
# Full CI-like validation
cargo install cargo-hack --locked
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features
cargo hack check --feature-powerset --exclude-no-default-features --keep-goingneuromod publishes test coverage to Codecov. Error monitoring belongs in application binaries (depend on the sentry crate there), not in this library.
- Configuration:
codecov.yml - Workflow:
.github/workflows/coverage.yml - Dashboard: codecov.io/gh/Limen-Neural/neuromod
The badge uses Codecov’s graph token (from Configuration → Badges & Graphs).
Uploads need the repository secret CODECOV_TOKEN (tokenless uploads return
HTTP 400 for this org). The coverage workflow passes that token and sets
fail_ci_if_error: false, so a missing/stale token does not fail CI—only the
badge may stay unknown until the secret is correct. After a successful upload on
main, the badge shows a coverage %.
Local coverage (also listed under Development):
cargo install cargo-llvm-cov
cargo llvm-cov --all-features --lcov --output-path lcov.info
# HTML report: cargo llvm-cov --all-features --html- Open
target/llvm-cov/html/index.htmlafter running the HTML report locally. - CI runs the
coverage.ymlworkflow on every PR and push tomain.
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE-2.0 or [http://www.apache.org/licenses/LICENSE-2.0])
- MIT license (LICENSE-MIT or [http://opensource.org/licenses/MIT])
at your option.
This repository uses a comprehensive CI setup for speed, quality, security, and observability:
-
Core CI (
.github/workflows/ci.yml): matrix over Linux / macOS / Windows (ubuntu-latest,macos-latest,windows-latest). On every OS: MSRV toolchain,clippy, and build. Whendorny/paths-filterdetects rust-relevant path changes (src/,tests/,examples/,benches/,Cargo.toml/Cargo.lock): tests viacargo-nexteston every OS, and feature-matrix testing (cargo-hack) on Linux only. Always on Linux:fmtand domain-agnostic docs check. UsesSwatinem/rust-cachefor faster feedback. -
Qodana (
.github/workflows/qodana_code_quality.yml): JetBrains code-quality scans on every PR/push tomainandreleases/*; results are published to Qodana Cloud. -
Codecov (
.github/workflows/coverage.yml):cargo-llvm-cov+ Test Analytics (stable JUnit via pinned nextest). See Observability for local usage and report links. -
reviewdog (
.github/workflows/reviewdog.yml): Inline PR comments for clippy and rustfmt. -
Security scanning:
- CodeQL (
.github/workflows/codeql.yml) rustsec/audit-check+ Trivy (.github/workflows/audit.yml)
- CodeQL (
-
Dependencies: Dependabot (
.github/dependabot.yml) for Cargo, GitHub Actions, Docker. -
Docker (
.github/workflows/docker.yml,Dockerfile): Reproducible example runtime image (not required for library use). On every push tomain, CI builds and pushes to:- Docker Hub:
pelon23/neuromod(tags: commit SHA, crate version,latest) - GitHub Container Registry:
ghcr.io/limen-neural/neuromod(same tags) — listed under org packages
Pull (examples only — prefer the crates.io library for embedding):
docker pull ghcr.io/limen-neural/neuromod:0.5.2 # or Docker Hub: docker pull pelon23/neuromod:0.5.2 docker run --rm ghcr.io/limen-neural/neuromod:0.5.2 ls /usr/local/binLocal usage:
# Runtime image (example binaries only — no cargo toolchain) docker build -t neuromod:runtime . docker run --rm neuromod:runtime ls /usr/local/bin # Run tests inside the builder stage (has Rust + source) docker build --target builder -t neuromod:builder . docker run --rm neuromod:builder cargo test --all-features --quiet
- Docker Hub:
- Crates.io: https://crates.io/crates/neuromod
- Docs.rs: https://docs.rs/neuromod
- Repository: https://github.com/Limen-Neural/neuromod
- GHCR: https://github.com/orgs/Limen-Neural/packages/container/package/neuromod
- Docker Hub: https://hub.docker.com/r/pelon23/neuromod