fv_shared_frame_data ==================== .. py:function:: t3toolbox.backend.sharing.fv_shared_frame_data(frame_data, groups) .. code-block:: python def fv_shared_frame_data( frame_data: typ.Tuple[ typ.Sequence[NDArray], # up_tucker_cores. len=d, elm_shape=C+(nUi, Ni) typ.Sequence[NDArray], # down_tt_cores. len=d, elm_shape=C+(rLi, nDi, rR(i+1)) typ.Sequence[NDArray], # left_tt_cores. len=d, elm_shape=C+(rLi, nUi, rL(i+1)) typ.Sequence[NDArray], # right_tt_cores. len=d, elm_shape=C+(rRi, nUi, rR(i+1)) ], groups: typ.Tuple[typ.Tuple[int, ...], ...], # static; canonical partition (validate_sharing) ) -> SharedFrameData: Derive the shared-geometry companion from an **orthogonal** frame. Three steps, all exact by construction rather than by tolerance: 1. The centers ``H_i = L_i Z_{i+1}`` from the STORED cores, with ``Z_{i+1}`` the right-to-left zipper of the left chain against the right chain (``tt_zipper_right_to_left``): GEMM-only, no SVD, and gauge-consistent with the stored ``R`` by construction -- the identities below need the ``H_i`` that pair with the frame's ``O_i``/``R_i``, which these are, whatever built the frame. (Until 2026-08-22 the centers came from RE-SWEEPING the left chain with fresh SVDs, which reproduces the construction's ``H_i`` only when the same SVD ran on the same arrays; on a ``UT3Frame.to_t3frame()`` leaf -- padded batched SVD vs sliced per-core SVD -- the signs differed and the tied projection was silently 30% off, review S9.) 2. Per mode of each nontrivial group, ``S_i^T = `` against the frame's STORED down core (``S_i S_i^T = Gamma_i`` and ``W2_i = S_i O2_i`` hold by the construction's own factorization; no re-SVD, so no sign/degenerate-block hazards). 3. Per nontrivial group, one thin (batched) SVD of the stacked ``M_g = concat_i(S_i^T)``, shape ``C + (sum_i nD_i, n_g)``. Requires an orthogonal frame (the identities above presume the frame's gauges); the shared geometry enforces that in safe mode at its check sites -- this backend function is check-free. ``svd_s`` is the group spectrum: the singular values of the concatenated matricizations ``[X_(i1) | ... | X_(ik)]`` of the represented tensor. Stack-aware (frame stack ``C`` rides every array). The uniform twin is :py:func:`ufv_shared_frame_data`. Design + measurements: ``docs/contributor/sharing_internals.md`` (the tilted subspace and the SVD-not-normal-equations measurement). .. rubric:: Examples The companion of a shared frame: the centers reproduce the construction's own centers exactly, and ``svd_s`` is the concatenated-matricization spectrum of the tensor: >>> import numpy as np >>> import t3toolbox.tucker_tensor_train as t3 >>> import t3toolbox.frame_variations_format as bvf >>> import t3toolbox.backend.sharing as sharing >>> np.random.seed(0) >>> x = t3.TuckerTensorTrain.randn((6, 6, 6), (3, 3, 3), (1, 2, 2, 1)) >>> tk, tt = x.data >>> x = t3.TuckerTensorTrain((tk[0],) * 3, tt) # tie all three modes >>> frame, variations = bvf.t3_orthogonal_representations(x) >>> groups = sharing.validate_sharing((0, 0, 0), x.shape) >>> sfd = sharing.fv_shared_frame_data(frame.data, groups) >>> print(len(sfd.centers[0]), sfd.svd_s[0].shape, sfd.row_splits[0]) 3 (3,) (0, 2, 5, 7) >>> print(all(np.allclose(np.asarray(H), np.asarray(V)) ... for H, V in zip(sfd.centers[0], variations.tt_variations))) True >>> Xd = np.asarray(x.to_dense()) >>> mats = [np.moveaxis(Xd, ii, 0).reshape(6, -1) for ii in range(3)] >>> s_dense = np.linalg.svd(np.concatenate(mats, axis=1), compute_uv=False) >>> print(bool(np.allclose(np.asarray(sfd.svd_s[0]), s_dense[:3]))) True