pub struct MatrixFreeSpdOperator { /* private fields */ }Expand description
Operator-backed SPD Hessian with exact spectral REML algebra.
The operator closure is still useful for construction paths that naturally
expose HVPs, but REML cost/gradient/Hessian terms must all come from one
exact decomposition so ∂ log|H| = tr(H⁻¹ ∂H) holds. We therefore
materialize the coefficient Hessian by canonical-basis HVPs under an
explicit memory cap and delegate logdet, traces, and solves to
DenseSpectralOperator.
Implementations§
Source§impl MatrixFreeSpdOperator
impl MatrixFreeSpdOperator
pub fn new_with_mode<F>(dim: usize, apply: F, mode: PseudoLogdetMode) -> Self
Sourcepub fn new_with_mode_and_dense_assemble<F>(
dim: usize,
apply: F,
mode: PseudoLogdetMode,
dense_assemble: Option<Arc<dyn Fn() -> Option<Array2<f64>> + Send + Sync>>,
) -> Self
pub fn new_with_mode_and_dense_assemble<F>( dim: usize, apply: F, mode: PseudoLogdetMode, dense_assemble: Option<Arc<dyn Fn() -> Option<Array2<f64>> + Send + Sync>>, ) -> Self
Like [new_with_mode], but additionally accepts an optional single-pass
dense assembly of the same penalized operator. When present and it yields
a matrix, materialize_dense_operator uses it instead of the dim
canonical-basis matvecs. See the field doc on dense_assemble.
Trait Implementations§
Source§impl HessianOperator for MatrixFreeSpdOperator
impl HessianOperator for MatrixFreeSpdOperator
Source§fn prefers_stochastic_trace_estimation(&self) -> bool
fn prefers_stochastic_trace_estimation(&self) -> bool
The operator delegates logdet, trace_hinv_*, trace_logdet_*,
solve, and solve_multi to a lazily-built DenseSpectralOperator
whenever the exact-dense materialization fits the configured byte cap
(see exact_dense_spectral_budget_ok / EXACT_DENSE_SPECTRAL_MAX_BYTES).
In that regime the algebra is exact spectral — there is no stochastic
preference to advertise, and forcing the caller to take the Hutchinson
path would replace an O(p²) exact reduction with O(k·apply) noisy probes.
When the budget is exceeded the dense factor cannot be built and the
CG trace-solve path added in 2bd6af68 is the only feasible route; the
flag flips to true so stochastic_trace_solve* callers route through
cg_trace_solve instead of crashing in exact_dense_spectral().expect.
Source§fn logdet_traces_match_hinv_kernel(&self) -> bool
fn logdet_traces_match_hinv_kernel(&self) -> bool
Mirror the prefers_stochastic_trace_estimation gate: when the dense
factor is reachable the operator’s logdet / trace_hinv reductions all
resolve through DenseSpectralOperator, whose
logdet_traces_match_hinv_kernel is false for the smooth-spectral
regularization variants we run. Reporting true here would let the
outer evaluator route logdet-gradient/Hessian traces through the
Hutchinson H⁻¹ kernel which does not satisfy
∂ log|H| = tr(H⁻¹ ∂H) under smooth-spectral. The CG-only regime
(budget exceeded) lacks a dense reference so falling back to the
stochastic kernel is acceptable as a best-effort estimate.
Source§fn as_exact_dense_spectral(&self) -> Option<&DenseSpectralOperator>
fn as_exact_dense_spectral(&self) -> Option<&DenseSpectralOperator>
Source§fn trace_hinv_product(&self, a: &Array2<f64>) -> f64
fn trace_hinv_product(&self, a: &Array2<f64>) -> f64
logdet.Source§fn trace_hinv_operator(&self, op: &dyn HyperOperator) -> f64
fn trace_hinv_operator(&self, op: &dyn HyperOperator) -> f64
Source§fn trace_hinv_product_cross(&self, a: &Array2<f64>, b: &Array2<f64>) -> f64
fn trace_hinv_product_cross(&self, a: &Array2<f64>, b: &Array2<f64>) -> f64
Source§fn trace_hinv_matrix_operator_cross(
&self,
matrix: &Array2<f64>,
op: &dyn HyperOperator,
) -> f64
fn trace_hinv_matrix_operator_cross( &self, matrix: &Array2<f64>, op: &dyn HyperOperator, ) -> f64
Source§fn trace_hinv_operator_cross(
&self,
left: &dyn HyperOperator,
right: &dyn HyperOperator,
) -> f64
fn trace_hinv_operator_cross( &self, left: &dyn HyperOperator, right: &dyn HyperOperator, ) -> f64
Source§fn trace_logdet_operator(&self, op: &dyn HyperOperator) -> f64
fn trace_logdet_operator(&self, op: &dyn HyperOperator) -> f64
Source§fn solve(&self, rhs: &Array1<f64>) -> Array1<f64>
fn solve(&self, rhs: &Array1<f64>) -> Array1<f64>
Source§fn stochastic_trace_solve(&self, rhs: &Array1<f64>, rel_tol: f64) -> Array1<f64>
fn stochastic_trace_solve(&self, rhs: &Array1<f64>, rel_tol: f64) -> Array1<f64>
Source§fn stochastic_trace_solve_for_probe(
&self,
rhs: &Array1<f64>,
rel_tol: f64,
probe_id: u64,
trace_state: Option<&Arc<Mutex<StochasticTraceState>>>,
) -> Array1<f64>
fn stochastic_trace_solve_for_probe( &self, rhs: &Array1<f64>, rel_tol: f64, probe_id: u64, trace_state: Option<&Arc<Mutex<StochasticTraceState>>>, ) -> Array1<f64>
Source§fn stochastic_trace_solve_multi(
&self,
rhs: &Array2<f64>,
rel_tol: f64,
) -> Array2<f64>
fn stochastic_trace_solve_multi( &self, rhs: &Array2<f64>, rel_tol: f64, ) -> Array2<f64>
Source§fn trace_logdet_hessian_cross(
&self,
h_i: &Array2<f64>,
h_j: &Array2<f64>,
) -> f64
fn trace_logdet_hessian_cross( &self, h_i: &Array2<f64>, h_j: &Array2<f64>, ) -> f64
∂²_{ij} log|R_ε(H)| = tr(G_ε Ḧ_{ij}) + spectral_cross(Ḣ_i, Ḣ_j). Read moreSource§fn trace_logdet_hessian_cross_matrix_operator(
&self,
h_i: &Array2<f64>,
h_j: &dyn HyperOperator,
) -> f64
fn trace_logdet_hessian_cross_matrix_operator( &self, h_i: &Array2<f64>, h_j: &dyn HyperOperator, ) -> f64
trace_logdet_hessian_cross]. Read moreSource§fn trace_logdet_hessian_cross_operator(
&self,
h_i: &dyn HyperOperator,
h_j: &dyn HyperOperator,
) -> f64
fn trace_logdet_hessian_cross_operator( &self, h_i: &dyn HyperOperator, h_j: &dyn HyperOperator, ) -> f64
trace_logdet_hessian_cross]. Read moreSource§fn active_rank(&self) -> usize
fn active_rank(&self) -> usize
Source§fn is_dense(&self) -> bool
fn is_dense(&self) -> bool
Source§fn as_dense_spectral(&self) -> Option<&DenseSpectralOperator>
fn as_dense_spectral(&self) -> Option<&DenseSpectralOperator>
Source§fn has_matrix_free_trace_cg_operator(&self) -> bool
fn has_matrix_free_trace_cg_operator(&self) -> bool
Source§fn assemble_h_dense_for_tangent_projection(&self) -> Result<Array2<f64>, String>
fn assemble_h_dense_for_tangent_projection(&self) -> Result<Array2<f64>, String>
Source§fn trace_logdet_gradient(&self, a: &Array2<f64>) -> f64
fn trace_logdet_gradient(&self, a: &Array2<f64>) -> f64
Source§fn xt_logdet_kernel_x_diagonal(&self, x: &DesignMatrix) -> Array1<f64>
fn xt_logdet_kernel_x_diagonal(&self, x: &DesignMatrix) -> Array1<f64>
trace_logdet_gradient.
trace_logdet_gradient(Xᵀ diag(w) X) = Σᵢ wᵢ · h^G[i]. Read moreAuto Trait Implementations§
impl !Freeze for MatrixFreeSpdOperator
impl !RefUnwindSafe for MatrixFreeSpdOperator
impl !UnwindSafe for MatrixFreeSpdOperator
impl Send for MatrixFreeSpdOperator
impl Sync for MatrixFreeSpdOperator
impl Unpin for MatrixFreeSpdOperator
impl UnsafeUnpin for MatrixFreeSpdOperator
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.