pub struct OuterProblem { /* private fields */ }Expand description
Declarative outer-problem builder. Produces both the
OuterCapability (what the objective can provide) and the
[OuterConfig] (how the runner should behave) from a small set
of high-level declarations.
Implementations§
Source§impl OuterProblem
impl OuterProblem
pub fn new(n_params: usize) -> Self
Sourcepub fn with_rho_canonical_keys(self, keys: Option<Vec<u64>>) -> Self
pub fn with_rho_canonical_keys(self, keys: Option<Vec<u64>>) -> Self
Supply per-ρ-coordinate structural keys (native/formula order) so the
outer search is canonicalized to be invariant to the order the smooth
terms / tensor margins were written (#1538/#1539). See
[OuterConfig::rho_canonical_keys].
pub fn with_gradient(self, d: Derivative) -> Self
pub fn with_hessian(self, form: DeclaredHessianForm) -> Self
pub fn with_prefer_gradient_only(self, prefer_gradient_only: bool) -> Self
Sourcepub fn with_disable_fixed_point(self, disable: bool) -> Self
pub fn with_disable_fixed_point(self, disable: bool) -> Self
Forbid the planner from selecting EFS/HybridEfs, even when the
objective implements eval_efs() and the coordinate structure would
otherwise make pure/hybrid EFS eligible.
Callers use this for families where the Wood-Fasiolo structural property is known not to hold (e.g. GAMLSS/location-scale with β-dependent joint Hessian), so EFS would stagnate and burn budget before the automatic cascade falls back to gradient-based BFGS.
pub fn with_psi_dim(self, dim: usize) -> Self
pub fn with_barrier(self, cfg: Option<BarrierConfig>) -> Self
pub fn with_tolerance(self, tol: f64) -> Self
pub fn with_max_iter(self, n: usize) -> Self
pub fn with_bounds(self, lo: Array1<f64>, hi: Array1<f64>) -> Self
pub fn with_rho_bound(self, b: f64) -> Self
pub fn with_seed_config(self, sc: SeedConfig) -> Self
pub fn with_heuristic_lambdas(self, h: Vec<f64>) -> Self
pub fn with_initial_rho(self, rho: Array1<f64>) -> Self
Sourcepub fn with_continuation_prewarm(self, enabled: bool) -> Self
pub fn with_continuation_prewarm(self, enabled: bool) -> Self
Toggle the generic rho-continuation seed pre-warm. This does not affect
objectives that require an explicit continuation path; it only controls
the cheap-by-default pre-pass gated by allow_continuation_prewarm().
pub fn with_screening_cap(self, screening_cap: Arc<AtomicUsize>) -> Self
Sourcepub fn with_screen_initial_rho(self, screen_initial_rho: bool) -> Self
pub fn with_screen_initial_rho(self, screen_initial_rho: bool) -> Self
Allow seed screening to rank the explicit initial rho against generated candidates even when the effective seed budget is one. The default keeps a user-provided initial point authoritative and avoids a separate screening pass.
Sourcepub fn with_outer_inner_cap(self, feedback: InnerProgressFeedback) -> Self
pub fn with_outer_inner_cap(self, feedback: InnerProgressFeedback) -> Self
Wire the bidirectional inner-PIRLS feedback channel.
The outer bridge writes a coarsened iteration cap into
feedback.cap on every accepted gradient/Hessian eval; the inner
solver writes back into feedback.last_iters /
feedback.last_converged after each non-screening solve so the
next outer iter’s schedule can adapt to the inner solver’s
actual convergence behavior. Typical caller passes
InnerProgressFeedback { cap: Arc::clone(&reml_state.outer_inner_cap), last_iters: Arc::clone(&reml_state.last_inner_iters), last_converged: Arc::clone(&reml_state.last_inner_converged), } so the inner and outer observe the same atomics.
pub fn with_operator_initial_trust_radius(self, radius: Option<f64>) -> Self
Sourcepub fn with_arc_initial_regularization(self, sigma: Option<f64>) -> Self
pub fn with_arc_initial_regularization(self, sigma: Option<f64>) -> Self
Override the ARC initial cubic-regularization parameter sigma
(default in opt: 1.0). Smaller sigma → less cubic penalty on the
first step → larger first move on benign objectives. The matrix-
free Newton-TR analog is with_operator_initial_trust_radius.
Used by Gaussian-identity REML at large-scale n: the objective is quadratic-like in log-λ near the optimum (sigma is the right scale), and log-λ moves of 2–4 units in the early iters otherwise burn 4–8 iters of trust-region expansion before the model trusts the analytic Hessian.
Sourcepub fn with_objective_scale(self, scale: Option<f64>) -> Self
pub fn with_objective_scale(self, scale: Option<f64>) -> Self
Set the objective’s natural magnitude scale, used to derive an
n-aware absolute gradient-norm floor. When set to Some(s),
the runner uses abs_floor = max(tol, s * 1e-9) for the
projected-gradient convergence check.
Rationale: a fixed abs = tol (e.g. 1e-6) is appropriate when the
objective and its gradient live on a unit scale, but Gaussian-
identity REML carries an O(n) likelihood constant that flows into
∂/∂logλ. At large-scale n the floor becomes binding even when the
relative-from-seed component (rel_initial_grad * ‖g0‖) declared
convergence iters earlier — chasing sub-ULP changes in log-λ at
the cost of repeated k²·n·p² analytic-Hessian assemblies.
Sourcepub fn with_rel_cost_tolerance(self, rel_cost: Option<f64>) -> Self
pub fn with_rel_cost_tolerance(self, rel_cost: Option<f64>) -> Self
Decouple the relative-cost-decrease convergence stop from the
absolute projected-gradient floor. By default both are derived from the
single with_tolerance value (abs = max(tol, scale·1e-9),
rel_cost = tol). Supplying Some(r) here makes the rel-cost stop use
r while the absolute floor keeps using tolerance (so a caller can
keep a tight absolute floor for accuracy at large n AND a loose
rel-cost stop for perf on a flat REML ridge — see #1082). None keeps
the legacy coupling.
Sourcepub fn with_bfgs_step_cap(self, cap: Option<f64>) -> Self
pub fn with_bfgs_step_cap(self, cap: Option<f64>) -> Self
Cap the infinity-norm displacement of BFGS cost-only line-search probes
on the rho axes (the first n_params - psi_dim outer parameters,
= log-λ). Also scales the initial inverse metric so the first trial
direction respects the same local budget coordinate-wise. Documented
natural step on log-λ is ≈ 5; tighter values throttle BFGS and starve
convergence on flat REML valleys.
Sourcepub fn with_bfgs_step_cap_psi(self, cap: Option<f64>) -> Self
pub fn with_bfgs_step_cap_psi(self, cap: Option<f64>) -> Self
Cap the infinity-norm displacement of BFGS cost-only line-search probes
on the psi axes (the trailing psi_dim outer parameters, = kappa
or anisotropic log-scales). Mirrors Self::with_bfgs_step_cap but
scoped to kernel-scale parameters whose natural step is much smaller
than log-λ (≈ ln 2 per iter keeps kappa from oscillating). Without
this split, a uniform rho-scale cap lets psi explode while a uniform
psi-scale cap throttles rho — both fail the survival-marginal-slope
path at large scale, where rho needs |d|≈5 while psi wants |d|≤1.
pub fn with_cache_session(self, session: Arc<CacheSession>) -> Self
Sourcepub fn with_cache_mirror_sessions(
self,
sessions: Vec<Arc<CacheSession>>,
) -> Self
pub fn with_cache_mirror_sessions( self, sessions: Vec<Arc<CacheSession>>, ) -> Self
Attach mirror cache sessions that receive a broadcast copy of
the final-result finalize write. See
[OuterConfig::cache_mirror_sessions].
pub fn with_problem_size(self, n_obs: usize, p_coefficients: usize) -> Self
Sourcepub fn with_fallback_policy(self, policy: FallbackPolicy) -> Self
pub fn with_fallback_policy(self, policy: FallbackPolicy) -> Self
Override the fallback policy. Default is FallbackPolicy::Automatic.
Set FallbackPolicy::Disabled when the caller requires the primary
plan to stand on its own. Exact-Hessian objectives use this to ensure
failures surface on the analytic geometry instead of being reinterpreted
by a different optimizer class.
Sourcepub fn build_objective<S, Fc, Fe, Fr, Fefs>(
&self,
state: S,
cost_fn: Fc,
eval_fn: Fe,
reset_fn: Option<Fr>,
efs_fn: Option<Fefs>,
) -> ClosureObjective<S, Fc, Fe, Fr, Fefs>
pub fn build_objective<S, Fc, Fe, Fr, Fefs>( &self, state: S, cost_fn: Fc, eval_fn: Fe, reset_fn: Option<Fr>, efs_fn: Option<Fefs>, ) -> ClosureObjective<S, Fc, Fe, Fr, Fefs>
Construct a ClosureObjective with capability flags derived from the
builder state and the closures actually provided.
fixed_point_available is set to true when efs_fn is Some,
regardless of whether .with_efs() was called. This is the canonical
way to create production objectives — it eliminates the drift risk of
manually entering capability flags.
Sourcepub fn build_objective_with_eval_order<S, Fc, Fe, Feo, Fr, Fefs>(
&self,
state: S,
cost_fn: Fc,
eval_fn: Fe,
eval_order_fn: Feo,
reset_fn: Option<Fr>,
efs_fn: Option<Fefs>,
) -> ClosureObjective<S, Fc, Fe, Fr, Fefs, Feo>where
Fc: FnMut(&mut S, &Array1<f64>) -> Result<f64, EstimationError>,
Fe: FnMut(&mut S, &Array1<f64>) -> Result<OuterEval, EstimationError>,
Feo: FnMut(&mut S, &Array1<f64>, OuterEvalOrder) -> Result<OuterEval, EstimationError>,
Fr: FnMut(&mut S),
Fefs: FnMut(&mut S, &Array1<f64>) -> Result<EfsEval, EstimationError>,
pub fn build_objective_with_eval_order<S, Fc, Fe, Feo, Fr, Fefs>(
&self,
state: S,
cost_fn: Fc,
eval_fn: Fe,
eval_order_fn: Feo,
reset_fn: Option<Fr>,
efs_fn: Option<Fefs>,
) -> ClosureObjective<S, Fc, Fe, Fr, Fefs, Feo>where
Fc: FnMut(&mut S, &Array1<f64>) -> Result<f64, EstimationError>,
Fe: FnMut(&mut S, &Array1<f64>) -> Result<OuterEval, EstimationError>,
Feo: FnMut(&mut S, &Array1<f64>, OuterEvalOrder) -> Result<OuterEval, EstimationError>,
Fr: FnMut(&mut S),
Fefs: FnMut(&mut S, &Array1<f64>) -> Result<EfsEval, EstimationError>,
Construct a ClosureObjective with an order-aware evaluation hook.
This lets the runner request first-order vs second-order work based on
the active outer plan while preserving the legacy eager eval_fn.
Sourcepub fn build_objective_with_screening_proxy<S, Fc, Fe, Feo, Fr, Fefs, Fsp>(
&self,
state: S,
cost_fn: Fc,
eval_fn: Fe,
eval_order_fn: Feo,
reset_fn: Option<Fr>,
efs_fn: Option<Fefs>,
screening_proxy_fn: Fsp,
) -> ClosureObjective<S, Fc, Fe, Fr, Fefs, Feo, Fsp>where
Fc: FnMut(&mut S, &Array1<f64>) -> Result<f64, EstimationError>,
Fe: FnMut(&mut S, &Array1<f64>) -> Result<OuterEval, EstimationError>,
Feo: FnMut(&mut S, &Array1<f64>, OuterEvalOrder) -> Result<OuterEval, EstimationError>,
Fr: FnMut(&mut S),
Fefs: FnMut(&mut S, &Array1<f64>) -> Result<EfsEval, EstimationError>,
Fsp: FnMut(&mut S, &Array1<f64>) -> Result<f64, EstimationError>,
pub fn build_objective_with_screening_proxy<S, Fc, Fe, Feo, Fr, Fefs, Fsp>(
&self,
state: S,
cost_fn: Fc,
eval_fn: Fe,
eval_order_fn: Feo,
reset_fn: Option<Fr>,
efs_fn: Option<Fefs>,
screening_proxy_fn: Fsp,
) -> ClosureObjective<S, Fc, Fe, Fr, Fefs, Feo, Fsp>where
Fc: FnMut(&mut S, &Array1<f64>) -> Result<f64, EstimationError>,
Fe: FnMut(&mut S, &Array1<f64>) -> Result<OuterEval, EstimationError>,
Feo: FnMut(&mut S, &Array1<f64>, OuterEvalOrder) -> Result<OuterEval, EstimationError>,
Fr: FnMut(&mut S),
Fefs: FnMut(&mut S, &Array1<f64>) -> Result<EfsEval, EstimationError>,
Fsp: FnMut(&mut S, &Array1<f64>) -> Result<f64, EstimationError>,
Construct a ClosureObjective with both an order-aware evaluation
hook and a custom seed-screening ranking proxy. The proxy fires only
when the cascade in rank_seeds_with_screening calls it; outside
screening the regular cost path is unaffected.
Sourcepub fn run(
&self,
obj: &mut dyn OuterObjective,
context: &str,
) -> Result<OuterResult, EstimationError>
pub fn run( &self, obj: &mut dyn OuterObjective, context: &str, ) -> Result<OuterResult, EstimationError>
Run the outer optimization with a given objective.
Auto Trait Implementations§
impl Freeze for OuterProblem
impl RefUnwindSafe for OuterProblem
impl Send for OuterProblem
impl Sync for OuterProblem
impl Unpin for OuterProblem
impl UnsafeUnpin for OuterProblem
impl UnwindSafe for OuterProblem
Blanket Implementations§
impl<T> Allocation 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> 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.