pub struct MonotoneMuUpdate {
pub mu_init: Number,
pub mu_min: Number,
pub mu_max: Number,
pub mu_linear_decrease_factor: Number,
pub mu_superlinear_decrease_power: Number,
pub tau_min: Number,
pub barrier_tol_factor: Number,
pub mu_target: Number,
pub mu_allow_fast_monotone_decrease: bool,
pub compl_inf_tol: Number,
pub first_iter_resto: bool,
}Fields§
§mu_init: Number§mu_min: Number§mu_max: NumberUpper bound on μ from IpMonotoneMuUpdate.cpp:RegisterOptions.
Used to clamp mu_init at MuUpdate::initialize so the
barrier doesn’t start above the registered ceiling regardless
of what the user set. Default 1e5 mirrors upstream.
mu_linear_decrease_factor: Number§mu_superlinear_decrease_power: Number§tau_min: Number§barrier_tol_factor: Numberbarrier_tol_factor from IpMonotoneMuUpdate.cpp:RegisterOptions.
μ only decreases when the barrier subproblem error drops below
barrier_tol_factor · μ.
mu_target: Numbermu_target floor — μ never goes below this regardless of the
reduction formula. Defaults to 0 (the floor is mu_min).
mu_allow_fast_monotone_decrease: boolmu_allow_fast_monotone_decrease from
IpMonotoneMuUpdate.cpp:RegisterOptions. When true (the
upstream default), the reduction loop keeps iterating while
the sub-error stays below barrier_tol_factor · μ, allowing
multiple consecutive μ reductions in one outer call. When
false, the loop exits after the first successful reduction —
useful on stiff problems where a runaway μ collapse destroys
the line search.
compl_inf_tol: NumberComplementarity tolerance — option compl_inf_tol, default 1e-4
per IpAlgorithmRegOp.cpp. Enters the dynamic μ floor via
min(tol, compl_inf_tol) / (barrier_tol_factor + 1) per
IpMonotoneMuUpdate.cpp:CalcNewMuAndTau:215. Without this floor,
μ can collapse to the absolute floor (mu_min) while primal
infeasibility is still large — observed on SSINE/DECONVBNE.
first_iter_resto: boolfirst_iter_resto_ flag from
Algorithm/IpMonotoneMuUpdate.cpp:118-121,144,196. When set,
the very next call to Self::update_barrier_parameter skips
the μ-reduction loop entirely and clears the flag. Wired by
the restoration sub-builder for the inner IPM (prefix
"resto.") so the inner doesn’t immediately collapse μ on
iteration 0 — it must use the resto_mu value that
[crate::resto::init::RestoIterateInitializer::SetInitialIterates]
seeded into data.curr_mu.
Implementations§
Source§impl MonotoneMuUpdate
impl MonotoneMuUpdate
pub fn new() -> Self
Sourcepub fn with_first_iter_resto(self, b: bool) -> Self
pub fn with_first_iter_resto(self, b: bool) -> Self
Builder helper for the first_iter_resto_ flag. Mirrors the
upstream prefix == "resto." branch in
IpMonotoneMuUpdate.cpp:InitializeImpl.
Sourcepub fn with_mu_min(self, mu_min: Number) -> Self
pub fn with_mu_min(self, mu_min: Number) -> Self
Builder for the mu_min floor. The restoration inner IPM uses
100 * outer_mu_min per upstream IpAdaptiveMuUpdate.cpp:206-211
(and the analogous monotone path); without the conservative
floor, near-feasible iterates collapse μ to the absolute floor
in a single step and the next direction is dominated by the
penalty/proximity terms instead of the barrier, which destroys
near-feasibility (DECONVBNE).
Sourcepub fn compute_tau(&self, mu: Number) -> Number
pub fn compute_tau(&self, mu: Number) -> Number
Fraction-to-the-bound parameter tau from upstream
IpMonotoneMuUpdate.cpp:Update:
tau = max(tau_min, 1 - mu)Returns a value in [tau_min, 1).
Sourcepub fn scaled_compl_inf_tol(&self, obj_scaling_factor: Number) -> Number
pub fn scaled_compl_inf_tol(&self, obj_scaling_factor: Number) -> Number
compl_inf_tol expressed in the internally scaled space that μ
lives in (pounce#257).
The dynamic μ floor exists so the barrier stops just below the accuracy
the convergence test demands, and its two terms are enforced in
different spaces. tol is compared against the scaled NLP error, so
it needs no conversion. compl_inf_tol is compared against the
unscaled complementarity (IpOptErrorConvCheck.cpp; pounce#173),
which is the scaled complementarity divided by the objective scaling
factor — so compl_inf_tol in scaled units is
compl_inf_tol · |obj_scaling_factor|.
Taking the raw value put the floor 1/|df| too high whenever the
objective was scaled down. On jit1’s branch-and-bound node subproblems
(df = 1e-5, tol = 1e-7) μ bottomed out at 9.09e-9, leaving an
unscaled complementarity of 9.09e-4 — a hard 9× over compl_inf_tol
that no further iteration could clear, since μ was already at its floor.
The iterate sat at the optimum with a scaled NLP error 10× under
tol, yet the strict certificate was unreachable; μ-at-floor plus the
vanishing step then exited STOP_AT_TINY_STEP
(Search_Direction_Becomes_Too_Small), which callers read as
unboundedness. Converting the tolerance into μ’s own space lets the
barrier descend far enough for the certificate to be issued.
The factor is signed (obj_scaling_factor = -1 poses a maximization),
so take its magnitude, and fall back to the unconverted tolerance when
it is absent or degenerate — a floor that is too low only costs
iterations, whereas one that is too high costs the certificate.
Sourcepub fn certificate_safe_mu_min(&self, obj_scaling_factor: Number) -> Number
pub fn certificate_safe_mu_min(&self, obj_scaling_factor: Number) -> Number
mu_min capped so it can never block the termination certificate
(pounce#266) — the companion of Self::scaled_compl_inf_tol.
#258 converted the dynamic term of the barrier floor into μ’s scaled
space, but the floor has a second, independent term: mu_min, a raw
absolute constant (default 1e-11) that also lives in scaled space.
Once compl_inf_tol·|df|/(barrier_tol_factor+1) < mu_min — i.e.
|df| below ≈ mu_min·(barrier_tol_factor+1)/compl_inf_tol — the
converted term stops mattering, μ bottoms out at mu_min, and the
unscaled complementarity is pinned at mu_min/|df| > compl_inf_tol:
the certificate is unreachable no matter how long the solve runs, and
μ-at-floor plus the vanishing step exits STOP_AT_TINY_STEP on an
iterate that is at the optimum (HS71 × 1e8, df = 8.3e-8).
Upstream’s monotone floor (IpMonotoneMuUpdate.cpp:CalcNewMuAndTau)
has no mu_min term at all — pounce added it so the restoration
sub-builder’s with_mu_min(100 * outer_mu_min) safeguard applies —
which is why Ipopt certifies these files even with mu_min=1e-11
forced. Capping at scaled_compl_inf_tol / (barrier_tol_factor + 1)
keeps mu_min inert exactly when it would cost the certificate, with
the same headroom the dynamic floor reserves (μ then bottoms out where
Ipopt’s does: 7.58e-13 on HS71 × 1e8). A floor that is too low only
costs iterations; one that is too high costs the certificate.
The restoration safeguard is unaffected: RestoIpoptNlp does not
override obj_scaling_factor, so the inner IPM sees df = 1 and the
cap (compl_inf_tol/(barrier_tol_factor+1) ≈ 9e-6 at defaults) sits
far above 100 · mu_min.
Sourcepub fn compute_next_mu(&self, curr_mu: Number) -> Number
pub fn compute_next_mu(&self, curr_mu: Number) -> Number
Pure scalar reduction used by the trait impl. Exposed so unit
tests can drive the formula without standing up an
IpoptData/IpoptCq fixture.
Trait Implementations§
Source§impl Default for MonotoneMuUpdate
impl Default for MonotoneMuUpdate
Source§impl MuUpdate for MonotoneMuUpdate
impl MuUpdate for MonotoneMuUpdate
Source§fn terminates_on_tiny_step(&self) -> bool
fn terminates_on_tiny_step(&self) -> bool
Monotone μ throws TINY_STEP_DETECTED when a tiny step is
flagged and μ is already at its floor — see
IpMonotoneMuUpdate.cpp. The main loop realises that throw as a
STOP_AT_TINY_STEP termination.
Source§fn initialize(&mut self, data: &IpoptDataHandle)
fn initialize(&mut self, data: &IpoptDataHandle)
Port of IpMonotoneMuUpdate.cpp:InitializeImpl. Seeds
curr_mu = min(mu_init, mu_max),
curr_tau = max(tau_min, 1 - curr_mu).
Source§fn update_barrier_parameter(
&mut self,
data: &IpoptDataHandle,
cq: &IpoptCqHandle,
_nlp: Option<&Rc<RefCell<dyn IpoptNlp>>>,
_pd_search_dir: Option<&mut PdSearchDirCalc>,
) -> Number
fn update_barrier_parameter( &mut self, data: &IpoptDataHandle, cq: &IpoptCqHandle, _nlp: Option<&Rc<RefCell<dyn IpoptNlp>>>, _pd_search_dir: Option<&mut PdSearchDirCalc>, ) -> Number
Port of IpMonotoneMuUpdate.cpp:UpdateBarrierParameter.
Reduces μ only while the barrier-subproblem error is below
barrier_tol_factor · μ (or a tiny step was just detected).
Each successful reduction also refreshes curr_tau and the new
μ in data. Returns the post-update μ.
A reduction also raises IpoptData::request_ls_reset, which the
main loop turns into the linesearch_->Reset() upstream issues at
IpMonotoneMuUpdate.cpp:165. This is the same behaviour the
caller previously inferred from “μ changed” — the loop below only
ever exits with a strictly smaller μ — but the flag is now the
single source of truth for both μ strategies (pounce#510).
Auto Trait Implementations§
impl Freeze for MonotoneMuUpdate
impl RefUnwindSafe for MonotoneMuUpdate
impl Send for MonotoneMuUpdate
impl Sync for MonotoneMuUpdate
impl Unpin for MonotoneMuUpdate
impl UnsafeUnpin for MonotoneMuUpdate
impl UnwindSafe for MonotoneMuUpdate
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