Esempio n. 1
0
File: base.py Progetto: freude/sisl
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
Esempio n. 2
0
File: base.py Progetto: freude/sisl
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
Esempio n. 3
0
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]
Esempio n. 4
0
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
Esempio n. 6
0
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
Esempio n. 7
0
File: svd.py Progetto: boisgera/wish
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()
Esempio n. 8
0
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