Skip to content

perf: drop explicit zeros from the constraint matrix (#814)#815

Draft
FBumann wants to merge 1 commit into
masterfrom
perf/drop-explicit-zeros
Draft

perf: drop explicit zeros from the constraint matrix (#814)#815
FBumann wants to merge 1 commit into
masterfrom
perf/drop-explicit-zeros

Conversation

@FBumann

@FBumann FBumann commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

This opportunity was discovered while exploring the regression introduced by highspy==1.15
Depeneding on the model, this is quite a impressive improvement. But id only merge it after someone tested it with real world models and maybe also hardened tests with other solvers.

Closes #814.

Note

The following was generated by AI.

What & why

Expressions that broadcast against a dense coordinate (e.g. a bus × line
incidence block) store one coefficient per coordinate pair, most of them
structurally zero. Those explicit zeros were carried into model.matrices.A
and handed to every solver. highspy.Highs.addRows — and the other direct
backends' matrix loaders — scale with stored nnz, so the handoff spent most
of its work describing zeros (sparse_network(250): 1.5M stored entries for
18k structural nonzeros, 98.8% zeros).

Change

Prune explicit zeros once, centrally, in matrices._stack via
eliminate_zeros(). This covers both A and indicator_A, so all
consumers benefit — HiGHS, gurobi, xpress, copt, mosek and the LP/MPS
writers — not just HiGHS. A zero coefficient never changes a constraint, so
the result is mathematically identical; row count (and thus clabels
alignment) is preserved, and the dual/sol paths recompute independently of
A.

Chose the central matrices layer over the per-backend _build_solver_model
patch from the issue precisely so every backend and writer shares the win.

Tests

  • New test_matrices_drops_explicit_zeros asserts a dense-broadcast constraint
    yields only structural nonzeros (stored-vs-structural nnz regression).
  • Existing test_matrices.py and test_solvers.py pass unchanged.
Expected addRows speedup (from #813 standalone repro)
highspy explicit zeros (1.5M nnz) eliminate_zeros (18k nnz) speedup
1.13.1 ~13 ms ~1.6 ms ~8×
1.15.0 ~51 ms ~1.7 ms ~30×

Side effect: makes linopy insensitive to the #813 highspy addRows regression.

🤖 Generated with Claude Code

Expressions that broadcast against a dense coordinate store one
coefficient per pair, most of them structurally zero. Those explicit
zeros were carried all the way into `matrices.A` and thus into every
solver handoff. `highspy.Highs.addRows` (and the other direct backends'
matrix loaders) scale with *stored* nnz, so the handoff spent most of
its work describing zeros — e.g. sparse_network(250) stored 1.5M entries
for 18k structural nonzeros (98.8% zeros).

Prune them once, centrally, in `_stack` via `eliminate_zeros()`, so `A`
and `indicator_A` — and hence HiGHS, gurobi, xpress, copt, mosek and the
LP/MPS writers — all hand the solver only structural nonzeros. A zero
coefficient never changes a constraint, so this is mathematically
identical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@FBumann FBumann marked this pull request as draft July 2, 2026 13:40
@codspeed-hq

codspeed-hq Bot commented Jul 2, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 29.51%

⚡ 2 improved benchmarks
✅ 171 untouched benchmarks
⏩ 173 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory test_to_solver[highs-sparse_network-n=250] 64.8 MB 47.8 MB +35.55%
Memory test_to_solver[highs-kvl_cycles-severity=50] 245.6 MB 198.5 MB +23.75%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing perf/drop-explicit-zeros (957b54f) with master (e861678)

Open in CodSpeed

Footnotes

  1. 173 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Speed up direct solver handoff by dropping explicit zeros from the constraint matrix

1 participant