t3toolbox.backend.probing.probe_tangent_transpose#

t3toolbox.backend.probing.probe_tangent_transpose(ztildes: t3toolbox.backend.common.typ.Union[t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray], t3toolbox.backend.common.NDArray], ww: t3toolbox.backend.common.typ.Union[t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray], t3toolbox.backend.common.NDArray], base: t3toolbox.backend.common.typ.Union[t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray], t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray], t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray], t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray]], t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.NDArray, t3toolbox.backend.common.NDArray, t3toolbox.backend.common.NDArray, t3toolbox.backend.common.NDArray]], edge_weights: t3toolbox.backend.common.typ.Union[t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray], t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray], t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray], t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray], t3toolbox.backend.common.typ.Sequence[t3toolbox.backend.common.NDArray]], t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.NDArray, t3toolbox.backend.common.NDArray, t3toolbox.backend.common.NDArray, t3toolbox.backend.common.NDArray, t3toolbox.backend.common.NDArray]] = (None, None, None, None, None), sum_over_probes: bool = False, use_jax: bool = False) t3toolbox.backend.common.typ.Union[t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.NDArray, Ellipsis], t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.NDArray, Ellipsis]], t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.NDArray, t3toolbox.backend.common.NDArray]]#

Apply the transpose of the map from a T3Tangent to its probes. Apply to ztildes.

See Section 5.2.4 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:
  • ztildes (typ.Sequence[NDArray]) – Probe residuals to apply the map to len=d, elm_shape=(Ni,) or (num_probes,Ni)

  • base (t3m.T3Base,) – Orthogonal base for point where the tangent space attaches to the manifold. shape=(N1,…,Nd)

  • sum_over_probes (bool) – Sum results over all probe residuals, rather than returning results for each probe residual

  • xnp – Linear algebra backend. Default: np (numpy)

Returns:

Tangent vector resulting from applying transpose map to ztildes

Return type:

t3m.T3Tangent

See also

probe_t3, tangent_probes

Examples

Apply transpose map with one set of probing vectors:

>>> import numpy as np
>>> import t3toolbox.corewise as cw
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.manifold as t3m
>>> import t3toolbox.backend.probing as t3p
>>> import t3toolbox.common as common
>>> import t3toolbox.orthogonalization as orth
>>> p = t3.t3_corewise_randn((10,11,12),(5,6,4),(2,3,4,2))
>>> base, _ = orth.orthogonal_representations(p)
>>> ww = (np.random.randn(10), np.random.randn(11), np.random.randn(12))
>>> v1 = t3m.tangent_randn(base)
>>> zz1 = t3p.probe_tangent(ww, v1, base)
>>> zz2 = (np.random.randn(10), np.random.randn(11), np.random.randn(12))
>>> v2 = t3p.probe_tangent_transpose(zz2, ww, base)
>>> ipA = cw.corewise_dot(v1, v2)
>>> print(ipA)
17.958317927787
>>> ipB = cw.corewise_dot(zz1, zz2)
>>> print(ipB)
17.958317927787

Apply transpose map with two sets of probing vectors:

>>> import numpy as np
>>> import t3toolbox.corewise as cw
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.manifold as t3m
>>> import t3toolbox.backend.probing as t3p
>>> import t3toolbox.common as common
>>> import t3toolbox.orthogonalization as orth
>>> p = t3.t3_corewise_randn((10,11,12),(5,6,4),(2,3,4,2))
>>> base, _ = orth.orthogonal_representations(p)
>>> ww = (np.random.randn(2,10), np.random.randn(2,11), np.random.randn(2,12))
>>> apply_J = lambda v: t3p.probe_tangent(ww, v, base)
>>> apply_Jt = lambda z: t3p.probe_tangent_transpose(z, ww, base)
>>> v = t3m.tangent_randn(base)
>>> z = (np.random.randn(2,10), np.random.randn(2,11), np.random.randn(2,12))
>>> print(cw.corewise_dot(z, apply_J(v)) - cw.corewise_dot(apply_Jt(z), v))
7.105427357601002e-15

Using weights:

>>> import numpy as np
>>> import t3toolbox.corewise as cw
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.manifold as t3m
>>> import t3toolbox.backend.probing as t3p
>>> import t3toolbox.common as common
>>> import t3toolbox.orthogonalization as orth
>>> import t3toolbox.basis_coordinates_format as bvf
>>> randn = np.random.randn
>>> p = t3.t3_corewise_randn((10,11,12),(5,6,4),(2,3,4,2))
>>> base, _ = orth.orthogonal_representations(p)
>>> NN, nnU, nnO, rrL, rrR = bvf.get_base_structure(base)
>>> shape_weights = [randn(N) for N in NN]
>>> up_tucker_weights = [randn(nU) for nU in nnU]
>>> outer_tucker_weights = [randn(nO) for nO in nnO]
>>> left_tt_weights = [randn(rL) for rL in rrL[:-1]]
>>> right_tt_weights = [randn(rR) for rR in rrR[1:]]
>>> edge_weights = (shape_weights, up_tucker_weights, outer_tucker_weights, left_tt_weights, right_tt_weights)
>>> ww = (np.random.randn(2,10), np.random.randn(2,11), np.random.randn(2,12))
>>> apply_J = lambda v: t3p.probe_tangent(ww, v, base, edge_weights=edge_weights)
>>> apply_Jt = lambda z: t3p.probe_tangent_transpose(z, ww, base, edge_weights=edge_weights)
>>> v = t3m.tangent_randn(base)
>>> z = (np.random.randn(2,10), np.random.randn(2,11), np.random.randn(2,12))
>>> print(cw.corewise_dot(z, apply_J(v)) - cw.corewise_dot(apply_Jt(z), v))
-1.7763568394002505e-15

Probe uniform T3

>>> import numpy as np
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.uniform as ut3
>>> import t3toolbox.manifold as t3m
>>> import t3toolbox.backend.probing as t3p
>>> import t3toolbox.orthogonalization as orth
>>> import t3toolbox.corewise as cw
>>> p = t3.t3_corewise_randn((10,11,12),(5,6,4),(2,3,4,2))
>>> base, _ = orth.orthogonal_representations(p)
>>> variation = t3m.tangent_randn(base)
>>> www = (np.random.randn(2,10), np.random.randn(2,11), np.random.randn(2,12))
>>> V, B, masks = ut3.bv_to_ubv(variation, base)
>>> uniform_ww = ut3.pack_tensors(www)
>>> apply_J = lambda v: t3p.probe_tangent(uniform_ww, v, B, edge_weights=masks)
>>> apply_Jt = lambda z: t3p.probe_tangent_transpose(z, uniform_ww, B, edge_weights=masks)
>>> z = (np.random.randn(2,10), np.random.randn(2,11), np.random.randn(2,12))
>>> Z = ut3.pack_tensors(z)
>>> JV = apply_J(V)
>>> JTZ = apply_Jt(Z)
>>> t0a = cw.corewise_dot([x[0,:] for x in Z], [x[0,:] for x in JV])
>>> t0b = cw.corewise_dot([x[:,0,:,:] for x in JTZ], V)
>>> print(t0a - t0b)
-7.105427357601002e-15
>>> t1a = cw.corewise_dot([x[1,:] for x in Z], [x[1,:] for x in JV])
>>> t1b = cw.corewise_dot([x[:,1,:,:] for x in JTZ], V)
>>> print(t1a - t1b)
-5.329070518200751e-15