t3_sharing_residual#

t3toolbox.backend.sharing.t3_sharing_residual(x, sharing)#
def t3_sharing_residual(
        x:          typ.Tuple[
            typ.Sequence[NDArray],  # tucker_cores. len=d, elm_shape=stack_shape+(ni, Ni)
            typ.Sequence[NDArray],  # tt_cores.     len=d, elm_shape=stack_shape+(ri, ni, r(i+1))
        ],
        sharing:    typ.Sequence,   # len=d, static; one hashable group label per mode
) -> NDArray:  # shape = stack_shape; max relative factor deviation per stack element (0 == exactly tied)

Non-enforcing check of the shared-factors property, per stack element.

Returns the max over groups and group modes of ||B_i - B_ref||_F / ||B_ref||_F (B_ref = the group’s first factor), reduced over the non-stack axes. Exactly-tied factors give 0; the measure is relative (the factors’ overall scale cancels), so a caller thresholds against a relative tolerance (<= rtol). A zero reference with a nonzero other factor gives inf. This is the residual behind the shared operations’ safe-mode tied-factors precondition (paired with safety.effective_rtol at the frontend check sites). Structural problems – invalid partition, unequal Tucker ranks within a group – raise unconditionally.

Examples

Exactly-tied factors (one array used at both modes) give exactly 0; independent random factors do not:

>>> import numpy as np
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.backend.sharing as sharing
>>> np.random.seed(0)
>>> x = t3.TuckerTensorTrain.randn((6, 6, 5), (3, 3, 2), (1, 2, 2, 1))
>>> tk, tt = x.data
>>> tied = ((tk[0], tk[0], tk[2]), tt)                       # tie modes 0, 1
>>> print(float(sharing.t3_sharing_residual(tied, (0, 0, 1))))
0.0
>>> print(bool(sharing.t3_sharing_residual(x.data, (0, 0, 1)) > 0.1))
True

Stack-aware – one verdict per stack element (perturb one element of a tied stack):

>>> xs = t3.TuckerTensorTrain.randn((6, 6), (3, 3), (1, 2, 1), stack_shape=(2,))
>>> tks, tts = xs.data
>>> B2 = np.asarray(tks[0]).copy()
>>> B2[1] += 1e-3 * np.random.randn(3, 6)                    # perturb stack element 1 only
>>> r = sharing.t3_sharing_residual(((tks[0], B2), tts), (0, 0))
>>> print(r.shape, bool(r[0] == 0.0), bool(r[1] > 1e-5))
(2,) True True
Parameters:
  • x (t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.typ.Sequence[NDArray], t3toolbox.backend.common.typ.Sequence[NDArray]])

  • sharing (t3toolbox.backend.common.typ.Sequence)

Return type:

NDArray