Skip to content

fix(dynold): STP construction, sparse-synapse drift, plasticity decay, Bellec init#848

Merged
chaoming0625 merged 1 commit into
masterfrom
fix/audit-20260619-dynold
Jun 18, 2026
Merged

fix(dynold): STP construction, sparse-synapse drift, plasticity decay, Bellec init#848
chaoming0625 merged 1 commit into
masterfrom
fix/audit-20260619-dynold

Conversation

@chaoming0625

@chaoming0625 chaoming0625 commented Jun 18, 2026

Copy link
Copy Markdown
Member

Fresh review of legacy brainpy/dynold.

  • CriticalSTP.reset_state passed args to variable_ in the wrong order, making STP unconstructable.
  • High — sparse Exponential+stp/DualExponential passed method='cusparse' to csrmv which no longer accepts it -> TypeError on every sparse update.
  • High — sparse Exponential+stp fed raw pre_spike to csrmv instead of the STP-filtered syn_value, silently ignoring STP on sparse layout.
  • Medium — STD/STP discrete jumps used pre-decay state (off-by-one); now use decayed x^-, u^- and facilitated u^+ (Tsodyks–Markram).
  • MediumALIFBellec2020/LIF_SFA_Bellec2020 default adaptation init OneInit(-50.) -> ZeroInit().

In-scope: 554 passed. Findings: docs/issues-found-20260619-dynold.md.

Summary by Sourcery

Fix multiple regressions in legacy dynold short-term plasticity, sparse synapses, and Bellec neuron defaults, and add regression tests and documentation for the audited issues.

Bug Fixes:

  • Correct STP state initialization so experimental STP instances construct and update properly with valid x/u states.
  • Fix sparse Exponential and DualExponential synapse paths to call csrmv with the current API and to apply STP filtering on sparse conductances.
  • Align STD/STP depression and facilitation jumps with the Tsodyks–Markram model by operating on decayed state at spike arrival instead of pre-decay variables.
  • Update Bellec 2020 SFA neuron models so the adaptation variable starts at rest rather than at a large negative offset, avoiding spurious initial firing.

Enhancements:

  • Adjust dynold Bellec adaptation defaults to use ZeroInit for the adaptation variable to reflect a physically reasonable resting state.

Documentation:

  • Add an audit report documenting dynold issues found on 2026-06-19, their severity, rationale, and fix status.

Tests:

  • Extend experimental synapse tests to cover sparse STP behaviour and ensure finite, correctly shaped sparse outputs.
  • Refactor and extend experimental STP tests now that construction works, checking initialization and spike-driven state changes.
  • Add dedicated STD/STP tests in synplast to pin correct Tsodyks–Markram jump behaviour using decayed local state.
  • Add regression tests to ensure Bellec SFA neuron adaptation starts at rest by default.

…, Bellec adaptation init

- STP.reset_state passed (batch_or_mode, sizes) to variable_ in the wrong order,
  making STP unconstructable (ValueError); swapped to (sizes, batch) like STD (Critical)
- sparse Exponential+stp / DualExponential called csrmv(..., method='cusparse');
  csrmv no longer accepts method -> TypeError on every sparse update; removed kwarg (High)
- Exponential sparse+stp branch fed raw pre_spike to csrmv instead of the
  STP-filtered syn_value, silently ignoring STP on sparse layout (High)
- STD/STP discrete jumps read pre-decay state instead of the decayed locals
  (off-by-one decay); use decayed x^-, u^- and facilitated u^+ (Medium)
- ALIFBellec2020 / LIF_SFA_Bellec2020 default a_initializer started SFA
  adaptation deeply negative; changed OneInit(-50.) -> ZeroInit() (Medium)

Findings recorded in docs/issues-found-20260619-dynold.md
@chaoming0625 chaoming0625 merged commit 9845a46 into master Jun 18, 2026
@sourcery-ai

sourcery-ai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Reviewer's Guide

