pub struct RowMetric { /* private fields */ }Expand description
The single per-row metric object. Holds one low-rank factor stack U_n (or
none, for Euclidean) plus the validated PSD blocks, tagged with its
MetricProvenance.
p is the output dimensionality (residual / Jacobian-column dimension); the
per-row factor U_n ∈ ℝ^{p × rank} so W_n = U_n U_nᵀ ∈ ℝ^{p × p} without
ever being materialized as p × p in any hot path.
Implementations§
Source§impl RowMetric
impl RowMetric
Sourcepub fn euclidean(n_rows: usize, p: usize) -> Result<Self, String>
pub fn euclidean(n_rows: usize, p: usize) -> Result<Self, String>
Euclidean metric: W_n = I_p for all n. Whitening is the identity, so
the likelihood residual path is bit-for-bit the prior isotropic φ̂.
Constructed directly: the identity stack is PSD axiomatically, so
routing it through the dense normalizer would materialize and
spectrum-check n identity blocks (n·p² memory, n·p³ flops) to
validate a tautology. tr(I_p) = p per row.
Sourcepub fn output_fisher(
u: Arc<Array2<f64>>,
p: usize,
rank: usize,
) -> Result<Self, String>
pub fn output_fisher( u: Arc<Array2<f64>>, p: usize, rank: usize, ) -> Result<Self, String>
Output-Fisher metric: per-row low-rank factors U_n ∈ ℝ^{p × rank}
supplied as a (n_rows, p * rank) row-major matrix (U_n[i, k] = u[n, i * rank + k]). The induced M_n = U_n U_nᵀ is PSD by
construction; it is validated through normalize_fisher_rao_blocks so
the validation path is shared. No solver floor (δ = 0).
Sourcepub fn output_fisher_downstream(
u: Arc<Array2<f64>>,
p: usize,
rank: usize,
) -> Result<Self, String>
pub fn output_fisher_downstream( u: Arc<Array2<f64>>, p: usize, rank: usize, ) -> Result<Self, String>
Downstream-influence output-Fisher metric: per-row factors U_n ∈ ℝ^{p × rank} whose M_n = U_n U_nᵀ is the aggregated output Fisher of
position n over the future positions it reaches through the KV path
(MetricProvenance::OutputFisherDownstream, #980 mechanism 2). The
factor layout is identical to Self::output_fisher; only the
provenance tag (and hence the scientific reading) differs. Whitens
nothing, drives the gauge / lens / enrichment exactly as the
same-position metric does — the consuming machinery is provenance-generic
(see Self::is_output_fisher_like).
Sourcepub fn output_fisher_with_solver_floor(
u: Arc<Array2<f64>>,
p: usize,
rank: usize,
solver_delta: f64,
) -> Result<Self, String>
pub fn output_fisher_with_solver_floor( u: Arc<Array2<f64>>, p: usize, rank: usize, solver_delta: f64, ) -> Result<Self, String>
Like Self::output_fisher but with a solver-only Tikhonov floor
δ ≥ 0. The floor is recorded for solver helpers only; every
criterion-facing method (quad_form, whiten_residual, fisher_mass)
ignores it (#747 discipline), so the evidence criterion is δ-free.
Sourcepub fn whitened_structured(
u: Arc<Array2<f64>>,
p: usize,
rank: usize,
) -> Result<Self, String>
pub fn whitened_structured( u: Arc<Array2<f64>>, p: usize, rank: usize, ) -> Result<Self, String>
Structured-residual whitening from supplied per-row precision factors.
u carries the per-row factor stack U_n ∈ ℝ^{p × rank} (row-major flat)
with U_n U_nᵀ = M_n = Σ_n^{-1} — the precision of the estimated
residual-covariance noise model. This is the low-level constructor; #974
producers that fit Σ_n (a low-rank factor + diagonal + smooth
activity-scale) assemble these factors and call through here. Because the
provenance is
MetricProvenance::WhitenedStructured, Self::whitens_likelihood is
true: a metric built this way is the first that whitens the likelihood.
Sourcepub fn provenance(&self) -> MetricProvenance
pub fn provenance(&self) -> MetricProvenance
The provenance tag (consumed by Object 4 to certify the inner product).
Sourcepub fn whitens_likelihood(&self) -> bool
pub fn whitens_likelihood(&self) -> bool
Whether this metric is allowed to whiten the likelihood (i.e. replace
the isotropic reconstruction data-fit ½ rᵀr with the whitened
½ rᵀ M_n r).
This is TRUE only for MetricProvenance::WhitenedStructured — a
genuinely estimated noise model (a factor-analytic residual covariance,
#974), for which whitening the likelihood is the statistically correct
thing to do. For MetricProvenance::Euclidean there is nothing to
whiten by, and for MetricProvenance::OutputFisher the inner product is
an output-geometry gauge, not an estimated noise model — whitening the
likelihood by it would silently replace the reconstruction loss with a
Fisher pullback (the #980 failure mode). So both leave the likelihood
untouched and only the gauge sees the metric (see Self::drives_gauge).
Sourcepub fn drives_gauge(&self) -> bool
pub fn drives_gauge(&self) -> bool
Whether this metric drives the gauge — i.e. the isometry-penalty pullback weight is taken from it rather than the identity.
TRUE for any non-MetricProvenance::Euclidean provenance: both
MetricProvenance::OutputFisher and
MetricProvenance::WhitenedStructured supply a non-identity per-row
inner product the gauge pulls back through. Euclidean reduces the gauge
pullback to the bare J_nᵀ J_n, so it does not drive the gauge.
Sourcepub fn is_output_fisher_like(&self) -> bool
pub fn is_output_fisher_like(&self) -> bool
Whether this metric is an output-Fisher gauge — either the
same-position MetricProvenance::OutputFisher or the downstream
MetricProvenance::OutputFisherDownstream (#980). The two share every
consumer behavior (Sym(F) separation under the gauge, two-lens coupling,
steering geometry, enrichment); they differ only in the scientific
reading of what behavioral coupling means (same-position vs
forward-looking). Consumers that gate on “is this an output-Fisher
pullback” should use this predicate rather than matching one variant, so
the downstream metric rides the identical path.
Sourcepub fn metric_rank(&self) -> usize
pub fn metric_rank(&self) -> usize
The factor rank: the dimension of the whitened residual
Self::whiten_residual_row returns (and the column count of the per-row
factor U_n ∈ ℝ^{p × rank}). For MetricProvenance::Euclidean this is
p (the implicit identity factor), so a consumer that sizes a whitened
buffer by metric_rank() gets the right length in every provenance.
Sourcepub fn row_traces(&self) -> ArrayView1<'_, f64>
pub fn row_traces(&self) -> ArrayView1<'_, f64>
Per-row traces tr(M_n) of the criterion-facing (un-floored) metric —
the Fisher-mass reduction the #980 row measure consumes. The dense
(n_rows, p, p) stack is validated streamingly at construction and
never retained; consumers wanting an explicit W_n rebuild it from
Self::metric_rank-sized factors.
Sourcepub fn whiten_residual_row(
&self,
row: usize,
r: ArrayView1<'_, f64>,
) -> Vec<f64>
pub fn whiten_residual_row( &self, row: usize, r: ArrayView1<'_, f64>, ) -> Vec<f64>
Whiten a single p-dimensional residual row r into the coordinates
whose squared Euclidean norm equals rᵀ W_n r.
- Euclidean: returns
runchanged (‖r‖² = rᵀ I r), so the likelihood reproduces the isotropic½ rᵀrdata-fit bit-for-bit. - Factored: returns
U_nᵀ r ∈ ℝ^{rank}, with‖U_nᵀ r‖² = rᵀ U_n U_nᵀ r = rᵀ W_n r.
This is the load-bearing identity that lets the data-fit loop sum
0.5 * Σ whitened² and recover exactly rᵀ W_n r whatever the
provenance.
Sourcepub fn factor_entry(&self, row: usize, i: usize, k: usize) -> f64
pub fn factor_entry(&self, row: usize, i: usize, k: usize) -> f64
The factor entry U_n[i, k] for one row (i ∈ [0, p), k ∈ [0, rank)).
For MetricProvenance::Euclidean the implicit factor is I_p, so this
returns 1.0 when i == k and 0.0 otherwise — letting a consumer that
whitens a Jacobian via factor_entry produce the identity whitening
without a provenance branch. Reads the un-floored factors (criterion
face, #747).
Sourcepub fn apply_metric_row(&self, row: usize, x: ArrayView1<'_, f64>) -> Vec<f64>
pub fn apply_metric_row(&self, row: usize, x: ArrayView1<'_, f64>) -> Vec<f64>
Apply the full per-row metric M_n x = U_n (U_nᵀ x) ∈ ℝ^p for one
p-vector x, formed factored (rank flops in, p flops out) — never
materializing M_n as p × p. Euclidean returns x unchanged
(M_n = I_p). This is the p-space metric-applied vector the SAE β-tier
data-fit gradient contracts (β lives in p-output space, so its gradient
needs M_n r_n, not the rank-space whitened residual U_nᵀ r_n). Uses the
un-floored factors (criterion face, δ-free, #747 invariant).
Sourcepub fn pullback(&self, row: usize, j_row: &[f64], d: usize) -> Array2<f64>
pub fn pullback(&self, row: usize, j_row: &[f64], d: usize) -> Array2<f64>
Pullback metric g_n = J_nᵀ W_n J_n for one row, formed as
(J_nᵀ U_n)(U_nᵀ J_n) — never materializing the p × p W_n.
j_row is the row’s Jacobian J_n ∈ ℝ^{p × d} flattened row-major
(J_n[i, a] = j_row[i * d + a]). Returns the d × d g_n.
Sourcepub fn quad_form(&self, row: usize, r: ArrayView1<'_, f64>) -> f64
pub fn quad_form(&self, row: usize, r: ArrayView1<'_, f64>) -> f64
Quadratic form r_nᵀ M_n r_n for one row’s residual r_n ∈ ℝ^p, formed
factored as ‖U_nᵀ r_n‖² — never materializing the p × p M_n.
This is the criterion-facing squared residual the likelihood sums; it uses
the un-floored U_n U_nᵀ, so the solver δ does not enter it
(#747 invariant). Euclidean provenance returns the bit-identical ‖r_n‖².
Sourcepub fn whiten_jacobian(
&self,
row: usize,
j_row: &[f64],
d: usize,
) -> Array2<f64>
pub fn whiten_jacobian( &self, row: usize, j_row: &[f64], d: usize, ) -> Array2<f64>
Whiten a per-row Jacobian J_n ∈ ℝ^{p × d} (row-major flat,
J_n[i, a] = j_row[i * d + a]) into M_n = U_nᵀ J_n ∈ ℝ^{rank × d} so
that M_nᵀ M_n = J_nᵀ (U_n U_nᵀ) J_n = J_nᵀ W_n J_n is the pullback
without any p × p intermediate. Euclidean returns J_n reshaped to
(p, d) (the identity whitening). Solver δ is not applied (criterion
face).
Sourcepub fn fisher_mass(&self, row: usize, x: ArrayView1<'_, f64>) -> f64
pub fn fisher_mass(&self, row: usize, x: ArrayView1<'_, f64>) -> f64
Fisher mass of a per-row output vector x_n ∈ ℝ^p: the scalar
x_nᵀ M_n x_n (alias of Self::quad_form read as an information mass
rather than a residual square). Factored, never p × p, δ-free.
Sourcepub fn solver_floor(&self) -> f64
pub fn solver_floor(&self) -> f64
The solver-only Tikhonov floor δ (#747). Returned for internal
solver helpers that need U_n U_nᵀ + δ I to be invertible; by contract
no caller may fold this into a criterion-facing quantity. Always 0 for
Euclidean and for factored metrics built without an explicit floor.
Sourcepub fn to_weight_field(&self) -> WeightField
pub fn to_weight_field(&self) -> WeightField
The gauge view of this metric: the
crate::WeightField the isometry penalty pulls back through.
This is the single way an IsometryPenalty acquires a non-identity
gauge metric — the independent WeightField setter has been removed — so
the gauge metric is, by construction, the same object the likelihood
whitens with.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for RowMetric
impl RefUnwindSafe for RowMetric
impl Send for RowMetric
impl Sync for RowMetric
impl Unpin for RowMetric
impl UnsafeUnpin for RowMetric
impl UnwindSafe for RowMetric
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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.