Skip to main content

Module handover

Module handover 

Source
Expand description

Interior-point → active-set handover inside one solve (gh#1054).

§Why

On large collocation models the interior-point method gets close fast and then spends a long tail meeting tol: the reporter of gh#1054 measured the objective within 0.1 % of final after ~40 % of the iterations, the rest going to a tail where the dual infeasibility oscillates and the filter backtracks. Near the solution the active set is already identified, and an SQP step on it converges in a few iterations. Running the two as separate solves needs a working set between them, and getting one at that size was the blocker: post-convergence crossover ran after the tail it was meant to avoid.

§What it does

With ipm_sqp_handover=yes, the interior-point loop offers each iterate that has not converged to HandoverTrigger::should_try. When the trigger fires, the iterate goes through the same bridge as post-convergence crossover (crate::crossover::run): identify the active set from the multipliers against the slacks, take one QP step over it, and fall back to the full active-set SQP from that working set. The point that comes back replaces the interior iterate only if it meets the stopping tolerances, and the solve then ends Solve_Succeeded. Otherwise the interior iteration continues from exactly where it was: nothing it carries is touched by a declined attempt, so the fallback the request asked for is the interior method itself, not a restart.

§When it fires

Either test, whichever comes first:

  • tolerance: the overall NLP error is at or below ipm_sqp_handover_tol (a loosened tol);
  • stall: ipm_sqp_handover_stall_iter > 0 and the best error seen has not halved in that many iterations.

A declined attempt re-arms only after the error has fallen another order of magnitude below the error at that attempt, or a full stall window has passed without one, and at most ipm_sqp_handover_max_attempts attempts are made. Without the back-off, a model whose active set is not yet identifiable would pay an SQP attempt on every remaining iteration.

§Identification

At an interior iterate a bound’s slack s and multiplier z satisfy s·z ≈ μ, so an active bound has s ≈ μ/z and an inactive one z ≈ μ/s; √μ separates the two. The primal tolerance handed to the classifier is therefore max(crossover_primal_tol, √μ): the crossover default (1e-6) is sized for a converged iterate, and at a loosened tolerance it would call every active bound inactive. A misclassified row costs pivots in the QP, not correctness.

Structs§

HandoverOptions
Tuning, read from the ipm_sqp_handover* options.
HandoverReport
What the handover did on the most recent solve. Retrieved from crate::application::IpoptApplication::handover_report.
HandoverTrigger
Decides, iteration by iteration, whether to attempt a handover. See the module docs for the rules.

Functions§

identification_primal_tol
The primal tolerance for classifying the active set at an interior iterate whose barrier parameter is mu. See the module docs.