tv_probe#

t3toolbox.backend.probing.tv_probe(ww, variation, frame)#
def tv_probe(
        ww:         typ.Union[typ.Sequence[NDArray],    NDArray],  # input vectors, len=d, elm_shape=(...,Ni)
        variation:  typ.Union[
            typ.Tuple[
                typ.Sequence[NDArray],  # var_tucker_cores. len=d, elm_shape=(nOi,Ni)
                typ.Sequence[NDArray],  # var_tt_cores.     len=d, elm_shape=(rLi,nUi,rRi)
            ],
            typ.Tuple[
                NDArray,  # var_tucker_supercore.
                NDArray,  # var_tt_supercore.
            ],
        ],
        frame:       typ.Union[
            typ.Tuple[
                typ.Sequence[NDArray],  # up_tucker_cores. len=d. U_xo U_yo   = I_xy, U.shape = (nU, N)
                typ.Sequence[NDArray],  # down_tt_cores.   len=d. O_ixj O_iyj = I_xy  O.shape = (rL, nO, rR)
                typ.Sequence[NDArray],  # left_tt_cores.   len=d. P_iax P_iay = I_xy, P.shape = (rL, nU, rR)
                typ.Sequence[NDArray],  # right_tt_cores.  len=d. Q_xaj Q_yaj = I_xy  Q.shape = (rL, nU, rR)
            ],
            typ.Tuple[
                NDArray,  # up_tucker_supercore. shape=(d, nU, N),      up orthogonal elements
                NDArray,  # down_tt_supercore.   shape=(d, rL, nO, rR), down orthogonal elements
                NDArray,  # left_tt_supercore.   shape=(d, rL, nU, rR), left orthogonal elements
                NDArray,  # right_tt_supercore.  shape=(d, rL, nU, rR), right orthogonal elements
            ],
        ], # frame order = T3Frame.data = (up, down, left, right) = (U, O, P, Q)
) -> typ.Union[typ.Sequence[NDArray], NDArray]: # len=d, elm_shape=(...,Ni)

Probe a tangent vector. Applies the (single-sample) least-squares Jacobian J^(s).

Two independent stackings may ride along (handled by the W/C custom contractions in contractions.py): the T3 stack C (the frame/variation cores’ stack_shape) and the probe stack W (the probing vectors’ batch). When both are present the probes are double-stacked, elm_shape = W + C + (Ni,) (probe outer, frame inner).

See Section 6.2.2, particularly Algorithms 6 and 7, in:

Alger, N., Christierson, B., Chen, P., & Ghattas, O. (2026). “Tucker Tensor Train Taylor Series.” arXiv preprint arXiv:2603.21141. https://arxiv.org/abs/2603.21141

Parameters:
  • ww (typ.Sequence[NDArray]) – input vectors to probe with. len=d, elm_shape=(…,Ni)

  • variation (bvf.T3Variations.data) – Tangent direction, as a (tucker_variations, tt_variations) data tuple.

  • frame ((up_tucker_cores, down_tt_cores, left_tt_cores, right_tt_cores)) – Orthogonal frame for the point where the tangent space attaches to the manifold. This is exactly T3Frame.data order (U, O, P, Q) – pass frame.data directly, no reorder.

Returns:

Probes, zz. len=d, elm_shape=(Ni,) or (…,Ni)

Return type:

typ.Tuple[NDArray,…]

Examples

Probe a tangent vector with one set of vectors; value-match against the dense reference:

>>> import numpy as np
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.frame_variations_format as bvf
>>> import t3toolbox.manifold as t3m
>>> import t3toolbox.backend.probing as t3p
>>> np.random.seed(0)
>>> x = t3.TuckerTensorTrain.randn((10, 11, 12), (5, 6, 4), (1, 2, 3, 1))
>>> frame, variations = bvf.t3_orthogonal_representations(x)
>>> probe_frame = frame.data  # probing's frame order == T3Frame.data, no reorder
>>> v = t3m.T3Tangent(frame, variations)
>>> ww = (np.random.randn(10), np.random.randn(11), np.random.randn(12))
>>> zz = t3p.tv_probe(ww, variations.data, probe_frame)
>>> zz_dense = t3p.dense_probe(ww, v.to_dense())   # dense reference J^(s) v
>>> print([z.shape for z in zz])        # one probe per mode, elm_shape=(Ni,)
[(10,), (11,), (12,)]
>>> print([bool(np.allclose(z, z2)) for z, z2 in zip(zz, zz_dense)])
[True, True, True]

Probe with a stack of vectors: the probe stack W rides through, elm_shape = W + (Ni,):

>>> import numpy as np
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.frame_variations_format as bvf
>>> import t3toolbox.manifold as t3m
>>> import t3toolbox.backend.probing as t3p
>>> np.random.seed(0)
>>> x = t3.TuckerTensorTrain.randn((10, 11, 12), (5, 6, 4), (1, 2, 3, 1))
>>> frame, variations = bvf.t3_orthogonal_representations(x)
>>> v = t3m.T3Tangent(frame, variations)
>>> www = (np.random.randn(2, 10), np.random.randn(2, 11), np.random.randn(2, 12))
>>> zzz = t3p.tv_probe(www, variations.data, frame.data)
>>> zzz_dense = t3p.dense_probe(www, v.to_dense())
>>> print(zzz[0].shape)                 # W=(2,) outer, then N0=10
(2, 10)
>>> print([bool(np.allclose(z, z2)) for z, z2 in zip(zzz, zzz_dense)])
[True, True, True]