Numerical contracts: what safe mode checks#
The library’s ambient safety mode (see the user guide’s “Safe and unsafe mode”) checks genuine
numerical preconditions and skips them under safety.unsafe() or a jax trace. This page is the
op-by-op reference: which operations check what, which properties are only caveats, and the
settled answer to “which operations need minimal ranks” (none — a reference result that does not
exist in the literature).
The classification rule#
Precondition — the operation is undefined or numerically wrong without the property. Safe mode checks it and raises; unsafe mode / under-jit skips the check.
Caveat — the operation is valid and correct as computed; the property only governs what the result means (e.g. “this coordinate inner product equals Hilbert–Schmidt”). Never enforced — enforcing it would reject legitimate use.
The classic example: orthogonality/gaugedness is a caveat for a raw coordinate inner product
(it is valid on any frame; the properties only make it equal HS) — which is why the semantic
inner/norm live on the MANIFOLD geometry (where the properties are preconditions) while
T3Tangent.corewise_inner/corewise_norm are the raw coordinate ops (no HS claim, no check).
Equality is explicit#
== is intentionally not defined on the runtime classes (TuckerTensorTrain, weights, frames,
variations, tangents, and their uniform twins): it raises a TypeError directing you to say which
equality you mean (x == x is True by identity; the classes are unhashable – key caches by
id(obj) and keep the object alive). The reason is honesty, not laziness: the arithmetic operators
act on the represented tensors, but exact mathematical equality is not a well-posed floating-point
predicate for an implicit representation (two representations of the same tensor differ in the last
ulp), and a tolerance inside == would not be an equivalence relation. The named checks are:
a.allclose(b, rtol=, atol=)– numerical equality of what the objects represent, per stack element (reduce with.all()), via‖a − b‖ ≤ atol + rtol·max(‖a‖, ‖b‖)with the difference formed in the representation and its norm taken through orthogonalization (stable exactly whena ≈ b). For trains this is gauge- and padding-invariant tensor equality; for frames it is the base point (gauge-invariant) – the same-FRAME / same-tangent-space question issafety.frames_equal; for tangents it checks the same-frame precondition first. Defaultrtolis the ambient jax-aware tolerance (safety.comparison_rtol).a.corewise_equal(b)– bitwise equality of the stored representation (shape, masks, and cores exactly;Falseon any mismatch, never raises).
Value-based hash/eq exists exactly where jit requires it: the aux_data family (mask holders,
geometries, sampling kinds), whose equality decides compiled-program reuse
(backend.common.ExplicitEquality records the rule).
The numerical properties and their checkers#
property |
meaning |
checker |
|---|---|---|
same-frame ( |
two tangents share one tangent space — their frames are numerically equal ( |
built into the checked ops |
orthogonal ( |
the frame is orthonormal (U/O/L/R conditions) |
|
gauged ( |
the variations satisfy the gauge conditions (48)–(49) |
|
minimal rank |
no stored rank is redundant |
|
tied factors ( |
the Tucker factors are numerically equal within each sharing group ( |
|
Checkers are per stack element (they return a verdict of shape stack_shape); a safe-mode
precondition requires all elements to pass. The checks are cheap in loops: the underlying
residuals (T3Frame.orthogonality_residual, T3Tangent.gauge_residual) are cached on the frozen
objects, so a fixed frame or tangent reused across an inner loop is contracted once. The tolerance
is jax-aware (rtol_jax, looser, when any operand is a jax array — jax defaults to float32 — else
rtol_numpy).
What each surface checks in safe mode#
— = no numerical precondition (structural checks — shapes, ranks, pair consistency — still apply
always, in both modes).
T3Tangent#
op |
precondition |
caveat (never checked) |
|---|---|---|
|
SF |
|
|
— |
|
|
SF |
|
|
SF |
“= HS iff orthogonal + gauged” (that claim belongs to |
|
— (unary) |
“= HS iff orthogonal + gauged” |
|
— |
realization is gauge-invariant, valid on any frame |
|
— |
bare |
|
— |
|
|
SF (all leaves) |
|
|
— |
|
the checkers ( |
— |
they are the checks; non-enforcing by design |
The geometries (the semantic inner/norm live here)#
op |
precondition |
caveat |
|---|---|---|
|
SF + ORTH + GAUGE (both operands) |
minimal (for strict HS exactness — see the verdict: not needed) |
|
ORTH + GAUGE (unary — no SF) |
minimal |
|
SF |
— (Euclidean by design; no ORTH/GAUGE) |
|
— |
|
|
ORTH |
minimal (for oblique’s HS-matching purpose) |
|
ORTH (gauge-invariant, so ORTH only) |
minimal (strict rank preservation — without it, retract drops numerically-redundant rank) |
|
ORTH |
— |
|
ORTH (the new frame) |
— |
|
ORTH (via the projection) |
minimal (for a true Gaussian on |
|
— |
|
GaussNewtonModel#
op |
precondition |
|---|---|
|
SF — |
Precondition-free surfaces#
surface |
why |
|---|---|
|
exact HS for any cores ( |
|
exact for any cores; only structural checks |
|
the raw coordinate layer; structural shape-match only |
the backend sampling machinery ( |
bare |
|
structural validation always (both modes); the orthogonal representation produces an orthonormal frame |
Minimal ranks: the settled verdict#
Minimal rank splits into structural (has_minimal_ranks — ranks equal the structural minimum;
cheap integer arithmetic) and numerical (has_numerically_minimal_ranks — no stored rank
numerically redundant). Which operations actually need minimal ranks was settled empirically
(each op compared on a minimal vs a non-minimal orthogonal frame against the dense oracle):
op |
needs minimal? |
evidence |
|---|---|---|
|
NO |
the gauged coordinate inner product equals the dense HS value exactly on a non-minimal orthonormal frame — orthogonal + gauged suffices |
|
NO |
the formula matches the true tangent-space dimension for any ranks |
|
caveat only |
on a structurally non-minimal but full-rank frame it is still a valid first-order retraction that drops the redundant rank (desirable cleanup) — minimal buys only strict rank preservation. At a numerically rank-deficient frame (zero singular values: a zero-padded |
|
NO |
correct on any orthonormal frame |
|
NO |
orthogonality suffices |
Verdict: minimal rank is not a correctness precondition for any verified operation, so it is
never checked — a minimal-rank gate would reject legitimate rank-redundant frames for no
correctness reason. It survives as the retract rank-preservation caveat and as the diagnostic
checkers. Naming rule: bare minimal_ranks means the structural notion; numerically_minimal means
the SVD-grade notion.
Why excess rank is inert (the mechanism, worth knowing before you reach for a rank check): a frame
carries four rank stores — up/down and left/right — and an over-ranked request is absorbed as
slack between them rather than breaking any single core’s orthonormality. So an orthonormal frame need
not be minimal: t3_orthogonal_representations does not guarantee it, and neither does
T3Frame.random_orthogonal, which happily returns up_ranks=(4,4,4) with down_ranks=(2,4,2) if you
ask for a Tucker rank the TT bonds cannot support. Such a frame is exactly orthogonal and every tangent
operation on it is exact — the tangent space, its dimension, and the HS identities are unchanged. Full
derivation and the measured numbers: frame_variations.md. Build from a
minimal-rank point only if you need retraction to preserve the rank tuple.
The decision record behind this page — the op-by-op sweep, the experiments, and the sign-off —
is preserved as contributor/numerical_contract_catalog.md.