Fixes multiple issues in legacy dynold short‑term plasticity, sparse synapse computation, and Bellec SFA neuron initialization, and adds regression tests plus an audit doc for the dynold package.

Sequence diagram for sparse Exponential synapse update with STP

sequenceDiagram
    participant ExponentialSynapse as Exponential
    participant STP as STP_module
    participant bm_sparse_csrmv as bm_sparse_csrmv

    ExponentialSynapse->>STP: __call__(pre_spike)
    STP-->>ExponentialSynapse: stp_factor
    ExponentialSynapse->>ExponentialSynapse: syn_value = stp_factor * pre_spike
    ExponentialSynapse->>bm_sparse_csrmv: csrmv(data, indices, indptr, syn_value, shape, transpose=True)
    bm_sparse_csrmv-->>ExponentialSynapse: post_vs
    ExponentialSynapse-->>ExponentialSynapse: update returns post_vs
Loading

File-Level Changes

Change Details Files
Correct STD/STP discrete jump logic to operate on decayed state at spike time (Tsodyks–Markram) in both experimental and synplast implementations.
  • In experimental.STD.update(), apply depression jump to the decayed local x (x^-), not the previous-step self.x.
  • In experimental.STP.update(), compute facilitation and depression using decayed locals u/x and use facilitated u^+ when depressing x, matching Tsodyks–Markram equations.
  • Mirrored the same corrections in dynold.synplast.short_term_plasticity.STD.update() and STP.update().
  • Added unit tests in synplast/short_term_plasticity_test.py to numerically pin that jumps use decayed state, not stored pre-decay variables.
brainpy/dynold/experimental/syn_plasticity.py
brainpy/dynold/synplast/short_term_plasticity.py
brainpy/dynold/synplast/short_term_plasticity_test.py
Fix construction and basic update behavior of experimental STP so it is usable via its public constructor.
  • In experimental.STP.reset_state(), corrected variable_ argument order to (sizes=self.num, batch_or_mode=batch_size), mirroring STD.reset_state.
  • Updated helper _make_stp() in tests to call the public STP constructor instead of manually constructing an instance.
  • Added tests asserting STP constructs with correct x/u shapes and initial values, and that update responds to spikes by facilitating u and depressing x.
brainpy/dynold/experimental/syn_plasticity.py
brainpy/dynold/experimental/syn_plasticity_test.py
Repair sparse Exponential and DualExponential synapse paths and ensure STP filtering is applied on sparse layouts.
  • Removed deprecated method='cusparse' keyword from bm.sparse.csrmv calls in experimental.abstract_synapses sparse paths for Exponential and DualExponential.
  • Changed sparse+stp Exponential branch to feed syn_value (STP-filtered drive) into csrmv instead of raw pre_spike so STP affects sparse conductance.
  • Updated tests for sparse Exponential and DualExponential to assert they run without TypeError, return finite outputs with correct post shapes, and that STD depresses sparse conductance vs no-STP case.
brainpy/dynold/experimental/abstract_synapses.py
brainpy/dynold/experimental/abstract_synapses_test.py
Change Bellec 2020 SFA neuron defaults so adaptation variable starts at rest instead of a large negative offset, and add tests for this behavior.
  • Updated ALIFBellec2020 and LIF_SFA_Bellec2020 constructors to use ZeroInit() for a_initializer instead of OneInit(-50.).
  • Added parameterized tests asserting that after reset_state(), the adaptation variable a starts at zero for both Bellec models.
brainpy/dynold/neurons/reduced_models.py
brainpy/dynold/neurons/reduced_neurons_test.py
Document dynold audit findings for this pass, including fixed and recorded-only issues.
  • Added a markdown report summarizing dynold audit findings (P11), including STP construction, sparse synapse csrmv API drift, Tsodyks–Markram jump issues, Bellec adaptation defaults, and a few recorded-only low-severity issues.
  • Linked tests and code locations in the doc for traceability of fixed issues.
