fv_share_tucker_variations ========================== .. py:function:: t3toolbox.backend.sharing.fv_share_tucker_variations(variations_data, shared_data, rcond = None) .. code-block:: python def fv_share_tucker_variations( variations_data: typ.Tuple[ typ.Sequence[NDArray], # tucker_variations. len=d, elm_shape=(K+C)+(nDi, Ni) typ.Sequence[NDArray], # tt_variations. len=d, elm_shape=(K+C)+(rLi, nUi, rRi) ], shared_data: 'SharedFrameData', # the frame's companion (fv_shared_frame_data) rcond: float = None, # relative clip on the group spectrum; None -> dtype eps * max dim ) -> typ.Tuple[ typ.Tuple[NDArray, ...], # tucker_variations, tied within groups (exact row blocks of one solve) typ.Tuple[NDArray, ...], # tt_variations, untouched ]: The tied post-pass of the shared MANIFOLD geometry: orthogonally project gauged Tucker variation coordinates onto the tied subspace ``{V_i = S_i^T Udot, common gauged Udot}``. Per nontrivial group, one clipped least-squares solve against the companion's stacked-``S`` SVD (``Udot = M_g^+ [V_{i_1}; ...; V_{i_k}]``, sensitivity ``kappa_g`` -- never the ``kappa_g^2`` normal equations) followed by the exact redistribution ``V_i <- S_i^T Udot`` (the row blocks of ``M_g Udot``). Gauge is preserved identically (each ``S_i^T Udot`` is gauged when ``Udot`` is, and ``Udot`` inherits the gauge from gauged inputs); the projection is idempotent and fixes exactly-tied inputs. TT variations are untouched (sharing constrains only the Tucker factors). The clip makes the solve well-defined (minimum-norm) at rank-deficient points -- which zero-padded continuation restarts visit by construction, where the gated directions correctly receive zero. Broadcasting: the companion carries the frame stack ``C``; the variations carry ``K + C`` -- the library-wide frame-inner layout makes the solve broadcast for free. Verified against the dense orthogonal projection onto the tied tangent subspace (design round, 1.6e-13; promoted to the permanent tests). The uniform twin is :py:func:`ufv_share_tucker_variations`. .. rubric:: Examples Gauge a raw direction at a tied frame, then tie it; the post-pass is idempotent and the result stays gauged: >>> import numpy as np >>> import t3toolbox.tucker_tensor_train as t3 >>> import t3toolbox.backend.fv_conversions as fvc >>> import t3toolbox.backend.tv_operations as tvo >>> import t3toolbox.backend.sharing as sharing >>> np.random.seed(0) >>> x = t3.TuckerTensorTrain.randn((6, 6), (3, 3), (1, 2, 1)) >>> tk, tt = x.data >>> frame_d, _ = fvc.t3_orthogonal_representations(((tk[0], tk[0]), tt)) >>> groups = sharing.validate_sharing((0, 0), (6, 6)) >>> sfd = sharing.fv_shared_frame_data(frame_d, groups) >>> raw = (tuple(np.random.randn(O.shape[-2], U.shape[-1]) ... for O, U in zip(frame_d[1], frame_d[0])), ... tuple(np.random.randn(*H.shape[-3:]) for H in frame_d[2])) >>> tied = tvo.tv_orthogonal_gauge_projection(frame_d, raw, shared_data=sfd) >>> tied2 = sharing.fv_share_tucker_variations(tied, sfd) >>> print(bool(np.allclose(np.asarray(tied[0][0]), np.asarray(tied2[0][0])))) # idempotent True >>> print(float(tvo.tv_gauge_residual(frame_d, tied)) < 1e-12) # still gauged True