Skip to main content

RowMetric

Struct RowMetric 

Source
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

Source

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.

Source

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).

Source

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).

Source

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.

Source

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.

Source

pub fn provenance(&self) -> MetricProvenance

The provenance tag (consumed by Object 4 to certify the inner product).

Source

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).

Source

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.

Source

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.

Source

pub fn n_rows(&self) -> usize

Number of rows the metric is defined over.

Source

pub fn p_out(&self) -> usize

Output dimensionality p (residual / Jacobian-column dimension).

Source

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.

Source

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.

Source

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 r unchanged (‖r‖² = rᵀ I r), so the likelihood reproduces the isotropic ½ rᵀr data-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.

Source

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).

Source

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).

Source

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.

Source

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‖².

Source

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).

Source

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.

Source

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.

Source

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§

Source§

impl Clone for RowMetric

Source§

fn clone(&self) -> RowMetric

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RowMetric

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DistributionExt for T
where T: ?Sized,

Source§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V