Skip to content

fix(simplex): preserve feasibility with anti-cycling pivots - #25

Draft
rasheedja wants to merge 2 commits into
masterfrom
junaidr/fix-bland-pivot-cycling
Draft

rasheedja wants to merge 2 commits into
masterfrom
junaidr/fix-bland-pivot-cycling

Conversation

@rasheedja

@rasheedja rasheedja commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Degenerate simplex problems could repeat the same dictionary indefinitely. They could also retain zero artificial basic variables after phase one and later let them become positive, relaxing the original constraints. For example, with x,y ∈ [1,2] and x+y ≤ 2, all four extrema must return the unique point (1,1).

  • Apply Bland's least-index rule to entering variables and minimum-ratio leaving ties in the shared pivot routine. Exclude retained objective rows from the ratio test. For valid feasible dictionaries with exact arithmetic this guarantees finite termination; Bland can take more pivots than largest-coefficient selection. See the Bland termination rule in MIT's linear programming notes.
  • After verifying a zero phase-one optimum, pivot remaining artificial basics out using nonzero non-artificial coefficients of either sign. Drop only redundant zero rows, remove artificial columns, and retain artificial-variable metadata so phase two still substitutes the objective correctly. Reuse the existing private dictionary pivot helper.
  • Add regressions for the bounded cycle through combined and separate public APIs, exact Max/Min optima and feasibility, both phase-one index choices, objective-row exclusion, the unique feasible point, redundant equalities, and a negative cleanup coefficient. Timeout tests force the complete result before the deadline and fail explicitly.
  • Add changelog entries. Different tied bases may change which zero variables appear in the sparse result, or select a different point among equal optima; objective values are preserved. Three existing assertions now accept omitted zero entries while checking the same numeric solutions.

Validation: the original policy failed both cycle regressions at five seconds and selected the wrong basis in the phase-one policy regression. Before artificial-basis cleanup, the phase-one transition regressions returned (2,0) instead of (1,1) and retained redundant artificial rows. The final stack --no-system-ghc test --no-terminal passes all 296 examples. Fourmolu 0.15.0.0, cabal check, Haddock, and git diff --check pass. The original cycle trace returns the exact optimum (a,b,c,d,z) = (0,1,0,1,1) without a repeated state.

Integration uses a copied LPPaver2 at 8f9b913aaa3f4ef6b0e7aeeac32f4ad0f41e087d with only this simplex dependency overridden. Its original pruning cycle completes with a nonempty box and z ∈ [0,1]; all 71 downstream examples pass, including the multivariate corner bound regression. This PR changes no LPPaver2 source or dependency pins. Local builds used Stack's GHC 9.6.7; the full compiler/platform matrix remains for CI.

@rasheedja rasheedja changed the title fix(simplex): prevent degenerate pivot cycles with Bland's rule fix(simplex): preserve feasibility with anti-cycling pivots Oct 4, 2026
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