right_svd#

t3toolbox.backend.linalg.right_svd(G0_i_a_j, min_rank=None, max_rank=None, rtol=None, atol=None)#
def right_svd(
        G0_i_a_j: NDArray, # shape=(ni, na, nj)
        min_rank: int = None, # 1 <= min_rank <= max_rank <= minimum(ni*na, nj)
        max_rank: int = None, # 1 <= min_rank <= max_rank <= minimum(ni*na, nj)
        rtol: float = None, # removes singular values satisfying sigma < maximum(atol, rtol*sigma1)
        atol: float = None, # removes singular values satisfying sigma < maximum(atol, rtol*sigma1)
) -> typ.Tuple[
    NDArray, # U_i_x,       shape=(ni, nx)
    NDArray, # ss_x,        shape=(nx,)
    NDArray, # Vt_x_a_j,    shape=(nx, na, nj)
]:

Compute (truncated) singular value decomposition of 3-tensor right unfolding.

Last two indices of the tensor are grouped for the SVD: G[i,a,j] = sum_x U[i,x] ss[x] Vt[x,a,j], with Vt orthonormal in its grouped (a,j) rows. Truncation args behave as in truncated_svd().

Examples

>>> import numpy as np
>>> import t3toolbox.backend.linalg as linalg
>>> np.random.seed(0)
>>> G = np.random.randn(4, 5, 6)                      # (ni, na, nj)
>>> U, ss, Vt = linalg.right_svd(G)
>>> print(U.shape, ss.shape, Vt.shape)               # U is the 2d left factor; Vt keeps (a,j)
(4, 4) (4,) (4, 5, 6)
>>> print(np.allclose(np.einsum('ix,x,xaj->iaj', U, ss, Vt), G))   # reconstructs G
True
>>> Vm = Vt.reshape(Vt.shape[0], -1)
>>> print(np.allclose(Vm @ Vm.T, np.eye(Vm.shape[0])))   # right unfolding of Vt is orthonormal
True
Parameters:
  • G0_i_a_j (NDArray)

  • min_rank (int)

  • max_rank (int)

  • rtol (float)

  • atol (float)

Return type:

t3toolbox.backend.common.typ.Tuple[NDArray, NDArray, NDArray]