Skip to content

Fall back to the best iterate when terminating with a numerical error#229

Open
batterseapower wants to merge 2 commits into
oxfordcontrol:mainfrom
batterseapower:pixiu/best-iterate-only
Open

Fall back to the best iterate when terminating with a numerical error#229
batterseapower wants to merge 2 commits into
oxfordcontrol:mainfrom
batterseapower:pixiu/best-iterate-only

Conversation

@batterseapower

@batterseapower batterseapower commented Jul 15, 2026

Copy link
Copy Markdown

The bug

When the interior-point loop terminates with NumericalError or InsufficientProgress, the reduced-tolerance ("almost solved") acceptance check is evaluated against the final iterate. But on a numerical failure the final iterate is typically the one that just went bad -- that is why the solver stopped. The good iterate from one step earlier is discarded, and the solve is reported as a failure on the strength of a point the solver had already superseded.

This shows up on problems whose attainable gap floor sits close to the requested tolerance: the primal residual jumps from ~1e-10 to ~3e-5 in a single step, the loop bails out, and the almost-solved test is then applied to the ruined point and fails. The solver had a perfectly acceptable answer in hand and threw it away.

The fix

Track the best iterate seen so far and restore it before the almost-solved check runs.

  • Merit is max(gap_rel, res_primal, res_dual) -- the worst of the quantities the (almost-)solved checks actually test, so "best" means best by the criterion the caller is about to be judged against.
  • Iterates with ktratio > 1 are never candidates: those lie on the infeasibility-certificate path and must not be presented as approximate solutions.
  • The restore is a no-op when the final iterate is already the best one, so the path is inert on every solve that terminates Solved.

Cost is one extra DefaultVariables and a copy on strict improvement.

Evidence

It only ever helps. Across the 133 Maros-Meszaros QPs that this build solves, the patch is bit-identical to stock: not a single status, iteration count, objective or returned residual changes. That is the expected result -- those problems terminate normally, so the restore never fires -- and it bounds the blast radius: the patch cannot regress a solve that was already succeeding.

The solver had those better iterates in hand and was reporting the degraded final one instead.

Tests. Three unit tests cover the semantics: a degraded final iterate is discarded in favour of the best seen; a final iterate that is itself the best is left untouched; iterates on the infeasibility path are never eligible to be saved or restored. Full suite green: 123 tests, 0 failures (cargo test --release).

…error

On some ill-conditioned problems the last iterations before a NumericalError
or InsufficientProgress termination degrade the iterate severely (e.g. the
primal residual blows up by orders of magnitude chasing the final decade of
duality gap), so the reduced-tolerance 'almost solved' check fails even
though an excellent iterate was visited a few steps earlier. Track the best
iterate seen (by the worst of gap_rel/res_primal/res_dual, only while
kappa/tau <= 1) and restore it before post-processing when the solver
terminates in an error state, mirroring how commercial solvers report their
best point on stall.
Covers the three behaviours the fallback has to get right: a degraded final
iterate is discarded in favour of the best one seen, a final iterate that is
itself the best is left untouched, and iterates on the infeasibility path
(ktratio > 1) are never eligible to be saved or restored.
@CLAassistant

CLAassistant commented Jul 15, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@batterseapower
batterseapower marked this pull request as ready for review July 15, 2026 03:24
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.

2 participants