t3_share_tucker_factors ======================= .. py:function:: t3toolbox.backend.t3_svd.t3_share_tucker_factors(x, sharing, max_tt_ranks = None, max_tucker_ranks = None, rtol = None, atol = None) .. code-block:: python def t3_share_tucker_factors( x: typ.Tuple[ typ.Tuple[NDArray, ...], # tucker_cores; factors may be arbitrary (untied) typ.Tuple[NDArray, ...], # tt_cores ], sharing: typ.Sequence, # len=d, static; one hashable group label per mode max_tt_ranks: typ.Sequence[int] = None, # len=d+1 (or scalar); passed to the grouped t3svd max_tucker_ranks: typ.Sequence[int] = None, # len=d (or scalar); equal within groups rtol: float = None, atol: float = None, ) -> typ.Tuple[ typ.Tuple[ typ.Tuple[NDArray, ...], # new_tucker_cores; ONE shared array per group typ.Tuple[NDArray, ...], # new_tt_cores ], typ.Tuple[NDArray,...], # Tucker singular values, len=d; group modes carry the group spectrum typ.Tuple[NDArray,...], # TT singular values, len=d+1 ]: Quasi-optimal projection of an arbitrary (unshared) T3 onto the shared format. The shared initializer (``docs/shared_t3_math.tex``, Algorithm 3, simplified): two steps. 1. **Exact common-span rewrite**, per group: one SVD of the row-stacked factors ``[B_{i_1}; ...; B_{i_k}] = W diag(s) V^T`` gives the common basis (``V^T``'s rows span every group factor's rows) and, for free, each factor's exact coefficients in it (``B_i = (W_i diag(s)) V^T`` -- the SVD's own row blocks). The shared factor ``V^T`` is assigned as ONE array per group and each group core's up leg absorbs its coefficient block. This is a LOSSLESS re-representation (no orthogonality assumptions on the input); the group rank becomes the structural span ``m = min(sum_i n_i, N_g)``. 2. The grouped :py:func:`t3svd` at the requested ranks/tolerances does ALL the selection (the optimal shared basis lies in the span of the group's factors, so nothing is lost to step 1; the large dimension ``N_g`` is touched only in step 1's stacked SVD). On an already-shared input this reports exactly the grouped ``t3svd``'s spectra (the rewrite changes the representation, not the tensor, and the group spectrum is representation-independent), and the result is quasi-optimal with respect to the best shared approximation with the constant ``C(d) = sqrt(d) + sqrt(d) sqrt(d-1) + sqrt(d-1)`` (the composition argument of the grouped rounding). Singleton-only partitions reduce to the plain :py:func:`t3svd`. Stack-aware (tolerances require an unstacked input, as everywhere). Without any cap or tolerance the result is the lossless common-span rewrite at rank ``m`` -- dropping numerically-zero directions requires a tolerance, exactly as in the unshared ``t3svd``.