Skip to content

fix(math/sparse): coo_to_csr bounds check + sparse/event/delay regression suite#845

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

fix(math/sparse): coo_to_csr bounds check + sparse/event/delay regression suite#845
chaoming0625 merged 1 commit into
masterfrom
fix/audit-20260619-math-sparse-event

Conversation

@chaoming0625

@chaoming0625 chaoming0625 commented Jun 18, 2026

Copy link
Copy Markdown
Member

Fresh review of brainpy/math sparse/event/jitconn operators + delay variables.

  • Mediumcoo_to_csr silently produced a corrupt CSR (indptr[-1] != nse) on out-of-range pre_ids; now raises a clear ValueError.
  • Added a thorough regression suite verifying CSR/COO/event matvec & matmat and jit-connectivity ops against dense references (including transpose=True and autodiff), and TimeDelay/LengthDelay ring-buffer modulo-wrap behavior. Prior-audit findings (csrmm transpose, TimeDelay modulo, coomv) verified already-fixed and now locked by tests.

In-scope: 58 passed. Findings: docs/issues-found-20260619-math-sparse-event.md.

Summary by Sourcery

Tighten sparse COO-to-CSR conversion error handling and add regression coverage for sparse/event operations and delay variables.

Bug Fixes:

  • Raise a clear ValueError in coo_to_csr when pre_ids fall outside [0, num_row) to avoid generating structurally invalid CSR matrices.

Enhancements:

  • Document coo_to_csr behaviour and constraints, including its eager-only nature due to jnp.unique.

Documentation:

  • Document the results of the math/sparse, math/event, jit connectivity, and delay variable audit in a new issues-found report.

Tests:

  • Add regression tests for coo_to_csr, csr_to_coo, and csr_to_dense against dense references.
  • Add regression tests for CSR matrix-matrix multiplication, COO matrix-vector multiplication, and event-driven CSR matmat to match dense and autodiff behaviour, including transpose variants.
  • Add regression tests for pre_syn_post helpers to validate event routing and per-group reductions.
  • Add regression tests for TimeDelay and LengthDelay ring-buffer wrap-around behaviour to lock in correct modulo/rotation semantics.

…elay correctness with tests

- coo_to_csr silently produced a corrupt CSR (indptr[-1] != nse) on
  out-of-range pre_ids; now raises a clear ValueError (Medium)
- Added regression tests comparing CSR/COO/event matvec+matmat and jitconn
  against dense references (incl. transpose and autodiff), plus TimeDelay /
  LengthDelay ring-buffer modulo-wrap tests, locking in prior correctness fixes

Findings recorded in docs/issues-found-20260619-math-sparse-event.md
@chaoming0625 chaoming0625 merged commit dca2e80 into master Jun 18, 2026
2 checks passed
@sourcery-ai

sourcery-ai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds an eager bounds check to sparse.coo_to_csr to prevent structurally invalid CSR output on out-of-range pre_ids, and introduces a focused regression test suite covering sparse COO/CSR helpers, event-driven CSR matvec/matmat paths (including transpose and autodiff), pre_syn_post routing utilities, and TimeDelay/LengthDelay ring-buffer wrap behaviour. The PR also records the sparse/event audit findings in docs/issues-found-20260619-math-sparse-event.md.

File-Level Changes

Change Details Files
Harden coo_to_csr against out-of-range pre_ids and improve its documentation.
  • Expand coo_to_csr docstring with detailed argument/return semantics, error conditions, and a note that it is an eager (non-jittable) helper.
  • Convert pre_ids/post_ids to JAX arrays up front, then compute min/max of pre_ids when non-empty and raise a ValueError if any pre_id is negative or >= num_row.
  • Keep the existing sorting/CSR construction logic intact so that valid inputs now yield CSR with indptr[-1] == len(indices) and int32 row pointers.
brainpy/math/sparse/utils.py
Add regression tests for sparse COO/CSR utilities and matvec/matmat paths, including transpose and autodiff.
  • Introduce utils_test covering coo_to_csr roundtrips (including unsorted COO, empty rows, and out-of-range/negative pre_ids), csr_to_coo roundtrips, and csr_to_dense vs dense numpy references.
  • Add csr_mm_test to validate csrmm forward results for transpose=False/True against dense references and to check gradients of the transpose=True path w.r.t. CSR values.
  • Add coo_mv_test to exercise coomv on unsorted COO triples for both orientations, scalar-weight broadcasting, and gradient of the scalar-weight path.
  • Add event csr_matmat tests to compare event.csrmm (binary CSR matmat) against dense references for both orientations and consistency with the float CSR path.
