Skip to content

Skip zero entries in fraction-free row elimination#4

Merged
adelaett merged 1 commit into
mainfrom
alain/fraction-free-simplex-pivot
Jul 2, 2026
Merged

Skip zero entries in fraction-free row elimination#4
adelaett merged 1 commit into
mainfrom
alain/fraction-free-simplex-pivot

Conversation

@adelaett

@adelaett adelaett commented Jul 2, 2026

Copy link
Copy Markdown
Owner

What

Short-circuit zero cells in ff_eliminate (the fraction-free pivot inner loop).

Why

I measured cell-level statistics for the inner loop on the benchmark corpus and found these exact-rational tableaux are 65–80% zero mid-solve — much sparser than the ~50% assumed when ff_eliminate was written. Concretely, 55–67% of all inner-loop cell visits have both a.(j)=0 and the pivot-row entry row.(j)=0. For those cells the new value a.(j)*p - ac*row.(j) is identically zero (and Z.divexact 0 dprev = 0), yet the old code spent two bignum multiplies, a subtraction and an exact division to recompute a zero.

How

Add an a.(j)=0 short-circuit to every branch of ff_eliminate:

  • both a.(j) and row.(j) zero → leave the cell zero, no work at all (the dominant case);
  • only a.(j) zero → value is -ac*row.(j) (drop the vanishing a.(j)*p product);
  • only row.(j) zero → value is a.(j)*p (the existing fast path).

Each simplified expression is still the full Bareiss numerator for that cell (the dropped term is provably zero), so the exact /dprev division stays valid and every result is bit-identical. dune runtest passes with no golden changes.

Result

Benchmark harness (bench/evaluate.py --baseline main --candidate <branch> --rule bland --trials 30), correctness-checked against the GLPK + Gurobi oracle consensus:

  • VERDICT: ACCEPTED
  • Correctness: passed on all 19 held-out instances
  • Geomean speedup: 1.12× (+12.5%), 95% bootstrap CI [1.086, 1.163] (entirely above 1.0)
  • Pivot ratio: exactly 1.0000× — identical pivot sequence, pure per-pivot arithmetic savings
  • rand_25x60 16.5ms → 14.6ms; best instance degen_14 1.31×

This lands on top of the fraction-free + pricing + phase-1 work already merged in #2.

The exact-rational tableaux are 65-80% zero mid-solve (much sparser than the
~50% assumed when ff_eliminate was written): measured 55-67% of all inner-loop
cell visits have both the row entry a.(j) and the pivot-row entry row.(j) equal
to zero. For those cells the new value aj*p - ac*r is identically zero (and
divexact 0 = 0), so the old code was spending two bignum multiplies, a
subtraction and an exact division to recompute a zero.

Short-circuit on a.(j) = 0 in every branch of ff_eliminate:
  - both a.(j) and row.(j) zero  -> leave the cell zero, no work at all;
  - only a.(j) zero              -> value is -ac*row.(j) (drop the aj*p product);
  - only row.(j) zero            -> value is aj*p (unchanged fast path).
Each simplified numerator is still the full Bareiss numerator for that cell, so
the exact /dprev division stays valid and every result is bit-identical.

dune runtest passes with no golden changes.
@adelaett adelaett merged commit 0e277f0 into main Jul 2, 2026
12 checks passed
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.

1 participant