pub struct BoundRelax {
pub factor: f64,
pub cap: f64,
}Expand description
Ipopt’s bound_relax_factor widening, as the convex extractors apply it.
The NLP path widens x_L/x_U and the inequality-row bounds d_L/d_U
before the algorithm ever sees them (OrigIpoptNlp::relax_bounds, driven
from Application with bound_relax_factor — Ipopt default 1e-8 —
capped by constr_viol_tol, default 1e-4). The convex path did not,
so the same binary solved a materially different model depending on
solver_selection.
That is not a hairline difference on a constraint-degenerate model. On
LISWET1 (gh #744) every one of the 10 000 monotonicity rows is active at
the optimum and the multipliers sum to 1.6e9, so a 1e-8 widening of the
rows buys 9.0 of objective — the convex arm returned the exact optimum
36.1224 and the NLP arm (and Ipopt-MA57) the relaxed one, 27.1221, and
the 33% gap was read as a convex-solver bug. Both arms now relax, so both
report 27.1221, and bound_relax_factor=0 gets 36.1224 from either.
Faithful to relax_bounds in three details that matter:
- Equality rows are not relaxed. Upstream they live in
c(x) = 0, whichrelax_boundsnever touches; onlyd_L/d_U(inequality rows) and the variable box are widened. - Rows use the scale-relative width
min(factor, cap)·|b|(with|b|read as1at a declared-zero bound), the gh #385 form. The variable box keeps the upstream absolute formulamin(factor·max(|b|,1), cap). - Fixed variables (
x_l == x_u) keep their bounds. Under the defaultfixed_variable_treatment=make_parameterupstream removes them beforerelax_boundsruns, so they are never widened.
Fields§
§factor: f64bound_relax_factor. Non-positive disables the widening entirely.
cap: f64constr_viol_tol — the cap on the widening.
Implementations§
Source§impl BoundRelax
impl BoundRelax
Sourcepub const NONE: Self
pub const NONE: Self
No widening — the model exactly as declared. What the convex path did
unconditionally before gh #744, and what bound_relax_factor=0 selects.
Sourcepub fn active(self) -> bool
pub fn active(self) -> bool
Whether any widening is actually applied. Public so a caller can tell
“the declared model and the solved model coincide” from “they differ”,
which struct equality against Self::NONE cannot: bound_relax_factor=0
zeroes the factor but leaves cap at constr_viol_tol, so the pair is
inactive without being NONE.
Trait Implementations§
Source§impl Clone for BoundRelax
impl Clone for BoundRelax
Source§fn clone(&self) -> BoundRelax
fn clone(&self) -> BoundRelax
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for BoundRelax
Source§impl Debug for BoundRelax
impl Debug for BoundRelax
Source§impl PartialEq for BoundRelax
impl PartialEq for BoundRelax
impl StructuralPartialEq for BoundRelax
Auto Trait Implementations§
impl Freeze for BoundRelax
impl RefUnwindSafe for BoundRelax
impl Send for BoundRelax
impl Sync for BoundRelax
impl Unpin for BoundRelax
impl UnsafeUnpin for BoundRelax
impl UnwindSafe for BoundRelax
Blanket Implementations§
impl<T> Boilerplate for T
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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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