pub struct Gauge {
pub t_full: Array2<f64>,
pub affine_shift: Array1<f64>,
pub block_starts_raw: Vec<usize>,
pub block_starts_reduced: Vec<usize>,
}Expand description
The lift T : reduced → raw plus the per-block partitions of both
coordinate systems. See the module docs for the lift conventions.
Fields§
§t_full: Array2<f64>Global lift matrix, shape (Σ p_b_raw) × (Σ r_b_reduced).
affine_shift: Array1<f64>Global affine shift in raw coordinates, length Σ p_b_raw.
block_starts_raw: Vec<usize>Raw-coordinate block partition: block_starts_raw[b]..block_starts_raw[b+1]
is block b’s raw row range in t_full. Length n_blocks + 1, starts at 0.
block_starts_reduced: Vec<usize>Reduced-coordinate block partition (columns of t_full), same layout.
Implementations§
Source§impl Gauge
impl Gauge
Sourcepub fn validate(&self) -> Result<(), String>
pub fn validate(&self) -> Result<(), String>
Validate the serialized affine section and its block topology.
A Gauge is persisted inside fitted models and its fields remain public
for matrix-oriented consumers. Consumers of decoded or manually
assembled state must therefore reject malformed dimensions, partitions,
and non-finite affine maps before coefficient or curvature transforms.
Sourcepub fn identity(raw_widths: &[usize]) -> Self
pub fn identity(raw_widths: &[usize]) -> Self
The trivial section: raw == reduced for every block.
Sourcepub fn from_block_transforms(transforms: &[Array2<f64>]) -> Self
pub fn from_block_transforms(transforms: &[Array2<f64>]) -> Self
Block-diagonal section from independent per-block lifts
T_b : reduced_b → raw_b (selection matrices from the canonical
audit, orthogonalisation V_bs, or their compositions).
Sourcepub fn from_block_transforms_with_shift(
transforms: &[Array2<f64>],
affine_shift: Array1<f64>,
) -> Self
pub fn from_block_transforms_with_shift( transforms: &[Array2<f64>], affine_shift: Array1<f64>, ) -> Self
Block-diagonal affine section from independent per-block lifts plus one concatenated raw-coordinate shift.
Sourcepub fn from_block_transform_with_shift(
transform: Array2<f64>,
affine_shift: Array1<f64>,
) -> Self
pub fn from_block_transform_with_shift( transform: Array2<f64>, affine_shift: Array1<f64>, ) -> Self
Single-block affine section.
Sourcepub fn from_v_and_r(
v_per_term: &[Array2<f64>],
r_per_term: &[Option<Array2<f64>>],
) -> Self
pub fn from_v_and_r( v_per_term: &[Array2<f64>], r_per_term: &[Option<Array2<f64>>], ) -> Self
Block-upper-triangular section from per-block V_b plus
cross-block residualisation stacks R_{a→b} — see
assemble_block_triangular_t for the packing convention.
Sourcepub fn sum_to_zero(z: Array2<f64>) -> Self
pub fn sum_to_zero(z: Array2<f64>) -> Self
The sum-to-zero (centering) section as a first-class single-block
gauge. z is the (k × (k−1)) reparametrisation matrix returned by
terms::basis::duchon_thinplate::apply_sum_to_zero_constraint
(an orthonormal basis for null(cᵀ), c = Bᵀw the weighted column
sums): the constrained design is B_c = B · z, so on the model
η = B · β_raw = B_c · θ = B · z · θ the raw coefficients lift back
from the reduced (centred) coefficients by exactly β_raw = z · θ.
That is the one Gauge convention with T = z over a single block, so
the centring constraint stops being a special-cased outside-the-object
transform and becomes a Gauge section like every other reduction:
the covariance of the centred fit pushes forward to the raw basis
through the SAME z via Gauge::lift_covariance. A raw-coordinate
Hessian or penalty instead pulls back to the centred coordinates as
zᵀ H z via Gauge::restrict_penalty.
z is taken as the section itself (rather than recomputed from a basis)
because the constraint matrix is the only gauge-relevant artifact — the
basis the column sums were taken over is irrelevant to the lift. The
only requirement is the structural one of a centring section:
z.ncols() < z.nrows() (at least one direction is removed); an identity
z would be Gauge::identity and is rejected so callers do not silently
treat an unconstrained block as centred.
Sourcepub fn from_t(
t_full: Array2<f64>,
raw_widths: &[usize],
reduced_widths: &[usize],
) -> Self
pub fn from_t( t_full: Array2<f64>, raw_widths: &[usize], reduced_widths: &[usize], ) -> Self
Wrap an already-assembled global T given the per-block raw and
reduced width partitions.
Sourcepub fn from_t_with_shift(
t_full: Array2<f64>,
raw_widths: &[usize],
reduced_widths: &[usize],
affine_shift: Array1<f64>,
) -> Self
pub fn from_t_with_shift( t_full: Array2<f64>, raw_widths: &[usize], reduced_widths: &[usize], affine_shift: Array1<f64>, ) -> Self
Wrap an already-assembled global affine section β = Tθ + a given the
per-block raw and reduced width partitions.
Sourcepub fn left_compose(&self, outer: &Gauge) -> Result<Gauge, String>
pub fn left_compose(&self, outer: &Gauge) -> Result<Gauge, String>
Compose this affine section on the left with outer.
self maps active geometry coordinates into a current raw coefficient
frame, while outer maps that current frame into a new raw frame:
current = T_self · active + a_self
new = T_outer · current + a_outerTherefore the returned section has lift T_outer · T_self and
shift T_outer · a_self + a_outer. The complete intermediate block
partition must agree exactly; matching only the total dimension would
lose the coefficient-block lineage persisted with a fit.
Sourcepub fn from_compiled_map<M: CompiledBlockMap, O>(
map: &M,
ordering: &[O],
) -> Self
pub fn from_compiled_map<M: CompiledBlockMap, O>( map: &M, ordering: &[O], ) -> Self
Build from a compiled identifiability reparametrisation
(see CompiledBlockMap, implemented for the CompiledMap emitted by
the identifiability compiler): map.raw_from_compiled() IS the global
triangular T, and the block ranges give both partitions. ordering
is accepted purely as a length sanity check.
Sourcepub fn reduced_total(&self) -> usize
pub fn reduced_total(&self) -> usize
Total reduced width Σ r_b.
Sourcepub fn raw_widths(&self) -> Vec<usize>
pub fn raw_widths(&self) -> Vec<usize>
Per-block raw widths.
Sourcepub fn reduced_widths(&self) -> Vec<usize>
pub fn reduced_widths(&self) -> Vec<usize>
Per-block reduced widths.
Sourcepub fn block_transform(&self, b: usize) -> Array2<f64>
pub fn block_transform(&self, b: usize) -> Array2<f64>
The diagonal slab T_b = T[raw_b, reduced_b] of block b.
For a block-diagonal gauge this is the whole story for the
block; for a triangular gauge it omits the cross-block −R.
Sourcepub fn restrict_design<S: Data<Elem = f64>>(
&self,
raw_design: &ArrayBase<S, Ix2>,
) -> Array2<f64>
pub fn restrict_design<S: Data<Elem = f64>>( &self, raw_design: &ArrayBase<S, Ix2>, ) -> Array2<f64>
Compose a raw design with the section: X_reduced = X_raw · T.
Sourcepub fn is_identity(&self) -> bool
pub fn is_identity(&self) -> bool
Whether this is the exact affine identity on every persisted block.
This is stricter than the internal linear fast-path predicate: the lift
must be a literal identity, the affine shift must be exactly zero, and
raw/reduced block boundaries must coincide. No tolerance is used, so a
true result is a proof that active and saved coordinates are identical
rather than merely numerically close.
Sourcepub fn restrict_design_and_offset<S: Data<Elem = f64>>(
&self,
raw_design: &ArrayBase<S, Ix2>,
raw_offset: &Array1<f64>,
) -> (Array2<f64>, Array1<f64>)
pub fn restrict_design_and_offset<S: Data<Elem = f64>>( &self, raw_design: &ArrayBase<S, Ix2>, raw_offset: &Array1<f64>, ) -> (Array2<f64>, Array1<f64>)
Compose a raw design and offset with the affine section:
X_raw · (Tθ + a) + o_raw = (X_raw · T)θ + (o_raw + X_raw · a).
Sourcepub fn restrict_penalty<S: Data<Elem = f64>>(
&self,
raw_penalty: &ArrayBase<S, Ix2>,
) -> Array2<f64>
pub fn restrict_penalty<S: Data<Elem = f64>>( &self, raw_penalty: &ArrayBase<S, Ix2>, ) -> Array2<f64>
Pull a raw-coordinate quadratic form (including a penalty or Hessian)
back to reduced coordinates: S_reduced = Tᵀ · S_raw · T.
Sourcepub fn restrict_quadratic_factor<S: Data<Elem = f64>>(
&self,
raw_factor: &ArrayBase<S, Ix2>,
) -> Array2<f64>
pub fn restrict_quadratic_factor<S: Data<Elem = f64>>( &self, raw_factor: &ArrayBase<S, Ix2>, ) -> Array2<f64>
Pull a constructive quadratic factor into reduced coordinates.
A positive-semidefinite quadratic represented as
S_raw = A_rawᵀ A_raw has energy ‖A_raw · β_raw‖². Under this
gauge’s section β_raw = T · θ + a, the quadratic part is therefore
represented constructively by
A_reduced = A_raw · T,
S_reduced = A_reducedᵀ A_reduced.Keeping the rectangular factor across the congruence is stronger than
materializing Tᵀ S_raw T: it preserves the proof that the restricted
form is PSD and its null space is null(A_raw T), even when two dense
matrix products would leave a signed roundoff residue in an exact null
direction (#2318).
Sourcepub fn extend_with_identity(&self, extra_raw_widths: &[usize]) -> Self
pub fn extend_with_identity(&self, extra_raw_widths: &[usize]) -> Self
Append blocks that were never reduced (raw == reduced, identity lift). Used to lift joint objects that span both gauged blocks and untouched ones (e.g. the survival flex blocks alongside the compiled parametric blocks).
Sourcepub fn lift_block_betas(
&self,
reduced_block_betas: &[Array1<f64>],
) -> Vec<Array1<f64>> ⓘ
pub fn lift_block_betas( &self, reduced_block_betas: &[Array1<f64>], ) -> Vec<Array1<f64>> ⓘ
Lift per-block reduced coefficients to per-block raw
coefficients: concatenate into θ, apply β = T · θ + a, split at
the raw partition.
Sourcepub fn lift_covariance(&self, covariance_reduced: &Array2<f64>) -> Array2<f64>
pub fn lift_covariance(&self, covariance_reduced: &Array2<f64>) -> Array2<f64>
Push a reduced-coordinate posterior covariance forward to raw
coordinates via the exact sandwich Σ_raw = T · Σ_θ · Tᵀ.
This is deliberately covariance-specific. Hessians and penalties are
covariant quadratic forms and transform in the opposite direction via
Gauge::restrict_penalty; T H Tᵀ is not a Hessian pushforward.
The result is explicitly symmetrised: T · M · Tᵀ is symmetric
for symmetric M, but the two matmuls accumulate independent
rounding, so the transpose pair is averaged to land an exactly
symmetric matrix for downstream Cholesky / eigensolves.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Gauge
impl<'de> Deserialize<'de> for Gauge
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for Gauge
impl RefUnwindSafe for Gauge
impl Send for Gauge
impl Sync for Gauge
impl Unpin for Gauge
impl UnsafeUnpin for Gauge
impl UnwindSafe for Gauge
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,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
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.