pub enum InnerConvergenceTerminalState {
Blockwise {
cycle: usize,
max_accepted_step: f64,
max_proposed_step: f64,
step_tol: f64,
objective_change: f64,
objective_tol: f64,
joint_stationarity_ok: bool,
},
JointNewton {
cycle: usize,
stationarity_residual: f64,
residual_tol: f64,
stationarity_scale: f64,
step_inf: f64,
step_tol: f64,
resolvable_negative_curvature: bool,
best_stationarity_residual: f64,
cycles_since_best_residual: usize,
termination_reason: JointNewtonTerminalReason,
},
}Variants§
Blockwise
The blockwise Gauss-Seidel route’s terminal cycle.
Fields
JointNewton
The exact joint-Newton route’s terminal cycle. This route DOES have a
genuine stationarity residual (the blockwise one does not, off a
converged iterate), and it has a third outcome the other lacks:
resolvable_negative_curvature marks a first-order stationary STRICT
SADDLE, where the score and the Newton proposal both vanish but the exact
penalized Hessian has resolvable negative curvature. That refuses
convergence deliberately, and it is nothing like exhausting a budget.
Fields
stationarity_scale: f64The magnitude the stationarity residual is denominated against:
max(‖∇L‖∞, ‖Sβ‖∞, ‖∇Φ‖∞) at the terminal iterate, i.e. the scale
in residual_tol = inner_tol · (1 + scale).
Carried because WITHOUT it the message cannot be ranked (gam#2713).
The natural thing to do with a printed residual (tol=…) pair is to
form R/T and read it as “N× over tolerance”; that ratio is
≈ (R/scale)/inner_tol, so it mixes two different tolerances (the
1e-6 default and the derivative lane’s 1e-11
JOINT_LAML_DERIV_INNER_TOL_FLOOR) and it is ANTI-correlated with
convergence across part of the range. Measured over 41 refusal pairs
from one survival sweep: a row printing R/T = 238× was stationary
to R/scale = 2.4e-9 — converged to nine digits — while a row
printing R/T = 1.4e3× sat at R/scale = 1.4e-3, a million times
less converged. Ranking on R/T sends triage to the first row.
The comparable column is relative_stationarity, printed below,
which is the gate’s own quantity: the gate accepts exactly when it
is ≤ inner_tol, so it is 0 at the optimum, ~1 where the
residual has collapsed onto one of its own terms, and directly
comparable across both inner_tol regimes.
best_stationarity_residual: f64The smallest stationarity residual this solve actually computed, and how many cycles have passed since it last improved.
The terminal residual alone cannot separate a solve that never got
close from one that reached a near-tolerance point and then walked
away from it, and those are different defects with different fixes.
Measured on the transformation-normal wine arm (#2600): the terminal
residual is 1.906e0 while the smallest this same solve computed is
1.578e-3 — 1200x better, within 1.9x of residual_tol, and reached
27 cycles earlier, after which every accepted step raised the
residual again. Read from the terminal value alone that solve looks
like it never approached stationarity; read with the best value it
is a solve that drifted off a point it had essentially reached.
termination_reason: JointNewtonTerminalReasonTrait Implementations§
Source§impl Clone for InnerConvergenceTerminalState
impl Clone for InnerConvergenceTerminalState
Source§fn clone(&self) -> InnerConvergenceTerminalState
fn clone(&self) -> InnerConvergenceTerminalState
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 InnerConvergenceTerminalState
impl StructuralPartialEq for InnerConvergenceTerminalState
Auto Trait Implementations§
impl Freeze for InnerConvergenceTerminalState
impl RefUnwindSafe for InnerConvergenceTerminalState
impl Send for InnerConvergenceTerminalState
impl Sync for InnerConvergenceTerminalState
impl Unpin for InnerConvergenceTerminalState
impl UnsafeUnpin for InnerConvergenceTerminalState
impl UnwindSafe for InnerConvergenceTerminalState
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,
Source§impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T> DistributionExt for Twhere
T: ?Sized,
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 moreSource§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
impl<T> Scalar for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.