| Crates.io | omega-snn |
| lib.rs | omega-snn |
| version | 1.1.0 |
| created_at | 2025-12-10 16:56:29.352341+00 |
| updated_at | 2025-12-12 07:06:36.396228+00 |
| description | Spiking Neural Network substrate for ExoGenesis Omega - biologically-inspired neural dynamics |
| homepage | |
| repository | https://github.com/prancer-io/ExoGenesis-Omega |
| max_upload_size | |
| id | 1978421 |
| size | 131,140 |
Biologically-inspired spiking neural network with LIF neurons, STDP learning, and neuromodulation.
Part of the ExoGenesis-Omega cognitive architecture.
omega-snn provides the neural substrate for the Omega cognitive architecture. Unlike rate-coded neural networks, spiking neural networks (SNNs) use discrete spike events for communication, matching biological neural computation.
Key components:
Add this to your Cargo.toml:
[dependencies]
omega-snn = "1.0.0"
use omega_snn::{SNNEngine, NetworkConfig, NeuronType};
fn main() {
// Create SNN with default configuration
let config = NetworkConfig::default();
let mut snn = SNNEngine::new(config);
// Add neurons
let sensory = snn.add_population(100, NeuronType::Sensory)?;
let hidden = snn.add_population(500, NeuronType::Excitatory)?;
let output = snn.add_population(50, NeuronType::Motor)?;
// Connect populations
snn.connect(&sensory, &hidden, 0.3, 0.5)?; // 30% connectivity, weight 0.5
snn.connect(&hidden, &output, 0.2, 0.3)?;
// Input as spike train
let input_spikes = generate_poisson_spikes(100.0, 100); // 100 Hz, 100ms
// Simulate
for t in 0..1000 {
// Inject input at sensory layer
snn.inject_spikes(&sensory, &input_spikes[t]);
// Step simulation (1ms)
snn.step(1.0)?;
// Get output spikes
let output_spikes = snn.get_spikes(&output);
if !output_spikes.is_empty() {
println!("Output spikes at t={}: {:?}", t, output_spikes);
}
}
}
┌─────────────────────────────────────────────────────────────┐
│ SPIKING NEURAL NETWORK │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ NEUROMODULATOR SYSTEM │ │
│ │ Dopamine │ Norepinephrine │ Serotonin │ Acetylcholine│ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ NEURAL POPULATIONS │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │Excitatory│ │Inhibitory│ │ Sensory │ │ Motor │ │ │
│ │ │ Neurons │ │ Neurons │ │ Neurons │ │ Neurons │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ SYNAPTIC CONNECTIONS │ │
│ │ STDP │ Short-Term Plasticity │ Weights │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ SPIKE TRAINS │ │
│ │ Temporal coding │ Rate coding │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Leaky Integrate-and-Fire is the workhorse neuron model:
use omega_snn::{LIFNeuron, LIFParams, NeuronState};
// Create neuron with custom parameters
let params = LIFParams {
tau_m: 20.0, // Membrane time constant (ms)
v_rest: -70.0, // Resting potential (mV)
v_thresh: -55.0, // Spike threshold (mV)
v_reset: -75.0, // Reset after spike (mV)
tau_ref: 2.0, // Refractory period (ms)
..Default::default()
};
let mut neuron = LIFNeuron::new(params);
// Integrate input current
for t in 0..100 {
let current = if t < 50 { 10.0 } else { 0.0 };
if neuron.integrate(current, 1.0) { // dt = 1ms
println!("Spike at t={}", t);
}
println!("V = {:.2} mV", neuron.voltage());
}
Includes spike-frequency adaptation:
use omega_snn::AdaptiveLIFNeuron;
let mut neuron = AdaptiveLIFNeuron::new_default();
// With constant input, firing rate decreases due to adaptation
for t in 0..500 {
if neuron.integrate(15.0, 1.0) {
println!("Spike at t={}, adaptation={:.2}",
t, neuron.adaptation());
}
}
Spike-Timing Dependent Plasticity for causal learning:
use omega_snn::{STDPRule, STDPParams, Synapse};
let params = STDPParams {
a_plus: 0.01, // LTP amplitude
a_minus: 0.012, // LTD amplitude
tau_plus: 20.0, // LTP time constant (ms)
tau_minus: 20.0, // LTD time constant (ms)
w_max: 1.0, // Maximum weight
w_min: 0.0, // Minimum weight
};
let stdp = STDPRule::new(params);
let mut synapse = Synapse::new(0.5); // Initial weight 0.5
// Pre-before-post: potentiation
let pre_time = 100.0;
let post_time = 110.0;
let dw = stdp.compute_update(pre_time, post_time);
synapse.update_weight(dw);
println!("Weight after pre→post: {:.3}", synapse.weight());
// Post-before-pre: depression
let post_time = 200.0;
let pre_time = 210.0;
let dw = stdp.compute_update(pre_time, post_time);
synapse.update_weight(dw);
println!("Weight after post→pre: {:.3}", synapse.weight());
Global modulation of network dynamics:
use omega_snn::{NeuromodulatorSystem, NeuromodulatorType};
let mut neuromod = NeuromodulatorSystem::new();
// Increase dopamine (reward/motivation)
neuromod.release(NeuromodulatorType::Dopamine, 0.8);
// Get current levels
let da = neuromod.level(NeuromodulatorType::Dopamine);
let ne = neuromod.level(NeuromodulatorType::Norepinephrine);
let ser = neuromod.level(NeuromodulatorType::Serotonin);
let ach = neuromod.level(NeuromodulatorType::Acetylcholine);
println!("Dopamine: {:.3} (reward, motivation)", da);
println!("Norepinephrine: {:.3} (arousal, attention)", ne);
println!("Serotonin: {:.3} (mood, inhibition)", ser);
println!("Acetylcholine: {:.3} (learning, memory)", ach);
// Neuromodulators decay over time
neuromod.decay(0.01); // 1% decay per step
// Dopamine modulates STDP learning rate
let learning_rate = base_rate * (1.0 + 0.5 * da);
// Norepinephrine modulates gain
let gain = base_gain * (1.0 + 0.3 * ne);
// Serotonin modulates inhibition
let inhibition = base_inhibition * (1.0 + 0.4 * ser);
// Acetylcholine modulates attention
let attention = base_attention * (1.0 + 0.6 * ach);
Temporal representations of neural activity:
use omega_snn::{SpikeTrain, SpikeAnalysis};
// Create spike train
let mut train = SpikeTrain::new();
train.add_spike(10.0);
train.add_spike(25.0);
train.add_spike(42.0);
train.add_spike(60.0);
// Analysis
let analysis = SpikeAnalysis::new(&train);
println!("Spike count: {}", analysis.count());
println!("Firing rate: {:.1} Hz", analysis.rate(100.0)); // 100ms window
println!("Mean ISI: {:.1} ms", analysis.mean_isi());
println!("CV of ISI: {:.3}", analysis.cv_isi()); // Regularity measure
// Inter-spike intervals
for isi in analysis.isis() {
println!("ISI: {:.1} ms", isi);
}
Organize neurons into functional groups:
use omega_snn::{NeuralPopulation, PopulationActivity, NeuronType};
let mut excitatory = NeuralPopulation::new(800, NeuronType::Excitatory);
let mut inhibitory = NeuralPopulation::new(200, NeuronType::Inhibitory);
// Connect (E-I balance)
excitatory.connect_to(&inhibitory, 0.2, 0.5); // E → I
inhibitory.connect_to(&excitatory, 0.4, -0.8); // I → E (inhibitory)
// Step simulation
excitatory.step(input, 1.0);
inhibitory.step(&[], 1.0); // Driven by excitatory
// Population activity
let activity = excitatory.activity();
println!("Active neurons: {}/{}", activity.active_count, 800);
println!("Population rate: {:.1} Hz", activity.rate);
println!("Sparsity: {:.3}", activity.sparsity());
Efficient distributed representations:
use omega_snn::SparseCode;
// Create sparse code (10% active)
let code = SparseCode::new(1000, 0.1);
// Encode input
let input = vec![0.5; 100];
let sparse = code.encode(&input);
println!("Active units: {}", sparse.iter().filter(|&&x| x > 0.0).count());
println!("Sparsity: {:.3}", code.sparsity(&sparse));
use omega_snn::NetworkConfig;
let config = NetworkConfig {
dt: 1.0, // Time step (ms)
neuron_type: Default::default(),
tau_m: 20.0, // Membrane time constant
v_thresh: -55.0, // Spike threshold
stdp_enabled: true, // Enable STDP learning
stp_enabled: true, // Short-term plasticity
neuromod_enabled: true, // Neuromodulation
max_delay: 20.0, // Maximum axonal delay (ms)
..Default::default()
};
let snn = SNNEngine::new(config);
// Visual input as spike patterns
let visual_input = encode_image_as_spikes(&image)?;
// Process through visual hierarchy
let v1_spikes = v1_layer.process(&visual_input)?;
let v2_spikes = v2_layer.process(&v1_spikes)?;
let it_spikes = it_layer.process(&v2_spikes)?; // Object recognition
// Reward prediction error modulates learning
if reward > expected_reward {
neuromod.release(NeuromodulatorType::Dopamine, 0.8);
} else if reward < expected_reward {
neuromod.release(NeuromodulatorType::Dopamine, -0.3);
}
// STDP learning is enhanced by dopamine
for synapse in active_synapses {
let dw = stdp.compute_update(pre_time, post_time);
let modulated_dw = dw * (1.0 + dopamine_level);
synapse.update_weight(modulated_dw);
}
// Persistent activity through recurrent excitation
let mut wm_circuit = NeuralPopulation::new(100, NeuronType::Excitatory);
wm_circuit.connect_to(&wm_circuit, 0.3, 0.1); // Recurrent connections
// Activate with input
wm_circuit.inject_current(input, 100.0);
// Activity persists after input removed
for t in 0..1000 {
wm_circuit.step(&[], 1.0);
if wm_circuit.activity().rate > 10.0 {
println!("Working memory active at t={}", t);
}
}
omega-brain (Unified Integration)
└── omega-snn (This crate)
├── LIF neurons
├── STDP learning
├── Neuromodulation
├── Populations
└── Spike trains
Provides substrate for:
├── omega-attention - Neural attention
├── omega-consciousness - Neural correlates
└── omega-hippocampus - Memory circuits
Licensed under the MIT License. See LICENSE for details.