stdp_nn_pre_centered_synapse#

class brainpy.state.stdp_nn_pre_centered_synapse(weight=1.0, delay=Quantity(1., 'ms'), receptor_type=0, tau_plus=Quantity(20., 'ms'), tau_minus=Quantity(20., 'ms'), lambda_=0.01, alpha=1.0, mu_plus=1.0, mu_minus=1.0, Wmax=100.0, Kplus=0.0, post=None, name=None)#

NEST-compatible stdp_nn_pre_centered_synapse connection model.

Short description

Synapse type for spike-timing dependent plasticity with presynaptic- centered nearest-neighbour spike pairing.

Description

stdp_nn_pre_centered_synapse mirrors NEST models/stdp_nn_pre_centered_synapse.h and implements the pairing scheme described by Izhikevich and Desai (2003) and Morrison et al. (2008):

  • Each presynaptic spike is depressed by the nearest preceding postsynaptic spike,

  • Each postsynaptic spike facilitates all presynaptic spikes that occurred after the previous postsynaptic spike.

Compared with stdp_synapse, this model introduces nearest-neighbor postsynaptic depression and a presynaptic trace reset behavior:

  • Kplus decays with tau_plus, increments by 1 per pre-spike, and is reset to 0 when any postsynaptic spike occurred in \((t_{\mathrm{last}}-d,\, t_{pre}-d]\).

  • The depression trace term is nearest-neighbor only: \(\exp((t_{post}^{\mathrm{last}}-t)/\tau_{-})\), where \(t_{post}^{\mathrm{last}} < t\).

1. Mathematical Model

The weight update follows the same functional forms as stdp_synapse, but with nearest-neighbor pairing constraints:

\[\hat{w} \leftarrow \hat{w} + \lambda (1-\hat{w})^{\mu_+} k_+^{\mathrm{NN}}\]
\[\hat{w} \leftarrow \hat{w} - \alpha \lambda \hat{w}^{\mu_-} k_-^{\mathrm{NN}}\]

where \(\hat{w} = w / W_{\mathrm{max}}\) is the normalized weight and

\[\begin{split}k_+^{\mathrm{NN}} = \begin{cases} K_+ \exp((t_{\mathrm{last}} - (t_{\mathrm{post}}^{(1)} + d))/\tau_+) & \text{if } \exists t_{\mathrm{post}}^{(1)} \in (t_{\mathrm{last}}-d,\, t_{\mathrm{pre}}-d] \\ 0 & \text{otherwise} \end{cases}\end{split}\]
\[\begin{split}k_-^{\mathrm{NN}} = \begin{cases} \exp((t_{\mathrm{post}}^{\mathrm{last}} - (t_{\mathrm{pre}}-d))/\tau_-) & \text{if } \exists t_{\mathrm{post}}^{\mathrm{last}} < t_{\mathrm{pre}}-d \\ 0 & \text{otherwise} \end{cases}\end{split}\]

Here \(t_{\mathrm{post}}^{(1)}\) denotes the first postsynaptic spike in the interval \((t_{\mathrm{last}}-d,\, t_{\mathrm{pre}}-d]\), and \(t_{\mathrm{post}}^{\mathrm{last}}\) denotes the nearest preceding postsynaptic spike before \(t_{\mathrm{pre}}-d\).

After processing a presynaptic spike that finds a postsynaptic spike in the facilitation window, the presynaptic trace is reset:

\[K_+ \leftarrow 0\]

2. Update Order (NEST Source Equivalent)

For a presynaptic spike at \(t_{\mathrm{pre}}\) with dendritic delay \(d\), NEST stdp_nn_pre_centered_synapse::send performs:

  1. Read postsynaptic history in \((t_{\mathrm{last}}-d,\, t_{\mathrm{pre}}-d]\).

  2. If non-empty, use only the first postsynaptic spike in this interval for facilitation with \(K_+ \exp((t_{\mathrm{last}}-(t_{\mathrm{post}}+d))/\tau_+)\).

  3. If step 2 happened, reset Kplus = 0.

  4. Apply depression from nearest-neighbor postsynaptic trace at \(t_{\mathrm{pre}}-d\).

  5. Update Kplus as \(K_+ \leftarrow K_+ \exp((t_{\mathrm{last}}-t_{\mathrm{pre}})/\tau_+) + 1\).

  6. Send event with updated weight.

  7. Set t_lastspike = t_pre.

This implementation preserves the same ordering.

3. Coincidence Semantics

Pairs with exact coincidence are discarded by strict time comparisons (NEST stdp_eps behavior). If \(t_{\mathrm{pre}} = t_{\mathrm{post}} + d\) (within 1e-6 ms), the coincident postsynaptic spike is not used for depression/facilitation; earlier valid nearest neighbors are used instead.

Parameters:
  • weight (ArrayLike, optional) – Initial synaptic weight. Default: 1.0.

  • delay (ArrayLike, optional) – Synaptic delay in ms. Default: 1.0 * u.ms.

  • receptor_type (int, optional) – Receiver port/receptor id. Default: 0.

  • tau_plus (ArrayLike, optional) – Potentiation time constant \(\tau_+\) in ms. Default: 20.0 * u.ms.

  • tau_minus (ArrayLike, optional) – Depression trace time constant \(\tau_-\) in ms. In NEST this is a postsynaptic-neuron parameter; here it is stored on the synapse for standalone compatibility. Default: 20.0 * u.ms.

  • lambda (ArrayLike, optional) – Learning-rate parameter \(\lambda\). Default: 0.01.

  • alpha (ArrayLike, optional) – Depression scaling parameter \(\alpha\). Default: 1.0.

  • mu_plus (ArrayLike, optional) – Potentiation exponent \(\mu_+\). Default: 1.0.

  • mu_minus (ArrayLike, optional) – Depression exponent \(\mu_-\). Default: 1.0.

  • Wmax (ArrayLike, optional) – Maximum weight bound \(W_{\mathrm{max}}\). Must have same sign as weight. Default: 100.0.

  • Kplus (ArrayLike, optional) – Initial presynaptic trace value \(K_+\). Must be non-negative. Default: 0.0.

  • post (object, optional) – Default receiver object for spike transmission.

  • name (str, optional) – Object name for debugging and serialization.

