pub struct ConstraintKktDiagnostics {
pub n_constraints: usize,
pub n_active: usize,
pub primal_feasibility: f64,
pub dual_feasibility: f64,
pub complementarity: f64,
pub stationarity: f64,
pub active_tolerance: f64,
pub working_set_rank_deficient: bool,
pub gradient_scale: f64,
}Expand description
KKT diagnostics for inequality-constrained Newton subproblems.
Constraints are represented as A * beta >= b in the same coefficient
coordinate system as the returned beta.
Invariants (held by all producers; not enforced at consumer boundary):
n_active <= n_constraints(a row cannot be active twice).- All four residual components (
primal_feasibility,dual_feasibility,complementarity,stationarity) are>= 0.0and finite. active_tolerance >= 0.0and finite.
Fields§
§n_constraints: usizeNumber of inequality rows.
n_active: usizeNumber of rows considered active (slack <= active_tolerance).
primal_feasibility: f64Maximum primal feasibility violation: max_i max(0, b_i - a_i^T beta).
dual_feasibility: f64Maximum dual feasibility violation: max_i max(0, -lambda_i).
complementarity: f64Maximum complementarity residual: max_i |lambda_i * slack_i|.
stationarity: f64Stationarity residual: ||grad - A^T lambda||_inf.
active_tolerance: f64Tolerance used to classify active constraints from slacks.
working_set_rank_deficient: booltrue when the active rows are linearly dependent (rank(A_active) < n_active) — a degenerate boundary face. On such a face the active-row
multipliers are non-unique and the strict stationarity tolerance is
unreachable by construction. The inner active-set solver certifies these
iterates via its ACTIVE_SET_KKT_DEGENERATE_STATIONARITY_TOL relaxation;
the outer validation gate must consult this flag to apply the matching
relaxation, or it will refuse a legitimately-converged constrained
optimum and abort the REML startup loop.
NOTE: B-spline shape=concave/shape=convex faces are not degenerate
— that path reparameterizes curvature into independent coordinate lower
bounds γ_j ≥ 0 (full-rank active subsets), so this flag stays false
for them. Their cold-start fragility is a seed problem fixed by the
strictly-interior seed, not by this relaxation.
gradient_scale: f64Inf-norm of the (raw, unprojected) gradient at beta, ‖gradient‖∞ —
the natural scale of the stationarity residual. A converged constrained
optimum drives stationarity = ‖grad − Aᵀλ‖∞ to zero relative to this
scale, not to a fixed absolute floor: the profiled REML latent objective
carries an O(n) gradient magnitude even at a genuine stationary point
(issue #879), so a bare absolute stationarity gate is unreachable there
by construction. The inner active-set solver already certifies
convergence on the scale-invariant ratio
stationarity / max(gradient_scale, 1) (its stationarity_rel path
against ACTIVE_SET_KKT_STATIONARITY_TOL); the outer validation gate
crate::estimate::reml::outer_eval::enforce_constraint_kkt consults this
field to apply the identical relative test, so the two stop on the same
contract instead of the gate spuriously aborting a constrained optimum
the solver legitimately reached (issue #989). Defaults to 0.0 when
deserialized from a model saved before this field existed, which makes
max(gradient_scale, 1) = 1 and recovers the bare absolute test.
Trait Implementations§
Source§impl Clone for ConstraintKktDiagnostics
impl Clone for ConstraintKktDiagnostics
Source§fn clone(&self) -> ConstraintKktDiagnostics
fn clone(&self) -> ConstraintKktDiagnostics
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ConstraintKktDiagnostics
impl Debug for ConstraintKktDiagnostics
Source§impl<'de> Deserialize<'de> for ConstraintKktDiagnostics
impl<'de> Deserialize<'de> for ConstraintKktDiagnostics
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for ConstraintKktDiagnostics
impl RefUnwindSafe for ConstraintKktDiagnostics
impl Send for ConstraintKktDiagnostics
impl Sync for ConstraintKktDiagnostics
impl Unpin for ConstraintKktDiagnostics
impl UnsafeUnpin for ConstraintKktDiagnostics
impl UnwindSafe for ConstraintKktDiagnostics
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
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.