dense_ttsvd =========== .. py:function:: t3toolbox.backend.t3_svd.dense_ttsvd(T, min_ranks = None, max_ranks = None, rtol = None, atol = None) .. code-block:: python def dense_ttsvd( T: common.NDArray, # shape=(N0,...,N(d-1)) min_ranks: typ.Sequence[int] = None, # len=d+1 max_ranks: typ.Sequence[int] = None, # len=d+1 rtol: float = None, atol: float = None, ) -> typ.Tuple[ typ.Tuple[common.NDArray,...], # tt_cores typ.Tuple[common.NDArray,...], # singular values of unfoldings ]: Compute tensor train (TT) decomposition and unfolding singular values for dense tensor. :param T: The dense tensor. shape=(N1, ..., Nd) :type T: NDArray :param min_ranks: Minimum TT-ranks for truncation. len=d+1. e.g., (1,3,3,3,1) :type min_ranks: typ.Sequence[int] :param max_ranks: Maximum TT-ranks for truncation. len=d+1. e.g., (1,5,5,5,1) :type max_ranks: typ.Sequence[int] :param rtol: Relative tolerance for truncation. :type rtol: float :param atol: Absolute tolerance for truncation. :type atol: float :param xnp: Linear algebra backend. Default: np (numpy) :returns: * *typ.Tuple[NDArray,...]* -- TT cores. len=d. elm_shape=(ri, ni, r(i+1)) * *typ.Tuple[NDArray,...]* -- Singular values of unfoldings. len=d+1. elm_shape=(ri,) .. seealso:: :py:obj:`truncated_svd`, :py:obj:`dense_tucker_svd`, :py:obj:`t3_svd_dense`, :py:obj:`t3_svd` .. rubric:: Examples No truncation -- a lossless TT decomposition. The cores reconstruct ``T``; there are ``d`` cores and ``d+1`` singular-value vectors (the two boundary entries are both just ``||T||``): >>> import numpy as np >>> import t3toolbox.backend.t3_svd as t3_svd >>> np.random.seed(0) >>> T = np.random.randn(5, 6, 7) >>> cores, ss = t3_svd.dense_ttsvd(T) >>> print([G.shape for G in cores]) # cores[i].shape = (ri, ni, r(i+1)) [(1, 5, 5), (5, 6, 7), (7, 7, 1)] >>> T2 = np.einsum('aib,bjc,ckd->ijk', cores[0], cores[1], cores[2]) >>> print(np.allclose(T, T2)) # exact reconstruction True >>> print(len(ss), np.allclose(ss[0], np.linalg.norm(T)), np.allclose(ss[-1], np.linalg.norm(T))) 4 True True The internal singular values ARE the singular values of the matrix unfoldings (shown for the first unfolding; the others are analogous): >>> import numpy as np >>> import t3toolbox.backend.t3_svd as t3_svd >>> np.random.seed(0) >>> T = np.random.randn(5, 6, 7) >>> _, ss = t3_svd.dense_ttsvd(T) >>> dense_svals = np.linalg.svd(T.reshape(5, 6 * 7), compute_uv=False) # first unfolding >>> print(np.allclose(ss[1], dense_svals[:len(ss[1])])) True Truncation -- a smooth tensor has gradually decaying unfolding spectra, so ``rtol`` truncates meaningfully (a sharp random spectrum would not): >>> import numpy as np >>> import t3toolbox.backend.t3_svd as t3_svd >>> i, j, k = np.ogrid[1:9, 1:9, 1:9] >>> T = 1.0 / (i + j + k) # graded-spectrum tensor >>> cores_f, ss_full = t3_svd.dense_ttsvd(T) # full (untruncated) spectra >>> cores, ss = t3_svd.dense_ttsvd(T, rtol=1e-3) # truncate at rtol >>> full_ranks = tuple(G.shape[0] for G in cores_f) + (1,) >>> tt_ranks = tuple(G.shape[0] for G in cores) + (1,) >>> print(full_ranks, '->', tt_ranks) (1, 8, 8, 1) -> (1, 3, 3, 1) >>> T2 = np.einsum('aib,bjc,ckd->ijk', cores[0], cores[1], cores[2]) >>> dropped_sq = sum(float(np.sum(s[r:]**2)) for s, r in zip(ss_full[1:-1], tt_ranks[1:-1])) >>> print(bool(np.linalg.norm(T - T2) <= np.sqrt(dropped_sq))) # accuracy bound [Oseledets] True