rate_neuron_opn#

class brainpy.state.rate_neuron_opn(in_size, tau=Quantity(10., 'ms'), sigma=1.0, mu=0.0, g=1.0, mult_coupling=False, g_ex=1.0, g_in=1.0, theta_ex=0.0, theta_in=0.0, linear_summation=True, input_nonlinearity=None, mult_coupling_ex_fn=None, mult_coupling_in_fn=None, rate_initializer=Constant(value=0.0), noise_initializer=Constant(value=0.0), noisy_rate_initializer=Constant(value=0.0), name=None)#

NEST-compatible rate_neuron_opn output-noise rate-neuron template.

rate_neuron_opn implements the NEST template model rate_neuron_opn<TNonlinearities> with the deterministic dynamics

\[\tau \frac{dX(t)}{dt} = -X(t) + \mu + I_\mathrm{net}(t),\]

and output noise applied after the nonlinearity:

\[X_\mathrm{noisy}(t) = X(t) + \sqrt{\frac{\tau}{h}}\,\sigma\,\xi(t),\]

where \(X(t)\) is the deterministic rate state, \(\tau\) is the time constant, \(\mu\) is the mean drive, \(\sigma\ge 0\) is the output-noise strength, \(h\) is the simulation time step, and \(\xi(t)\sim\mathcal{N}(0,1)\) is standard Gaussian white noise approximated as piecewise constant over \(h\).

With default callables this is equivalent to NEST lin_rate_opn:

  • input(h) = g * h

  • mult_coupling_ex(rate) = g_ex * (theta_ex - rate)

  • mult_coupling_in(rate) = g_in * (theta_in + rate)

Mathematical Description

1. Continuous-Time Deterministic Dynamics

The deterministic rate state \(X(t)\) evolves according to

\[\tau \frac{dX(t)}{dt} = -X(t) + \mu + I_\mathrm{net}(t),\]

where \(\tau>0\) is the time constant and \(I_\mathrm{net}(t)\) is the network input decomposed as

\[I_\mathrm{net}(t) = H_\mathrm{ex}(X_\mathrm{noisy}) \cdot g(I_\mathrm{ex}(t)) + H_\mathrm{in}(X_\mathrm{noisy}) \cdot g(I_\mathrm{in}(t)),\]

where:

  • \(I_\mathrm{ex}(t)\) and \(I_\mathrm{in}(t)\) are excitatory and inhibitory synaptic input branches.

  • \(g(\cdot)\) is the input nonlinearity. Default: \(g(h)=g\,h\).

  • \(H_\mathrm{ex}(X_\mathrm{noisy})\) and \(H_\mathrm{in}(X_\mathrm{noisy})\) are optional multiplicative coupling factors dependent on the noisy rate. Default: \(H_\mathrm{ex}=g_\mathrm{ex}(\theta_\mathrm{ex}-X_\mathrm{noisy})\), \(H_\mathrm{in}=g_\mathrm{in}(\theta_\mathrm{in}+X_\mathrm{noisy})\). Only active if mult_coupling=True.

The linear_summation switch controls whether the nonlinearity is applied to the summed input or to individual synaptic branches:

  • linear_summation=True: \(I_\mathrm{net}(t) = H\cdot g(I_\mathrm{ex}+I_\mathrm{in})\).

  • linear_summation=False: \(I_\mathrm{net}(t) = H_\mathrm{ex}\cdot g(I_\mathrm{ex}) + H_\mathrm{in}\cdot g(I_\mathrm{in})\).

2. Output Noise (Postsynaptic Noise Model)

Output noise is added after the deterministic dynamics, creating a noisy observation of the rate:

\[X_\mathrm{noisy}(t) = X(t) + \sqrt{\frac{\tau}{h}}\,\sigma\,\xi(t),\]

where \(\xi(t)\sim\mathcal{N}(0,1)\) is standard Gaussian white noise. The scaling factor \(\sqrt{\tau/h}\) ensures that the noise amplitude is independent of the discretization time step \(h\) in the limit \(h\to 0\).

Critical difference from input-noise model: The noisy rate \(X_\mathrm{noisy}\) is used for multiplicative coupling evaluation (if mult_coupling=True) and as the outgoing signal to downstream neurons, but the noise does not feed back into the deterministic dynamics. This contrasts with the input-noise variant (rate_neuron_ipn) where noise enters the differential equation directly.

3. Discrete-Time Integration

For time step \(h=dt\) (in ms), the deterministic part uses exponential Euler integration (exact for the linear ODE):

