tsodyks_synapse_hom#
- class brainpy.state.tsodyks_synapse_hom(weight=1.0, delay=Quantity(1., 'ms'), receptor_type=0, tau_psc=Quantity(3., 'ms'), tau_fac=Quantity(0., 'ms'), tau_rec=Quantity(800., 'ms'), U=0.5, x=1.0, y=0.0, u=0.0, post=None, name=None)#
NEST-compatible
tsodyks_synapse_homconnection model with homogeneous short-term plasticity.1. Short Description
Synapse type with short-term plasticity using homogeneous parameters across all connections, implementing the Tsodyks-Markram model with depressing and facilitating dynamics.
2. Mathematical Description
tsodyks_synapse_hommirrors NESTmodels/tsodyks_synapse_hom.hand implements the short-term plasticity model of Tsodyks, Uziel and Markram (2000) [2], with dynamic per-connection state variables:x: fraction of resources in recovered state (available for release)y: fraction of resources in active state (released but not yet decayed)u: utilization (release probability upon spike arrival)z = 1 - x - y: fraction of resources in inactive state (released and decayed, recovering)
For a presynaptic spike at time \(t_s\) with inter-spike interval \(h = t_s - t_{\mathrm{last}}\), NEST updates states in this exact order:
Step 1: Continuous-time propagation from \(t_{\mathrm{last}}\) to \(t_s\)
First compute propagation factors:
\[\begin{split}P_{uu} &= \begin{cases} 0, & \tau_{\mathrm{fac}}=0 \\ e^{-h/\tau_{\mathrm{fac}}}, & \tau_{\mathrm{fac}}>0 \end{cases} \\ P_{yy} &= e^{-h/\tau_{\mathrm{psc}}} \\ P_{zz} &= e^{-h/\tau_{\mathrm{rec}}} \\ P_{xy} &= \frac{(P_{zz}-1)\tau_{\mathrm{rec}} - (P_{yy}-1)\tau_{\mathrm{psc}}} {\tau_{\mathrm{psc}}-\tau_{\mathrm{rec}}} \\ P_{xz} &= 1 - P_{zz}\end{split}\]Then update state variables:
\[\begin{split}u &\leftarrow u \cdot P_{uu} \\ x &\leftarrow x + P_{xy} y + P_{xz} z \\ y &\leftarrow y \cdot P_{yy}\end{split}\]Step 2: Spike-triggered facilitation
\[u \leftarrow u + U(1-u)\]where \(U\) is the utilization increment parameter.
Step 3: Resource release calculation
\[\Delta y = u \cdot x\]This is the fraction of resources released by the current spike.
Step 4: State updates for resource depletion
\[\begin{split}x &\leftarrow x - \Delta y \\ y &\leftarrow y + \Delta y\end{split}\]Step 5: Event amplitude computation
\[w_{\mathrm{eff}} = \Delta y \cdot w\]where \(w\) is the common synaptic weight.
This implementation preserves the exact NEST ordering in
send(). Delay scheduling and delivery followstatic_synapse_hom_w.3. Homogeneous-Property Semantics
In NEST,
weight,U,tau_psc,tau_facandtau_recare common synapse-model properties (stored inTsodyksHomCommonProperties), shared across all connections using this synapse type. In contrast,x,yanduare per-connection state variables that evolve independently for each synapse.This implementation mirrors that behavior by:
Forbidding
set_weight(...)calls (same as NEST)Rejecting these common properties in connect-time synapse specs via
check_synapse_params()Allowing model-level parameter updates via
set(...)()
4. Event Timing Semantics
As in NEST, this model uses spike timestamps (grid-aligned) and ignores precise sub-step offsets when computing plasticity updates. All spikes are treated as occurring at the beginning of their respective time step.
- Parameters:
weight (
floatorarray-like, optional) – Common synaptic weight (dimensionless). Shared across all connections. Must be scalar. Default:1.0.delay (
Quantity (time)orarray-like, optional) – Synaptic transmission delay. Must be positive. Scalar or broadcastable to connection count. Default:1.0 * u.ms.receptor_type (
int, optional) – Target receptor port ID on the postsynaptic neuron. Default:0.tau_psc (
Quantity (time)orarray-like, optional) – Time constant for postsynaptic current (active resource decay). Must be> 0and scalar. Corresponds to NEST’stau_pscparameter. Default:3.0 * u.ms.tau_fac (
Quantity (time)orarray-like, optional) – Facilitation time constant (utilization decay). Must be>= 0and scalar. Whentau_fac = 0, facilitation is disabled (\(P_{uu} = 0\)). Corresponds to NEST’stau_facparameter. Default:0.0 * u.ms.tau_rec (
Quantity (time)orarray-like, optional) – Recovery time constant (inactive → recovered transition). Must be> 0and scalar. Corresponds to NEST’stau_recparameter. Default:800.0 * u.ms.U (
floatorarray-like, optional) – Utilization increment parameter. Must be in[0, 1]and scalar. Determines the spike-triggered increase in release probability. Corresponds to NEST’sUparameter. Default:0.5.x (
floatorarray-like, optional) – Initial fraction of recovered resources. Must satisfyx + y <= 1and be scalar. Default:1.0(all resources initially available).y (
floatorarray-like, optional) – Initial fraction of active resources. Must satisfyx + y <= 1and be scalar. Default:0.0(no resources initially active).u (
floatorarray-like, optional) – Initial utilization state (release probability). Must be scalar. NEST stores this as mutable per-connection state without enforcing bounds on assignment. Default:0.0.post (
object, optional) – Default postsynaptic target object. Can be overridden insend()andupdate().name (
str, optional) – Descriptive name for this synapse model instance.
Parameter Mapping
NEST Parameter
brainpy.state Parameter
Type
Scope
weight
weight
float
Common
delay
delay
Quantity
Common
receptor_type
receptor_type
int
Common
tau_psc
tau_psc
Quantity
Common
tau_fac
tau_fac
Quantity
Common
tau_rec
tau_rec
Quantity
Common
U
U
float
Common
x
x
float
State
y
y
float
State
u
u
float
State
Notes
Event type: This model transmits spike-like events only, not continuous currents.
State initialization:
init_state()resets queue state and restoresx,y,uto their constructor-specified initial values.Last-spike timestamp:
t_lastspikestarts at0.0ms (as in NEST). Ifx != 1initially, the first-spike dynamics depend on this initial timestamp.Homogeneous constraints: Common properties (
weight,U,tau_psc,tau_fac,tau_rec) cannot be set per-connection via connect-time synapse specs. Useset()to modify them at the model level.Validation: Constructor validates
tau_psc > 0,tau_fac >= 0,tau_rec > 0,U ∈ [0,1], andx + y <= 1.set()re-validates on updates.Numerical stability: When
tau_psc ≈ tau_rec, the \(P_{xy}\) calculation may become numerically unstable. NEST uses the same formula without special handling.
See also
tsodyks_synapseHeterogeneous variant with per-connection parameters
static_synapse_hom_wParent class for homogeneous static connections
References
Examples
Create a depressing synapse (default parameters):
>>> import brainpy.state as bs >>> import saiunit as u >>> syn = bs.tsodyks_synapse_hom( ... weight=2.0, ... delay=1.5 * u.ms, ... U=0.5, ... tau_rec=800.0 * u.ms, ... tau_fac=0.0 * u.ms, # no facilitation ... )
Create a facilitating synapse:
>>> syn_fac = bs.tsodyks_synapse_hom( ... weight=1.5, ... U=0.15, ... tau_rec=200.0 * u.ms, ... tau_fac=750.0 * u.ms, # strong facilitation ... tau_psc=5.0 * u.ms, ... )
Update common properties (e.g., increase facilitation):
>>> syn_fac.set(tau_fac=1000.0 * u.ms, U=0.2)
Initialize state for simulation:
>>> syn.init_state() >>> print(syn.x, syn.y, syn.u) # (1.0, 0.0, 0.0)
Retrieve current parameters and state:
>>> params = syn.get() >>> print(params['synapse_model']) # 'tsodyks_synapse_hom' >>> print(params['U'], params['tau_rec']) # (0.5, 800.0)
- check_synapse_params(syn_spec)[source]#
Reject common-property assignments in connect-time synapse specs.
Validates that connect-time synapse specifications do not attempt to override common (homogeneous) properties that must be shared across all connections. This enforces NEST’s homogeneous synapse semantics where
weight,U,tau_psc,tau_fac, andtau_recare model-level properties.- Parameters:
syn_spec (
dictorNone) – Synapse specification dictionary passed during connection creation. IfNone, validation is skipped (no parameters to check).- Raises:
ValueError – If
syn_speccontains any of the disallowed keys:'weight','U','tau_psc','tau_rec', or'tau_fac'. These must be set at the model level usingset()(or NEST’sCopyModel/SetDefaults).
Notes
This method is called internally during connection setup to prevent misuse.
In NEST,
weightis a common property fortsodyks_synapse_hombut can vary per-connection intsodyks_synapse. This model follows the_homvariant’s restrictions.To modify common properties, use
model.set(weight=..., U=..., ...)before or during simulation, not during connection creation.
- get()[source]#
Return current public parameters and mutable state.
Retrieves all public parameters (
weight,delay,receptor_type,tau_psc,tau_fac,tau_rec,U) and current state variables (x,y,u) as a dictionary. Inherited parameters are retrieved viasuper().get().- Returns:
Dictionary with keys: -
'weight'(float): Common synaptic weight. -'delay'(float): Synaptic delay in ms. -'receptor_type'(int): Receiver port ID. -'tau_psc'(float): PSC time constant in ms. -'tau_fac'(float): Facilitation time constant in ms. -'tau_rec'(float): Recovery time constant in ms. -'U'(float): Utilization increment parameter. -'x'(float): Current recovered resource fraction. -'y'(float): Current active resource fraction. -'u'(float): Current utilization state. -'synapse_model'(str): Always'tsodyks_synapse_hom'.- Return type:
Notes
All time constants are returned in milliseconds (converted from internal storage).
State variables (
x,y,u) reflect the current simulation state, not initial values.This method is compatible with NEST’s
GetStatus()semantics.
- init_state(batch_size=None, **kwargs)[source]#
Reset queue state and restore initial resource/utilization values.
Resets the event delivery queue (inherited from parent) and restores the short-term plasticity state variables (
x,y,u) to their constructor-specified initial values (_x0,_y0,_u0). Also resets the last-spike timestamp to0.0ms.- Parameters:
Notes
This method should be called before starting a new simulation to ensure consistent initial conditions.
After calling
init_state(), the synapse is in a “naive” state witht_lastspike = 0.0, meaning the first spike will have inter-spike interval \(h = t_{\mathrm{spike}} - 0.0\).
- send(multiplicity=1.0, *, post=None, receptor_type=None)[source]#
Schedule one outgoing event with NEST
tsodyks_synapse_homdynamics.Computes short-term plasticity state updates following the Tsodyks-Markram model, calculates the effective synaptic weight, and schedules a delayed spike event for delivery to the postsynaptic target.
Algorithm:
Compute inter-spike interval \(h = t_{\mathrm{spike}} - t_{\mathrm{lastspike}}\)
Apply continuous-time propagation (exponential decay) to
u,x,yApply spike-triggered facilitation: \(u \leftarrow u + U(1-u)\)
Compute released resources: \(\Delta y = u \cdot x\)
Update
xandyfor depletion/releaseCompute effective weight: \(w_{\mathrm{eff}} = \Delta y \cdot w \cdot \text{multiplicity}\)
Schedule delayed event in delivery queue
Update
t_lastspiketo current spike time
- Parameters:
multiplicity (
floatorarray-like, optional) – Spike count or scaling factor. If zero, no event is scheduled andFalseis returned immediately. Default:1.0.post (
object, optional) – Target postsynaptic object. IfNone, uses the default receiver stored inself.post.receptor_type (
intorarray-like, optional) – Target receptor port ID. IfNone, usesself.receptor_type.
- Returns:
Trueif an event was successfully scheduled,Falseifmultiplicitywas zero (no event sent).- Return type:
Notes
State updates: This method mutates
self.x,self.y,self.u, andself.t_lastspikein-place.Ordering: The update order exactly matches NEST’s
tsodyks_synapse_hom.h::send().Delay handling: The event is scheduled for delivery at \(t_{\mathrm{current}} + \text{dt} + \text{delay}\), where
dtis the simulation timestep.Queue structure: Events are stored as
(receiver, payload, port, 'spike')tuples in the internal delay queue.Numerical stability: When
tau_psc ≈ tau_rec, the \(P_{xy}\) calculation may lose precision (same limitation as NEST).
See also
updateDelivers queued events and schedules new ones from presynaptic input
- set(*, weight=<object object>, delay=<object object>, receptor_type=<object object>, tau_psc=<object object>, tau_fac=<object object>, tau_rec=<object object>, U=<object object>, x=<object object>, y=<object object>, u=<object object>, post=<object object>)[source]#
Set public parameters following NEST-style validation semantics.
Updates model parameters and/or state variables with comprehensive validation. All parameters are optional; only specified values are updated. This method mirrors NEST’s
SetStatus()for homogeneous synapse models.- Parameters:
weight (
floatorarray-like, optional) – New common synaptic weight (dimensionless). Must be scalar.delay (
Quantity (time)orarray-like, optional) – New synaptic transmission delay. Must be positive.receptor_type (
int, optional) – New target receptor port ID.tau_psc (
Quantity (time)orarray-like, optional) – New PSC time constant. Must be> 0and scalar.tau_fac (
Quantity (time)orarray-like, optional) – New facilitation time constant. Must be>= 0and scalar.tau_rec (
Quantity (time)orarray-like, optional) – New recovery time constant. Must be> 0and scalar.U (
floatorarray-like, optional) – New utilization increment parameter. Must be in[0, 1]and scalar.x (
floatorarray-like, optional) – New recovered resource fraction. Must satisfyx + y <= 1and be scalar.y (
floatorarray-like, optional) – New active resource fraction. Must satisfyx + y <= 1and be scalar.u (
floatorarray-like, optional) – New utilization state. Must be scalar.post (
object, optional) – New default postsynaptic target object.
- Raises:
ValueError – If any parameter fails validation: -
tau_psc <= 0-tau_fac < 0-tau_rec <= 0-U ∉ [0, 1]-x + y > 1- Non-scalar values for common properties
Notes
All validation is performed before any state is modified (atomic update).
When updating
xory, the sum constraint is checked with the new values.Updating
x,y, orualso updates the internal initial-value cache (_x0,_y0,_u0), so subsequentinit_state()calls will use the new values.Time constants are validated after conversion to milliseconds.
This method does not reset
t_lastspikeor clear the event queue.
Examples
Update facilitation parameters:
>>> syn.set(tau_fac=500.0 * u.ms, U=0.3)
Update state variables (e.g., after external perturbation):
>>> syn.set(x=0.8, y=0.1, u=0.2)
Update multiple parameters atomically:
>>> syn.set( ... weight=2.5, ... delay=2.0 * u.ms, ... tau_rec=600.0 * u.ms, ... U=0.6, ... )
- update(pre_spike=0.0, *, post=None, receptor_type=None)[source]#
Deliver due events, then schedule current-step presynaptic input.
This is the main simulation-step method, combining event delivery and spike transmission. It first delivers all queued events that are due for the current time step, then processes new presynaptic input (if any) by calling
send().Workflow:
Refresh delay computation if needed (inherited from parent)
Deliver all events scheduled for the current simulation step
Sum presynaptic inputs from
pre_spike,current_inputs, anddelta_inputsIf total input is non-zero, call
send()to schedule a new event with short-term plasticity
- Parameters:
pre_spike (
floatorarray-like, optional) – Presynaptic spike input for the current time step (dimensionless spike count or activation). Default:0.0(no input).post (
object, optional) – Target postsynaptic object for new events. IfNone, usesself.post.receptor_type (
intorarray-like, optional) – Target receptor port ID for new events. IfNone, usesself.receptor_type.
- Returns:
Number of events delivered to postsynaptic targets during this time step.
- Return type:
Notes
Event delivery: Delivered events are removed from the internal queue after processing.
Input summation: The method sums: 1. Explicit
pre_spikeargument 2. Accumulatedcurrent_inputs(from projections) 3. Accumulateddelta_inputs(from delta-function sources)Plasticity application: Short-term plasticity state updates occur only when
send()is called (i.e., when total input is non-zero).Typical usage: Called once per simulation time step for each synapse model instance.
Examples
Simulation loop with explicit presynaptic spike:
>>> for t in range(1000): ... spike = 1.0 if t % 100 == 0 else 0.0 # spike every 100 steps ... delivered = syn.update(pre_spike=spike, post=target_neuron)
Simulation with projection-driven input (no explicit spike):
>>> # Projections accumulate input in syn.current_inputs >>> for t in range(1000): ... delivered = syn.update(post=target_neuron)