t3toolbox.tucker_tensor_train.t3svd =================================== .. py:function:: t3toolbox.tucker_tensor_train.t3svd(x: TuckerTensorTrain, min_tt_ranks: t3toolbox.backend.common.typ.Sequence[int] = None, min_tucker_ranks: t3toolbox.backend.common.typ.Sequence[int] = None, max_tt_ranks: t3toolbox.backend.common.typ.Sequence[int] = None, max_tucker_ranks: t3toolbox.backend.common.typ.Sequence[int] = None, rtol: float = None, atol: float = None, squash_tails_first: bool = True, use_jax: bool = False) -> t3toolbox.backend.common.typ.Tuple[TuckerTensorTrain, t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.NDArray, Ellipsis], t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.NDArray, Ellipsis]] Compute (truncated) T3-SVD of TuckerTensorTrain. :param x: The Tucker tensor train. structure=((N1,...,Nd), (n1,...,nd), (1,r1,...r(d-1),1)) :type x: TuckerTensorTrain :param min_tucker_ranks: Minimum Tucker ranks for truncation. :type min_tucker_ranks: typ.Sequence[int] :param min_tt_ranks: Minimum TT-ranks for truncation. :type min_tt_ranks: typ.Sequence[int] :param max_tucker_ranks: Maximum Tucker ranks for truncation. :type max_tucker_ranks: typ.Sequence[int] :param max_tt_ranks: Maximum TT-ranks for truncation. :type max_tt_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: * *NDArray* -- New TuckerTensorTrain representing the same tensor (or a truncated version), but with modified cores * *typ.Tuple[NDArray,...]* -- Singular values associated with edges between Tucker cores and TT-cores * *typ.Tuple[NDArray,...]* -- Singular values associated with edges between adjacent TT-cores .. seealso:: :py:obj:`left_svd_3tensor`, :py:obj:`right_svd_3tensor`, :py:obj:`outer_svd_3tensor`, :py:obj:`up_svd_ith_tucker_core`, :py:obj:`left_svd_ith_tt_core`, :py:obj:`right_svd_ith_tt_core`, :py:obj:`up_svd_ith_tt_core`, :py:obj:`down_svd_ith_tt_core`, :py:obj:`truncated_svd` .. rubric:: Examples T3-SVD with no truncation: (ranks may decrease to minimal values, but no approximation error) >>> import numpy as np >>> import t3toolbox.tucker_tensor_train as t3 >>> x = t3.t3_corewise_randn((5,6,3), (4,4,3), (1,3,2,1)) >>> x2, ss_tucker, ss_tt = t3.t3svd(x) # Compute T3-SVD >>> x_dense = x.to_dense() >>> x2_dense = x2.to_dense() >>> print(np.linalg.norm(x_dense - x2_dense)) # Tensor unchanged 7.556835759880194e-13 >>> ss_tt1 = np.linalg.svd(x_dense.reshape((5, 6*3)))[1] # Singular values of unfolding 1 >>> print(ss_tt1); print(ss_tt[1]) [1.75326490e+02 3.41363029e+01 9.31164204e+00 1.33610061e-14 4.11601708e-15] [175.32648969 34.13630287 9.31164204] >>> ss_tucker2 = np.linalg.svd(x_dense.transpose([2,0,1]).reshape((3,5*6)))[1] # Singular values of matricization 2 >>> print(ss_tucker2); print(ss_tucker[2]) [1.71350937e+02 5.12857505e+01 1.36927051e-14] [171.35093708 51.28575045] T3-SVD with truncation based on relative tolerance: >>> import numpy as np >>> import t3toolbox.tucker_tensor_train as t3 >>> B0 = np.random.randn(35,40) @ np.diag(1.0 / np.arange(1, 41)**2) # preconditioned indices >>> B1 = np.random.randn(45,50) @ np.diag(1.0 / np.arange(1, 51)**2) >>> B2 = np.random.randn(55,60) @ np.diag(1.0 / np.arange(1, 61)**2) >>> G0 = np.random.randn(1,35,30) >>> G1 = np.random.randn(30,45,40) >>> G2 = np.random.randn(40,55,1) >>> tucker_cores_x = (B0, B1, B2) >>> tt_cores_x = (G0, G1, G2) >>> x = t3.TuckerTensorTrain(tucker_cores_x, tt_cores_x) # Tensor has spectral decay due to preconditioning >>> x2, ss_tucker, ss_tt = t3.t3svd(x, rtol=1e-2) # Truncate singular values to reduce rank >>> print(x.uniform_structure) ((40, 50, 60), (35, 45, 55), (1, 30, 40, 1), ()) >>> print(x2.uniform_structure) ((40, 50, 60), (6, 6, 5), (1, 6, 5, 1), ()) >>> x_dense = x.to_dense() >>> x2_dense = x2.to_dense() >>> print(np.linalg.norm(x_dense - x2_dense)/np.linalg.norm(x_dense)) # Should be near rtol=1e-2 0.01919726997372989 T3-SVD with truncation based on absolute tolerance: >>> import numpy as np >>> import t3toolbox.tucker_tensor_train as t3 >>> x = t3.t3_corewise_randn((14,15,16), (10,11,12), (1,8,9,1)) >>> x2, ss_tucker, ss_tt = t3.t3svd(x, max_tucker_ranks=(3,3,3), max_tt_ranks=(1,2,2,1)) # Truncate based on ranks >>> print(x.uniform_structure) ((14, 15, 16), (10, 11, 12), (1, 8, 9, 1), ()) >>> print(x2.uniform_structure) ((14, 15, 16), (3, 3, 2), (1, 2, 2, 1), ()) Example where first and last ranks are not ones: >>> import numpy as np >>> import t3toolbox.tucker_tensor_train as t3 >>> x = t3.t3_corewise_randn((5,6,3), (4,4,3), (2,3,2,2)) >>> x2, ss_tucker, ss_tt = t3.t3svd(x, squash_tails_first=False) # Compute T3-SVD >>> x_dense = x.to_dense(squash_tails=False) >>> x2_dense = x2.to_dense(squash_tails=False) >>> print(np.linalg.norm(x_dense - x2_dense)) # Tensor unchanged 5.486408687260824e-13 >>> ss_tt0 = np.linalg.svd(x_dense.reshape((2,5*6*3*2)))[1] # Singular values of leading unfolding >>> print(ss_tt0); print(ss_tt[0]) [303.0474449 88.85034392] [303.0474449 88.85034392] >>> ss_tt3 = np.linalg.svd(x_dense.reshape((2*5*6*3,2)))[1] # Singular values of trailing unfolding >>> print(ss_tt3); print(ss_tt[3]) [299.45433768 100.29574828] [299.45433768 100.29574828]