\[X_{n+1} = P_1 X_n + P_2 (\mu + I_\mathrm{net,n}),\]

where

\[P_1 = \exp(-h/\tau), \quad P_2 = 1 - P_1 = -\mathrm{expm1}(-h/\tau).\]

Output noise is added independently at each step:

\[X_\mathrm{noisy,n} = X_n + \sqrt{\frac{\tau}{h}}\,\sigma\,\xi_n,\]

where \(\xi_n\sim\mathcal{N}(0,1)\) is drawn at each step.

4. Update Ordering (Matching NEST ``rate_neuron_opn_impl.h``)

Per simulation step:

  1. Draw noise sample \(\xi_n\sim\mathcal{N}(0,1)\), compute \(\mathrm{noise}_n = \sigma\,\xi_n\).

  2. Compute noisy rate: \(X_\mathrm{noisy,n} = X_n + \sqrt{\tau/h}\,\mathrm{noise}_n\).

  3. Propagate deterministic intrinsic dynamics: \(X' = P_1 X_n + P_2 (\mu + \mu_\mathrm{ext})\).

  4. Read delayed and instantaneous event buffers.

  5. Apply network input according to NEST semantics:

    • linear_summation=True: nonlinearity applied to summed branch input during update.

    • linear_summation=False: nonlinearity applied per incoming event while buffering (handled in event processing).

  6. If mult_coupling=True, multiplicative coupling factors \(H_\mathrm{ex}(X_\mathrm{noisy,n})\) and \(H_\mathrm{in}(X_\mathrm{noisy,n})\) are evaluated at the noisy rate (matching NEST rate_neuron_opn_impl.h).

  7. Store updated rate, noise, and expose noisy_rate as outgoing delayed/instantaneous event value.

5. Stability Constraints and Computational Implications

  • Construction enforces \(\tau>0\), \(\sigma\ge 0\).

  • The deterministic dynamics are unconditionally stable (exponential relaxation to \(\mu + I_\mathrm{net}\) with time constant \(\tau\)).

  • Output noise does not affect stability but may violate rate bounds; no automatic rectification is provided (unlike rate_neuron_ipn).

  • Noise variance scales as \(\tau\sigma^2/h\) per step. For fixed \(\tau\) and \(\sigma\), this diverges as \(h\to 0\), reflecting the white-noise nature of \(\xi(t)\).

  • The exponential Euler scheme is numerically stable for all \(h>0\).

  • Per-call cost is \(O(\prod\mathrm{varshape})\) with vectorized NumPy operations in float64 for coefficient evaluation and state update.

Parameters:
  • in_size (Size) – Population shape specification (tuple of int or single int). All per-neuron parameters are broadcast to self.varshape. For example, in_size=10 creates 10 neurons, in_size=(4, 5) creates a 4×5 grid.

  • tau (ArrayLike, optional) – Time constant \(\tau\) (saiunit quantity with ms dimension). Scalar or array broadcastable to self.varshape. Must be \(>0\). Controls the exponential relaxation rate of the deterministic dynamics. Default: 10.0 * u.ms.

  • sigma (ArrayLike, optional) – Output-noise scale \(\sigma\) (dimensionless scalar or array). Broadcastable to self.varshape. Must be \(\ge 0\). Determines the standard deviation of the Gaussian noise added to the output rate. Default: 1.0.

  • mu (ArrayLike, optional) – Mean drive \(\mu\) (dimensionless scalar or array). Broadcastable to self.varshape. External constant input to the rate dynamics, added to the network input. Default: 0.0.

  • g (ArrayLike, optional) – Linear gain parameter \(g\) (dimensionless scalar or array). Broadcastable to self.varshape. Used by the default input nonlinearity \(g(h)=g\,h\). Ignored if input_nonlinearity is provided. Default: 1.0.

  • mult_coupling (bool, optional) – Enable multiplicative coupling (rate-dependent synaptic efficacy). If True, applies \(H_\mathrm{ex}(X_\mathrm{noisy})\) and \(H_\mathrm{in}(X_\mathrm{noisy})\) to synaptic inputs, evaluated at the noisy rate. If False, \(H_\mathrm{ex}=H_\mathrm{in}=1\). Default: False.

  • g_ex (ArrayLike, optional) – Excitatory multiplicative coupling gain \(g_\mathrm{ex}\) (dimensionless scalar or array). Broadcastable to self.varshape. Only used if mult_coupling=True. Default: 1.0.

  • g_in (ArrayLike, optional) – Inhibitory multiplicative coupling gain \(g_\mathrm{in}\) (dimensionless scalar or array). Broadcastable to self.varshape. Only used if mult_coupling=True. Default: 1.0.

  • theta_ex (ArrayLike, optional) – Excitatory coupling reference rate \(\theta_\mathrm{ex}\) (dimensionless scalar or array). Broadcastable to self.varshape. Only used if mult_coupling=True. Default: 0.0.

  • theta_in (ArrayLike, optional) – Inhibitory coupling reference rate \(\theta_\mathrm{in}\) (dimensionless scalar or array). Broadcastable to self.varshape. Only used if mult_coupling=True. Default: 0.0.

  • linear_summation (bool, optional) – NEST switch controlling where the input nonlinearity is applied. If True, the nonlinearity is applied to the sum of excitatory and inhibitory inputs (post-summation). If False, the nonlinearity is applied separately to each input branch before summation (per-branch). Default: True.

  • input_nonlinearity (Callable[[ArrayLike], ArrayLike] or Callable[[rate_neuron_opn, ArrayLike], ArrayLike] or None, optional) – Custom input nonlinearity \(g(\cdot)\) replacing the default \(g(h)=g\,h\). Callable signature can be f(h) (receives float64 NumPy array of shape state_shape, returns array of same shape) or f(model, h) (receives model instance and array, returns array). Must be vectorized and compatible with NumPy broadcasting. If None, uses default linear gain. Default: None.

  • mult_coupling_ex_fn (Callable[[ArrayLike], ArrayLike] or Callable[[rate_neuron_opn, ArrayLike], ArrayLike] or None, optional) – Custom excitatory multiplicative coupling function \(H_\mathrm{ex}(X_\mathrm{noisy})\). Callable signature can be f(rate) or f(model, rate). Must return array of same shape as input. Evaluated at the noisy rate. If None, uses default \(g_\mathrm{ex}(\theta_\mathrm{ex}-X_\mathrm{noisy})\). Default: None.

  • mult_coupling_in_fn (Callable[[ArrayLike], ArrayLike] or Callable[[rate_neuron_opn, ArrayLike], ArrayLike] or None, optional) – Custom inhibitory multiplicative coupling function \(H_\mathrm{in}(X_\mathrm{noisy})\). Callable signature can be f(rate) or f(model, rate). Must return array of same shape as input. Evaluated at the noisy rate. If None, uses default \(g_\mathrm{in}(\theta_\mathrm{in}+X_\mathrm{noisy})\). Default: None.

  • rate_initializer (Callable, optional) – Initializer for the deterministic rate state variable \(X_0\). Callable compatible with braintools.init API (signature: (shape, batch_size) -> ArrayLike). Default: braintools.init.Constant(0.0).

  • noise_initializer (Callable, optional) – Initializer for the noise state variable (records last noise sample \(\sigma\,\xi_{n-1}\)). Callable compatible with braintools.init API. Default: braintools.init.Constant(0.0).

  • noisy_rate_initializer (Callable, optional) – Initializer for the noisy_rate state variable \(X_\mathrm{noisy,0}\) and outgoing event values. Callable compatible with braintools.init API. Default: braintools.init.Constant(0.0).

  • name (str or None, optional) – Module name for identification in hierarchies. If None, auto-generates a unique name. Default: None.

Parameter Mapping

The following table maps NEST rate_neuron_opn / lin_rate_opn parameters to brainpy.state equivalents:

NEST Parameter

brainpy.state

Default

tau

tau

10 ms

sigma

sigma

1.0

mu

mu

0.0

g (nonlinearity gain)

g

1.0

mult_coupling

mult_coupling

False

g_ex, g_in

g_ex, g_in

1.0

theta_ex, theta_in

theta_ex, theta_in

0.0

linear_summation

linear_summation

True

rate#

Deterministic rate state \(X_n\) (float64 array of shape self.varshape or (batch_size,) + self.varshape). This is the noise-free rate variable.

Type:

brainstate.ShortTermState

noise#

Last noise sample \(\sigma\,\xi_{n-1}\) (float64 array, same shape as rate). Records the noise term used in the previous step.

Type:

brainstate.ShortTermState

noisy_rate#

Noisy rate \(X_\mathrm{noisy,n} = X_n + \sqrt{\tau/h}\,\mathrm{noise}_n\) (float64 array, same shape as rate). This is the outgoing signal sent to downstream neurons and used for multiplicative coupling evaluation.

Type:

brainstate.ShortTermState

instant_rate#

Noisy rate value for instantaneous event propagation (float64 array, same shape as rate). Set to noisy_rate after each update.

Type:

brainstate.ShortTermState

delayed_rate#

Noisy rate value for delayed projections (float64 array, same shape as rate). Set to noisy_rate after each update.

Type:

brainstate.ShortTermState

_step_count#

Internal step counter for delayed event scheduling (int64 scalar). Incremented by 1 after each update call.

Type:

brainstate.ShortTermState

_delayed_ex_queue#

Internal queue mapping step_idx (int) to accumulated excitatory delayed events (float64 array of shape state_shape).

Type:

dict

_delayed_in_queue#

Internal queue mapping step_idx (int) to accumulated inhibitory delayed events (float64 array of shape state_shape).

Type:

dict

Raises:
  • ValueError – If tau <= 0 (checked during __init__ via _validate_parameters).

  • ValueError – If sigma < 0 (checked during __init__ via _validate_parameters).

  • ValueError – If instant_rate_events contain non-zero delay_steps (checked during update via _accumulate_instant_events).

  • ValueError – If delayed_rate_events contain negative delay_steps (checked during update via _schedule_delayed_events).

  • ValueError – If event tuples have length other than 2, 3, or 4 (checked during update via _extract_event_fields).

Notes

Runtime Events

Events can be provided to update() via instant_rate_events and delayed_rate_events parameters. Each event can be specified as:

  • Scalar: Treated as rate value with weight=1.0.

  • Tuple: (rate, weight) or (rate, weight, delay_steps) or (rate, weight, delay_steps, multiplicity).

  • Dict: Keys 'rate'/'coeff'/'value' (event value), 'weight' (synaptic weight), 'delay_steps'/'delay' (integer delay in time steps), 'multiplicity' (event count).

Sign Convention: Events with weight >= 0 contribute to the excitatory branch; events with weight < 0 contribute to the inhibitory branch.

Linear Summation Semantics: For linear_summation=False, event values are transformed by the input nonlinearity during buffering (matching NEST event handlers). For linear_summation=True, the nonlinearity is applied to the summed input during the update step.

Comparison to ``rate_neuron_ipn``

The _opn variant uses output noise (applied after nonlinearity and transmitted to downstream neurons), while _ipn uses input noise (applied before dynamics propagation, directly affecting the state evolution). This leads to different stationary distributions, noise scaling, and stability properties. In _opn, noise does not feed back into the deterministic dynamics.

Examples

Minimal output-noise rate neuron:

>>> import brainpy.state as bst
>>> import saiunit as u
>>> model = bst.rate_neuron_opn(in_size=10, tau=20*u.ms, sigma=0.5)
>>> model.init_all_states(batch_size=1)
>>> rate = model(x=0.1)  # external drive
>>> print(rate.shape)
(1, 10)

Multiplicative coupling with custom nonlinearity:

>>> import numpy as np
>>> def tanh_nonlin(h):
...     return np.tanh(h)
>>> model = bst.rate_neuron_opn(
...     in_size=5,
...     tau=10*u.ms,
...     sigma=0.3,
...     mult_coupling=True,
...     g_ex=1.5, theta_ex=1.0,
...     input_nonlinearity=tanh_nonlin
... )

Accessing noisy rate output:

>>> model = bst.rate_neuron_opn(in_size=3, tau=10*u.ms, sigma=0.2)
>>> model.init_all_states()
>>> rate_deterministic = model.update(x=0.5)  # propagates deterministic dynamics
>>> rate_noisy = model.noisy_rate.value        # includes output noise
>>> print(rate_noisy.shape)
(3,)

References

See also

rate_neuron_ipn

Input-noise variant of the rate neuron template.

lin_rate

Deterministic linear rate neuron (sigma=0).

init_state(**kwargs)[source]#

Initialize all state variables for simulation.

This method must be called before the first update() call. It creates all internal state variables (rate, noise, noisy_rate, instant_rate, delayed_rate, _step_count) and resets the delayed event queues.

Parameters:

**kwargs – Unused compatibility parameters accepted by the base-state API.

Notes

Initialized State Variables

This method initializes the following state variables:

  • rate (brainstate.ShortTermState): Deterministic rate state \(X_n\) (float64 array). Initialized using rate_initializer.

  • noise (brainstate.ShortTermState): Last noise sample \(\sigma\,\xi_{n-1}\) (float64 array). Initialized using noise_initializer.

  • noisy_rate (brainstate.ShortTermState): Noisy rate \(X_\mathrm{noisy,n} = X_n + \sqrt{\tau/h}\,\mathrm{noise}_n\) (float64 array). Initialized using noisy_rate_initializer.

  • instant_rate (brainstate.ShortTermState): Noisy rate value for instantaneous event propagation (float64 array). Initialized as a copy of noisy_rate.

  • delayed_rate (brainstate.ShortTermState): Noisy rate value for delayed projections (float64 array). Initialized as a copy of noisy_rate.

  • _step_count (brainstate.ShortTermState): Internal step counter for delayed event scheduling (int64 scalar). Initialized to 0.

  • _delayed_ex_queue (dict): Internal queue mapping step_idx (int) to accumulated excitatory delayed events (float64 array). Initialized as empty dict.

  • _delayed_in_queue (dict): Internal queue mapping step_idx (int) to accumulated inhibitory delayed events (float64 array). Initialized as empty dict.

Array Precision

All state arrays are float64 NumPy arrays. All parameters (tau, sigma, mu, etc.) are coerced to float64 during initialization.

Repeated Calls

Calling init_state() multiple times will overwrite existing state variables and clear the delayed event queues. This can be used to reset the model to initial conditions.

Examples

Initialize a single population:

>>> import brainpy.state as bst
>>> import saiunit as u
>>> model = bst.rate_neuron_opn(in_size=10, tau=20*u.ms)
>>> model.init_state()
>>> print(model.rate.value.shape)
(10,)

Custom initializers:

>>> import braintools
>>> model = bst.rate_neuron_opn(
...     in_size=5,
...     tau=10*u.ms,
...     rate_initializer=braintools.init.Normal(0.5, 0.1),
...     noisy_rate_initializer=braintools.init.Normal(0.5, 0.1)
... )
>>> model.init_state()
>>> print(model.rate.value.mean())  # approximately 0.5

See also

update

Perform one simulation step after initialization.

property receptor_types#

Receptor type dictionary for projection compatibility.

Returns:

{'RATE': 0}. Rate neurons have a single receptor type.

Return type:

dict[str, int]

property recordables#

List of state variable names that can be recorded.

Returns:

['rate', 'noise', 'noisy_rate'].

Return type:

list of str

update(x=0.0, instant_rate_events=None, delayed_rate_events=None, noise=None, _precomputed_ex=None, _precomputed_in=None)[source]#

Perform one simulation step of output-noise rate dynamics.

This method implements the core update algorithm for the output-noise rate neuron model. It propagates the deterministic rate dynamics, applies output noise, processes delayed and instantaneous synaptic events, and evaluates optional multiplicative coupling factors.

Parameters:
  • x (ArrayLike, optional) – External drive (dimensionless scalar or array). Broadcastable to self.varshape or current batch shape. Added to mu as constant forcing term. Default: 0.0.

  • instant_rate_events (None or dict or tuple or list or iterable, optional) –

    Instantaneous rate events applied in the current step without delay. Each event can be:

    • Scalar (treated as rate value with weight=1.0).

    • Tuple: (rate, weight) or (rate, weight, delay_steps) or (rate, weight, delay_steps, multiplicity).

    • Dict with keys 'rate'/'coeff'/'value', 'weight', 'delay_steps'/'delay', 'multiplicity'.

    Events with non-zero delay_steps will raise ValueError. Default: None (no instantaneous events).

  • delayed_rate_events (None or dict or tuple or list or iterable, optional) – Delayed rate events scheduled with integer delay_steps (units of simulation time step \(h\)). Same format as instant_rate_events. Events with delay_steps=0 are applied immediately. Events with delay_steps>0 are queued and applied after the specified delay. Negative delay_steps raise ValueError. Default: None (no delayed events).

  • noise (ArrayLike or None, optional) – Externally supplied noise sample \(\xi_n\) (dimensionless scalar or array). Broadcastable to current batch shape. If None (default), draws \(\xi_n\sim\mathcal{N}(0,1)\) internally using np.random.normal. If provided, must have zero mean and unit variance for correct noise amplitude. Default: None.

Returns:

rate_new – Updated deterministic rate state \(X_{n+1}\) (float64 array of shape self.rate.value.shape). This is the noise-free rate after one simulation step. To access the noisy rate, use self.noisy_rate.value.

Return type:

np.ndarray

Raises:
  • ValueError – If instant_rate_events contain non-zero delay_steps.

  • ValueError – If delayed_rate_events contain negative delay_steps.

  • ValueError – If event tuples have length other than 2, 3, or 4.

Notes

Update Algorithm

The method performs the following steps in order:

1. Input Collection

Collect all input contributions for the current step:

  • Delayed events arriving at current step (drained from internal queues _delayed_ex_queue and _delayed_in_queue).

  • Newly scheduled delayed events with delay_steps=0 (from delayed_rate_events).

  • Instantaneous events (from instant_rate_events).

  • Delta inputs via sum_delta_inputs(0.0) (sign-separated into excitatory/inhibitory branches).

  • Current inputs via sum_current_inputs(x, rate) (external drive and synaptic inputs).

2. Propagator Coefficients

Compute exponential Euler integration coefficients:

\[P_1 = \exp(-h/\tau), \quad P_2 = 1 - P_1 = -\mathrm{expm1}(-h/\tau),\]

where \(h\) is the simulation time step (in ms) and \(\tau\) is the time constant. Uses np.expm1 for numerically stable evaluation of \(1-e^{-x}\).

3. Output Noise

Draw noise sample \(\xi_n\sim\mathcal{N}(0,1)\) (or use external noise parameter) and compute noisy rate:

\[X_\mathrm{noisy,n} = X_n + \sqrt{\frac{\tau}{h}}\,\sigma\,\xi_n.\]

The scaling factor \(\sqrt{\tau/h}\) ensures correct amplitude scaling in the \(h\to 0\) limit.

4. Deterministic Dynamics Propagation

Propagate the deterministic part of the dynamics:

\[X' = P_1 X_n + P_2(\mu + \mu_\mathrm{ext}),\]

where \(\mu_\mathrm{ext}\) is the external drive from x and current inputs.

5. Multiplicative Coupling

If mult_coupling=True, evaluate multiplicative coupling factors at the noisy rate:

\[H_\mathrm{ex}(X_\mathrm{noisy,n}), \quad H_\mathrm{in}(X_\mathrm{noisy,n}).\]

If mult_coupling=False, \(H_\mathrm{ex}=H_\mathrm{in}=1\).

6. Network Input Application

Apply network input according to linear_summation mode:

  • linear_summation=True: Nonlinearity applied to summed input:

    \[X_{n+1} = X' + P_2 [H_\mathrm{ex}\cdot g(I_\mathrm{ex}) + H_\mathrm{in}\cdot g(I_\mathrm{in})].\]

    If mult_coupling=False, simplifies to:

    \[X_{n+1} = X' + P_2 g(I_\mathrm{ex} + I_\mathrm{in}).\]
  • linear_summation=False: Nonlinearity applied per branch during event processing. Network input is already transformed:

    \[X_{n+1} = X' + P_2 [H_\mathrm{ex}\cdot I_\mathrm{ex} + H_\mathrm{in}\cdot I_\mathrm{in}].\]

7. State Updates

Update all state variables:

  • rate: Deterministic rate \(X_{n+1}\).

  • noise: Noise sample \(\sigma\,\xi_n\).

  • noisy_rate: Noisy rate \(X_\mathrm{noisy,n}\).

  • delayed_rate: Noisy rate for delayed projections.

  • instant_rate: Noisy rate for instantaneous projections.

  • _step_count: Incremented by 1.

Key Distinction from ``rate_neuron_ipn``

The noisy rate \(X_\mathrm{noisy,n}\) is used for multiplicative coupling and as the outgoing signal to downstream neurons, but the noise does not feed back into the deterministic dynamics (i.e., \(X'\) depends only on the noise-free rate \(X_n\)). This contrasts with the input-noise variant (rate_neuron_ipn) where noise enters the differential equation directly.

Numerical Stability

  • The exponential Euler scheme is unconditionally stable for all \(h>0\).

  • Uses np.expm1(-h/tau) to avoid catastrophic cancellation for small \(h/\tau\).

  • Noise scaling \(\sqrt{\tau/h}\) ensures correct amplitude in the \(h\to 0\) limit, but per-step noise variance diverges (reflecting white-noise nature).

Failure Modes

  • Invalid time constants: Caught at construction by _validate_parameters (enforces \(\tau>0\), \(\sigma\ge 0\)).

  • Invalid events: Raises ValueError for events with incorrect delay_steps or tuple length.

  • Unbounded rates: No automatic rectification or clipping. Noisy rate can exceed any bounds.

  • NaN propagation: If input contains NaN, all downstream states will be NaN. No automatic detection or recovery.

See also

init_state

Initialize all state variables before first update.

rate_neuron_ipn.update

Input-noise variant update method.