Skip to main content

EstimationError

Enum EstimationError 

Source
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

Re-export of the neutral estimation error so crate-local macros (bail_invalid_estim!) and call sites can reference crate::EstimationError. A comprehensive error type for the model estimation process.

Variants§

§

InvalidStabilization(InvalidStabilization)

§

BasisError(BasisError)

§

CustomFamily(CustomFamilyError)

§

LinearSystemSolveFailed(FaerLinalgError)

§

EigendecompositionFailed(FaerLinalgError)

§

PenaltySpectrumNonFinite

Fields

§context: String
§index: usize
§value: f64
§

PenaltySpectrumIndefinite

Fields

§context: String
§index: usize
§value: f64
§tolerance: f64
§scale: f64
§

ParameterConstraintViolation(String)

§

PirlsDidNotConverge

Fields

§max_iterations: usize
§last_change: f64
§

FixedLambdaNewtonDidNotConverge

Fields

§context: String

Which fixed-λ Newton entry stalled (e.g. the multinomial softmax or independent-binomial vector-GLM solve, or the Firth refit lane).

§reason: FixedLambdaStallReason

Why the solver stopped without its convergence certificate.

§objective_value: f64

Final 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: FixedLambdaStationarityEvidence

Exact first-order residual and the bound it failed to clear.

§checkpoint: FixedLambdaCheckpoint

Last accepted coefficients and cumulative iteration count. This is work-preservation state, not a fitted model, and carries no covariance or prediction surface.

§

BlockOrthogonalRemlDidNotConverge

Fields

§iterations: usize

Outer alternation passes executed before exhaustion.

§max_score_residual: f64

Largest per-block |dV/drho| at the final iterate, normalized by the score’s natural magnitude d * max(1, rank).

§score_tol: f64

Tolerance the residual had to meet for the convergence certificate.

§min_profile_curvature: f64

Smallest eigenvalue of the analytic rho Hessian after profiling out the exact conditional scale block.

§profile_curvature_roundoff: f64

Dimension-scaled eigensolver roundoff allowed below zero when certifying positive semidefiniteness.

§last_scale_step: f64

Last max |Δ log scale-precision| fixed-point movement (evidence of whether the alternation was still moving or had stalled).

§cycle_detected: bool

The alternation revisited an earlier (rho, scale) state exactly; as a deterministic map it can never certify, so it stopped early.

§rho_checkpoint: Vec<f64>

Per-block log-lambda iterates at exhaustion; feed back through the entry point’s init_rhos to resume rather than restart.

§

NegativeBinomialAlternationDidNotConverge

Fields

§rounds: usize

Joint block-coordinate rounds executed before exhaustion.

§theta_checkpoint: f64

Conditional theta coordinate at the best measured checkpoint.

§rho_projected_grad_norm: f64

KKT-projected rho-gradient norm at that checkpoint.

§rho_stationarity_bound: f64

Bound the rho residual had to clear.

§theta_score_residual: f64

Curvature-normalized log-theta score residual at that checkpoint.

§theta_stationarity_bound: f64

Bound the theta residual had to clear.

§rho_checkpoint: Vec<f64>

Best measured log-smoothing checkpoint for warm-started resume.

§

PerfectSeparationDetected

Fields

§iteration: usize
§max_abs_eta: f64
§

PrefitPerfectSeparationDetected

Fields

§column_index: usize
§threshold: f64
§positive_above_threshold: bool
§

PrefitLinearSeparationDetected

Fields

§min_signed_margin: f64
§num_unpenalized_columns: usize
§column_indices: Vec<usize>
§

PrefitRankDeficientDesignDetected

Fields

§rank: usize
§num_unpenalized_columns: usize
§min_eigenvalue: f64
§tolerance: f64
§column_indices: Vec<usize>
§

PrefitNearDegenerateDesignDetected

Fields

§num_unpenalized_columns: usize
§condition_number: f64
§min_eigenvalue: f64
§max_eigenvalue: f64
§tolerance: f64
§column_indices: Vec<usize>
§

MultinomialSeparationDetected

Fields

