pub struct IpoptApplication { /* private fields */ }Implementations§
Source§impl IpoptApplication
impl IpoptApplication
Sourcepub fn new() -> Self
pub fn new() -> Self
New application with empty options and a default journalist.
Equivalent to IpoptApplication::IpoptApplication(true,true).
pub fn options(&self) -> &OptionsList
pub fn options_mut(&mut self) -> &mut OptionsList
Sourcepub fn set_presolve_already_applied(&mut self, applied: bool)
pub fn set_presolve_already_applied(&mut self, applied: bool)
Declare whether callers have already applied an explicit presolve
wrapper to the TNLPs submitted to Self::optimize_tnlp.
When set, optimize_tnlp leaves its input TNLP unchanged even if the
presolve option is enabled. This preserves the option table for
reporting and debugger use while allowing specialized frontends to
supply a wrapper with capabilities unavailable to generic callback
TNLPs, such as an expression provider for FBBT.
Sourcepub fn optimize_tnlp_without_presolve(
&mut self,
tnlp: Rc<RefCell<dyn TNLP>>,
) -> ApplicationReturnStatus
pub fn optimize_tnlp_without_presolve( &mut self, tnlp: Rc<RefCell<dyn TNLP>>, ) -> ApplicationReturnStatus
Solve without materializing the generic presolve wrapper.
This is for consumers that require the original TNLP coordinate system
for the solve’s KKT matrix, such as sensitivity and reduced-Hessian
drivers. It is scoped to this invocation and does not change the
application’s presolve option or persistent explicit-wrapper setting.
pub fn registered_options(&self) -> &Rc<RegisteredOptions>
pub fn journalist(&self) -> &Rc<Journalist>
Sourcepub fn set_linear_backend_factory(&mut self, factory: LinearBackendFactory)
pub fn set_linear_backend_factory(&mut self, factory: LinearBackendFactory)
Plug a custom symmetric-linear-solver factory. Useful for tests
that want to swap MA57 for a stub. Production callers should
leave this unset — the default (default_backend_factory)
returns the workspace’s MA57 binding.
Sourcepub fn set_restoration_factory(&mut self, factory: RestorationFactory)
pub fn set_restoration_factory(&mut self, factory: RestorationFactory)
Plug a restoration-phase factory. Called once per
optimize_tnlp invocation to mint a fresh
Box<dyn RestorationPhase> that the outer algorithm uses as
its line-search restoration fallback. Lives behind a setter
(rather than at construction) because the concrete restoration
strategies live in pounce-restoration, which depends on this
crate; consumers in pounce-cli / integration tests wire the
factory at the application boundary.
Sourcepub fn set_diagnostics(&mut self, diag: Rc<DiagnosticsState>)
pub fn set_diagnostics(&mut self, diag: Rc<DiagnosticsState>)
Install the shared diagnostics state. Once set, every
subsequent optimize_tnlp call forwards the state into the
algorithm via IpoptAlgorithm::with_diagnostics so the KKT
solver can emit --dump kkt:... artifacts.
Sourcepub fn set_debug_hook(&mut self, hook: Rc<RefCell<dyn DebugHook>>)
pub fn set_debug_hook(&mut self, hook: Rc<RefCell<dyn DebugHook>>)
Install an interactive debugger hook for the next optimize_*
call. The hook is moved into the main IpoptAlgorithm and
consumed by that solve; reinstall it to debug a subsequent solve.
Sourcepub fn diagnostics(&self) -> Option<Rc<DiagnosticsState>>
pub fn diagnostics(&self) -> Option<Rc<DiagnosticsState>>
Read-side accessor for the installed diagnostics state, if any. Lets the CLI write the top-level manifest/timing files after the solve completes.
Sourcepub fn reports_fixed_var_duals(&self) -> bool
pub fn reports_fixed_var_duals(&self) -> bool
Whether the final solution reports bound multipliers for variables
make_parameter removed (see
OrigIpoptNlp::complete_fixed_var_bound_multipliers).
Ipopt 3.14 does, for every treatment except make_parameter_nodual,
which exists to ask it not to.
Sourcepub fn set_in_retry_sequence(&self, active: bool)
pub fn set_in_retry_sequence(&self, active: bool)
Mark that the next optimize_* calls are further attempts at the
same problem, driven from outside, rather than new solves.
Retry drivers that re-enter optimize_tnlp per attempt — the
second-opinion ladder is the only one today — bracket their attempts
with true … false. The effect is confined to console presentation:
the Ipopt-style problem-statistics header is printed once for the run
instead of once per attempt. Nothing about the solve changes.
Callers must clear it on every exit path, including the early returns a
ladder takes when a rung promotes; a stuck true costs a later solve
its header and nothing worse.
Sourcepub fn defer_end_verdict(&self)
pub fn defer_end_verdict(&self)
Take ownership of the run-ending EXIT: / POUNCE <version>: verdict
for the attempts that follow.
Between this and Self::release_end_verdict the per-attempt end
summary prints its statistics block but not the verdict, so a retried
run no longer reports a mid-run verdict that reads as the final answer.
The releaser prints it once, with the status it is returning.
Callers must pair the two on every exit path. An unmatched acquire costs the run its verdict line; the counter saturates rather than wrapping, so an unmatched release cannot make a nested driver print one early.
Sourcepub fn release_end_verdict(&self) -> bool
pub fn release_end_verdict(&self) -> bool
Release one Self::defer_end_verdict. Returns true when this was
the outermost one — i.e. when the caller now owns printing the verdict.
Sourcepub fn print_end_verdict(&self, status: ApplicationReturnStatus)
pub fn print_end_verdict(&self, status: ApplicationReturnStatus)
Print the run-ending verdict, honouring print_level.
The gate matches emit_end_summary’s, which is the block this follows:
at print_level 0 there is no summary for it to end.
Sourcepub fn set_restoration_factory_provider(
&mut self,
provider: RestorationFactoryProvider,
)
pub fn set_restoration_factory_provider( &mut self, provider: RestorationFactoryProvider, )
Plug a restoration-phase factory provider for drivers that
need to run the inner IPM more than once per optimize_tnlp
call (notably the Phase-3 ℓ₁-exact penalty-barrier outer loop,
pounce#10). On each inner solve, the application consults the
provider to mint a fresh RestorationFactory, replacing any
stale one, so the default one-shot restoration factory does
not panic on its second invocation. If both set_restoration_factory
and this are configured, the provider wins.
Sourcepub fn set_on_converged(&mut self, cb: ConvergedCallback)
pub fn set_on_converged(&mut self, cb: ConvergedCallback)
Register a callback to run once the IPM has converged (status
ApplicationReturnStatus::SolveSucceeded or
ApplicationReturnStatus::SolvedToAcceptableLevel) but before
finalize_solution flows back to the TNLP. See
ConvergedCallback for the use case (post-optimal sensitivity).
Sourcepub fn take_on_converged(&mut self) -> Option<ConvergedCallback>
pub fn take_on_converged(&mut self) -> Option<ConvergedCallback>
Remove and return the registered on-converged callback, if any, so a
caller that installs its own for a while can put the previous one
back (pounce_minima::IpoptLocalSolve does, gh#966).
Sourcepub fn answer_restored_from_floor(&self) -> bool
pub fn answer_restored_from_floor(&self) -> bool
Was the reported answer replayed from an earlier attempt’s floor, after a later attempt lost?
A caller that captures the solution in Self::set_on_converged
must consult this. That callback fires once per attempt, and a
losing retry that converged has already run it, so the capture
belongs to the discarded point while everything else — status,
objective, statistics — has been floored back. When this is true,
take x and the multipliers from the last finalize_solution
payload instead; that one is always the answer being reported,
because the floor restores it by calling finalize_solution.
The payload is in the model’s own units and in the reduced
presolve space: CountingTnlp-style consumers sit inside the gh#486
scaling wrapper (so x /= d, z *= d have already been applied) and
outside the presolve one (so the row/column lift has not). A caller
swapping it in must therefore skip its own scaling correction and keep
its own lift; getting that backwards squares the factor, which is a
silent wrong answer of exactly the shape this flag exists to remove.
Not consulted, and known not to be: the three other
Self::set_on_converged consumers —
pounce-sensitivity/src/{solver,convenience}.rs and
pounce-cli/src/minima/mod.rs — read the converged KKT state and the
factorization, which the finalize_solution payload does not carry
and which cannot be rewound. After any floor replay their result
describes the attempt that lost. Pre-existing, unfixed, and annotated
at each site.
false on every solve that never spent a second attempt, which is
almost all of them, so the ordinary path is unaffected.
Sourcepub fn enable_iter_history(&mut self)
pub fn enable_iter_history(&mut self)
Enable per-iteration trajectory capture. After the solve
returns, Self::statistics() exposes
pounce_nlp::solve_statistics::SolveStatistics::iterations
populated with one pounce_nlp::solve_statistics::IterRecord
per accepted iterate. Off by default — the pounce_sens and
pounce binaries opt in when --json-output is passed.
Sourcepub fn iter_history_enabled(&self) -> bool
pub fn iter_history_enabled(&self) -> bool
Whether Self::enable_iter_history is in force — read by a stage
that produces a verdict outside optimize_tnlp (the second-opinion
ladder’s square-system stage) so its statistics keep the same
iterations / iteration_count pairing.
Sourcepub fn initialize_with_option_file(
&mut self,
explicit: Option<&Path>,
) -> Result<OptionFileLoad, SolverException>
pub fn initialize_with_option_file( &mut self, explicit: Option<&Path>, ) -> Result<OptionFileLoad, SolverException>
Read the run’s options file, resolving which file the way
upstream’s IpoptApplication::Initialize does — with one
deliberate difference, below.
explicit is the file the caller named (upstream: the
option_file_name option, read out of the option store before
this point). With None, the working directory is probed for
DEFAULT_OPTION_FILE_NAMES and the first hit is read; an
absent default file is not an error, it just means “no file”.
The difference: upstream opens a named file with a bare
std::ifstream and reads nothing if the open fails, so a typo’d
option_file_name runs at stock defaults without a word. That
silence is what gh#518 was reported for — a benchmark that
measured defaults while claiming to measure a configuration — so
a named file that cannot be read is an error here.
Sourcepub fn initialize_with_options_file(
&mut self,
path: &Path,
) -> Result<(), SolverException>
pub fn initialize_with_options_file( &mut self, path: &Path, ) -> Result<(), SolverException>
Read an ipopt.opt-format options file. Equivalent to
IpoptApplication::Initialize(const std::string& options_file).
Sourcepub fn initialize_with_options_str(
&mut self,
s: &str,
) -> Result<(), SolverException>
pub fn initialize_with_options_str( &mut self, s: &str, ) -> Result<(), SolverException>
Read options from a string in ipopt.opt format. Useful for
tests and embedded callers.
Sourcepub fn initialize(&mut self) -> Result<(), SolverException>
pub fn initialize(&mut self) -> Result<(), SolverException>
No-op initialize (just succeeds). Mirrors
IpoptApplication::Initialize(bool allow_clobber) with no
options file.
Sourcepub fn open_output_file(&mut self, fname: &str, print_level: i32) -> bool
pub fn open_output_file(&mut self, fname: &str, print_level: i32) -> bool
Mirror IpoptApplication::OpenOutputFile. Sets the output_file
/ file_print_level options and attaches a matching
FileJournal named OutputFile:<fname> to the journalist.
Returns false if the file could not be opened or the option
store rejected the request (e.g. clamped print level).
Sourcepub fn problem_dimensions(&self, tnlp: &mut dyn TNLP) -> Option<NlpInfo>
pub fn problem_dimensions(&self, tnlp: &mut dyn TNLP) -> Option<NlpInfo>
Wrap a TNLP and report problem dimensions. Used in tests until the full IPM path covers every entry shape.
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 of the last solve (gh#605): the nonlinear
violation before and after, the accepted step norm, how many
backtracking trials were rejected, and why it stopped. None
when least_square_init_primal was off or the model had no
constraints.
pub fn statistics(&self) -> SolveStatistics
Sourcepub fn warm_start_diagnostics(&self) -> Option<WarmStartDiagnostics>
pub fn warm_start_diagnostics(&self) -> Option<WarmStartDiagnostics>
What the warm-start initializer made of the iterate the caller supplied to the most recent solve (gh#606): the residuals it measured, whether each multiplier block was accepted, reconstructed or discarded, and the barrier parameter it settled on.
None when the last solve was a cold start
(warm_start_init_point=no), or when no solve has run. Reset at
the top of every solve, like Self::timing_stats.
Sourcepub fn timing_stats(&self) -> Rc<TimingStatistics>
pub fn timing_stats(&self) -> Rc<TimingStatistics>
Shared timing accumulator from the most recent optimize_tnlp
call. Each subsystem (algorithm, NLP, KKT solver) bumped its own
fields during the solve; consumers read totals out of the
returned Rc. The instance is replaced at the top of every
subsequent solve, so cloning the Rc and holding it past a
re-solve will give you the previous solve’s timings — by design.
Sourcepub fn linear_solver_summary(&self) -> Option<LinearSolverSummary>
pub fn linear_solver_summary(&self) -> Option<LinearSolverSummary>
Aggregate linear-solver post-mortem from the most recent
optimize_tnlp call. Some when the workspace-default FERAL
backend ran at least one factor; None when no factors were
recorded (custom factory plugged via
Self::set_linear_backend_factory, or solve aborted before
the first KKT factor). Reset at the top of every solve.
Restoration-phase factorizations are attached as
LinearSolverSummary::restoration when the frontend wired
Self::restoration_summary_sink into its restoration factory.
Sourcepub fn linear_solver_summary_state(&self) -> LinearSolverSummaryState
pub fn linear_solver_summary_state(&self) -> LinearSolverSummaryState
Snapshot of both linear-solver summary sinks (main and restoration), for a driver that re-solves and must report the summary of the solve whose verdict it keeps. The second-opinion ladder takes one before its rungs and restores it when no rung is promoted, exactly as it does for the statistics.
Sourcepub fn restore_linear_solver_summary_state(
&self,
state: LinearSolverSummaryState,
)
pub fn restore_linear_solver_summary_state( &self, state: LinearSolverSummaryState, )
Put back a Self::linear_solver_summary_state snapshot.
Sourcepub fn restoration_summary_sink(&self) -> Arc<Mutex<LinearSolverSummary>> ⓘ
pub fn restoration_summary_sink(&self) -> Arc<Mutex<LinearSolverSummary>> ⓘ
The sink a restoration backend factory should record into, e.g.
through default_backend_factory_with_sink. Kept separate from
the main solve’s sink so the main-solve totals stay about the main
solve.
Sourcepub fn variable_scaling(&self) -> Option<Vec<Number>>
pub fn variable_scaling(&self) -> Option<Vec<Number>>
The per-variable scaling factors applied to the last solve, if
any (gh#486). A consumer reading the algorithm’s iterate rather
than the finalize_solution payload sees scaled coordinates and
must divide x by these, and multiply bound multipliers.
pub fn optimize_tnlp( &mut self, tnlp: Rc<RefCell<dyn TNLP>>, ) -> ApplicationReturnStatus
Sourcepub fn optimize_tnlp_with_derivative_test_tnlp(
&mut self,
tnlp: Rc<RefCell<dyn TNLP>>,
derivative_test_tnlp: Option<Rc<RefCell<dyn TNLP>>>,
) -> ApplicationReturnStatus
pub fn optimize_tnlp_with_derivative_test_tnlp( &mut self, tnlp: Rc<RefCell<dyn TNLP>>, derivative_test_tnlp: Option<Rc<RefCell<dyn TNLP>>>, ) -> ApplicationReturnStatus
Solve through tnlp, optionally overriding the derivative-test target.
None tests the scaled and conditioned TNLP.
Sourcepub fn mark_mu_strategy_pounce_chosen(&mut self)
pub fn mark_mu_strategy_pounce_chosen(&mut self)
Record that the mu_strategy now in the option table was chosen by a
POUNCE frontend, not by the caller (gh#990).
The Python path for a problem without hessian writes
mu_strategy=monotone so that gh#746’s limited-memory -> adaptive
substitution does not read a barrier preference out of a Hessian
choice POUNCE made itself. Written as an ordinary option, that pin
also read as “the caller named a strategy” to
Self::is_mu_strategy_fallback_enabled, which switched off the
default-on stall retry (gh#748) on exactly that path — the same
set-ness defect the second-opinion ladder’s write-backs once had.
With this mark the pin still decides the schedule, and the fallback
stays on. A frontend calls it only when the caller’s own options carry
no mu_strategy.
Sourcepub fn set_sqp_warm_start(&mut self, warm: SqpIterates)
pub fn set_sqp_warm_start(&mut self, warm: SqpIterates)
Has the user set algorithm = active-set-sqp? Reads the
string option and matches case-insensitively against the
design-note §7.1 spelling. Any value other than
“active-set-sqp” (including absence) routes to the
default IPM path.
Stash a warm-start iterate for the SQP path. Consumed by
the next optimize_tnlp call when the algorithm option
resolves to active-set-sqp; the IPM path ignores it.
Phase 5c (§6) — the parametric / MPC warm-start hand-off.
The iterate is auto-cleared after use, so a follow-up
solve without an intervening set_sqp_warm_start call
cold-starts.
x, lambda_g and lambda_x are in the caller’s space — what
finalize_solution reports: full-n x in model units, lambda_g
in g order on the unscaled Lagrangian f + λᵀg, and
lambda_x = z_L − z_U. The solve maps them into the algorithm’s
space (fixed variables dropped, [y_c; y_d] row order, objective,
constraint and per-variable scaling) itself, so a converged solve’s
reported multipliers can be fed back unchanged. The working set is in
the same space: bound statuses full-n in variable order (fixed
variables’ entries are ignored), constraint statuses one per g row
in the user’s row order — exactly what Self::last_sqp_working_set
publishes, so a published set can be fed back as-is.
Sourcepub fn clear_sqp_warm_start(&mut self)
pub fn clear_sqp_warm_start(&mut self)
Drop any pending warm-start iterate without solving.
Sourcepub fn crossover_report(&self) -> Option<&CrossoverReport>
pub fn crossover_report(&self) -> Option<&CrossoverReport>
What the crossover phase did on the most recent solve (gh#612).
None means crossover never ran — either crossover=no (the
default) or the solve did not converge. A Some whose
CrossoverReport::accepted is false means it ran and declined;
the two are different facts about a solve and consumers that reason
about active-set certainty (sensitivity’s AMBIGUOUS class, a
downstream var_status) need to tell them apart.
Sourcepub fn set_warm_start_iterate(&mut self, snap: IterateSnapshot)
pub fn set_warm_start_iterate(&mut self, snap: IterateSnapshot)
Install a full primal-dual warm-start iterate for the next IPM
optimize_tnlp. Captured by the debugger’s resolve so the
re-solve continues from the paused interior point. The caller is
responsible for also enabling warm_start_init_point=yes (and
usually warm_start_target_mu=<μ>) so the re-optimize branch of
WarmStartIterateInitializer preserves the installed iterate.
Consumed once per solve, then auto-cleared.
Sourcepub fn set_external_ordering(&mut self, perm: Vec<usize>)
pub fn set_external_ordering(&mut self, perm: Vec<usize>)
Install a caller-supplied fill-reducing permutation for the KKT
linear solver (pounce#180 item 1). The next optimize_* builds
the FERAL backend with pounce_feral::OrderingMethod::External,
overriding the feral_ordering string option / env var. Use this
to inject a block-triangular / Schur ordering a generic algorithm
cannot see (Parker, Garcia & Bent, arXiv:2602.17968) or a tearing
ordering from equation-oriented decomposition.
perm is a 0-based, new-to-old permutation (perm[k] is the
original index that becomes index k), and its length must equal
the augmented KKT system dimension (variables + slacks +
constraint duals), not the problem’s n. A wrong length or a
non-bijection is rejected by FERAL at the first factorization with
an InvalidInput error (never a panic), surfacing as a solver
failure rather than a silently-wrong solve — the ordering only
affects fill/time, never the computed solution.
Persistent config: unlike the warm-start hooks it is not
auto-cleared after a solve. Call Self::clear_external_ordering
to drop it. Ignored by non-FERAL backends and by any custom
factory plugged via Self::set_linear_backend_factory.
Sourcepub fn clear_external_ordering(&mut self)
pub fn clear_external_ordering(&mut self)
Drop any installed external KKT ordering, restoring the
feral_ordering-driven default for subsequent solves.
Sourcepub fn external_ordering(&self) -> Option<&[usize]>
pub fn external_ordering(&self) -> Option<&[usize]>
The currently-installed external KKT ordering, if any.
Sourcepub fn set_block_structure(
&mut self,
var_blocks: Vec<i32>,
con_blocks: Vec<i32>,
)
pub fn set_block_structure( &mut self, var_blocks: Vec<i32>, con_blocks: Vec<i32>, )
Install a block-triangular / Schur KKT partition (pounce#180 item 2).
indices are KKT-space indices (0..dim in the x, s, c, d block
order the aug-system solver assembles) naming the Schur block S; that
block is Schur-complemented out and only the two diagonal blocks are
factorized (inertia via Sylvester’s law). Honored on the IPM + feral +
exact-Hessian path; the Schur solver falls back to the standard
full-space solver transparently when the partition is unsuitable (too
large a fraction of the system, malformed, or a backend error), so a
stray hook never breaks a solve. Persistent config (not auto-cleared);
drop it via Self::clear_kkt_schur_block.
Declare the block structure in the model’s own terms: one block id
per variable and per constraint, negative for the shared ones
(structured-KKT Phase 5b). Blocks must couple only through the shared
entries; the solver checks that against the assembled KKT and falls
back when it does not hold.
This is the form a model can produce — “pg[g] is shared, everything
in contingency k is block k” — and pounce maps it to KKT indices
itself, accounting for fixed variables and the equality / inequality
split. Lengths are the problem’s own n and m; a mismatch is
reported and the solve proceeds monolithically.
Persistent config; drop it with Self::clear_block_structure.
Sourcepub fn clear_block_structure(&mut self)
pub fn clear_block_structure(&mut self)
Drop any declared model-space block structure.
Sourcepub fn block_structure(&self) -> Option<(&[i32], &[i32])>
pub fn block_structure(&self) -> Option<(&[i32], &[i32])>
The declared model-space block structure, if any.
Sourcepub fn set_kkt_block_structure(&mut self, labels: Vec<i32>)
pub fn set_kkt_block_structure(&mut self, labels: Vec<i32>)
Install a block-parallel KKT partition (structured-KKT Phase 5b).
labels are KKT-space block ids in the solver’s internal
x, slack, eq-dual, ineq-dual order, < 0 for the shared border; an
empty vector asks the solver to detect the structure from the
assembled KKT. Honored on the IPM + feral + exact-Hessian path, with a
transparent fallback to the standard solver when the partition does not
match the matrix. Persistent config; drop it with
Self::clear_kkt_block_structure.
Sourcepub fn clear_kkt_block_structure(&mut self)
pub fn clear_kkt_block_structure(&mut self)
Drop any installed block partition.
Sourcepub fn kkt_block_structure(&self) -> Option<&[i32]>
pub fn kkt_block_structure(&self) -> Option<&[i32]>
The currently-installed block partition, if any.
pub fn set_kkt_schur_block(&mut self, indices: Vec<usize>)
Sourcepub fn clear_kkt_schur_block(&mut self)
pub fn clear_kkt_schur_block(&mut self)
Drop any installed Schur KKT partition, restoring the standard full-space solver for subsequent solves.
Sourcepub fn kkt_schur_block(&self) -> Option<&[usize]>
pub fn kkt_schur_block(&self) -> Option<&[usize]>
The currently-installed Schur KKT partition, if any.
Sourcepub fn last_sqp_working_set(&self) -> Option<&WorkingSet>
pub fn last_sqp_working_set(&self) -> Option<&WorkingSet>
Return the final QP working set from the most recent SQP
solve, or None if the last solve wasn’t SQP, didn’t
produce a working set (cold-start declared the iterate
optimal before solving any QP), or no SQP solve has run.
The set is in the caller’s index spaces, the ones
finalize_solution uses: bounds[j] is variable j of the full
n (a variable fixed_variable_treatment = make_parameter removed
reads Fixed), and constraints[i] is g row i in the model’s
own row order — not the SQP’s internal equalities-first order. It is
the form Self::set_sqp_warm_start takes back.
Sourcepub fn unimplemented_linear_solver(&self) -> Option<String>
pub fn unimplemented_linear_solver(&self) -> Option<String>
The linear_solver value when the caller explicitly asked for a
backend pounce does not implement; None when the request can be
served (or was never made).
pounce ships two: FERAL (pure Rust, the effective default) and
MA57 (HSL, behind the ma57 feature). The option’s valid-value
list is a faithful port of upstream Ipopt’s — ma27, ma77,
ma86, ma97, mumps, pardiso, pardisomkl, spral, wsmp,
custom — so an ipopt.opt written for Ipopt parses here, and
every one of those names used to fall through a _ => arm to
FERAL. A run “using MUMPS” was a FERAL run; a benchmark comparing
backends compared FERAL with itself (gh#483 follow-up).
The registered default is feral, which pounce implements, so no
explicit-vs-default distinction is needed: whatever the option
resolves to must be a backend that exists. (It is checked
unconditionally on purpose — a future default naming something
unimplemented should trip this, not slip past it.)
Explicit ma57 on a build that lacks the feature is not refused;
that fallback is reported in the banner (“ma57 requested but not
compiled”), so it is visible rather than silent, and failing a
portable ipopt.opt over a build flag would cost more than it buys.
Sourcepub fn unimplemented_option_refusal(&self) -> Option<String>
pub fn unimplemented_option_refusal(&self) -> Option<String>
The message for the first option the caller set that names a
feature pounce does not implement, or None. Public so the CLI
can refuse before routing — the convex dispatch never reaches
optimize_tnlp. See crate::unimplemented_options.
A run configuring nothing but backends pounce does not ship is
refused here too, after the per-option table has had its say —
see crate::unimplemented_options::backend_only_refusal. It
is folded in rather than given its own accessor so that every
surface already refusing on this method refuses on it as well;
the CLI is not the only frontend, and a condition worth failing
on is not worth failing on only from the CLI.
Sourcepub fn unimplemented_option_value_refusal(&self) -> Option<String>
pub fn unimplemented_option_value_refusal(&self) -> Option<String>
The message for the first string option the caller set to a
registered value pounce does not implement, or None.
Separate from Self::unimplemented_option_refusal because the
option itself is read and its other values work — it is one mode
that is missing, not the feature. See
crate::unimplemented_options::UNIMPLEMENTED_VALUES.
Sourcepub fn unhonored_option_file_name(&self) -> Option<String>
pub fn unhonored_option_file_name(&self) -> Option<String>
option_file_name set on a surface that never resolves it.
The option reaches a file through exactly one path —
Self::initialize_with_option_file, which the pounce CLI
drives. A library caller (Python, the C interface, WASM) sets its
options directly and calls no such thing, so on those surfaces the
option names a whole configuration and applies none of it: gh#518’s
failure mode, one surface over. It used to be caught by the blanket
crate::unimplemented_options refusal, which no longer covers it
now that the feature exists; this keeps the guard exactly where the
feature still doesn’t.
Deliberately not fixed by having the library read an options file
too: an implicit ./ipopt.opt lookup under Python or the GAMS C
link would be a surprising action at a distance, and pounce.opt
already means something else to GAMS.
Sourcepub fn set_convex_routing_available(&mut self, available: bool)
pub fn set_convex_routing_available(&mut self, available: bool)
Declare that this caller can route a model to the convex LP/QP /
SOCP engines, so the qp_* knobs they read configure something.
The pounce CLI calls this: it owns the .nl structure
extraction that classifies a model, which is the whole of what
solver_selection’s convex values need. No library frontend can
(see Self::unsupported_library_solver_selection), so the
default is false and Self::unhonored_convex_option refuses
the knobs there.
Declaring it also covers the CLI’s fallback: a convex attempt
that returns no verified point hands the model to
Self::optimize_tnlp, and the qp_* values it was given
configured that attempt for real. Refusing them at the handoff
would fail a run that used them.
Sourcepub fn unhonored_convex_option(&self) -> Option<String>
pub fn unhonored_convex_option(&self) -> Option<String>
The convex LP/QP knobs are registered core-side so every frontend parses them — but only the CLI can reach the engines that read them. On any other entry point the option names a whole configuration and applies none of it; this is the message that says so, in place of the silence.
gh#604. Same shape and same default gate as
Self::unhonored_option_file_name: an explicitly-set default
asks for nothing and must keep working, so only a value that
differs is refused.
Sourcepub fn unexploited_hint_warnings(&self) -> Vec<String>
pub fn unexploited_hint_warnings(&self) -> Vec<String>
Warnings for caching hints pounce does not exploit. These never block a solve: the answer is identical either way, so refusing would cost the caller more than the silence did.
Sourcepub fn convex_unexploited_hint_warnings(&self) -> Vec<String>
pub fn convex_unexploited_hint_warnings(&self) -> Vec<String>
Warnings for the constant-derivative hints when the solve routes to
pounce-convex instead of here. Call site is the convex dispatch
in the CLI, next to the other guards that live there for the same
reason: that dispatch never reaches Self::optimize_tnlp, so
install_constant_derivative_hints never runs and the hints are
unread. On the NLP route they are honoured, so this must not be
called there.
Sourcepub fn unimplemented_backend_warnings(&self) -> Vec<String>
pub fn unimplemented_backend_warnings(&self) -> Vec<String>
Warnings for knobs of a linear-solver backend pounce does not
ship (ma97_*, pardiso_*, …), one line per backend family.
Warnings and not refusals: an ipopt.opt carrying settings for
several backends so that one file runs everywhere is exactly what
the registry exists to accept, and refusing it would fail a run
over knobs it never touches. See the “Backend knobs warn, they do
not refuse” section of crate::unimplemented_options. gh#551.
Sourcepub fn take_unimplemented_backend_warnings(&mut self) -> Vec<String>
pub fn take_unimplemented_backend_warnings(&mut self) -> Vec<String>
The same warnings, but at most once per application: the second caller gets nothing.
Two sites emit them — the CLI, before routing, because a convex
model never reaches Self::optimize_tnlp, and optimize_tnlp
itself, for every frontend that is not the CLI. A CLI run passes
through both, and printing the identical paragraph twice is how a
warning teaches its reader to skip warnings.
Sourcepub fn derivative_check(&self) -> Option<DerivativeCheckSummary>
pub fn derivative_check(&self) -> Option<DerivativeCheckSummary>
The derivative checker’s structured verdict from the most recent
Self::run_derivative_test, or None when no test ran (gh#990).
The IPM and SQP drains copy it into SolveStatistics; a caller that
builds its own report (the CLI’s convex route) reads it here.
Sourcepub fn run_derivative_test(&self, tnlp: &Rc<RefCell<dyn TNLP>>)
pub fn run_derivative_test(&self, tnlp: &Rc<RefCell<dyn TNLP>>)
Run the derivative checker, if requested, against tnlp.
Advisory, like upstream: a suspicious entry is reported and the
solve continues. The report goes to stderr so it survives
print_level=0 and leaves --json-output’s stdout clean.
Sourcepub fn unimplemented_linear_solver_message(value: &str) -> String
pub fn unimplemented_linear_solver_message(value: &str) -> String
The message Self::unimplemented_linear_solver earns, shared by
every frontend so they cannot drift apart.
Sourcepub fn is_sqp_algorithm_selected(&self) -> bool
pub fn is_sqp_algorithm_selected(&self) -> bool
Will the next optimize_tnlp run the active-set SQP driver rather
than the interior-point one?
Public because the dispatch decision has to be reportable, not just
taken: before this was reachable, the CLI’s Selected solver: line
and the JSON report’s solution.engine both named the filter-IPM on
every algorithm=active-set-sqp run, because the only thing either
consulted was solver_selection — which is auto on a general NLP
however the algorithm option is set. Reading the same predicate
optimize_tnlp dispatches on is what keeps the report and the run
from disagreeing; deriving it a second time in the CLI is how they
drifted in the first place.
Sourcepub fn algorithm_builder_from_options(&self) -> AlgorithmBuilder
pub fn algorithm_builder_from_options(&self) -> AlgorithmBuilder
Build an AlgorithmBuilder populated from the app’s
OptionsList. Public so callers wiring the restoration
factory can hand the inner IPM a builder that mirrors the
outer’s mu_strategy/mu_oracle/line-search choices —
matching upstream IpAlgBuilder::BuildRestoIpoptAlgorithm,
which reads the same mu_strategy option with prefix `“resto.”
- prefix` and falls back to the outer setting.
Trait Implementations§
Source§impl Debug for IpoptApplication
impl Debug for IpoptApplication
Auto Trait Implementations§
impl !Freeze for IpoptApplication
impl !RefUnwindSafe for IpoptApplication
impl !Send for IpoptApplication
impl !Sync for IpoptApplication
impl !UnwindSafe for IpoptApplication
impl Unpin for IpoptApplication
impl UnsafeUnpin for IpoptApplication
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