right_svd ========= .. py:function:: t3toolbox.backend.linalg.right_svd(G0_i_a_j, min_rank = None, max_rank = None, rtol = None, atol = None) .. code-block:: python 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 :py:func:`truncated_svd`. .. rubric:: 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