pub struct FactoredFrameKroneckerOp {
pub ranks: Vec<usize>,
pub basis_sizes: Vec<usize>,
pub offsets: Vec<usize>,
pub dim: usize,
pub blocks: Vec<FactoredFrameGBlock>,
}Expand description
Frame-factored data-fit Gauss–Newton β-Hessian operator (#972 / #977 T1):
the Σ_k M_k·r_k reduced-border analogue of SparseBlockKroneckerPenaltyOp.
When every atom’s decoder B_k = C_k U_kᵀ is profiled onto a Grassmann
frame U_k ∈ St(p, r_k), the border carries only the shape coefficients
C_k (M_k · r_k entries) instead of the full B_k (M_k · p). The data
Gram in this reduced space is, for the isotropic likelihood,
H[(i,li,a),(j,lj,b)] = G_{ij}[li,lj] · (U_iᵀ U_j)[a,b] — within an atom the
orthonormal frame gives U_iᵀU_i = I_{r_i} and the block is the clean
G ⊗ I_r collapse; across co-active atoms the frames do not share a basis
so the output factor is the dense U_iᵀU_j.
The β layout is μ-major / frame-minor with a variable per-atom width
r_k: the index of (atom k, basis li, frame coord a) is
offset[k] + li·r_k + a, where offset is the prefix sum of M_k · r_k.
With every r_k = p and U_k = I_p this reproduces
SparseBlockKroneckerPenaltyOp exactly (a unit test pins the reduction),
so it is a strict generalization, not a separate code path.
Fields§
§ranks: Vec<usize>Per-atom frame rank r_k (the factored output width).
basis_sizes: Vec<usize>Per-atom basis size M_k.
offsets: Vec<usize>Per-atom β offset (prefix sum of M_k · r_k); offsets[k] is the start
of atom k’s C_k block, offsets[n_atoms] the total dim.
dim: usizeTotal reduced β dimension Σ_k M_k · r_k.
blocks: Vec<FactoredFrameGBlock>Non-empty co-occurring (atom_i, atom_j) blocks.
Implementations§
Source§impl FactoredFrameKroneckerOp
impl FactoredFrameKroneckerOp
Sourcepub fn new(
ranks: Vec<usize>,
basis_sizes: Vec<usize>,
blocks: Vec<FactoredFrameGBlock>,
) -> Result<Self, String>
pub fn new( ranks: Vec<usize>, basis_sizes: Vec<usize>, blocks: Vec<FactoredFrameGBlock>, ) -> Result<Self, String>
Build from per-atom ranks + basis sizes and the co-occurring blocks.
Computes the β offsets (prefix sum of M_k·r_k) and validates that each
block’s g/w shapes match the atoms’ (M, r).
Sourcepub fn from_frames_and_blocks(
frames: &[Option<Array2<f64>>],
basis_sizes: &[usize],
p: usize,
g_blocks: &BTreeMap<(usize, usize), Array2<f64>>,
) -> Result<Self, String>
pub fn from_frames_and_blocks( frames: &[Option<Array2<f64>>], basis_sizes: &[usize], p: usize, g_blocks: &BTreeMap<(usize, usize), Array2<f64>>, ) -> Result<Self, String>
Convenience constructor that builds the operator directly from per-atom
output frames + the basis-space Gram block map, computing the per-pair
frame factors W_ij = U_iᵀ U_j itself.
frames[k] is either Some(U_k) — a p × r_k (r_k ≤ p) output frame
(a Grassmann representative St(p, r_k) need not be orthonormal here; the
W factor carries whatever frame is supplied) — or None, meaning atom
k keeps the full ambient output (U_k = I_p, so r_k = p). For each
non-empty Gram block (atom_i, atom_j) the factor W is
U_iᵀ U_j (r_i × r_j), with the None frame standing in for I_p:
a framed×unframed cross gives W = U_iᵀ (r_i × p) and an unframed
diagonal gives W = I_p — exactly reproducing the g ⊗ I_p full-B
block. The resulting blocks are handed to Self::new, which validates
the (M, r) shapes and computes the β offsets.
Trait Implementations§
Source§impl BetaPenaltyOp for FactoredFrameKroneckerOp
impl BetaPenaltyOp for FactoredFrameKroneckerOp
Source§fn matvec(&self, x: &[f64], y: &mut [f64])
fn matvec(&self, x: &[f64], y: &mut [f64])
y += P x — penalty Hessian-vector product (length K).Source§fn diagonal(&self, diag: &mut [f64])
fn diagonal(&self, diag: &mut [f64])
diag += diag(P) — diagonal entries used by Jacobi preconditioner.Source§fn block(
&self,
id: BetaBlockId,
offsets: &[Range<usize>],
out: &mut Array2<f64>,
)
fn block( &self, id: BetaBlockId, offsets: &[Range<usize>], out: &mut Array2<f64>, )
b×b dense penalty sub-block for block id into out
(row-major, block size b = offsets[id.0].len()).
Used by the block-Jacobi Schur preconditioner (#287).Source§fn to_dense(&self) -> Array2<f64>
fn to_dense(&self) -> Array2<f64>
K×K dense penalty matrix (needed by
Direct / SqrtBA modes that form the Schur complement explicitly).Source§fn fingerprint(&self, hasher: &mut Fingerprinter)
fn fingerprint(&self, hasher: &mut Fingerprinter)
hasher for cache-validity
fingerprinting. Must change whenever matvec / to_dense would change,
so the factorization / evidence cache (cache_matches_system) is
invalidated when the β-block content changes. Implementations hash their
own compact defining data (e.g. Kronecker factors, block matrices)
rather than the full K×K dense form, which would defeat the structured
operator’s storage savings.Source§fn row_abs_sums(&self) -> Array1<f64>
fn row_abs_sums(&self) -> Array1<f64>
out[r] = Σ_c |P[r,c]|, the row contribution
to the operator’s ∞-norm. The default folds to_dense(), which costs an
O(K²) materialization; structured operators override this to fold their
compact factors directly so the backward-error certificate’s
arrow_operator_infinity_norm never builds a dense K×K matrix on the
SAE LLM-border critical path (#1017). Overrides MUST agree bit-for-bit with
the to_dense() row sums (verified by the cross-check tests).Auto Trait Implementations§
impl Freeze for FactoredFrameKroneckerOp
impl RefUnwindSafe for FactoredFrameKroneckerOp
impl Send for FactoredFrameKroneckerOp
impl Sync for FactoredFrameKroneckerOp
impl Unpin for FactoredFrameKroneckerOp
impl UnsafeUnpin for FactoredFrameKroneckerOp
impl UnwindSafe for FactoredFrameKroneckerOp
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.