Notes

  • In NEST, tau_minus belongs to the postsynaptic archiving neuron. This backend stores equivalent state locally for standalone compatibility, while preserving update semantics.

  • As in NEST, the model uses on-grid spike stamps and ignores sub-step precise spike offsets for STDP updates.

  • The presynaptic trace reset when a postsynaptic spike is found distinguishes this model from stdp_synapse, which accumulates potentiation from all postsynaptic spikes without forgetting prior presynaptic activity.

Examples

Nearest-neighbor pre-centered STDP with custom parameters:

>>> import brainpy.state as bp
>>> import saiunit as u
>>> syn = bp.stdp_nn_pre_centered_synapse(
...     weight=0.5,
...     delay=1.5 * u.ms,
...     tau_plus=16.8 * u.ms,
...     tau_minus=33.7 * u.ms,
...     lambda_=0.005,
...     alpha=0.85,
...     Wmax=5.0,
... )
>>> syn.weight
0.5

References

get()[source]#

Return current public parameters and mutable state.

Returns a dictionary containing all synapse parameters and internal state variables, including weight, delay, receptor_type, plasticity parameters (tau_plus, tau_minus, lambda, alpha, mu_plus, mu_minus, Wmax), and the presynaptic trace Kplus.

Returns:

Dictionary with keys 'synapse_model' (str, set to 'stdp_nn_pre_centered_synapse'), 'weight' (float), 'delay' (float in ms), 'receptor_type' (int), 'tau_plus' (float in ms), 'tau_minus' (float in ms), 'lambda' (float), 'alpha' (float), 'mu_plus' (float), 'mu_minus' (float), 'Wmax' (float), 'Kplus' (float), 't_lastspike' (float in ms), and internal history state.

Return type:

dict

Notes

  • The returned dictionary is a snapshot and does not dynamically reflect subsequent state changes.

  • This method is used for serialization, debugging, and NEST-API compatibility (GetStatus).

send(multiplicity=1.0, *, post=None, receptor_type=None)[source]#

Schedule one outgoing spike event with nearest-neighbor pre-centered STDP.

This method implements the complete NEST stdp_nn_pre_centered_synapse::send update sequence:

  1. Query postsynaptic spike history in the interval \((t_{\mathrm{last}}-d,\, t_{\mathrm{spike}}-d]\).

  2. If at least one postsynaptic spike exists in that interval, apply facilitation using the first such spike:

    \[w \leftarrow w + \lambda (1-w/W_{\mathrm{max}})^{\mu_+} K_+ \exp((t_{\mathrm{last}} - (t_{\mathrm{post}}^{(1)} + d))/\tau_+)\]

    and reset the presynaptic trace \(K_+ \leftarrow 0\).

  3. Apply depression from the nearest preceding postsynaptic spike:

    \[w \leftarrow w - \alpha \lambda (w/W_{\mathrm{max}})^{\mu_-} \exp((t_{\mathrm{post}}^{\mathrm{last}} - (t_{\mathrm{spike}}-d))/\tau_-)\]
  4. Update the presynaptic trace:

    \[K_+ \leftarrow K_+ \exp((t_{\mathrm{last}} - t_{\mathrm{spike}})/\tau_+) + 1\]
  5. Enqueue a spike event with the updated weight for delivery at step \(\mathrm{current\_step} + \mathrm{delay\_steps}\).

  6. Update t_lastspike to the current spike time.

Parameters:
  • multiplicity (ArrayLike, optional) – Spike multiplicity (weight scaling factor). If zero, no event is sent. Default: 1.0.

  • post (object, optional) – Target receiver object. If None, uses the default receiver set at construction.

  • receptor_type (ArrayLike or None, optional) – Receptor port id for the event. If None, uses self.receptor_type. Must be a non-negative integer.

Returns:

True if the event was scheduled, False if multiplicity was zero and no event was sent.

Return type:

bool

Notes

  • The weight update occurs before the event is enqueued, so the transmitted spike carries the plasticity-modified weight.

  • If no postsynaptic spike exists in the facilitation window, facilitation is skipped and Kplus is not reset.

  • Depression uses a strict nearest-neighbor rule: only the most recent postsynaptic spike before \(t_{\mathrm{spike}}-d\) contributes.

  • Coincident spikes (within 1e-6 ms tolerance) are excluded from both facilitation and depression windows.

  • This method is typically called by the presynaptic neuron’s spike transmission logic; it can also be invoked manually for testing or standalone STDP simulation.

Examples

Manually trigger a presynaptic spike event:

>>> import brainpy.state as bp
>>> import saiunit as u
>>> syn = bp.stdp_nn_pre_centered_synapse(
...     weight=1.0, delay=1.0 * u.ms, tau_plus=20.0 * u.ms
... )
>>> # Assume postsynaptic spikes have been recorded...
>>> success = syn.send(multiplicity=1.0)
>>> print(success)
True
>>> print(syn.weight)  # Weight has been updated by STDP