docs/issues-found-20260619-dynold.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The STD/STP jump logic is now duplicated between experimental.syn_plasticity and synplast.short_term_plasticity; consider factoring the Tsodyks–Markram update into a shared helper or base to avoid future drift between the two implementations.
  • Several new STP/STD tests encode the exact numerical evolution (e.g., hand-computing x_dec, u_dec with a specific dt and integrator expectation); you may want to loosen these slightly or centralize the expected update formula so they remain robust if the default ODE method or time-step handling changes.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The STD/STP jump logic is now duplicated between `experimental.syn_plasticity` and `synplast.short_term_plasticity`; consider factoring the Tsodyks–Markram update into a shared helper or base to avoid future drift between the two implementations.
- Several new STP/STD tests encode the exact numerical evolution (e.g., hand-computing `x_dec`, `u_dec` with a specific `dt` and integrator expectation); you may want to loosen these slightly or centralize the expected update formula so they remain robust if the default ODE method or time-step handling changes.

## Individual Comments

### Comment 1
<location path="brainpy/dynold/experimental/syn_plasticity_test.py" line_range="96-105" />
<code_context>
+        np.testing.assert_allclose(bm.as_jax(stp.x.value), np.ones(4))
+        np.testing.assert_allclose(bm.as_jax(stp.u.value), np.full(4, 0.15))
+
+    def test_stp_update_state_changes(self):
+        # P11-C1 regression: a constructed STP must update without error and
+        # respond to a presynaptic spike (u facilitates, x depresses).
+        stp = sp.STP(4, U=0.15, tau_f=1500., tau_d=200.)
+        share.save(t=0.0, dt=bm.dt)
+        x_before = bm.as_jax(stp.x.value).copy()
+        u_before = bm.as_jax(stp.u.value).copy()
+        r = bm.as_jax(stp.update(bm.ones(4, dtype=bool)))
+        self.assertEqual(r.shape, (4,))
+        self.assertTrue(np.all(bm.as_jax(stp.u.value) >= u_before - 1e-6))
+        self.assertTrue(np.all(bm.as_jax(stp.x.value) <= x_before + 1e-6))

     def _make_stp(self, num=4, U=0.15, tau_f=1500., tau_d=200.):
</code_context>
<issue_to_address>
**issue (testing):** The regression test for STP update only checks weak inequalities and could pass even if the spike has no effect.

In `test_stp_update_state_changes`, the checks `u >= u_before - 1e-6` and `x <= x_before + 1e-6` would still pass if `u` and `x` never change, so the test doesn’t actually guarantee that spikes modify the state. To make this a true regression, consider either (1) asserting that at least one element satisfies `u > u_before + eps` and `x < x_before - eps` for a small `eps`, or (2) checking against the analytically expected Tsodyks–Markram jump given `U`, `tau_f`, and `tau_d`, so the test will fail if STP stops responding to presynaptic spikes.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +96 to +105
def test_stp_update_state_changes(self):
# P11-C1 regression: a constructed STP must update without error and
# respond to a presynaptic spike (u facilitates, x depresses).
stp = sp.STP(4, U=0.15, tau_f=1500., tau_d=200.)
share.save(t=0.0, dt=bm.dt)
x_before = bm.as_jax(stp.x.value).copy()
u_before = bm.as_jax(stp.u.value).copy()
r = bm.as_jax(stp.update(bm.ones(4, dtype=bool)))
self.assertEqual(r.shape, (4,))
self.assertTrue(np.all(bm.as_jax(stp.u.value) >= u_before - 1e-6))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (testing): The regression test for STP update only checks weak inequalities and could pass even if the spike has no effect.

In test_stp_update_state_changes, the checks u >= u_before - 1e-6 and x <= x_before + 1e-6 would still pass if u and x never change, so the test doesn’t actually guarantee that spikes modify the state. To make this a true regression, consider either (1) asserting that at least one element satisfies u > u_before + eps and x < x_before - eps for a small eps, or (2) checking against the analytically expected Tsodyks–Markram jump given U, tau_f, and tau_d, so the test will fail if STP stops responding to presynaptic spikes.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests labels Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant