#[non_exhaustive]pub enum TerminationReason {
Show 13 variants
GradientTolerance {
grad_norm: f64,
threshold: f64,
},
SmallStepFlatObjective {
step_norm: f64,
objective_change: f64,
grad_norm: f64,
threshold: f64,
},
RelativeStationarityWindow {
grad_inf: f64,
threshold: f64,
window: usize,
},
CostStallStationary {
grad_norm: f64,
threshold: f64,
window: usize,
},
CostStallFloor {
grad_norm: f64,
threshold: f64,
window: usize,
},
ModelNoiseFloor {
predicted_decrease: f64,
noise_floor: f64,
grad_norm: f64,
},
TrustRegionRejectFloor {
radius: f64,
floor: f64,
consecutive_rejections: usize,
grad_norm: f64,
},
StepNormTolerance {
step_norm: f64,
threshold: f64,
},
FixedPointRequestedStop {
step_norm: f64,
},
IterationBudget {
iterations: usize,
grad_norm: f64,
threshold: f64,
},
LineSearchFailed {
grad_norm: f64,
},
ObjectiveFailed,
NumericalFailure,
}Expand description
Why a solver stopped, and the quantities that decided it.
Every opt solver reaches its return through exactly one of these
tests. Before this type existed the choice was discarded at the
return statement: forty-two distinct stop decisions across the five
solvers collapsed into three observable outcomes (Ok,
MaxIterationsReached, LineSearchFailed), and every consumer
re-derived the reason from the error variant, from the rendered
message text, or from whichever solver branch it happened to call.
Those re-derivations disagreed with each other and with the solver.
The reason is therefore a required field of Solution, not an
Option on a side channel: an absent reason and a reason that
happens to be uninteresting must not render identically, and a stop
site that forgets to name its test must not compile.
§Not every “converged” is the same claim
GradientTolerance and
RelativeStationarityWindow both
return successfully, but the second applies a threshold scaled by
1 + ‖x‖∞ and measured in L∞ — at a large iterate it can be
orders of magnitude weaker. Consumers that certify optimality must
read stationarity_evidence rather
than treating every success alike.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
GradientTolerance
The bound-projected gradient norm fell below the resolved gradient tolerance. The strongest claim any solver here makes.
SmallStepFlatObjective
The step became negligible, the objective flat across it, and the projected gradient below tolerance — all three together.
RelativeStationarityWindow
An L∞ stationarity test, with the threshold rescaled by
1 + ‖x‖∞, held for window consecutive iterations. Weaker
than GradientTolerance by the
scaling factor and by the norm change; see
StationarityScaling::RelativeToIterate.
CostStallStationary
The objective flatlined over the cost-stall window and the projected gradient at the best iterate cleared its tolerance: a genuine stationary optimum on a flat valley.
CostStallFloor
The objective flatlined over the cost-stall window but the projected gradient did not clear tolerance. Halting is correct — no further cost progress is available — but the point is not stationary. Not a success.
ModelNoiseFloor
The model’s predicted decrease fell below the objective’s round-off noise floor, so the acceptance ratio carries no curvature information. Stationary in the finite-precision sense.
TrustRegionRejectFloor
The trust radius (or cubic regularization) reached its floor
with consecutive_rejections steps rejected in a row: the
region cannot shrink further and no step is acceptable. Further
iterations would re-evaluate the objective without any prospect
of progress, so the loop stops here rather than grinding out its
iteration budget.
StepNormTolerance
A fixed-point iteration’s accepted step norm fell below tolerance.
FixedPointRequestedStop
A fixed-point objective returned FixedPointStatus::Stop.
The objective, not the solver, decided to stop; the solver makes
no stationarity claim of its own.
IterationBudget
The iteration budget was exhausted with no test satisfied. The returned point is the best seen.
LineSearchFailed
The line search could not produce an acceptable point.
ObjectiveFailed
The objective returned a fatal evaluation error.
NumericalFailure
Numerical instability: non-finite gradient or objective, a model Hessian that could not be made positive definite, a subproblem solver that produced no usable step.
Implementations§
Source§impl TerminationReason
impl TerminationReason
Sourcepub fn stationarity_evidence(&self) -> Option<StationarityEvidence>
pub fn stationarity_evidence(&self) -> Option<StationarityEvidence>
The quantity this stop was decided against, when it asserts first-order stationarity at all.
None for stops that make no stationarity claim
(IterationBudget,
ObjectiveFailed, …). For those the
gradient norm, where known, is still readable via
grad_norm — but it was not compared against
anything, and reporting it as though it had been is the defect
this distinction exists to prevent.
Sourcepub fn grad_norm(&self) -> Option<f64>
pub fn grad_norm(&self) -> Option<f64>
The gradient norm at the returned point, where the stop site knew
one. Unlike stationarity_evidence
this makes no claim that the value was compared against anything.
Sourcepub fn is_stationary_claim(&self) -> bool
pub fn is_stationary_claim(&self) -> bool
true when the solver asserts the returned point is stationary.
Note this is a claim about the test that fired, not about its
strength: RelativeStationarityWindow
answers true while applying a threshold that can be orders of
magnitude looser than the absolute one. Read
stationarity_evidence to judge
the strength.
Sourcepub fn status(&self) -> OptimizationStatus
pub fn status(&self) -> OptimizationStatus
The OptimizationStatus this reason maps to.
OptimizationStatus is derived from the reason rather than being
set independently, so the coarse classification can never
disagree with the test that actually fired.
Sourcepub fn is_success(&self) -> bool
pub fn is_success(&self) -> bool
true when the run terminated at a point the solver is willing
to certify. Equivalent to self.status().is_success().
Trait Implementations§
Source§impl Clone for TerminationReason
impl Clone for TerminationReason
Source§fn clone(&self) -> TerminationReason
fn clone(&self) -> TerminationReason
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 TerminationReason
Source§impl Debug for TerminationReason
impl Debug for TerminationReason
Source§impl Display for TerminationReason
impl Display for TerminationReason
Source§impl PartialEq for TerminationReason
impl PartialEq for TerminationReason
impl StructuralPartialEq for TerminationReason
Auto Trait Implementations§
impl Freeze for TerminationReason
impl RefUnwindSafe for TerminationReason
impl Send for TerminationReason
impl Sync for TerminationReason
impl Unpin for TerminationReason
impl UnsafeUnpin for TerminationReason
impl UnwindSafe for TerminationReason
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
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> 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