t3_tie_tucker_factors#
- t3toolbox.backend.sharing.t3_tie_tucker_factors(x, sharing)#
def t3_tie_tucker_factors( 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 ) -> typ.Tuple[ typ.Tuple[NDArray, ...], # new_tucker_cores. len=d; ONE shared array per group typ.Tuple[NDArray, ...], # tt_cores, untouched ]:
Tie the Tucker factors exactly, by per-group arithmetic averaging.
Each group’s factor is replaced by the group mean, and the SAME array is assigned to every mode of the group – the tie is exact by construction, never floating-point agreement. TT cores are untouched. The represented tensor changes unless the factors were already tied (drift repair for NEARLY-tied points, e.g. insurance after an operation that guarantees ties only to roundoff). The mean is computed as
B_ref + mean(B_i - B_ref), so an exactly-tied group is a bitwise fixed point for any group size (the plainsum(B_i)/kwould perturb the last ulp already atk = 3).This is a repair of a POINT’s representation, not the metric projection of a tangent onto the tied tangent space – tangent tying is geometry-specific (the manifold geometry weights coordinates by the frame’s
Sfactors; the corewise geometry averages raw core perturbations) and lives with the shared geometry.Examples
The group factor becomes the mean, assigned as one array (identity, not just equality), and the result passes the tied-factors check exactly:
>>> 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 >>> tk2, tt2 = sharing.t3_tie_tucker_factors(x.data, (0, 0, 1)) >>> print(tk2[0] is tk2[1], tt2 is tt) True True >>> print(bool(np.allclose(np.asarray(tk2[0]), (np.asarray(tk[0]) + np.asarray(tk[1])) / 2))) True >>> print(float(sharing.t3_sharing_residual((tk2, tt2), (0, 0, 1)))) 0.0
Already-tied input comes back with unchanged factor values:
>>> tk3, _ = sharing.t3_tie_tucker_factors(((tk[0], tk[0], tk[2]), tt), (0, 0, 1)) >>> print(bool(np.array_equal(np.asarray(tk3[0]), np.asarray(tk[0])))) True