§iteration: usize
§max_abs_eta: f64
§active_class_index: usize
§row_index: usize
§

HessianNotPositiveDefinite

Fields

§min_eigenvalue: f64
§

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.

Fields

§reason: String
§

OuterObjectiveEvaluationFailed

§

RemlDidNotConverge

Fields

§context: String

Fit context label (the same string the outer runner logs under).

§reason: String

Which certificate failed: budget exhaustion, line-search collapse, non-stationary cost stall, or a failed post-solve stationarity certificate.

§iterations: usize

Outer iterations executed across all solver restarts.

§final_value: f64

Objective value at the abandoned best iterate.

§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: StationarityStandard

The 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.

§rho_checkpoint: Vec<f64>

Best (lowest-objective feasible) outer iterate at exhaustion. This is work-preservation evidence for resume — it is NOT a fit and no fitted-model API is reachable from it.

§

FitDidNotConverge

Fields

§inner_status: String

Diagnostic inner-solver terminal status. This is deliberately a string at the neutral problem layer; concrete solver status enums live in downstream fitting crates.

§outer_status: String

Outer terminal/certificate verdict.

§outer_iterations: usize

Completed outer iterations at the rejected checkpoint.

§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: FitStationarityEvidence

The first-order residual together with the bound it was weighed against, or an explicit statement that no comparison was made.

§step: FitStationarityEvidence

The 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.

§rho_checkpoint: Vec<f64>

Work-preserving smoothing checkpoint; this is not a fit.

§resume_token: Option<String>

Opaque durable-cache resume token, when checkpoint persistence was enabled for the failed run.

§

GradientUnavailable

Fields

§context: &'static str
§mode: &'static str
§

LayoutError(String)

§

ModelIsIllConditioned

Fields

§condition_number: f64
§

InvalidInput(String)

§

InverseLinkDomainViolation

Fields

§link: &'static str
§eta: f64
§lower: f64
§upper: f64
§

PirlsRowGeometryUnrepresentable

Fields

§row: usize
§quantity: &'static str
§eta: f64
§value: f64
§

ExactTweedieSeriesWorkLimit

Fields

§row: usize
§required_terms_lower_bound: f64
§budget: usize
§

LogStrengthDomainViolation

Fields

§coordinate: usize
§value: f64
§lower: f64
§upper: f64
§

MonotoneRoot(MonotoneRootError)

§

CalibratorTrainingFailed(String)

§

InvalidSpecification(String)

§

PredictionError

Implementations§

Source§

impl EstimationError

Source

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).

Source

pub fn fatal_outer_evaluation( context: impl Into<String>, source: EstimationError, ) -> EstimationError

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.

Source

pub fn fatal_objective_evaluation( context: impl Into<String>, source: ObjectiveEvalError, ) -> EstimationError

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.

Source

pub fn is_fatal_outer_evaluation(&self) -> bool

Source

pub fn wrap_preserving_trial_point(self, context: &str) -> EstimationError

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.

Source

pub fn is_inner_solve_retreat(&self) -> bool

Trait Implementations§

Source§

impl Debug for EstimationError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for EstimationError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Error for EstimationError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<BasisError> for EstimationError

Source§

fn from(source: BasisError) -> EstimationError

Converts to this type from the input type.
Source§

impl From<CustomFamilyError> for EstimationError

Source§

fn from(source: CustomFamilyError) -> EstimationError

Converts to this type from the input type.
Source§

impl From<IndexedLogStrengthDomainError> for EstimationError

Source§

fn from(error: IndexedLogStrengthDomainError) -> EstimationError

Converts to this type from the input type.
Source§

impl From<InvalidStabilization> for EstimationError

Source§

fn from(source: InvalidStabilization) -> EstimationError

Converts to this type from the input type.
Source§

impl From<LinalgError> for EstimationError

Source§

fn from(error: LinalgError) -> EstimationError

Converts to this type from the input type.
Source§

impl From<MonotoneRootError> for EstimationError

Source§

fn from(source: MonotoneRootError) -> EstimationError

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> DistributionExt for T
where T: ?Sized,

Source§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V