Skip to content

CSRConstraint: cache positional CSR so the snapshot diff keeps its identity fast path #933

Description

@FabianHofmann

Note

The following content was generated by AI (Claude Code) during the review of #929, verified by @FabianHofmann.

Since #929, CSRConstraint stores raw variable labels as CSR columns and maps them to dense positions at matrix assembly (CSRConstraint._to_positional_csr). That mapping allocates a fresh indices array on every call, so the persistent snapshot diff (linopy/persistent/diff.py, _same) can no longer short-circuit on array identity for indices and falls through to a full np.array_equal over all non-zeros. data and indptr keep their identity, so the rest of the fast path survives.

Measured on a frozen model with about 600k non-zeros: the gather plus compare costs about 4.5 ms of a 36 ms diff, roughly 12%.

Proposal

Cache the positional CSR on the constraint, keyed on the VariableLabelIndex (or its invalidation counter), so repeated to_matrix / to_matrix_with_rhs calls without variable changes return the same indices buffer. Constraints._invalidate_label_position_index and the variable container's invalidation are the natural hooks.

Follow-up to #926 / #929.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    sparseSparse / CSR-backed expressions and constraints

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions