pub enum EstimationError {
Show 36 variants
InvalidStabilization(InvalidStabilization),
BasisError(BasisError),
CustomFamily(CustomFamilyError),
LinearSystemSolveFailed(FaerLinalgError),
EigendecompositionFailed(FaerLinalgError),
PenaltySpectrumNonFinite {
context: String,
index: usize,
value: f64,
},
PenaltySpectrumIndefinite {
context: String,
index: usize,
value: f64,
tolerance: f64,
scale: f64,
},
ParameterConstraintViolation(String),
PirlsDidNotConverge {
max_iterations: usize,
last_change: f64,
},
FixedLambdaNewtonDidNotConverge {
context: String,
reason: FixedLambdaStallReason,
objective_value: f64,
stationarity: FixedLambdaStationarityEvidence,
checkpoint: FixedLambdaCheckpoint,
},
BlockOrthogonalRemlDidNotConverge {
iterations: usize,
max_score_residual: f64,
score_tol: f64,
min_profile_curvature: f64,
profile_curvature_roundoff: f64,
last_scale_step: f64,
cycle_detected: bool,
rho_checkpoint: Vec<f64>,
},
NegativeBinomialAlternationDidNotConverge {
rounds: usize,
theta_checkpoint: f64,
rho_projected_grad_norm: f64,
rho_stationarity_bound: f64,
theta_score_residual: f64,
theta_stationarity_bound: f64,
rho_checkpoint: Vec<f64>,
},
PerfectSeparationDetected {
iteration: usize,
max_abs_eta: f64,
},
PrefitPerfectSeparationDetected {
column_index: usize,
threshold: f64,
positive_above_threshold: bool,
},
PrefitLinearSeparationDetected {
min_signed_margin: f64,
num_unpenalized_columns: usize,
column_indices: Vec<usize>,
},
PrefitRankDeficientDesignDetected {
rank: usize,
num_unpenalized_columns: usize,
min_eigenvalue: f64,
tolerance: f64,
column_indices: Vec<usize>,
},
PrefitNearDegenerateDesignDetected {
num_unpenalized_columns: usize,
condition_number: f64,
min_eigenvalue: f64,
max_eigenvalue: f64,
tolerance: f64,
column_indices: Vec<usize>,
},
MultinomialSeparationDetected {
iteration: usize,
max_abs_eta: f64,
active_class_index: usize,
row_index: usize,
},
HessianNotPositiveDefinite {
min_eigenvalue: f64,
},
RemlOptimizationFailed(String),
TrialPointRefused {
reason: String,
},
OuterObjectiveEvaluationFailed {
context: String,
source: OuterObjectiveErrorSource,
},
RemlDidNotConverge {
context: String,
reason: String,
iterations: usize,
final_value: f64,
projected_grad_norm: Option<f64>,
stationarity_standard: StationarityStandard,
rho_checkpoint: Vec<f64>,
},
FitDidNotConverge {
inner_status: String,
outer_status: String,
outer_iterations: usize,
final_value: Option<f64>,
stationarity: FitStationarityEvidence,
step: FitStationarityEvidence,
rho_checkpoint: Vec<f64>,
resume_token: Option<String>,
},
GradientUnavailable {
context: &'static str,
mode: &'static str,
},
LayoutError(String),
ModelIsIllConditioned {
condition_number: f64,
},
InvalidInput(String),
InverseLinkDomainViolation {
link: &'static str,
eta: f64,
lower: f64,
upper: f64,
},
PirlsRowGeometryUnrepresentable {
row: usize,
quantity: &'static str,
eta: f64,
value: f64,
},
ExactTweedieSeriesWorkLimit {
row: usize,
required_terms_lower_bound: f64,
budget: usize,
},
LogStrengthDomainViolation {
coordinate: usize,
value: f64,
lower: f64,
upper: f64,
},
MonotoneRoot(MonotoneRootError),
CalibratorTrainingFailed(String),
InvalidSpecification(String),
PredictionError,
}Expand description
A comprehensive error type for the model estimation process.
Variants§
InvalidStabilization(InvalidStabilization)
BasisError(BasisError)
CustomFamily(CustomFamilyError)
LinearSystemSolveFailed(FaerLinalgError)
EigendecompositionFailed(FaerLinalgError)
PenaltySpectrumNonFinite
PenaltySpectrumIndefinite
ParameterConstraintViolation(String)
PirlsDidNotConverge
FixedLambdaNewtonDidNotConverge
Fields
context: StringWhich fixed-λ Newton entry stalled (e.g. the multinomial softmax or independent-binomial vector-GLM solve, or the Firth refit lane).
reason: FixedLambdaStallReasonWhy the solver stopped without its convergence certificate.
objective_value: f64Final value of the solver’s minimized criterion. For ordinary vector
GLMs this is -log L + penalty; for the Firth lane it also includes
the negative Jeffreys 0.5 log det(I) contribution.
stationarity: FixedLambdaStationarityEvidenceExact first-order residual and the bound it failed to clear.
checkpoint: FixedLambdaCheckpointLast accepted coefficients and cumulative iteration count. This is work-preservation state, not a fitted model, and carries no covariance or prediction surface.
BlockOrthogonalRemlDidNotConverge
Fields
max_score_residual: f64Largest per-block |dV/drho| at the final iterate, normalized by the
score’s natural magnitude d * max(1, rank).
min_profile_curvature: f64Smallest eigenvalue of the analytic rho Hessian after profiling out the exact conditional scale block.
profile_curvature_roundoff: f64Dimension-scaled eigensolver roundoff allowed below zero when certifying positive semidefiniteness.
last_scale_step: f64Last max |Δ log scale-precision| fixed-point movement (evidence of whether the alternation was still moving or had stalled).
NegativeBinomialAlternationDidNotConverge
Fields
PerfectSeparationDetected
PrefitPerfectSeparationDetected
PrefitLinearSeparationDetected
PrefitRankDeficientDesignDetected
Fields
PrefitNearDegenerateDesignDetected
Fields
MultinomialSeparationDetected
HessianNotPositiveDefinite
RemlOptimizationFailed(String)
TrialPointRefused
A numerical refusal evaluated AT ONE TRIAL POINT of the outer smoothing search: no Laplace mode at this rho, an inner solve that missed its KKT bar at this rho, an indefinite trial Hessian at this rho.
The outer search’s response to this is to map the point to
OuterEval::infeasible and step away — which is a normal thing for a
lambda-search to consume, and the only response it has, since the only
thing it can change is rho. Saying so in the type is the whole point:
these refusals used to be reported as
InvalidInput or RemlOptimizationFailed, both
of which carry prose and both of which
Self::is_trial_point_infeasible answers false for, so a correct
per-rho verdict aborted the entire fit (#2531, #2590).
It renders as the bare reason so a producer switching to it does not change the message a user or a regression test reads.
OuterObjectiveEvaluationFailed
RemlDidNotConverge
Fields
reason: StringWhich certificate failed: budget exhaustion, line-search collapse, non-stationary cost stall, or a failed post-solve stationarity certificate.
projected_grad_norm: Option<f64>KKT-projected gradient norm at the best iterate, when the solver
measured a gradient there (None for gradient-free exits).
stationarity_standard: StationarityStandardThe standard this refusal was decided against: the bound together with the rung that produced it, or an explicit statement that no stationarity comparison was made (#2458/#2465). They are ONE field precisely so neither can be reported without the other, and so that a route which never formed a bound cannot print one.
FitDidNotConverge
Fields
inner_status: StringDiagnostic inner-solver terminal status. This is deliberately a string at the neutral problem layer; concrete solver status enums live in downstream fitting crates.
final_value: Option<f64>Objective value at the best available checkpoint, or None when the
rejected fit has no criterion value at all (the exact-fit Gaussian
boundary). A refusal must not invent an objective it could not read.
stationarity: FitStationarityEvidenceThe first-order residual together with the bound it was weighed against, or an explicit statement that no comparison was made.
step: FitStationarityEvidenceThe accepted-step residual and its bound, same rule. Currently
always NoComparison at the sole production site – which is what
the type should say, rather than leaving two independent Options
armed with the identical hazard for whoever wires them up.
LayoutError(String)
ModelIsIllConditioned
InvalidInput(String)
InverseLinkDomainViolation
PirlsRowGeometryUnrepresentable
ExactTweedieSeriesWorkLimit
LogStrengthDomainViolation
MonotoneRoot(MonotoneRootError)
CalibratorTrainingFailed(String)
InvalidSpecification(String)
PredictionError
Implementations§
Source§impl EstimationError
impl EstimationError
Sourcepub fn is_trial_point_infeasible(&self) -> bool
pub fn is_trial_point_infeasible(&self) -> bool
Whether this failure invalidates the whole outer run or only the trial point it was produced at.
The outer optimizer can survive an infeasible trial: it maps the
point to OuterEval::infeasible, backs off, and continues. It
cannot survive a structural failure. Deciding which is which is
the producer’s job, and the answer must travel with the error
rather than be reconstructed downstream from its rendered text
(#2553).
Only failures that are genuinely a property of this theta answer
true. Everything else stays fatal, which is the conservative
direction: misclassifying a structural failure as recoverable
would let the search grind through a problem that can never work.
The match is deliberately exhaustive with no wildcard arm, for the
same reason CustomFamilyError::is_trial_point_infeasible is: under
a _ => false a newly added variant is classified fatal by the
absence of a decision, and whoever adds it is never asked. That is how
a rho-local refusal reached this function as RemlOptimizationFailed —
a variant that carries only prose — and aborted a fit the outer search
was equipped to walk away from (#2590).
Sourcepub fn fatal_outer_evaluation(
context: impl Into<String>,
source: EstimationError,
) -> Self
pub fn fatal_outer_evaluation( context: impl Into<String>, source: EstimationError, ) -> Self
Preserve a thrown outer-objective failure across seed, solver, and
fallback-plan orchestration. Trial-domain refusals must be represented
as a finite API outcome (+inf / OuterEval::infeasible); an Err
means the evaluation artifact itself could not be constructed and must
never be retried as another numerical point.
Sourcepub fn fatal_objective_evaluation(
context: impl Into<String>,
source: ObjectiveEvalError,
) -> Self
pub fn fatal_objective_evaluation( context: impl Into<String>, source: ObjectiveEvalError, ) -> Self
Preserve an optimizer-facing fatal evaluator failure without reminting
its message as an unrelated Self::RemlOptimizationFailed.
The caller must have already consumed recoverable failures as rejected trial points. Requiring the producer’s fatal verdict here makes an accidental promotion fail at the boundary that attempted it instead of silently changing control flow.
pub fn is_fatal_outer_evaluation(&self) -> bool
Sourcepub fn wrap_preserving_trial_point(self, context: &str) -> Self
pub fn wrap_preserving_trial_point(self, context: &str) -> Self
Classifies inner-solve failures that the outer REML loop should treat as a soft retreat (return +inf cost / infeasible outer-eval) rather than propagate as a hard error.
Why: when the penalised Hessian becomes effectively singular at the current rho, when P-IRLS hits a perfect-separation diagnostic, or when it exhausts its iteration budget, the outer optimiser’s correct response is to back away from this rho — not to terminate the fit. All three variants encode “the inner problem at this rho is too hard to evaluate, try a different rho”. Re-report this failure with more context WITHOUT changing whether it is a trial-point refusal.
A wrapper that renders its source into a string and then picks a fresh
variant silently overwrites the producer’s verdict. That is how a
per-rho survival-LAML stationarity refusal reached the outer boundary
as InvalidInput and killed the fit (#2531), and how a typed
InnerSolveNotConverged reached it as RemlOptimizationFailed and did
the same (#2590). Any site that adds context to an error it did not
produce should use this instead of choosing a variant for it.
pub fn is_inner_solve_retreat(&self) -> bool
Trait Implementations§
Source§impl Debug for EstimationError
impl Debug for EstimationError
Source§impl Display for EstimationError
impl Display for EstimationError
Source§impl Error for EstimationError
impl Error for EstimationError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<BasisError> for EstimationError
impl From<BasisError> for EstimationError
Source§fn from(source: BasisError) -> Self
fn from(source: BasisError) -> Self
Source§impl From<CustomFamilyError> for EstimationError
impl From<CustomFamilyError> for EstimationError
Source§fn from(source: CustomFamilyError) -> Self
fn from(source: CustomFamilyError) -> Self
Source§impl From<IndexedLogStrengthDomainError> for EstimationError
impl From<IndexedLogStrengthDomainError> for EstimationError
Source§fn from(error: IndexedLogStrengthDomainError) -> Self
fn from(error: IndexedLogStrengthDomainError) -> Self
Source§impl From<InvalidStabilization> for EstimationError
impl From<InvalidStabilization> for EstimationError
Source§fn from(source: InvalidStabilization) -> Self
fn from(source: InvalidStabilization) -> Self
Source§impl From<LinalgError> for EstimationError
impl From<LinalgError> for EstimationError
Source§fn from(error: LinalgError) -> Self
fn from(error: LinalgError) -> Self
Source§impl From<MonotoneRootError> for EstimationError
impl From<MonotoneRootError> for EstimationError
Source§fn from(source: MonotoneRootError) -> Self
fn from(source: MonotoneRootError) -> Self
Auto Trait Implementations§
impl !RefUnwindSafe for EstimationError
impl !UnwindSafe for EstimationError
impl Freeze for EstimationError
impl Send for EstimationError
impl Sync for EstimationError
impl Unpin for EstimationError
impl UnsafeUnpin for EstimationError
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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
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,
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.