brainpy/math/sparse/utils_test.py
brainpy/math/sparse/csr_mm_test.py
brainpy/math/sparse/coo_mv_test.py
brainpy/math/event/csr_matmat_test.py
Add regression tests for pre_syn_post routing and delay variable ring-buffer behaviour.
  • Add pre_syn_post_test to cover pre2post_event_sum (scalar and per-synapse values, and dense transpose reference), syn2post_sum, syn2post_mean handling of empty groups (no NaNs), and syn2post_softmax per-group normalization.
  • Extend delayvars_coverage_test with ring-buffer regression tests: TimeDelay modulo-based wrap-around on the true-branch (exact-step, no interpolation) and LengthDelay ramp behaviour for both ROTATE_UPDATE and CONCAT_UPDATE update methods.
brainpy/math/pre_syn_post_test.py
brainpy/math/delayvars_coverage_test.py
Record the sparse/event/delay audit scope, findings, and status in documentation.
  • Add an issues-found audit document describing the reviewed modules, summarizing correctness of sparse/event/jitconn operators against dense references, detailing the Medium coo_to_csr bounds bug fix, and listing remaining low-priority observations with their status.
  • Cross-reference prior audit IDs and mark them as already fixed and re-verified in this branch.
docs/issues-found-20260619-math-sparse-event.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 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="brainpy/math/sparse/utils_test.py" line_range="21" />
<code_context>
+# coo_to_csr
+# ---------------------------------------------------------------------------
+
+def test_coo_to_csr_valid_roundtrip():
+    # 3 x 4 matrix:
+    #   [[0, 2, 0, 4],
</code_context>
<issue_to_address>
**suggestion (testing):** Add an explicit test for the empty-COO case in `coo_to_csr`.

There’s no test case for empty `pre_ids`/`post_ids` (e.g. `num_row > 0` with `nse == 0`), which is easy to implement incorrectly (e.g. `indptr` length/dtype or `indptr[-1]` not zero). Please add a test (e.g. `test_coo_to_csr_empty_matrix`) using `pre = post = np.array([], dtype=int)`, `num_row = 3`, and asserting that `indices` is empty and `indptr` is `np.array([0, 0, 0, 0], dtype=np.int32)` to cover structurally empty matrices.
</issue_to_address>

### Comment 2
<location path="brainpy/math/sparse/utils_test.py" line_range="85" />
<code_context>
+    return np.asarray(indptr), np.asarray(indices), np.asarray(order)
+
+
+def test_csr_to_coo_roundtrip():
+    rows = np.array([0, 0, 1, 2, 2])
+    cols = np.array([1, 3, 0, 1, 3])
</code_context>
<issue_to_address>
**suggestion (testing):** Consider adding a test for `csr_to_coo` with a completely empty CSR (no non-zeros).

You already cover a standard roundtrip and CSR with empty rows. It would be helpful to add a case where the CSR represents an all-zero matrix, e.g. `indptr = np.zeros(num_rows + 1, dtype=int)` and empty `indices`. A test like `test_csr_to_coo_all_zero_matrix` can assert `csr_to_coo` returns empty `rows`/`cols` with the correct dtype/shape and handles this corner case without errors.
</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.

# coo_to_csr
# ---------------------------------------------------------------------------

def test_coo_to_csr_valid_roundtrip():

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (testing): Add an explicit test for the empty-COO case in coo_to_csr.

There’s no test case for empty pre_ids/post_ids (e.g. num_row > 0 with nse == 0), which is easy to implement incorrectly (e.g. indptr length/dtype or indptr[-1] not zero). Please add a test (e.g. test_coo_to_csr_empty_matrix) using pre = post = np.array([], dtype=int), num_row = 3, and asserting that indices is empty and indptr is np.array([0, 0, 0, 0], dtype=np.int32) to cover structurally empty matrices.

return np.asarray(indptr), np.asarray(indices), np.asarray(order)


def test_csr_to_coo_roundtrip():

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (testing): Consider adding a test for csr_to_coo with a completely empty CSR (no non-zeros).

You already cover a standard roundtrip and CSR with empty rows. It would be helpful to add a case where the CSR represents an all-zero matrix, e.g. indptr = np.zeros(num_rows + 1, dtype=int) and empty indices. A test like test_csr_to_coo_all_zero_matrix can assert csr_to_coo returns empty rows/cols with the correct dtype/shape and handles this corner case without errors.

@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