mip presolve: worklist-fixpoint propagation, singleton-column elimination#14
Merged
Conversation
Replaces the 4-full-pass cap with a worklist seeded with all rows that re-enqueues only rows touching a tightened column. Reaches the unique fixpoint (bounds only shrink) while doing less work per call: untouched rows are never rescanned. Gate: 13/13 green; 020 6.9s -> 6.5s, 016 0.5s -> 0.2s, 018 1.2s -> 0.9s. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Costed continuous columns appearing in exactly one row are substituted out before the LP is built: a column whose cost is capped only by its row pins that row at any optimum (x = (b - rest)/a, cost folded onto the row's remaining columns), and one whose row never resists its cost sits at its bound. Folding can re-classify same-row siblings, so the pass iterates to fixpoint. Solutions, duals, reduced costs and row activities are reconstructed exactly in the caller's original space. On the evcc golden instances this finds nothing — their 616 singletons are penalty slacks (cost fights the row: a max(0, .) term no linear presolve can remove); an earlier census misread them as eliminable by ignoring ObjSense. The transform fires on minimize-form models with revenue-style singletons, e.g. via the cbc CLI. Gate: 13/13 green, trajectories bit-identical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two presolve-side reductions, follow-up to #13:
Bound propagation runs to fixpoint via a row worklist (
mip/presolve.go). The previous 4-full-pass cap both overworked (rescanning untouched rows) and underworked (stopping short of the fixpoint on long implication chains). The worklist seeds all rows and re-enqueues only rows touching a tightened column; the fixpoint is unique since bounds only shrink, with a generous pivot-count safety cap for degenerate chains. Node-level propagation gets cheaper and tighter: golden case 020 6.9s → 6.5s, 016 0.5s → 0.2s, 018 1.2s → 0.9s.Singleton-column elimination with exact postsolve (
mip/eliminate.go). Costed continuous columns appearing in exactly one row are substituted out before the LP is built: a column whose cost is capped only by its row pins that row at any optimum (x = (b - rest)/a, cost folded onto the row's remaining columns); one whose row never resists its cost is fixed at its bound. Folding can re-classify same-row siblings, so the pass iterates. Solutions, duals, reduced costs and row activities are reconstructed exactly in the caller's column space, including across the warm-restart path.An honest note on the second one: on the evcc golden instances it finds nothing — their ~616 continuous singletons are penalty slacks whose cost fights the row (a
max(0, ·)term no exact linear presolve can remove). An earlier census misread them as eliminable by ignoringObjSense. The transform does fire on minimize-form models with revenue-style singletons, e.g. anything fed through thecbcCLI, and comes with unit tests covering tight-pin, bound-fix, and partial same-row chains plus a dual-identity check.Testing
go test ./...green; three new unit tests for the elimination (structure, values, duals).🤖 Generated with Claude Code