t3svd ===== .. py:function:: t3toolbox.backend.t3_svd.t3svd(x, max_tt_ranks = None, max_tucker_ranks = None, rtol = None, atol = None, assume_orthogonal = False) .. code-block:: python def t3svd( x: typ.Tuple[ typ.Tuple[NDArray,...], # tucker_cores typ.Tuple[NDArray,...], # tt_cores ], max_tt_ranks: typ.Sequence[int] = None, # len=d+1 max_tucker_ranks: typ.Sequence[int] = None, # len=d rtol: float = None, atol: float = None, assume_orthogonal: bool = False, ) -> typ.Tuple[ typ.Tuple[ typ.Tuple[NDArray, ...], # new_tucker_cores typ.Tuple[NDArray, ...], # new_tt_cores ], typ.Tuple[NDArray,...], # Tucker singular values, len=d typ.Tuple[NDArray,...], # TT singular values, len=d+1 ]: Compute (truncated) T3-SVD of TuckerTensorTrain. Implicit T3-SVD (Algorithm 10), Appendix A.2, of Alger et al. (2026), "Tucker Tensor Train Taylor Series" (arXiv:2603.21141) -- the basic algorithm, analogous to Oseledets' TT-SVD. Orthogonalize, then a single left-to-right truncating sweep. The result is **always left-orthogonal**. It is **not** re-tuned to minimal ranks: a hard rank cap can leave a Tucker rank / bond above its structural minimum (non-minimal), exactly as the paper's algorithm does. To reduce to minimal ranks, follow with :py:func:`t3_rank_adjustment_sweep` -- the output is left-orthogonal, so ``t3_rank_adjustment_sweep(x, 'right_to_left')`` minimizes it; check with ``TuckerTensorTrain.has_minimal_ranks``. See ``docs/t3svd_minimal_ranks.md``. ``assume_orthogonal=True`` skips the initial orthogonalization, asserting the input is already **right-orthogonal** (Tucker down-orthogonal + TT right-orthogonal -- the form the L->R sweep needs). **Not enforced** (verify with ``TuckerTensorTrain.is_right_orthogonal``). A left-orthogonal input must be reversed by the caller (a left-orthogonal T3 reversed is right-orthogonal).