pub struct IpoptAlgorithm {Show 33 fields
pub data: IpoptDataHandle,
pub cq: IpoptCqHandle,
pub bundle: AlgorithmBundle,
pub nlp: Option<Rc<RefCell<dyn IpoptNlp>>>,
pub tnlp: Option<Rc<RefCell<dyn TNLP>>>,
pub fires_as_restoration: bool,
pub search_dir: Option<PdSearchDirCalc>,
pub restoration: Option<Box<dyn RestorationPhase>>,
pub kappa_sigma: Number,
pub slack_based_scaling: bool,
pub recalc_y: bool,
pub recalc_y_feas_tol: Number,
pub max_iter: Index,
pub start_with_resto: bool,
pub alpha_init: Number,
pub tiny_step_tol: Number,
pub diverging_iterates_tol: Number,
pub tiny_step_y_tol: Number,
pub dual_diverging_streak: usize,
pub dual_divergence_retry_step_tol: Number,
pub dual_divergence_retry_du_floor: Number,
pub tiny_step_last_iteration: bool,
pub resto_decline_deferrals: usize,
pub resto_decline_progress_ratio: Number,
pub neg_curv_escapes: usize,
pub lbfgs_ls_failure_restarts: usize,
pub last_iter_stats_sink: Option<Rc<RefCell<Option<IterStats>>>>,
pub kkt_fidelity_tol: Number,
pub resto_calls: Index,
pub resto_inner_iters: Index,
pub resto_outer_iters: Index,
pub resto_wall_secs: Number,
pub print_iter_output: bool,
/* private fields */
}Fields§
§data: IpoptDataHandle§cq: IpoptCqHandle§bundle: AlgorithmBundle§nlp: Option<Rc<RefCell<dyn IpoptNlp>>>Optional NLP handle. Required for any step that evaluates problem functions or pulls bound expansion matrices (init, search direction, line-search trial-point evaluation). Absent in the structural unit tests of Phases 5-6.
tnlp: Option<Rc<RefCell<dyn TNLP>>>Optional TNLP handle — the user-facing problem. When present,
iterate() fires TNLP::intermediate_callback once per outer
iteration so callers can monitor progress or request early
termination (returning false from the callback surfaces as
SolverReturn::UserRequestedStop). Kept separate from nlp
because the algorithm-side NLP is the compressed OrigIpoptNlp
view (fixed-variable elimination, c/d split) while the callback
payload needs to expose the original-coordinate iterate.
fires_as_restoration: boolSet on the restoration inner IPM so its callback fires report
AlgorithmMode::RestorationPhaseMode (gh#645). Two things hang
off it, both in Self::fire_intermediate:
- the mode field of the
IterStatspayload, which is what tells a caller the numbers beside it (obj,inf_pr,inf_du,alpha_*) describe the min-C1-norm feasibility subproblem rather than the user’s NLP; - whether the live-inspector
IntermediateContextis installed — and for a restoration fire it deliberately is not. The inner iterate is aCompoundVectorover(x_orig, n, p), so it does not even have the user’sn, and the C API’sGetIpoptCurrent*family checks the caller’sn/magainst the problem’s registered dimensions rather than the context’s. Installing this context would sail past that check and read a differently-shapedcq. The live accessors therefore report “no data” during restoration, which is the truth: there is no current iterate of the user’s problem while the subproblem is being solved.
search_dir: Option<PdSearchDirCalc>Search-direction calculator (PdSearchDirCalc). Lands once a
concrete SymLinearSolver backend (MUMPS / FERAL) is wired
through AlgBuilder in Phase 7’s tail.
restoration: Option<Box<dyn RestorationPhase>>Restoration-phase strategy. Invoked when the line search
returns Outcome::Failed (port of upstream
IpBacktrackingLineSearch::ActivateLineSearch’s resto
fallback). Optional: in its absence, line-search failure maps
directly to SolverReturn::RestorationFailure so the main
loop’s exit-code semantics match upstream’s “no resto built”
case.
kappa_sigma: Numberkappa_sigma for the post-AcceptTrialPoint multiplier reset
(IpIpoptAlg.cpp:correct_bound_multiplier, line 1055-1134).
slack_based_scaling: boolrecalc_y — recompute y_c/y_d as least-square estimates
once the iterate is feasible enough, instead of carrying the
multipliers the Newton step produced. Upstream registers this
no, but its own option text says “If a limited memory
quasi-Newton option is chosen, this is used by default”, so the
L-BFGS path auto-enables it (see
application.rs). Costs one extra augmented-system solve on
every iteration where it fires.
It exists because a quasi-Newton model’s multipliers are only as
good as the Hessian approximation behind them: L-BFGS can reach
a feasible primal and still fail to drive inf_du down, because
the dual step is computed from an approximate W. Re-estimating
y by least squares side-steps the approximation entirely.
linear_system_scaling=slack-based is active, so the
iterate-dependent s-block scaling must be refreshed each
iteration. See Self::push_slack_scaling.
recalc_y: bool§recalc_y_feas_tol: Numberrecalc_y_feas_tol — the constraint-violation threshold below
which Self::recalc_y fires. Upstream default 1e-6.
max_iter: Index§start_with_resto: boolstart_with_resto — force the feasibility restoration phase in
the first iteration.
This is an outer-loop behaviour, which is where it went wrong
before: the option was threaded from the OptionsList through
AlgorithmBuilder::resto into RestoAlgorithmBuilder and on into
MinC1NrmDriver, a field on the inner restoration solver, where
there is no first iteration of the outer algorithm to act on. It
was set by everything and read by nothing, so start_with_resto yes was a silent no-op. unimplemented_options.rs’s
the_restoration_switches_reach_the_builder asserted only that the
value reached the builder — the very “read site populating a field
nobody consumes” its own comment names as the defect to avoid.
alpha_init: NumberInitial primal step length offered to the line search at the
top of each iteration. Mirrors IpBacktrackingLineSearch’s
fraction-to-the-boundary primal step (with τ = data.curr_tau).
In v1.0 the structural value here is 1.0 and the FTB cap is
applied per-component when the line-search driver computes
trial slacks; the simplification holds for non-degenerate runs.
tiny_step_tol: NumberTiny-step relative tolerance — port of upstream
IpBacktrackingLineSearch::tiny_step_tol_ (default 10·EPSILON).
Step is “tiny” when max_i |δx_i|/(1+|x_i|) ≤ tiny_step_tol
(and same for s, and c_viol ≤ 1e-4).
diverging_iterates_tol: NumberPort of upstream IpIpoptAlg.cpp divergence guard: when
max_i |x_i| exceeds this threshold the optimization aborts with
SolverReturn::DivergingIterates. Default 1e20 matches the
registered diverging_iterates_tol option. Catches MESH and
similar cases where the normal-mode IPM heads off to infinity
(orig f to ±1e33 by iter 90) before line-search failure forces
a degenerate restoration entry.
tiny_step_y_tol: NumberCompanion threshold on the dual step — when both primal and dual
steps are tiny in two consecutive iterations the algorithm
declares convergence at the best attainable accuracy. Default
1e-2 matches upstream.
dual_diverging_streak: usizedual_diverging_streak (pounce#246) — number of consecutive
iterations of growing dual infeasibility (in the elevated regime,
inf_du > [DUAL_DIV_COUNT_FLOOR]) that must accumulate before the
dual-divergence guard fires. When the streak reaches the limit and
inf_du > [DUAL_DIV_FIRE_TOL], the outer routes to restoration.
0 (off) is the default, set from the option of the same name
(application.rs). It defaulted to 15 when introduced; see the option
help in upstream_options.rs for why that changed, and
Self::honour_best_acceptable_after_dual_guard for what protects a
solve when it is enabled. See the guard itself in Self::iterate.
dual_divergence_retry_step_tol: Numbergh#884 — thresholds for the dual-divergence retry signature.
Distinct from the pounce#246 guard above in both mechanism and
consequence: that one diverts a running solve to restoration, this
one only records that a cold retry is worth attempting after the
solve has already given up. Set from options of the same name; see
[DUAL_DIV_RETRY_STEP_TOL] for the measured populations.
dual_divergence_retry_du_floor: NumberCompanion floor on the unscaled dual — see
[DUAL_DIV_RETRY_DU_FLOOR].
tiny_step_last_iteration: boolSet true when the previous iterate was tagged tiny; on the
second consecutive tiny step the loop sets data.tiny_step_flag
so the mu update can attempt to terminate. Mirrors
IpBacktrackingLineSearch::tiny_step_last_iteration_.
resto_decline_deferrals: usizeresto_decline_deferrals (gh #534) — how many times the
acceptable-point restoration decline in Self::invoke_restoration may
be deferred on a solve whose NLP error is still contracting. 0
restores the pre-#534 behaviour (decline immediately, always).
See Self::may_defer_acceptable_decline for the progress test and
Self::honour_decline_floor for what makes a spent deferral harmless.
resto_decline_progress_ratio: Numberresto_decline_progress_ratio (gh #534) — the contraction each of the
last [DECLINE_PROGRESS_SAMPLES] - 1 iterations must have achieved for
the decline to be deferred. Default
[DEFAULT_DECLINE_PROGRESS_RATIO]. A value of 1 admits any
non-increasing window and a large one drops the progress requirement
altogether, which is the “patch the guard and see” experiment the issue
asks for, available without patching.
neg_curv_escapes: usizeneg_curv_escapes (gh #797) — how many times a certified stationary
point whose reduced Hessian is not positive semidefinite may be left
along a direction of negative curvature instead of reported. 0 restores
the pre-#797 behaviour (report the first-order certificate, whatever its
curvature).
See Self::try_neg_curv_escape for the test and the step, and
Self::honour_neg_curv_floor for what makes a lost bet harmless.
lbfgs_ls_failure_restarts: usizelimited_memory_ls_failure_restarts (gh #818) — how many times a
line-search failure at an already feasible point may re-anchor
the quasi-Newton model and retry, instead of handing off to a
restoration phase that has no constraint violation to reduce.
0 restores the pre-#818 behaviour (always hand off).
See Self::try_reanchor_before_restoration for the rung and
what bounds it.
last_iter_stats_sink: Option<Rc<RefCell<Option<IterStats>>>>Sink for the last IterStats handed to the user’s
intermediate_callback (pounce#870). A second-opinion retry that loses
needs it, so that the trace a consumer accumulated can be made to end
on the iterate actually reported. Set by IpoptApplication; None
everywhere else.
kkt_fidelity_tol: Numberkkt_fidelity_tol (pounce#173), needed here — not just at termination —
because the fallback’s tiebreak has to predict the post-solve status
gate. See Self::honour_refused_certificate. Zero (the default)
disables the gate, and with it every tiebreak effect it has.
resto_calls: IndexNumber of invoke_restoration entries.
resto_inner_iters: IndexSum of inner-IPM iter counts across every restoration call.
resto_outer_iters: IndexNumber of outer iters that ran in restoration mode (R-line
equivalents in print_level=5 output).
resto_wall_secs: NumberCumulative wall-clock seconds spent inside perform_restoration.
print_iter_output: boolWhen false, the per-iteration table that iterate() writes
straight to stdout is suppressed. Wired from
IpoptApplication’s print_level option: level 0 turns this
off (matches upstream’s “no console output” contract). Default
true so CLI / direct-driver users keep the familiar trace.
Implementations§
Source§impl IpoptAlgorithm
impl IpoptAlgorithm
Sourcepub fn least_square_init_report(&self) -> Option<LeastSquareInitReport>
pub fn least_square_init_report(&self) -> Option<LeastSquareInitReport>
Diagnostics from the safeguarded least_square_init_primal
initializer step (gh#605). None when the step was not run.
pub fn new( data: IpoptDataHandle, cq: IpoptCqHandle, bundle: AlgorithmBundle, ) -> Self
pub fn with_nlp(self, nlp: Rc<RefCell<dyn IpoptNlp>>) -> Self
Sourcepub fn with_tnlp(self, tnlp: Rc<RefCell<dyn TNLP>>) -> Self
pub fn with_tnlp(self, tnlp: Rc<RefCell<dyn TNLP>>) -> Self
Install a user-facing TNLP handle. Enables per-iteration
TNLP::intermediate_callback invocation from optimize().
pub fn with_search_dir(self, sd: PdSearchDirCalc) -> Self
pub fn with_restoration(self, resto: Box<dyn RestorationPhase>) -> Self
Sourcepub fn with_diagnostics(self, diag: Rc<DiagnosticsState>) -> Self
pub fn with_diagnostics(self, diag: Rc<DiagnosticsState>) -> Self
Install the shared diagnostics state. The state is propagated
to the augmented-system solver at the top of Self::optimize
so dump sites can consult per-iter gating.
Sourcepub fn with_debug_hook(self, hook: Rc<RefCell<dyn DebugHook>>) -> Self
pub fn with_debug_hook(self, hook: Rc<RefCell<dyn DebugHook>>) -> Self
Install an interactive debugger hook. Fired at each checkpoint
in Self::optimize; returning crate::debug::DebugAction::Stop
ends the solve with SolverReturn::UserRequestedStop.
Sourcepub fn debug_hook(&self) -> Option<Rc<RefCell<dyn DebugHook>>>
pub fn debug_hook(&self) -> Option<Rc<RefCell<dyn DebugHook>>>
Shared handle to the installed debugger, if any — used to forward it into the restoration inner IPM.
Sourcepub fn dual_divergence_signature(&self) -> bool
pub fn dual_divergence_signature(&self) -> bool
Whether this solve ever saw gh#884’s dual-divergence-at-a-settled-primal
signature. Sticky; see Self::dual_divergence_signature.
Sourcepub fn optimize(&mut self) -> SolverReturn
pub fn optimize(&mut self) -> SolverReturn
Outer entry point — port of IpoptAlgorithm::Optimize(). Calls
the iterate-initializer once, then loops iterate() until a
terminal status. The exception → SolverReturn mapping
(TINY_STEP_DETECTED → STEP_BECOMES_TINY,
RESTORATION_FAILED → RESTORATION_FAILURE, etc.) lands in
Phase 9 alongside the restoration phase.
Run the solve and finalize its result.
A thin wrapper on purpose. The gh #200 fallback must see every exit
of the driver loop, and wiring it into individual termination sites was
tried and failed — there are sixteen, and the ones easiest to overlook
are the ones most likely to matter. Keeping the loop in a separate
function means every return inside it, present or future, flows through
Self::honour_refused_certificate by construction rather than by the
author remembering to.
This got more important once the fallback started changing the status in
both directions: it can now hand back StopAtAcceptablePoint for a
Success it was given. Anything reading result before the hook is
reading a status that is not the one reported.
Auto Trait Implementations§
impl !RefUnwindSafe for IpoptAlgorithm
impl !Send for IpoptAlgorithm
impl !Sync for IpoptAlgorithm
impl !UnwindSafe for IpoptAlgorithm
impl Freeze for IpoptAlgorithm
impl Unpin for IpoptAlgorithm
impl UnsafeUnpin for IpoptAlgorithm
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T, U> Imply<T> for U
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more