| name | dual-timescale-memory-spiking-neuron-astrocyte |
| description | Dual-timescale memory mechanism in spiking neuron-astrocyte networks (SNAN). Combines STDP-based long-term memory with astrocytic short-term suppression for efficient navigation and working memory. Activation: dual timescale memory, SNAN, spiking neuron astrocyte network, astrocyte working memory, topological context memory, neuromorphic navigation. |
Dual-Timescale Memory in Spiking Neuron-Astrocyte Networks
Overview
This skill implements the Spiking Neuron-Astrocyte Network (SNAN) methodology - a biologically-inspired dual-timescale memory mechanism that combines spike-timing-dependent plasticity (STDP) for long-term memory with astrocytic calcium dynamics for short-term suppression of recently visited states. This creates an emergent "Topological-Context Memory" ideal for navigation tasks under partial observability.
Key Features
- Dual-Timescale Architecture: Fast astrocytic suppression + slow synaptic plasticity
- STDP Learning: Reinforces successful action sequences on long timescales
- Astrocytic Modulation: Suppresses recently visited states via calcium transients
- Topological-Context Memory: Novel working memory type for spatial navigation
- Hardware Implementation: Memristive crossbar array compatibility
Biological Inspiration
Biological agents navigate by combining:
- Long-term memory: Successful actions reinforced by STDP (slow timescale)
- Short-term suppression: Recently visited locations blocked by astrocytic activity (fast timescale)
This creates an efficient exploration mechanism without explicit global statistics.
Methodology
Core Architecture
Neural Layer (Spiking Neurons)
├── STDP-based learning (τ_STDP ~ minutes)
└── Action selection via winner-take-all
Astrocytic Layer (Calcium Dynamics)
├── Fast calcium transients (τ_Ca ~ seconds)
└── Local state suppression
Interaction: Astrocytes modulate synaptic efficacy
Mathematical Formulation
Neural Dynamics (LIF Neurons):
τ_m * dV_i/dt = -(V_i - V_rest) + Σ_j w_ij * s_j + I_ext
if V_i ≥ θ: spike, V_i ← V_reset
STDP Learning:
Δw_ij = A+ * exp(-Δt/τ+) if Δt > 0 (post after pre)
Δw_ij = -A- * exp(Δt/τ-) if Δt < 0 (pre after post)
Astrocytic Calcium Dynamics:
τ_Ca * d[Ca²⁺]_k/dt = -[Ca²⁺]_k + R * Σ_i∈region_k s_i
Gliotransmitter release: G_k = σ([Ca²⁺]_k - θ_Ca)
Astrocytic Modulation:
w_ij^eff = w_ij * (1 - α * G_k)
Where:
G_k: Gliotransmitter concentration in region k
α: Modulation strength
w_ij^eff: Effective synaptic weight after astrocytic modulation
Implementation
Spiking Neuron-Astrocyte Network
import torch
import torch.nn as nn
import torch.nn.functional as F
class SpikingNeuronAstrocyteNetwork(nn.Module):
"""
SNAN: Spiking Neuron-Astrocyte Network
Args:
num_neurons: Number of spiking neurons
num_astrocytes: Number of astrocytes (typically < num_neurons)
neuron_per_astrocyte: Neurons regulated by each astrocyte
tau_m: Membrane time constant (ms)
tau_ca: Calcium time constant (ms)
tau_stdp: STDP time window (ms)
"""
def __init__(self, num_neurons=100, num_astrocytes=20,
neuron_per_astrocyte=5, tau_m=20.0, tau_ca=1000.0,
tau_stdp=100.0):
super().__init__()
self.num_neurons = num_neurons
self.num_astrocytes = num_astrocytes
self.neuron_per_astrocyte = neuron_per_astrocyte
self.tau_m = tau_m
self.tau_ca = tau_ca
self.tau_stdp = tau_stdp
self.register_buffer('astrocyte_map',
torch.arange(num_neurons).reshape(num_astrocytes, neuron_per_astrocyte))
self.weights = nn.Parameter(torch.randn(num_neurons, num_neurons) * 0.1)
self.V = None
self.Ca = None
self.spike_trace = None
def reset_state(self, batch_size=1):
"""Reset network state"""
self.V = torch.zeros(batch_size, self.num_neurons)
self.Ca = torch.zeros(batch_size, self.num_astrocytes)
self.spike_trace = torch.zeros(batch_size, self.num_neurons)
def forward(self, input_current, dt=1.0):
"""
Single timestep forward pass
Args:
input_current: External input (batch, num_neurons)
dt: Time step (ms)
"""
modulation = torch.ones_like(self.V)
for a in range(self.num_astrocytes):
neurons = self.astrocyte_map[a]
suppression = torch.sigmoid(self.Ca[:, a:a+1] - 0.5)
modulation[:, neurons] *= (1 - 0.5 * suppression)
effective_weights = self.weights * modulation.unsqueeze(1)
synaptic_input = torch.matmul(self.spike_trace, effective_weights.t())
dV = (-(self.V - 0.0) + input_current + synaptic_input) / self.tau_m * dt
self.V = self.V + dV
spikes = (self.V >= 1.0).float()
self.V = self.V * (1 - spikes)
self.spike_trace = self.spike_trace * (1 - dt/self.tau_stdp) + spikes
for a in range(self.num_astrocytes):
neurons = self.astrocyte_map[a]
spike_sum = spikes[:, neurons].sum(dim=1)
self.Ca[:, a] += (-self.Ca[:, a] + spike_sum) / self.tau_ca * dt
return spikes
STDP Learning Rule
class STDPLearning:
"""
Spike-Timing-Dependent Plasticity implementation for SNAN
"""
def __init__(self, A_plus=0.01, A_minus=0.01, tau_plus=20.0, tau_minus=20.0):
self.A_plus = A_plus
self.A_minus = A_minus
self.tau_plus = tau_plus
self.tau_minus = tau_minus
def compute_weight_update(self, pre_times, post_times):
"""
Compute STDP weight updates
Args:
pre_times: Spike times of presynaptic neuron
post_times: Spike times of postsynaptic neuron
"""
delta_w = 0.0
for t_post in post_times:
for t_pre in pre_times:
delta_t = t_post - t_pre
if delta_t > 0:
delta_w += self.A_plus * np.exp(-delta_t / self.tau_plus)
elif delta_t < 0:
delta_w -= self.A_minus * np.exp(delta_t / self.tau_minus)
return delta_w
Navigation Agent with SNAN
class SNANNavigator:
"""
Navigation agent using SNAN for dual-timescale memory
"""
def __init__(self, grid_size=(10, 10), num_actions=4):
self.grid_size = grid_size
self.num_actions = num_actions
state_dim = grid_size[0] * grid_size[1]
self.snan = SpikingNeuronAstrocyteNetwork(
num_neurons=state_dim + num_actions,
num_astrocytes=20,
neuron_per_astrocyte=5
)
self.stdp = STDPLearning()
def encode_state(self, position):
"""Encode grid position as spike pattern"""
code = torch.zeros(self.grid_size[0] * self.grid_size[1])
idx = position[0] * self.grid_size[1] + position[1]
code[idx] = 1.0
return code
def select_action(self, state, epsilon=0.1):
"""
Select action using SNAN with astrocytic modulation
"""
state_input = self.encode_state(state)
self.snan.reset_state()
spikes = self.snan.forward(state_input.unsqueeze(0))
action_spikes = spikes[0, -self.num_actions:]
if torch.rand(1).item() < epsilon:
astrocyte_activity = self.snan.Ca[0].mean()
if astrocyte_activity > 0.5:
action = torch.randint(0, self.num_actions, (1,)).item()
else:
action = torch.randint(0, self.num_actions, (1,)).item()
else:
action = torch.argmax(action_spikes).item()
return action
def update(self, state, action, reward, next_state, done):
"""
Update network using STDP if reward is positive
"""
if reward > 0:
state_input = self.encode_state(state)
next_input = self.encode_state(next_state)
with torch.no_grad():
self.snan.weights += 0.01 * reward * torch.outer(
state_input, next_input
)
self.snan.weights.clamp_(-1, 1)
Hardware Implementation
Memristive Crossbar Array
class MemristiveSNAN:
"""
SNAN implementation using memristive crossbar arrays
Based on VTEAM (Voltage-Threshold Adaptive Memristor) model
"""
def __init__(self, crossbar_size=(100, 100)):
self.crossbar = np.zeros(crossbar_size)
self.vteam_params = {
'alpha_on': 1,
'alpha_off': 1,
'v_on': 0.27,
'v_off': 0.37,
'R_on': 100,
'R_off': 10000
}
def stdp_to_memristor(self, delta_w, current_g):
"""
Map STDP weight update to memristor conductance change
"""
if delta_w > 0:
v_pulse = self.vteam_params['v_on'] * min(abs(delta_w) * 10, 1.0)
else:
v_pulse = -self.vteam_params['v_off'] * min(abs(delta_w) * 10, 1.0)
if v_pulse > 0:
delta_g = 0.01 * (1 - current_g / self.vteam_params['R_off'])
else:
delta_g = -0.01 * (current_g / self.vteam_params['R_on'] - 1)
return current_g + delta_g
Performance Metrics
From original paper:
| Metric | SNAN | Baseline | Improvement |
|---|
| Median path length (grid-world) | 12 steps | 72 steps | 6x reduction |
| Goal completion rate | 94% | 45% | 2x improvement |
| Energy per decision (hardware) | 0.1 nJ | 1.2 nJ | 12x reduction |
| Area efficiency (crossbar) | 10^4 neurons/mm² | - | State-of-art |
Advantages
- Efficient Exploration: Astrocytic suppression avoids revisiting states
- Stable Learning: STDP provides long-term memory without catastrophic forgetting
- Emergent Behavior: Exploration-exploitation trade-off emerges naturally
- Hardware Compatible: Maps directly to memristive crossbars
- No Global Information: Local computation only - scalable to large spaces
Applications
- Robotic Navigation: Partially observable environments
- Autonomous Exploration: Unknown territory mapping
- Reinforcement Learning: Credit assignment in sparse reward settings
- Neuromorphic Edge AI: Low-power navigation systems
References
- Paper: "Dual-Timescale Memory in a Spiking Neuron-Astrocyte Network for Efficient Navigation" (arXiv:2604.15391)
- Authors: Tsybina et al., 2026
- Categories: q-bio.QM (Quantitative Methods)
Related Skills
working-memory-heterogeneous-delays: Alternative working memory approach
snn-astrocyte-learning: General astrocyte-SNN interactions
neuromorphic-hardware: Deployment guidelines for neuromorphic chips
Last updated: 2026-04-27