nlcpy.linalg.svd

nlcpy.linalg.svd(a, full_matrices=True, compute_uv=True, hermitian=False)[source]

Singular Value Decomposition.

When a is a 2D array, it is factorized as u @ nlcpy.diag(s) @ vh = (u * s) @ vh, where u and vh are 2D unitary arrays and s is a 1D array of a’s singular values. When a is higher-dimensional, SVD is applied in stacked mode as explained below.

Parameters
a(…, M, N) array_like

A real or complex array with a.ndim >= 2.

full_matricesbool, optional

If True (default), u and vh have the shapes (..., M, M) and (..., N, N), respectively. Otherwise, the shapes are (..., M, K) and (..., K, N), respectively, where K = min(M, N).

compute_uvbool, optional

Whether or not to compute u and vh in addition to s. True by default.

hermitianbool, optional

If True, a is assumed to be Hermitian (symmetric if real-valued), enabling a more efficient method for finding singular values. Defaults to False.

Returns
u{(…, M, M), (…, M, K)} ndarray

Unitary array(s). The first a.ndim - 2 dimensions have the same size as those of the input a. The size of the last two dimensions depends on the value of full_matrices. Only returned when compute_uv is True.

s(…, K) ndarray

Vector(s) with the singular values, within each vector sorted in descending order. The first a.ndim - 2 dimensions have the same size as those of the input a.

vh{(…, N, N), (…, K, N)} ndarray

Unitary array(s). The first a.ndim - 2 dimensions have the same size as those of the input a. The size of the last two dimensions depends on the value of full_matrices. Only returned when compute_uv is True.

Note

The decomposition is performed using LAPACK routine _gesdd.

SVD is usually described for the factorization of a 2D matrix A. The higher-dimensional case will be discussed below. In the 2D case, SVD is written as A=USV^{H}, where A = a, U = u, S = nlcpy.diag(s) and V^{H} = vh. The 1D array s contains the singular values of a and u and vh are unitary. The rows of vh are the eigenvectors of A^{H}A and the columns of u are the eigenvectors of AA^{H}. In both cases the corresponding (possibly non-zero) eigenvalues are given by s**2.

If a has more than two dimensions, then broadcasting rules apply, as explained in Linear algebra on several matrices at once. This means that SVD is working in “stacked” mode: it iterates over all indices of the first a.ndim - 2 dimensions and for each combination SVD is applied to the last two indices.

Examples

>>> import nlcpy as vp
>>> from nlcpy import testing
>>> a = vp.random.randn(9, 6) + 1j*vp.random.randn(9, 6)

Reconstruction based on full SVD, 2D case:

>>> u, s, vh = vp.linalg.svd(a, full_matrices=True)
>>> u.shape, s.shape, vh.shape
((9, 9), (6,), (6, 6))
>>> vp.testing.assert_allclose(a, vp.dot(u[:, :6] * s, vh))
>>> smat = vp.zeros((9, 6), dtype=complex)
>>> smat[:6, :6] = vp.diag(s)
>>> vp.testing.assert_allclose(a, vp.dot(u, vp.dot(smat, vh)))

Reconstruction based on reduced SVD, 2D case:

>>> u, s, vh = vp.linalg.svd(a, full_matrices=False)
>>> u.shape, s.shape, vh.shape
((9, 6), (6,), (6, 6))
>>> vp.testing.assert_allclose(a, vp.dot(u * s, vh))
>>> smat = vp.diag(s)
>>> vp.testing.assert_allclose(a, vp.dot(u, vp.dot(smat, vh)))