T3Tangent#

class t3toolbox.manifold.T3Tangent#

Tangent vector to the manifold of fixed-rank Tucker tensor trains.

A T3Tangent bundles a T3Frame (the frame at the base point where the tangent space is attached) with a T3Variations (the tangent direction in that frame). Bundling them makes “which tangent space” a checkable property: linear algebra between two tangent vectors is only defined when they live in the same tangent space, which here means they hold the same T3Frame object (identity, not merely numerically-equal cores).

The metric lives on the geometry, not here: ManifoldGeometry.inner() / norm are the Hilbert-Schmidt inner product / norm (which check the orthogonal-frame + gauged preconditions in safe mode), and CorewiseGeometry.inner() / norm are the Euclidean ones. This class exposes only the raw coordinate corewise_inner() / corewise_norm() (equal to HS only on an orthonormal, gauged, minimal-rank frame – see is_orthogonal() / is_gauged() and the contract catalog), with no HS claim.

A tangent vector is the sum of 2d single-core variation terms – equation (47), Appendix A.3, of Alger, Christierson, Chen & Ghattas (2026), “Tucker Tensor Train Taylor Series” (arXiv:2603.21141).

Examples

>>> import numpy as np
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.frame_variations_format as bvf
>>> import t3toolbox.manifold as t3m
>>> x = t3.TuckerTensorTrain.randn((10, 11, 12), (3, 4, 3), (1, 2, 2, 1))
>>> frame, variations = bvf.t3_orthogonal_representations(x)
>>> v = t3m.T3Tangent(frame, variations)
>>> print(v.shape, v.stack_shape)
(10, 11, 12) ()
>>> print(v.is_orthogonal())   # frame from t3_orthogonal_representations is orthogonal
True
>>> print(v.is_gauged())       # ...but those variations are not gauged
False
>>> w = 2.0 * v - v            # linear algebra stays in the same tangent space
>>> print(np.linalg.norm(w.to_dense() - v.to_dense()))   # (2v - v) == v
0.0
frame: T3Frame#
variations: T3Variations#
__rmul__#

Methods#

__post_init__()

validate()

Validate this tangent: both components well-formed and a compatible (frame, variations) pair.

__repr__()

d()

shape()

frame_stack_shape()

Frame stack C: the batch of base points, shared with the frame (frame.stack_shape).

tangent_stack_shape()

Tangent stack K: the extra outer batch of tangent vectors sharing this frame.

stack_shape()

Full stack K + C (tangent_stack_shape + frame_stack_shape), outer-to-inner.

structure()

data()

to_jax()

Copy with frame and variation cores converted to jax arrays.

to_numpy()

Copy with frame and variation cores converted to numpy arrays.

copy()

Deep copy (copies the frame and variation cores).

contains_jax()

True if any frame or variation core is a jax array.

size()

Number of elements of the represented dense tangent vector (prod(shape)).

data_size()

Number of stored core entries (size on disk): frame + variations.

to_dense([include_shift])

Form the dense tensor represented by this tangent vector.

to_t3([include_shift])

Doubled-rank TuckerTensorTrain representation of this tangent vector.

to_vector()

Flatten this tangent's variation degrees of freedom to a 1D vector (the frame is the fixed

from_vector(flat, frame[, tangent_stack_shape])

Inverse of to_vector(): rebuild the tangent at frame from a 1D DOF vector.

save(file)

Save the frame + variation cores to a .npz file (load with load()).

load(file[, use_jax])

Load a tangent saved by save().

reverse()

Reverse the mode order of this tangent (reverses both the frame and the variations).

sum_tangents([axis])

Sum over the tangent stack K (a batch of tangents at the shared frame) into one tangent.

zeros(frame[, stack_shape])

Zero tangent vector at a given frame (numpy/jax matching the frame).

unit(frame, index)

Canonical unit tangent at frame: variations zero except a single core entry.

zeros_like(tangent)

Zero tangent at tangent's frame, with tangent's tangent stack K.

__add__(other)

Add tangent vectors. Requires both to share the same T3Frame object.

__sub__(other)

Subtract tangent vectors. Requires both to share the same T3Frame object.

__mul__(scalar)

Scale a tangent vector by a scalar.

__neg__()

corewise_inner(other)

The raw corewise (coordinate) dot of two tangents' variations -- not the HS inner product.

corewise_norm()

The raw corewise (coordinate) norm of the variations -- not the HS norm.

absorb_weights(weights)

Absorb the metric weights into this tangent's variation cores (down->V,

weighted_norm(weights)

The weighted (Grasedyck-Kramer) coordinate norm: absorb the metric weights into the

weighted_inner(other, weights)

The weighted coordinate inner product <absorb(W,self), absorb(W,other)> w.r.t. one

normalized()

Unit-norm rescaling self / self.corewise_norm(), vectorized over the stack.

allclose(other[, rtol, atol])

True (per stack element) if other is the same tangent vector as self at the same frame.

minimal_ranks()

Structural minimal ranks of this tangent's base point. See T3Frame.minimal_ranks.

tangent_space_dimension()

Dimension of the tangent space at this base point (= the fixed-rank manifold dimension).

has_minimal_ranks()

True if this tangent's frame has structurally minimal ranks. See

has_numerically_minimal_ranks([atol])

True (per frame-stack element) if this tangent's frame is numerically minimal. See

is_orthogonal([atol])

True (per frame-stack element) if this tangent's frame is orthogonal. See

gauge_residual()

Max absolute gauge-condition violation, per stack element (shape = variation stack K+C;

is_gauged([atol])

True (per stack element) if the variations are gauged with respect to the frame.

probe(ww)

Probe this tangent vector: apply the single-sample least-squares Jacobian J^(s).

probe_transpose(ztildes, ww, frame[, sum_over_probes])

Apply the transpose (J^(s))^T of the probe map to residuals; returns a T3Tangent at frame.

apply(ww)

Apply this tangent vector in all modes: contract the dense tangent with ww everywhere.

entries(index)

Extract entries of the dense tangent at index (without forming the dense tangent).

apply_transpose(c, ww, frame[, sum_over_probes])

Apply the transpose apply^T of apply(): back-project a residual c into a tangent.

entries_transpose(c, index, frame[, sum_over_probes])

Apply the transpose entries^T of entries(): scatter c at index into a tangent.

probe_derivatives(ww, pp, order)

Symmetric directional derivatives of probing this tangent vector, in one repeated direction.

apply_derivatives(ww, pp, order)

Symmetric directional derivatives of applying this tangent vector in all modes.

entries_derivatives(index, pp, order)

Symmetric directional derivatives of this tangent's entries at index, in direction P.

probe_derivatives_transpose(ztildes, ww, pp, frame, order)

Transpose (J^(s))^T of probe_derivatives(); returns a T3Tangent at frame.

apply_derivatives_transpose(c, ww, pp, frame, order[, ...])

Transpose of apply_derivatives(): back-project residual jets c into a tangent.

entries_derivatives_transpose(c, index, pp, frame, order)

Transpose of entries_derivatives(): scatter residual jets c at index into a tangent.

unstack_tangents()

Unstack over the tangent stack K: a K-shaped tree of tangents sharing this frame.

unstack_frame()

Unstack over the frame stack C: a C-shaped tree of single-base-point tangents.

stack_tangents(tree)

Stack a K-shaped tree of tangents (sharing one frame) into a tangent-stacked T3Tangent.

stack_frame(tree)

Stack a C-shaped tree of single-base-point tangents into a frame-stacked T3Tangent.