use synapse_models::{Synapse, SynapticNetwork};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Neural Network Simulation ===\n");
feedforward_network()?;
println!("\n");
balanced_network()?;
println!("\n");
gap_junction_network()?;
Ok(())
}
fn feedforward_network() -> Result<(), Box<dyn std::error::Error>> {
println!("1. Feedforward Network (5 neurons)");
let mut network = SynapticNetwork::new(5);
for i in 0..4 {
let syn = Synapse::excitatory(1.5, 2.0)?; network.add_connection(i, i + 1, syn)?;
}
let stats = network.connectivity_stats();
println!(" Neurons: {}", stats.n_neurons);
println!(" Connections: {}", stats.n_connections);
println!(" Avg in-degree: {:.2}", stats.avg_in_degree);
println!(" Avg out-degree: {:.2}", stats.avg_out_degree);
println!("\n Spiking neuron 0 at t=0");
network.spike(0)?;
let voltages = vec![-65.0; 5];
println!("\n Time (ms) | Neuron 0 | Neuron 1 | Neuron 2 | Neuron 3 | Neuron 4");
println! (" ----------|----------|----------|----------|----------|----------");
for t in 0..100 {
let time = t as f64 * 0.5; network.update(&voltages, 0.5)?;
if t % 4 == 0 {
print!(" {:8.1} |", time);
for neuron_id in 0..5 {
let current = network.get_synaptic_current(neuron_id)?;
print!(" {:8.2} |", current);
}
println!();
}
}
println!("\n Note: Spike propagates through the chain with delays");
Ok(())
}
fn balanced_network() -> Result<(), Box<dyn std::error::Error>> {
println!("2. Balanced Excitatory-Inhibitory Network");
let n_exc = 8; let n_inh = 2; let n_total = n_exc + n_inh;
let mut network = SynapticNetwork::new(n_total);
let mut n_exc_conn = 0;
for i in 0..n_exc {
for j in 0..n_total {
if i != j && rand::random::<f64>() < 0.3 {
let syn = Synapse::excitatory(1.0, 1.0)?;
network.add_connection(i, j, syn)?;
n_exc_conn += 1;
}
}
}
let mut n_inh_conn = 0;
for i in n_exc..n_total {
for j in 0..n_exc {
let syn = Synapse::inhibitory(2.0, 1.0)?; network.add_connection(i, j, syn)?;
n_inh_conn += 1;
}
}
println!(" Total neurons: {}", n_total);
println!(" Excitatory: {}, Inhibitory: {}", n_exc, n_inh);
println!(" Excitatory connections: {}", n_exc_conn);
println!(" Inhibitory connections: {}", n_inh_conn);
println!(" E/I ratio: {:.2}", n_exc_conn as f64 / n_inh_conn as f64);
let stats = network.connectivity_stats();
println!("\n Network statistics:");
println!(" Total connections: {}", stats.n_connections);
println!(" Average in-degree: {:.2}", stats.avg_in_degree);
println!(" Average out-degree: {:.2}", stats.avg_out_degree);
Ok(())
}
fn gap_junction_network() -> Result<(), Box<dyn std::error::Error>> {
println!("3. Gap Junction Network");
let mut network = SynapticNetwork::new(4);
let syn1 = Synapse::excitatory(1.0, 1.0)?;
let syn2 = Synapse::excitatory(1.0, 1.0)?;
network.add_connection(0, 1, syn1)?;
network.add_connection(1, 2, syn2)?;
network.add_gap_junction(2, 3, 0.5)?;
println!(" Network structure:");
println!(" Neuron 0 --chemical--> Neuron 1 --chemical--> Neuron 2 --gap junction-- Neuron 3");
println!(" Gap junction conductance: 0.5 nS");
let stats = network.connectivity_stats();
println!("\n Chemical synapses: {}", stats.n_connections);
println!(" Gap junctions: {}", stats.n_gap_junctions);
println!("\n Simulating with voltage difference across gap junction:");
println!(" V2 = -60 mV, V3 = -70 mV");
let mut voltages = vec![-65.0; 4];
voltages[2] = -60.0; voltages[3] = -70.0;
network.update(&voltages, 0.1)?;
let i_chem_2 = network.get_synaptic_current(2)?;
let i_chem_3 = network.get_synaptic_current(3)?;
println!("\n Current to neuron 2: {:.4} pA (chemical)", i_chem_2);
println!(" Current to neuron 3: {:.4} pA (includes gap junction)", i_chem_3);
println!("\n Note: Gap junction provides bidirectional current flow");
Ok(())
}