Skip to main content

gam_linalg/
types.rs

1use serde::{Deserialize, Serialize};
2
3/// How ridge-adjusted determinants should be evaluated for outer criteria.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5pub enum RidgeDeterminantMode {
6    /// Use exact full logdet.
7    Auto,
8    /// Use full log-determinant of the ridged matrix (requires SPD in practice).
9    Full,
10    /// Use positive-part pseudo-determinant (sum log ev for ev > floor).
11    PositivePart,
12}
13
14/// Global policy governing how a stabilization ridge participates in objectives.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
16pub struct RidgePolicy {
17    /// Must remain independent of smoothing parameters (`rho`) for smooth outer derivatives.
18    pub rho_independent: bool,
19    /// Include ridge in quadratic penalty term: `0.5 * delta * ||beta||^2`.
20    pub include_quadratic_penalty: bool,
21    /// Include ridge in penalty determinant term (e.g. `log|S_lambda + delta I|`).
22    pub include_penalty_logdet: bool,
23    /// Include ridge in Hessian used by Laplace term / implicit differentiation.
24    pub include_laplacehessian: bool,
25    /// Determinant evaluation mode when ridge participates in logdet terms.
26    pub determinant_mode: RidgeDeterminantMode,
27}
28
29impl RidgePolicy {
30    /// Default policy used by PIRLS/REML path:
31    /// treat stabilization ridge as an explicit `delta I` prior contribution
32    /// with adaptive logdet evaluation.
33    pub const fn explicit_stabilization_full() -> Self {
34        Self {
35            rho_independent: true,
36            include_quadratic_penalty: true,
37            include_penalty_logdet: true,
38            include_laplacehessian: true,
39            determinant_mode: RidgeDeterminantMode::Auto,
40        }
41    }
42
43    pub const fn explicit_stabilization_full_exact() -> Self {
44        Self {
45            rho_independent: true,
46            include_quadratic_penalty: true,
47            include_penalty_logdet: true,
48            include_laplacehessian: true,
49            determinant_mode: RidgeDeterminantMode::Full,
50        }
51    }
52
53    /// Variant used when pseudo-determinants are required for indefinite matrices.
54    pub const fn explicit_stabilization_pospart() -> Self {
55        Self {
56            rho_independent: true,
57            include_quadratic_penalty: true,
58            include_penalty_logdet: true,
59            include_laplacehessian: true,
60            determinant_mode: RidgeDeterminantMode::PositivePart,
61        }
62    }
63
64    /// Solver-only stabilization: the ridge `δI` stabilizes the inner linear
65    /// solve (it bounds the Newton step `(H+δI)⁻¹∇`) but is **excluded** from
66    /// the REML/LAML objective — no `½·δ·‖β‖²` quadratic-penalty term, no
67    /// `δ`-shift of the penalty log-determinant, no `δ`-shift of the Laplace
68    /// Hessian. Use this when a numerical floor is needed purely to keep the
69    /// linear algebra finite during screening and must NOT bias the
70    /// smoothing-parameter selection or shrink identified coefficients off the
71    /// MLE. With every `include_*` false the optimized objective equals the
72    /// true penalized REML criterion, so the value surface and its analytic
73    /// gradient describe the same objective (gam#747/#748).
74    pub const fn solver_only() -> Self {
75        Self {
76            rho_independent: true,
77            include_quadratic_penalty: false,
78            include_penalty_logdet: false,
79            include_laplacehessian: false,
80            determinant_mode: RidgeDeterminantMode::PositivePart,
81        }
82    }
83}