def solve(a, b, overwrite_a=False, overwrite_b=False): """ Solve a linear system ``a x = b`` Parameters ---------- a : (N, N) array_like left-hand-side matrix b : (N, NRHS) array_like right-hand-side matrix overwrite_a : bool, optional whether we are allowed to overwrite the matrix `a` overwrite_b : bool, optional whether we are allowed to overwrite the matrix `b` Returns ------- x : (N, NRHS) ndarray solution matrix """ a1 = atleast_2d(_asarray_validated(a, check_finite=False)) b1 = atleast_1d(_asarray_validated(b, check_finite=False)) n = a1.shape[0] overwrite_a = overwrite_a or _datacopied(a1, a) overwrite_b = overwrite_b or _datacopied(b1, b) if a1.shape[0] != a1.shape[1]: raise ValueError('LHS needs to be a square matrix.') if n != b1.shape[0]: # Last chance to catch 1x1 scalar a and 1D b arrays if not (n == 1 and b1.size != 0): raise ValueError('Input b has to have same number of rows as ' 'input a') # regularize 1D b arrays to 2D if b1.ndim == 1: if n == 1: b1 = b1[None, :] else: b1 = b1[:, None] b_is_1D = True else: b_is_1D = False gesv = get_lapack_funcs('gesv', (a1, b1)) _, _, x, info = gesv(a1, b1, overwrite_a=overwrite_a, overwrite_b=overwrite_b) if info > 0: raise LinAlgError("Singular matrix") if info < 0: raise ValueError('illegal value in %d-th argument of internal ' 'gesv' % -info) if b_is_1D: return x.ravel() return x
def inv(a, overwrite_a=False): """ Inverts a matrix Parameters ---------- a : (N, N) array_like the matrix to be inverted. overwrite_a : bool, optional whether we are allowed to overwrite the matrix `a` Returns ------- x : (N, N) ndarray The inverted matrix """ a1 = atleast_2d(_asarray_validated(a, check_finite=False)) overwrite_a = overwrite_a or _datacopied(a1, a) if a1.shape[0] != a1.shape[1]: raise ValueError('Input a needs to be a square matrix.') getrf, getri, getri_lwork = get_lapack_funcs( ('getrf', 'getri', 'getri_lwork'), (a1, )) lu, piv, info = getrf(a1, overwrite_a=overwrite_a) if info == 0: lwork = _compute_lwork(getri_lwork, a1.shape[0]) lwork = int(1.01 * lwork) x, info = getri(lu, piv, lwork=lwork, overwrite_lu=True) if info > 0: raise LinAlgError("Singular matrix") if info < 0: raise ValueError('illegal value in %d-th argument of internal ' 'getrf|getri' % -info) return x
def generalized_schur(a, b, output='real', lwork=None, overwrite_a=False, overwrite_b=False, sort=None, check_finite=True): if output not in ['real', 'complex', 'r', 'c']: raise ValueError("argument must be 'real', or 'complex'") if check_finite: a1 = numpy.asarray_chkfinite(a) b1 = numpy.asarray_chkfinite(b) else: a1 = numpy.asarray(a) b1 = numpy.asarray(b) if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]) or \ len(b1.shape) != 2 or (b1.shape[0] != b1.shape[1]): raise ValueError('expected square matrix') typ = a1.dtype.char if output in ['complex', 'c'] and typ not in ['F', 'D']: if typ in _double_precision: a1 = a1.astype('D') b1 = b1.astype('D') typ = 'D' else: a1 = a1.astype('F') b1 = b1.astype('F') typ = 'F' overwrite_a = overwrite_a or (_datacopied(a1, a)) overwrite_b = overwrite_b or (_datacopied(b1, b)) gges, = scipy.linalg.get_lapack_funcs(('gges', ), ( a1, b1, )) if lwork is None or lwork == -1: # get optimal work array result = gges(lambda x: None, a1, b1, lwork=-1) lwork = result[-2][0].real.astype(numpy.int_) if sort is None: sort_t = 0 sfunction = lambda x: None else: sort_t = 1 if callable(sort): sfunction = sort elif sort == 'lhp': sfunction = lambda x: (x.real < 0.0) elif sort == 'rhp': sfunction = lambda x: (x.real >= 0.0) elif sort == 'iuc': sfunction = lambda x: (abs(x) <= 1.0) elif sort == 'ouc': sfunction = lambda x: (abs(x) > 1.0) else: raise ValueError("'sort' parameter must either be 'None', or a " "callable, or one of ('lhp','rhp','iuc','ouc')") result = gges(sfunction, a1, b1, lwork=lwork, overwrite_a=overwrite_a, overwrite_b=overwrite_b, sort_t=sort_t) info = result[-1] if info < 0: raise ValueError('illegal value in {}-th argument of internal gges' ''.format(-info)) elif info == a1.shape[0] + 1: raise scipy.linalg.LinAlgError( 'Eigenvalues could not be separated for reordering.') elif info == a1.shape[0] + 2: raise scipy.linalg.LinAlgError( 'Leading eigenvalues do not satisfy sort condition.') elif info > 0: raise scipy.linalg.LinAlgError( "Schur form not found. Possibly ill-conditioned.") if sort_t == 0: return result[0], result[1], result[-4], result[-3] else: return result[0], result[1], result[-4], result[-3], result[2]
def svd(a, full_matrices=True, compute_uv=True, overwrite_a=False, check_finite=True, lapack_driver='gesdd'): """ Singular Value Decomposition. Factorizes the matrix `a` into two unitary matrices ``U`` and ``Vh``, and a 1-D array ``s`` of singular values (real, non-negative) such that ``a == U @ S @ Vh``, where ``S`` is a suitably shaped matrix of zeros with main diagonal ``s``. Parameters ---------- a : (M, N) array_like Matrix to decompose. full_matrices : bool, optional If True (default), `U` and `Vh` are of shape ``(M, M)``, ``(N, N)``. If False, the shapes are ``(M, K)`` and ``(K, N)``, where ``K = min(M, N)``. compute_uv : bool, optional Whether to compute also ``U`` and ``Vh`` in addition to ``s``. Default is True. overwrite_a : bool, optional Whether to overwrite `a`; may improve performance. Default is False. check_finite : bool, optional Whether to check that the input matrix contains only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. lapack_driver : {'gesdd', 'gesvd'}, optional Whether to use the more efficient divide-and-conquer approach (``'gesdd'``) or general rectangular approach (``'gesvd'``) to compute the SVD. MATLAB and Octave use the ``'gesvd'`` approach. Default is ``'gesdd'``. .. versionadded:: 0.18 Returns ------- U : ndarray Unitary matrix having left singular vectors as columns. Of shape ``(M, M)`` or ``(M, K)``, depending on `full_matrices`. s : ndarray The singular values, sorted in non-increasing order. Of shape (K,), with ``K = min(M, N)``. Vh : ndarray Unitary matrix having right singular vectors as rows. Of shape ``(N, N)`` or ``(K, N)`` depending on `full_matrices`. For ``compute_uv=False``, only ``s`` is returned. Raises ------ LinAlgError If SVD computation does not converge. See also -------- svdvals : Compute singular values of a matrix. diagsvd : Construct the Sigma matrix, given the vector s. Examples -------- >>> from scipy import linalg >>> m, n = 9, 6 >>> a = np.random.randn(m, n) + 1.j*np.random.randn(m, n) >>> U, s, Vh = linalg.svd(a) >>> U.shape, s.shape, Vh.shape ((9, 9), (6,), (6, 6)) Reconstruct the original matrix from the decomposition: >>> sigma = np.zeros((m, n)) >>> for i in range(min(m, n)): ... sigma[i, i] = s[i] >>> a1 = np.dot(U, np.dot(sigma, Vh)) >>> np.allclose(a, a1) True Alternatively, use ``full_matrices=False`` (notice that the shape of ``U`` is then ``(m, n)`` instead of ``(m, m)``): >>> U, s, Vh = linalg.svd(a, full_matrices=False) >>> U.shape, s.shape, Vh.shape ((9, 6), (6,), (6, 6)) >>> S = np.diag(s) >>> np.allclose(a, np.dot(U, np.dot(S, Vh))) True >>> s2 = linalg.svd(a, compute_uv=False) >>> np.allclose(s, s2) True """ a1 = _asarray_validated(a, check_finite=check_finite) if len(a1.shape) != 2: raise ValueError('expected matrix') m, n = a1.shape overwrite_a = overwrite_a or (_datacopied(a1, a)) if not isinstance(lapack_driver, string_types): raise TypeError('lapack_driver must be a string') if lapack_driver not in ('gesdd', 'gesvd'): raise ValueError('lapack_driver must be "gesdd" or "gesvd", not "%s"' % (lapack_driver, )) funcs = (lapack_driver, lapack_driver + '_lwork') gesXd, gesXd_lwork = get_lapack_funcs(funcs, (a1, )) # compute optimal lwork lwork = _compute_lwork(gesXd_lwork, a1.shape[0], a1.shape[1], compute_uv=compute_uv, full_matrices=full_matrices) # perform decomposition u, s, v, info = gesXd(a1, compute_uv=compute_uv, lwork=lwork, full_matrices=full_matrices, overwrite_a=overwrite_a) if info > 0: raise LinAlgError("SVD did not converge") if info < 0: raise ValueError('illegal value in %d-th argument of internal gesdd' % -info) if compute_uv: return u, s, v else: return s
def lstsq(a, b, cond=None, overwrite_a=False, overwrite_b=False, check_finite=True, lapack_driver=None): """ Compute least-squares solution to equation Ax = b. Compute a vector x such that the 2-norm ``|b - A x|`` is minimized. This code was adapted from the Scipy distribution: https://github.com/scipy/scipy/blob/v1.2.1/scipy/linalg/basic.py#L1047-L1264 Parameters ---------- a : (M, N) array_like Left hand side matrix (2-D array). b : (M,) or (M, K) array_like Right hand side matrix or vector (1-D or 2-D array). cond : float, optional Cutoff for 'small' singular values; used to determine effective rank of a. Singular values smaller than ``rcond * largest_singular_value`` are considered zero. overwrite_a : bool, optional Discard data in `a` (may enhance performance). Default is False. overwrite_b : bool, optional Discard data in `b` (may enhance performance). Default is False. check_finite : bool, optional Whether to check that the input matrices contain only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. lapack_driver : str, optional Which LAPACK driver is used to solve the least-squares problem. Options are ``'gelsd'``, ``'gelsy'``, ``'gelss'``. Default (``'gelsd'``) is a good choice. However, ``'gelsy'`` can be slightly faster on many problems. ``'gelss'`` was used historically. It is generally slow but uses less memory. .. versionadded:: 0.17.0 Returns ------- x : (N,) or (N, K) ndarray Least-squares solution. Return shape matches shape of `b`. residues : (0,) or () or (K,) ndarray Sums of residues, squared 2-norm for each column in ``b - a x``. If rank of matrix a is ``< N`` or ``N > M``, or ``'gelsy'`` is used, this is a length zero array. If b was 1-D, this is a () shape array (numpy scalar), otherwise the shape is (K,). rank : int Effective rank of matrix `a`. s : (min(M,N),) ndarray or None Singular values of `a`. The condition number of a is ``abs(s[0] / s[-1])``. None is returned when ``'gelsy'`` is used. Raises ------ LinAlgError If computation does not converge. ValueError When parameters are wrong. See Also -------- optimize.nnls : linear least squares with non-negativity constraint Examples -------- >>> from scipy.linalg import lstsq >>> import matplotlib.pyplot as plt Suppose we have the following data: >>> x = np.array([1, 2.5, 3.5, 4, 5, 7, 8.5]) >>> y = np.array([0.3, 1.1, 1.5, 2.0, 3.2, 6.6, 8.6]) We want to fit a quadratic polynomial of the form ``y = a + b*x**2`` to this data. We first form the "design matrix" M, with a constant column of 1s and a column containing ``x**2``: >>> M = x[:, np.newaxis]**[0, 2] >>> M array([[ 1. , 1. ], [ 1. , 6.25], [ 1. , 12.25], [ 1. , 16. ], [ 1. , 25. ], [ 1. , 49. ], [ 1. , 72.25]]) We want to find the least-squares solution to ``M.dot(p) = y``, where ``p`` is a vector with length 2 that holds the parameters ``a`` and ``b``. >>> p, res, rnk, s = lstsq(M, y) >>> p array([ 0.20925829, 0.12013861]) Plot the data and the fitted curve. >>> plt.plot(x, y, 'o', label='data') >>> xx = np.linspace(0, 9, 101) >>> yy = p[0] + p[1]*xx**2 >>> plt.plot(xx, yy, label='least squares fit, $y = a + bx^2$') >>> plt.xlabel('x') >>> plt.ylabel('y') >>> plt.legend(framealpha=1, shadow=True) >>> plt.grid(alpha=0.25) >>> plt.show() """ a1 = _asarray_validated(a, check_finite=check_finite) b1 = _asarray_validated(b, check_finite=check_finite) if len(a1.shape) != 2: raise ValueError('expected matrix') m, n = a1.shape if len(b1.shape) == 2: nrhs = b1.shape[1] else: nrhs = 1 if m != b1.shape[0]: raise ValueError('incompatible dimensions') if m == 0 or n == 0: # Zero-sized problem, confuses LAPACK x = np.zeros((n, ) + b1.shape[1:], dtype=np.common_type(a1, b1)) if n == 0: residues = np.linalg.norm(b1, axis=0)**2 else: residues = np.empty((0, )) return x, residues, 0, np.empty((0, )) driver = lapack_driver if driver is None: global default_lapack_driver driver = default_lapack_driver if driver not in ('gelsd', 'gelsy', 'gelss'): raise ValueError('LAPACK driver "%s" is not found' % driver) lapack_func, lapack_lwork = get_lapack_funcs( (driver, '%s_lwork' % driver), (a1, b1)) real_data = True if (lapack_func.dtype.kind == 'f') else False if m < n: # need to extend b matrix as it will be filled with # a larger solution matrix if len(b1.shape) == 2: b2 = np.zeros((n, nrhs), dtype=lapack_func.dtype) b2[:m, :] = b1 else: b2 = np.zeros(n, dtype=lapack_func.dtype) b2[:m] = b1 b1 = b2 overwrite_a = overwrite_a or _datacopied(a1, a) overwrite_b = overwrite_b or _datacopied(b1, b) if cond is None: cond = np.finfo(lapack_func.dtype).eps a1_wrk = np.copy(a1) b1_wrk = np.copy(b1) lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond) x_check, s_check, rank_check, info = lapack_func( a1_wrk, b1_wrk, lwork, iwork, cond, False, False) driver = 'gelss' if driver in ('gelss', 'gelsd'): if driver == 'gelss': if not context: a1_wrk = np.copy(a1) b1_wrk = np.copy(b1) lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond) x, s, rank, info = lapack_func(a1_wrk, b1_wrk, lwork, iwork, cond, False, False) else: try: # Check that we aren't dealing with an underconstrained problem ... if m < n: pkg.log.error( Exception( "Underconstrained problems not yet supported by Magma." )) # Initialize a1_trans = np.copy(a1, order='F') a1_gpu = gpuarray.to_gpu(a1_trans) # Note that the result for 'x' gets written to the vector inputted for b x_trans = np.copy(b1, order='F') x_gpu = gpuarray.to_gpu(x_trans) # Init singular-value decomposition (SVD) output & buffer arrays s = np.zeros(min(m, n), np.float32) u = np.zeros((m, m), np.float32) vh = np.zeros((n, n), np.float32) # Query and allocate optimal workspace # n.b.: - the result for 'x' gets written to the input vector for b, so we just label b->x # - assume magma variables lda=ldb=m throughout here lwork_SVD = magma.magma_sgesvd_buffersize( 'A', 'A', m, n, a1_trans.ctypes.data, m, s.ctypes.data, u.ctypes.data, m, vh.ctypes.data, n) # For some reason, magma_sgels_buffersize() does not return the right value for large problems, so # we compute the values used for the validation check (see Magma SGELS documentation) directly and use that #lwork_LS = magma.magma_sgels_buffersize('n', m, n, nrhs, a1_trans.ctypes.data, m, x_trans.ctypes.data, m) nb = magma.magma_get_sgeqrf_nb(m, n) check = (m - n + nb) * (nrhs + nb) + nrhs * nb lwork_LS = check # Allocate workspaces hwork_SVD = np.zeros(lwork_SVD, np.float32, order='F') hwork_LS = np.zeros(lwork_LS, np.float32) # Compute SVD timer.start("SVD") magma.magma_sgesvd('A', 'A', m, n, a1_trans.ctypes.data, m, s.ctypes.data, u.ctypes.data, m, vh.ctypes.data, n, hwork_SVD.ctypes.data, lwork_SVD) timer.stop("SVD") # Note, the use of s_i>rcond here; this is meant to select # values that are effectively non-zero. Results will depend # somewhat on the choice for this value. This criterion was # adopted from that utilized by scipy.linalg.basic.lstsq() rcond = np.finfo(lapack_func.dtype).eps * s[0] rank = sum(1 for s_i in s if s_i > rcond) # Run LS solver timer.start("LS") magma.magma_sgels_gpu('n', m, n, nrhs, a1_gpu.gpudata, m, x_gpu.gpudata, m, hwork_LS.ctypes.data, lwork_LS) timer.stop("LS") # Unload result from GPU x = x_gpu.get() except magma.MagmaError as e: info = e._status else: info = 0 elif driver == 'gelsd': if real_data: if not context: raise Exception( "For some reason, the CUDA implementation of fit() is being called when context is False." ) else: raise Exception( "gelsd not supported using Cuda yet") else: # complex data raise LinAlgError( "driver=%s not yet supported for complex data" % (driver)) if info > 0: raise LinAlgError( "SVD did not converge in Linear Least Squares") if info < 0: raise ValueError( 'illegal value in %d-th argument of internal %s' % (-info, lapack_driver)) resids = np.asarray([], dtype=x.dtype) if m > n: x1 = x[:n] if rank == n: resids = np.sum(np.abs(x[n:])**2, axis=0) x = x1 elif driver == 'gelsy': raise LinAlgError("driver=%s not yet supported" % (driver)) #pkg.log.close("Done", time_elapsed=True) return x, resids, rank, s
def tri_inv(c, lower=False, unit_diagonal=False, overwrite_c=False, check_finite=True): """ Compute the inverse of a triangular matrix. Parameters ---------- c : array_like A triangular matrix to be inverted lower : bool, optional Use only data contained in the lower triangle of `c`. Default is to use upper triangle. unit_diagonal : bool, optional If True, diagonal elements of `c` are assumed to be 1 and will not be referenced. overwrite_c : bool, optional Allow overwriting data in `c` (may improve performance). check_finite : bool, optional Whether to check that the input matrix contains only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Returns ------- inv_c : ndarray Inverse of the matrix `c`. Raises ------ LinAlgError If `c` is singular ValueError If `c` is not square, or not 2-dimensional. Examples -------- >>> c = numpy.array([(1., 2.), (0., 4.)]) >>> tri_inv(c) array([[ 1. , -0.5 ], [ 0. , 0.25]]) >>> numpy.dot(c, tri_inv(c)) array([[ 1., 0.], [ 0., 1.]]) """ if check_finite: c1 = numpy.asarray_chkfinite(c) else: c1 = numpy.asarray(c) if len(c1.shape) != 2 or c1.shape[0] != c1.shape[1]: raise ValueError('expected square matrix') overwrite_c = overwrite_c or _datacopied(c1, c) trtri, = get_lapack_funcs(('trtri',), (c1,)) inv_c, info = trtri(c1, overwrite_c=overwrite_c, lower=lower, unitdiag=unit_diagonal) if info > 0: raise LinAlgError("singular matrix") if info < 0: raise ValueError("illegal value in %d-th argument of internal trtri" % -info) return inv_c
def svd(a, full_matrices=True, compute_uv=True, overwrite_a=False, check_finite=True, returns="U, S, V"): """ Singular Value Decomposition. Factorizes the matrix a into two unitary matrices U and Vh, and a diagonal matrix S of suitable shape with non-negative real numbers on the diagonal. . Parameters ---------- a : (M, N) array_like Matrix to decompose. full_matrices : bool, optional If True, `U` and `Vh` are of shape ``(M,M)``, ``(N,N)``. If False, the shapes are ``(M,K)`` and ``(K,N)``, where ``K = min(M,N)``. overwrite_a : bool, optional Whether to overwrite `a`; may improve performance. Default is False. check_finite : boolean, optional Whether to check that the input matrix contains only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. returns: string, optional Select the returned values, among ``U``, ``S``, ``s``, ``V`` and ``Vh``,. Default is ``"U, S, Vh"``. Returns ------- The selection of return values is configurable by the ``returns`` parameter. U : ndarray Unitary matrix having left singular vectors as columns. Of shape ``(M,M)`` or ``(M,K)``, depending on `full_matrices`. S : ndarray A matrix with the singular values of ``a``, sorted in non-increasing order, in the main diagonal and zeros elsewhere. Of shape ``(M,N)`` or ``(K,K)``, depending on `full_matrices`. V : ndarray Unitary matrix having right singular vectors as columns. Of shape ``(N,N)`` or ``(N, K)`` depending on `full_matrices`. s : ndarray, not returned by default The singular values, sorted in non-increasing order. Of shape (K,), with ``K = min(M, N)``. Vh : ndarray Unitary matrix having right singular vectors as rows. Of shape ``(N,N)`` or ``(N, K)`` depending on `full_matrices`. Raises ------ LinAlgError If SVD computation does not converge. Examples -------- >>> import numpy as np >>> from wish.examples import svd >>> a = np.random.randn(9, 6) + 1.j*np.random.randn(9, 6) >>> U, S, V = svd(a) >>> U.shape, S.shape, V.shape ((9, 9), (9, 6), (6, 6)) >>> U, S, Vh = svd(a, full_matrices=False, returns="U, S, Vh") >>> U.shape, S.shape, Vh.shape ((9, 9), (9, 6), (6, 6)) >>> np.allclose(a, np.dot(U, np.dot(S, Vh))) True >>> s = svd(a, returns="s") >>> np.allclose(s, np.diagonal(S)) True """ wishlist = wish.make(returns) for name in wishlist: if name not in ["U", "S", "V", "s", "Vh"]: error = "unexpected return value {name!r}" raise TypeError(error.format(name=name)) if check_finite: a1 = asarray_chkfinite(a) else: a1 = asarray(a) if len(a1.shape) != 2: raise ValueError('expected matrix') m,n = a1.shape overwrite_a = overwrite_a or (_datacopied(a1, a)) gesdd, = get_lapack_funcs(('gesdd',), (a1,)) lwork = calc_lwork.gesdd(gesdd.typecode, m, n, compute_uv)[1] compute_uv = "U" in wishlist or "V" in wishlist or "Vh" in wishlist U,s,Vh,info = gesdd(a1,compute_uv=compute_uv, lwork=lwork, full_matrices=full_matrices, overwrite_a=overwrite_a) if info > 0: raise LinAlgError("SVD did not converge") if info < 0: raise ValueError('illegal value in %d-th argument of internal gesdd' % -info) if "V" in wishlist: V = Vh.transpose().conjugate() if "S" in wishlist: S = _diagsvd(s, U.shape[1], Vh.shape[0]) # f**k, maybe not computed. Use shape of A. # Interaction with full_matrices? return wishlist.grant()
def svd(a, full_matrices=True, compute_uv=True, overwrite_a=False, check_finite=True): """ Singular Value Decomposition. Factorizes the matrix a into two unitary matrices U and Vh, and a 1-D array s of singular values (real, non-negative) such that ``a == U*S*Vh``, where S is a suitably shaped matrix of zeros with main diagonal s. Parameters ---------- a : (M, N) array_like Matrix to decompose. full_matrices : bool, optional If True, `U` and `Vh` are of shape ``(M,M)``, ``(N,N)``. If False, the shapes are ``(M,K)`` and ``(K,N)``, where ``K = min(M,N)``. compute_uv : bool, optional Whether to compute also `U` and `Vh` in addition to `s`. Default is True. overwrite_a : bool, optional Whether to overwrite `a`; may improve performance. Default is False. check_finite : boolean, optional Whether to check that the input matrix contains only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Returns ------- U : ndarray Unitary matrix having left singular vectors as columns. Of shape ``(M,M)`` or ``(M,K)``, depending on `full_matrices`. s : ndarray The singular values, sorted in non-increasing order. Of shape (K,), with ``K = min(M, N)``. Vh : ndarray Unitary matrix having right singular vectors as rows. Of shape ``(N,N)`` or ``(K,N)`` depending on `full_matrices`. For ``compute_uv = False``, only `s` is returned. Raises ------ LinAlgError If SVD computation does not converge. See also -------- svdvals : Compute singular values of a matrix. diagsvd : Construct the Sigma matrix, given the vector s. Examples -------- >>> from scipy import linalg >>> a = np.random.randn(9, 6) + 1.j*np.random.randn(9, 6) >>> U, s, Vh = linalg.svd(a) >>> U.shape, Vh.shape, s.shape ((9, 9), (6, 6), (6,)) >>> U, s, Vh = linalg.svd(a, full_matrices=False) >>> U.shape, Vh.shape, s.shape ((9, 6), (6, 6), (6,)) >>> S = linalg.diagsvd(s, 6, 6) >>> np.allclose(a, np.dot(U, np.dot(S, Vh))) True >>> s2 = linalg.svd(a, compute_uv=False) >>> np.allclose(s, s2) True """ if check_finite: a1 = asarray_chkfinite(a) else: a1 = asarray(a) if len(a1.shape) != 2: raise ValueError('expected matrix') m,n = a1.shape overwrite_a = overwrite_a or (_datacopied(a1, a)) gesdd, = get_lapack_funcs(('gesdd',), (a1,)) lwork = calc_lwork.gesdd(gesdd.typecode, m, n, compute_uv)[1] u,s,v,info = gesdd(a1,compute_uv=compute_uv, lwork=lwork, full_matrices=full_matrices, overwrite_a=overwrite_a) if info > 0: raise LinAlgError("SVD did not converge") if info < 0: raise ValueError('illegal value in %d-th argument of internal gesdd' % -info) if compute_uv: return u, s, v else: return s