def rq(a, overwrite_a=False, lwork=None): """Compute RQ decomposition of a square real matrix. Calculate the decomposition :lm:`A = R Q` where Q is unitary/orthogonal and R upper triangular. Parameters ---------- a : array, shape (M, M) Square real matrix to be decomposed overwrite_a : boolean Whether data in a is overwritten (may improve performance) lwork : integer Work array size, lwork >= a.shape[1]. If None or -1, an optimal size is computed. econ : boolean Returns ------- R : double array, shape (M, N) or (K, N) for econ==True Size K = min(M, N) Q : double or complex array, shape (M, M) or (M, K) for econ==True Raises LinAlgError if decomposition fails """ # TODO: implement support for non-square and complex arrays a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError('expected matrix') M, N = a1.shape if M != N: raise ValueError('expected square matrix') if issubclass(a1.dtype.type, complexfloating): raise ValueError('expected real (non-complex) matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) gerqf, = get_lapack_funcs(('gerqf', ), (a1, )) if lwork is None or lwork == -1: # get optimal work array rq, tau, work, info = gerqf(a1, lwork=-1, overwrite_a=1) lwork = work[0] rq, tau, work, info = gerqf(a1, lwork=lwork, overwrite_a=overwrite_a) if info < 0: raise ValueError('illegal value in %d-th argument of internal geqrf' % -info) gemm, = get_blas_funcs(('gemm', ), (rq, )) t = rq.dtype.char R = special_matrices.triu(rq) Q = numpy.identity(M, dtype=t) ident = numpy.identity(M, dtype=t) zeros = numpy.zeros k = min(M, N) for i in range(k): v = zeros((M, ), t) v[N - k + i] = 1 v[0:N - k + i] = rq[M - k + i, 0:N - k + i] H = gemm(-tau[i], v, v, 1 + 0j, ident, trans_b=2) Q = gemm(1, Q, H) return R, Q
def rq(a, overwrite_a=False, lwork=None): """Compute RQ decomposition of a square real matrix. Calculate the decomposition :lm:`A = R Q` where Q is unitary/orthogonal and R upper triangular. Parameters ---------- a : array, shape (M, M) Square real matrix to be decomposed overwrite_a : boolean Whether data in a is overwritten (may improve performance) lwork : integer Work array size, lwork >= a.shape[1]. If None or -1, an optimal size is computed. econ : boolean Returns ------- R : double array, shape (M, N) or (K, N) for econ==True Size K = min(M, N) Q : double or complex array, shape (M, M) or (M, K) for econ==True Raises LinAlgError if decomposition fails """ # TODO: implement support for non-square and complex arrays a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError('expected matrix') M,N = a1.shape if M != N: raise ValueError('expected square matrix') if issubclass(a1.dtype.type, complexfloating): raise ValueError('expected real (non-complex) matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) gerqf, = get_lapack_funcs(('gerqf',), (a1,)) if lwork is None or lwork == -1: # get optimal work array rq, tau, work, info = gerqf(a1, lwork=-1, overwrite_a=1) lwork = work[0] rq, tau, work, info = gerqf(a1, lwork=lwork, overwrite_a=overwrite_a) if info < 0: raise ValueError('illegal value in %d-th argument of internal geqrf' % -info) gemm, = get_blas_funcs(('gemm',), (rq,)) t = rq.dtype.char R = special_matrices.triu(rq) Q = numpy.identity(M, dtype=t) ident = numpy.identity(M, dtype=t) zeros = numpy.zeros k = min(M, N) for i in range(k): v = zeros((M,), t) v[N-k+i] = 1 v[0:N-k+i] = rq[M-k+i, 0:N-k+i] H = gemm(-tau[i], v, v, 1+0j, ident, trans_b=2) Q = gemm(1, Q, H) return R, Q
def lu(a, permute_l=False, overwrite_a=False): """Compute pivoted LU decompostion of a matrix. The decomposition is:: A = P L U where P is a permutation matrix, L lower triangular with unit diagonal elements, and U upper triangular. Parameters ---------- a : array, shape (M, N) Array to decompose permute_l : boolean Perform the multiplication P*L (Default: do not permute) overwrite_a : boolean Whether to overwrite data in a (may improve performance) Returns ------- (If permute_l == False) p : array, shape (M, M) Permutation matrix l : array, shape (M, K) Lower triangular or trapezoidal matrix with unit diagonal. K = min(M, N) u : array, shape (K, N) Upper triangular or trapezoidal matrix (If permute_l == True) pl : array, shape (M, K) Permuted L matrix. K = min(M, N) u : array, shape (K, N) Upper triangular or trapezoidal matrix Notes ----- This is a LU factorization routine written for Scipy. """ a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError('expected matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) flu, = get_flinalg_funcs(('lu',), (a1,)) p, l, u, info = flu(a1, permute_l=permute_l, overwrite_a=overwrite_a) if info < 0: raise ValueError('illegal value in %d-th argument of ' 'internal lu.getrf' % -info) if permute_l: return l, u return p, l, u
def lu(a, permute_l=False, overwrite_a=False): """Compute pivoted LU decompostion of a matrix. The decomposition is:: A = P L U where P is a permutation matrix, L lower triangular with unit diagonal elements, and U upper triangular. Parameters ---------- a : array, shape (M, N) Array to decompose permute_l : boolean Perform the multiplication P*L (Default: do not permute) overwrite_a : boolean Whether to overwrite data in a (may improve performance) Returns ------- (If permute_l == False) p : array, shape (M, M) Permutation matrix l : array, shape (M, K) Lower triangular or trapezoidal matrix with unit diagonal. K = min(M, N) u : array, shape (K, N) Upper triangular or trapezoidal matrix (If permute_l == True) pl : array, shape (M, K) Permuted L matrix. K = min(M, N) u : array, shape (K, N) Upper triangular or trapezoidal matrix Notes ----- This is a LU factorization routine written for Scipy. """ a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError('expected matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) flu, = get_flinalg_funcs(('lu', ), (a1, )) p, l, u, info = flu(a1, permute_l=permute_l, overwrite_a=overwrite_a) if info < 0: raise ValueError('illegal value in %d-th argument of ' 'internal lu.getrf' % -info) if permute_l: return l, u return p, l, u
def qr_old(a, overwrite_a=False, lwork=None): """Compute QR decomposition of a matrix. Calculate the decomposition :lm:`A = Q R` where Q is unitary/orthogonal and R upper triangular. Parameters ---------- a : array, shape (M, N) Matrix to be decomposed overwrite_a : boolean Whether data in a is overwritten (may improve performance) lwork : integer Work array size, lwork >= a.shape[1]. If None or -1, an optimal size is computed. Returns ------- Q : double or complex array, shape (M, M) R : double or complex array, shape (M, N) Size K = min(M, N) Raises LinAlgError if decomposition fails """ a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError('expected matrix') M,N = a1.shape overwrite_a = overwrite_a or (_datanotshared(a1, a)) geqrf, = get_lapack_funcs(('geqrf',), (a1,)) if lwork is None or lwork == -1: # get optimal work array qr, tau, work, info = geqrf(a1, lwork=-1, overwrite_a=1) lwork = work[0] qr, tau, work, info = geqrf(a1, lwork=lwork, overwrite_a=overwrite_a) if info < 0: raise ValueError('illegal value in %d-th argument of internal geqrf' % -info) gemm, = get_blas_funcs(('gemm',), (qr,)) t = qr.dtype.char R = special_matrices.triu(qr) Q = numpy.identity(M, dtype=t) ident = numpy.identity(M, dtype=t) zeros = numpy.zeros for i in range(min(M, N)): v = zeros((M,), t) v[i] = 1 v[i+1:M] = qr[i+1:M, i] H = gemm(-tau[i], v, v, 1+0j, ident, trans_b=2) Q = gemm(1, Q, H) return Q, R
def _cholesky(a, lower=False, overwrite_a=False, clean=True): """Common code for cholesky() and cho_factor().""" a1 = asarray_chkfinite(a) if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]: raise ValueError("expected square matrix") overwrite_a = overwrite_a or _datanotshared(a1, a) potrf, = get_lapack_funcs(("potrf",), (a1,)) c, info = potrf(a1, lower=lower, overwrite_a=overwrite_a, clean=clean) if info > 0: raise LinAlgError("%d-th leading minor not positive definite" % info) if info < 0: raise ValueError("illegal value in %d-th argument of internal potrf" % -info) return c, lower
def lu_factor(a, overwrite_a=False): """Compute pivoted LU decomposition of a matrix. The decomposition is:: A = P L U where P is a permutation matrix, L lower triangular with unit diagonal elements, and U upper triangular. Parameters ---------- a : array, shape (M, M) Matrix to decompose overwrite_a : boolean Whether to overwrite data in A (may increase performance) Returns ------- lu : array, shape (N, N) Matrix containing U in its upper triangle, and L in its lower triangle. The unit diagonal elements of L are not stored. piv : array, shape (N,) Pivot indices representing the permutation matrix P: row i of matrix was interchanged with row piv[i]. See also -------- lu_solve : solve an equation system using the LU factorization of a matrix Notes ----- This is a wrapper to the *GETRF routines from LAPACK. """ a1 = asarray(a) if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]): raise ValueError('expected square matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) getrf, = get_lapack_funcs(('getrf',), (a1,)) lu, piv, info = getrf(a, overwrite_a=overwrite_a) if info < 0: raise ValueError('illegal value in %d-th argument of ' 'internal getrf (lu_factor)' % -info) if info > 0: warn("Diagonal number %d is exactly zero. Singular matrix." % info, RuntimeWarning) return lu, piv
def lu_factor(a, overwrite_a=False): """Compute pivoted LU decomposition of a matrix. The decomposition is:: A = P L U where P is a permutation matrix, L lower triangular with unit diagonal elements, and U upper triangular. Parameters ---------- a : array, shape (M, M) Matrix to decompose overwrite_a : boolean Whether to overwrite data in A (may increase performance) Returns ------- lu : array, shape (N, N) Matrix containing U in its upper triangle, and L in its lower triangle. The unit diagonal elements of L are not stored. piv : array, shape (N,) Pivot indices representing the permutation matrix P: row i of matrix was interchanged with row piv[i]. See also -------- lu_solve : solve an equation system using the LU factorization of a matrix Notes ----- This is a wrapper to the *GETRF routines from LAPACK. """ a1 = asarray(a) if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]): raise ValueError, 'expected square matrix' overwrite_a = overwrite_a or (_datanotshared(a1, a)) getrf, = get_lapack_funcs(('getrf', ), (a1, )) lu, piv, info = getrf(a, overwrite_a=overwrite_a) if info < 0: raise ValueError('illegal value in %d-th argument of ' 'internal getrf (lu_factor)' % -info) if info > 0: warn("Diagonal number %d is exactly zero. Singular matrix." % info, RuntimeWarning) return lu, piv
def _cholesky(a, lower=False, overwrite_a=False, clean=True): """Common code for cholesky() and cho_factor().""" a1 = asarray_chkfinite(a) if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]: raise ValueError('expected square matrix') overwrite_a = overwrite_a or _datanotshared(a1, a) potrf, = get_lapack_funcs(('potrf', ), (a1, )) c, info = potrf(a1, lower=lower, overwrite_a=overwrite_a, clean=clean) if info > 0: raise LinAlgError("%d-th leading minor not positive definite" % info) if info < 0: raise ValueError('illegal value in %d-th argument of internal potrf' % -info) return c, lower
def _geneig(a1, b, left, right, overwrite_a, overwrite_b): b1 = asarray(b) overwrite_b = overwrite_b or _datanotshared(b1, b) if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]: raise ValueError('expected square matrix') ggev, = get_lapack_funcs(('ggev', ), (a1, b1)) cvl, cvr = left, right if ggev.module_name[:7] == 'clapack': raise NotImplementedError('calling ggev from %s' % ggev.module_name) res = ggev(a1, b1, lwork=-1) lwork = res[-2][0] if ggev.prefix in 'cz': alpha, beta, vl, vr, work, info = ggev(a1, b1, cvl, cvr, lwork, overwrite_a, overwrite_b) w = alpha / beta else: alphar, alphai, beta, vl, vr, work, info = ggev( a1, b1, cvl, cvr, lwork, overwrite_a, overwrite_b) w = (alphar + _I * alphai) / beta if info < 0: raise ValueError('illegal value in %d-th argument of internal ggev' % -info) if info > 0: raise LinAlgError( "generalized eig algorithm did not converge (info=%d)" % info) only_real = numpy.logical_and.reduce(numpy.equal(w.imag, 0.0)) if not (ggev.prefix in 'cz' or only_real): t = w.dtype.char if left: vl = _make_complex_eigvecs(w, vl, t) if right: vr = _make_complex_eigvecs(w, vr, t) if not (left or right): return w if left: if right: return w, vl, vr return w, vl return w, vr
def _geneig(a1, b, left, right, overwrite_a, overwrite_b): b1 = asarray(b) overwrite_b = overwrite_b or _datanotshared(b1, b) if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]: raise ValueError('expected square matrix') ggev, = get_lapack_funcs(('ggev',), (a1, b1)) cvl, cvr = left, right if ggev.module_name[:7] == 'clapack': raise NotImplementedError('calling ggev from %s' % ggev.module_name) res = ggev(a1, b1, lwork=-1) lwork = res[-2][0] if ggev.prefix in 'cz': alpha, beta, vl, vr, work, info = ggev(a1, b1, cvl, cvr, lwork, overwrite_a, overwrite_b) w = alpha / beta else: alphar, alphai, beta, vl, vr, work, info = ggev(a1, b1, cvl, cvr, lwork, overwrite_a,overwrite_b) w = (alphar + _I * alphai) / beta if info < 0: raise ValueError('illegal value in %d-th argument of internal ggev' % -info) if info > 0: raise LinAlgError("generalized eig algorithm did not converge (info=%d)" % info) only_real = numpy.logical_and.reduce(numpy.equal(w.imag, 0.0)) if not (ggev.prefix in 'cz' or only_real): t = w.dtype.char if left: vl = _make_complex_eigvecs(w, vl, t) if right: vr = _make_complex_eigvecs(w, vr, t) if not (left or right): return w if left: if right: return w, vl, vr return w, vl return w, vr
def hessenberg(a, calc_q=False, overwrite_a=False): """Compute Hessenberg form of a matrix. The Hessenberg decomposition is A = Q H Q^H where Q is unitary/orthogonal and H has only zero elements below the first subdiagonal. Parameters ---------- a : array, shape (M,M) Matrix to bring into Hessenberg form calc_q : boolean Whether to compute the transformation matrix overwrite_a : boolean Whether to ovewrite data in a (may improve performance) Returns ------- H : array, shape (M,M) Hessenberg form of A (If calc_q == True) Q : array, shape (M,M) Unitary/orthogonal similarity transformation matrix s.t. A = Q H Q^H """ a1 = asarray(a) if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]): raise ValueError('expected square matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) gehrd, gebal = get_lapack_funcs(('gehrd', 'gebal'), (a1, )) ba, lo, hi, pivscale, info = gebal(a, permute=1, overwrite_a=overwrite_a) if info < 0: raise ValueError('illegal value in %d-th argument of internal gebal ' '(hessenberg)' % -info) n = len(a1) lwork = calc_lwork.gehrd(gehrd.prefix, n, lo, hi) hq, tau, info = gehrd(ba, lo=lo, hi=hi, lwork=lwork, overwrite_a=1) if info < 0: raise ValueError('illegal value in %d-th argument of internal gehrd ' '(hessenberg)' % -info) if not calc_q: for i in range(lo, hi): hq[i + 2:hi + 1, i] = 0.0 return hq # XXX: Use ORGHR routines to compute q. ger, gemm = get_blas_funcs(('ger', 'gemm'), (hq, )) typecode = hq.dtype.char q = None for i in range(lo, hi): if tau[i] == 0.0: continue v = zeros(n, dtype=typecode) v[i + 1] = 1.0 v[i + 2:hi + 1] = hq[i + 2:hi + 1, i] hq[i + 2:hi + 1, i] = 0.0 h = ger(-tau[i], v, v, a=diag(ones(n, dtype=typecode)), overwrite_a=1) if q is None: q = h else: q = gemm(1.0, q, h) if q is None: q = diag(ones(n, dtype=typecode)) return hq, q
def schur(a, output='real', lwork=None, overwrite_a=False): """Compute Schur decomposition of a matrix. The Schur decomposition is A = Z T Z^H where Z is unitary and T is either upper-triangular, or for real Schur decomposition (output='real'), quasi-upper triangular. In the quasi-triangular form, 2x2 blocks describing complex-valued eigenvalue pairs may extrude from the diagonal. Parameters ---------- a : array, shape (M, M) Matrix to decompose output : {'real', 'complex'} Construct the real or complex Schur decomposition (for real matrices). lwork : integer Work array size. If None or -1, it is automatically computed. overwrite_a : boolean Whether to overwrite data in a (may improve performance) Returns ------- T : array, shape (M, M) Schur form of A. It is real-valued for the real Schur decomposition. Z : array, shape (M, M) An unitary Schur transformation matrix for A. It is real-valued for the real Schur decomposition. See also -------- rsf2csf : Convert real Schur form to complex Schur form """ if not output in ['real','complex','r','c']: raise ValueError("argument must be 'real', or 'complex'") a1 = asarray_chkfinite(a) if len(a1.shape) != 2 or (a1.shape[0] != a1.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') typ = 'D' else: a1 = a1.astype('F') typ = 'F' overwrite_a = overwrite_a or (_datanotshared(a1, a)) gees, = get_lapack_funcs(('gees',), (a1,)) if lwork is None or lwork == -1: # get optimal work array result = gees(lambda x: None, a, lwork=-1) lwork = result[-2][0].real.astype(numpy.int) result = gees(lambda x: None, a, lwork=lwork, overwrite_a=overwrite_a) info = result[-1] if info < 0: raise ValueError('illegal value in %d-th argument of internal gees' % -info) elif info > 0: raise LinAlgError("Schur form not found. Possibly ill-conditioned.") return result[0], result[-3]
def eig(a, b=None, left=False, right=True, overwrite_a=False, overwrite_b=False): """Solve an ordinary or generalized eigenvalue problem of a square matrix. Find eigenvalues w and right or left eigenvectors of a general matrix:: a vr[:,i] = w[i] b vr[:,i] a.H vl[:,i] = w[i].conj() b.H vl[:,i] where .H is the Hermitean conjugation. Parameters ---------- a : array, shape (M, M) A complex or real matrix whose eigenvalues and eigenvectors will be computed. b : array, shape (M, M) Right-hand side matrix in a generalized eigenvalue problem. If omitted, identity matrix is assumed. left : boolean Whether to calculate and return left eigenvectors right : boolean Whether to calculate and return right eigenvectors overwrite_a : boolean Whether to overwrite data in a (may improve performance) overwrite_b : boolean Whether to overwrite data in b (may improve performance) Returns ------- w : double or complex array, shape (M,) The eigenvalues, each repeated according to its multiplicity. (if left == True) vl : double or complex array, shape (M, M) The normalized left eigenvector corresponding to the eigenvalue w[i] is the column v[:,i]. (if right == True) vr : double or complex array, shape (M, M) The normalized right eigenvector corresponding to the eigenvalue w[i] is the column vr[:,i]. Raises LinAlgError if eigenvalue computation does not converge See Also -------- eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays """ a1 = asarray_chkfinite(a) if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]: raise ValueError('expected square matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) if b is not None: b = asarray_chkfinite(b) if b.shape != a1.shape: raise ValueError('a and b must have the same shape') return _geneig(a1, b, left, right, overwrite_a, overwrite_b) geev, = get_lapack_funcs(('geev',), (a1,)) compute_vl, compute_vr = left, right if geev.module_name[:7] == 'flapack': lwork = calc_lwork.geev(geev.prefix, a1.shape[0], compute_vl, compute_vr)[1] if geev.prefix in 'cz': w, vl, vr, info = geev(a1, lwork=lwork, compute_vl=compute_vl, compute_vr=compute_vr, overwrite_a=overwrite_a) else: wr, wi, vl, vr, info = geev(a1, lwork=lwork, compute_vl=compute_vl, compute_vr=compute_vr, overwrite_a=overwrite_a) t = {'f':'F','d':'D'}[wr.dtype.char] w = wr + _I * wi else: # 'clapack' if geev.prefix in 'cz': w, vl, vr, info = geev(a1, compute_vl=compute_vl, compute_vr=compute_vr, overwrite_a=overwrite_a) else: wr, wi, vl, vr, info = geev(a1, compute_vl=compute_vl, compute_vr=compute_vr, overwrite_a=overwrite_a) t = {'f':'F','d':'D'}[wr.dtype.char] w = wr + _I * wi if info < 0: raise ValueError('illegal value in %d-th argument of internal geev' % -info) if info > 0: raise LinAlgError("eig algorithm did not converge (only eigenvalues " "with order >= %d have converged)" % info) only_real = numpy.logical_and.reduce(numpy.equal(w.imag, 0.0)) if not (geev.prefix in 'cz' or only_real): t = w.dtype.char if left: vl = _make_complex_eigvecs(w, vl, t) if right: vr = _make_complex_eigvecs(w, vr, t) if not (left or right): return w if left: if right: return w, vl, vr return w, vl return w, vr
def hessenberg(a, calc_q=False, overwrite_a=False): """Compute Hessenberg form of a matrix. The Hessenberg decomposition is A = Q H Q^H where Q is unitary/orthogonal and H has only zero elements below the first subdiagonal. Parameters ---------- a : array, shape (M,M) Matrix to bring into Hessenberg form calc_q : boolean Whether to compute the transformation matrix overwrite_a : boolean Whether to ovewrite data in a (may improve performance) Returns ------- H : array, shape (M,M) Hessenberg form of A (If calc_q == True) Q : array, shape (M,M) Unitary/orthogonal similarity transformation matrix s.t. A = Q H Q^H """ a1 = asarray(a) if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]): raise ValueError('expected square matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) gehrd,gebal = get_lapack_funcs(('gehrd','gebal'), (a1,)) ba, lo, hi, pivscale, info = gebal(a, permute=1, overwrite_a=overwrite_a) if info < 0: raise ValueError('illegal value in %d-th argument of internal gebal ' '(hessenberg)' % -info) n = len(a1) lwork = calc_lwork.gehrd(gehrd.prefix, n, lo, hi) hq, tau, info = gehrd(ba, lo=lo, hi=hi, lwork=lwork, overwrite_a=1) if info < 0: raise ValueError('illegal value in %d-th argument of internal gehrd ' '(hessenberg)' % -info) if not calc_q: for i in range(lo, hi): hq[i+2:hi+1, i] = 0.0 return hq # XXX: Use ORGHR routines to compute q. ger,gemm = get_blas_funcs(('ger','gemm'), (hq,)) typecode = hq.dtype.char q = None for i in range(lo, hi): if tau[i]==0.0: continue v = zeros(n, dtype=typecode) v[i+1] = 1.0 v[i+2:hi+1] = hq[i+2:hi+1, i] hq[i+2:hi+1, i] = 0.0 h = ger(-tau[i], v, v,a=diag(ones(n, dtype=typecode)), overwrite_a=1) if q is None: q = h else: q = gemm(1.0, q, h) if q is None: q = diag(ones(n, dtype=typecode)) return hq, q
def eig_banded(a_band, lower=False, eigvals_only=False, overwrite_a_band=False, select='a', select_range=None, max_ev = 0): """Solve real symmetric or complex hermitian band matrix eigenvalue problem. Find eigenvalues w and optionally right eigenvectors v of a:: a v[:,i] = w[i] v[:,i] v.H v = identity The matrix a is stored in ab either in lower diagonal or upper diagonal ordered form: ab[u + i - j, j] == a[i,j] (if upper form; i <= j) ab[ i - j, j] == a[i,j] (if lower form; i >= j) Example of ab (shape of a is (6,6), u=2):: upper form: * * a02 a13 a24 a35 * a01 a12 a23 a34 a45 a00 a11 a22 a33 a44 a55 lower form: a00 a11 a22 a33 a44 a55 a10 a21 a32 a43 a54 * a20 a31 a42 a53 * * Cells marked with * are not used. Parameters ---------- a_band : array, shape (M, u+1) Banded matrix whose eigenvalues to calculate lower : boolean Is the matrix in the lower form. (Default is upper form) eigvals_only : boolean Compute only the eigenvalues and no eigenvectors. (Default: calculate also eigenvectors) overwrite_a_band: Discard data in a_band (may enhance performance) select: {'a', 'v', 'i'} Which eigenvalues to calculate ====== ======================================== select calculated ====== ======================================== 'a' All eigenvalues 'v' Eigenvalues in the interval (min, max] 'i' Eigenvalues with indices min <= i <= max ====== ======================================== select_range : (min, max) Range of selected eigenvalues max_ev : integer For select=='v', maximum number of eigenvalues expected. For other values of select, has no meaning. In doubt, leave this parameter untouched. Returns ------- w : array, shape (M,) The eigenvalues, in ascending order, each repeated according to its multiplicity. v : double or complex double array, shape (M, M) The normalized eigenvector corresponding to the eigenvalue w[i] is the column v[:,i]. Raises LinAlgError if eigenvalue computation does not converge """ if eigvals_only or overwrite_a_band: a1 = asarray_chkfinite(a_band) overwrite_a_band = overwrite_a_band or (_datanotshared(a1, a_band)) else: a1 = array(a_band) if issubclass(a1.dtype.type, inexact) and not isfinite(a1).all(): raise ValueError("array must not contain infs or NaNs") overwrite_a_band = 1 if len(a1.shape) != 2: raise ValueError('expected two-dimensional array') if select.lower() not in [0, 1, 2, 'a', 'v', 'i', 'all', 'value', 'index']: raise ValueError('invalid argument for select') if select.lower() in [0, 'a', 'all']: if a1.dtype.char in 'GFD': bevd, = get_lapack_funcs(('hbevd',), (a1,)) # FIXME: implement this somewhen, for now go with builtin values # FIXME: calc optimal lwork by calling ?hbevd(lwork=-1) # or by using calc_lwork.f ??? # lwork = calc_lwork.hbevd(bevd.prefix, a1.shape[0], lower) internal_name = 'hbevd' else: # a1.dtype.char in 'fd': bevd, = get_lapack_funcs(('sbevd',), (a1,)) # FIXME: implement this somewhen, for now go with builtin values # see above # lwork = calc_lwork.sbevd(bevd.prefix, a1.shape[0], lower) internal_name = 'sbevd' w,v,info = bevd(a1, compute_v=not eigvals_only, lower=lower, overwrite_ab=overwrite_a_band) if select.lower() in [1, 2, 'i', 'v', 'index', 'value']: # calculate certain range only if select.lower() in [2, 'i', 'index']: select = 2 vl, vu, il, iu = 0.0, 0.0, min(select_range), max(select_range) if min(il, iu) < 0 or max(il, iu) >= a1.shape[1]: raise ValueError, 'select_range out of bounds' max_ev = iu - il + 1 else: # 1, 'v', 'value' select = 1 vl, vu, il, iu = min(select_range), max(select_range), 0, 0 if max_ev == 0: max_ev = a_band.shape[1] if eigvals_only: max_ev = 1 # calculate optimal abstol for dsbevx (see manpage) if a1.dtype.char in 'fF': # single precision lamch, = get_lapack_funcs(('lamch',), (array(0, dtype='f'),)) else: lamch, = get_lapack_funcs(('lamch',), (array(0, dtype='d'),)) abstol = 2 * lamch('s') if a1.dtype.char in 'GFD': bevx, = get_lapack_funcs(('hbevx',), (a1,)) internal_name = 'hbevx' else: # a1.dtype.char in 'gfd' bevx, = get_lapack_funcs(('sbevx',), (a1,)) internal_name = 'sbevx' # il+1, iu+1: translate python indexing (0 ... N-1) into Fortran # indexing (1 ... N) w, v, m, ifail, info = bevx(a1, vl, vu, il+1, iu+1, compute_v=not eigvals_only, mmax=max_ev, range=select, lower=lower, overwrite_ab=overwrite_a_band, abstol=abstol) # crop off w and v w = w[:m] if not eigvals_only: v = v[:, :m] if info < 0: raise ValueError('illegal value in %d-th argument of internal %s' % (-info, internal_name)) if info > 0: raise LinAlgError("eig algorithm did not converge") if eigvals_only: return w return w, v
def qr(a, overwrite_a=False, lwork=None, econ=None, mode='qr'): """Compute QR decomposition of a matrix. Calculate the decomposition :lm:`A = Q R` where Q is unitary/orthogonal and R upper triangular. Parameters ---------- a : array, shape (M, N) Matrix to be decomposed overwrite_a : boolean Whether data in a is overwritten (may improve performance) lwork : integer Work array size, lwork >= a.shape[1]. If None or -1, an optimal size is computed. econ : boolean Whether to compute the economy-size QR decomposition, making shapes of Q and R (M, K) and (K, N) instead of (M,M) and (M,N). K=min(M,N). Default is False. mode : {'qr', 'r'} Determines what information is to be returned: either both Q and R or only R. Returns ------- (if mode == 'qr') Q : double or complex array, shape (M, M) or (M, K) for econ==True (for any mode) R : double or complex array, shape (M, N) or (K, N) for econ==True Size K = min(M, N) Raises LinAlgError if decomposition fails Notes ----- This is an interface to the LAPACK routines dgeqrf, zgeqrf, dorgqr, and zungqr. Examples -------- >>> from scipy import random, linalg, dot >>> a = random.randn(9, 6) >>> q, r = linalg.qr(a) >>> allclose(a, dot(q, r)) True >>> q.shape, r.shape ((9, 9), (9, 6)) >>> r2 = linalg.qr(a, mode='r') >>> allclose(r, r2) >>> q3, r3 = linalg.qr(a, econ=True) >>> q3.shape, r3.shape ((9, 6), (6, 6)) """ if econ is None: econ = False else: warn( "qr econ argument will be removed after scipy 0.7. " "The economy transform will then be available through " "the mode='economic' argument.", DeprecationWarning) a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError("expected 2D array") M, N = a1.shape overwrite_a = overwrite_a or (_datanotshared(a1, a)) geqrf, = get_lapack_funcs(('geqrf', ), (a1, )) if lwork is None or lwork == -1: # get optimal work array qr, tau, work, info = geqrf(a1, lwork=-1, overwrite_a=1) lwork = work[0] qr, tau, work, info = geqrf(a1, lwork=lwork, overwrite_a=overwrite_a) if info < 0: raise ValueError("illegal value in %d-th argument of internal geqrf" % -info) if not econ or M < N: R = special_matrices.triu(qr) else: R = special_matrices.triu(qr[0:N, 0:N]) if mode == 'r': return R if find_best_lapack_type((a1,))[0] == 's' or \ find_best_lapack_type((a1,))[0] == 'd': gor_un_gqr, = get_lapack_funcs(('orgqr', ), (qr, )) else: gor_un_gqr, = get_lapack_funcs(('ungqr', ), (qr, )) if M < N: # get optimal work array Q, work, info = gor_un_gqr(qr[:, 0:M], tau, lwork=-1, overwrite_a=1) lwork = work[0] Q, work, info = gor_un_gqr(qr[:, 0:M], tau, lwork=lwork, overwrite_a=1) elif econ: # get optimal work array Q, work, info = gor_un_gqr(qr, tau, lwork=-1, overwrite_a=1) lwork = work[0] Q, work, info = gor_un_gqr(qr, tau, lwork=lwork, overwrite_a=1) else: t = qr.dtype.char qqr = numpy.empty((M, M), dtype=t) qqr[:, 0:N] = qr # get optimal work array Q, work, info = gor_un_gqr(qqr, tau, lwork=-1, overwrite_a=1) lwork = work[0] Q, work, info = gor_un_gqr(qqr, tau, lwork=lwork, overwrite_a=1) if info < 0: raise ValueError("illegal value in %d-th argument of internal gorgqr" % -info) return Q, R
def eigh(a, b=None, lower=True, eigvals_only=False, overwrite_a=False, overwrite_b=False, turbo=True, eigvals=None, type=1): """Solve an ordinary or generalized eigenvalue problem for a complex Hermitian or real symmetric matrix. Find eigenvalues w and optionally eigenvectors v of matrix a, where b is positive definite:: a v[:,i] = w[i] b v[:,i] v[i,:].conj() a v[:,i] = w[i] v[i,:].conj() b v[:,i] = 1 Parameters ---------- a : array, shape (M, M) A complex Hermitian or real symmetric matrix whose eigenvalues and eigenvectors will be computed. b : array, shape (M, M) A complex Hermitian or real symmetric definite positive matrix in. If omitted, identity matrix is assumed. lower : boolean Whether the pertinent array data is taken from the lower or upper triangle of a. (Default: lower) eigvals_only : boolean Whether to calculate only eigenvalues and no eigenvectors. (Default: both are calculated) turbo : boolean Use divide and conquer algorithm (faster but expensive in memory, only for generalized eigenvalue problem and if eigvals=None) eigvals : tuple (lo, hi) Indexes of the smallest and largest (in ascending order) eigenvalues and corresponding eigenvectors to be returned: 0 <= lo < hi <= M-1. If omitted, all eigenvalues and eigenvectors are returned. type: integer Specifies the problem type to be solved: type = 1: a v[:,i] = w[i] b v[:,i] type = 2: a b v[:,i] = w[i] v[:,i] type = 3: b a v[:,i] = w[i] v[:,i] overwrite_a : boolean Whether to overwrite data in a (may improve performance) overwrite_b : boolean Whether to overwrite data in b (may improve performance) Returns ------- w : real array, shape (N,) The N (1<=N<=M) selected eigenvalues, in ascending order, each repeated according to its multiplicity. (if eigvals_only == False) v : complex array, shape (M, N) The normalized selected eigenvector corresponding to the eigenvalue w[i] is the column v[:,i]. Normalization: type 1 and 3: v.conj() a v = w type 2: inv(v).conj() a inv(v) = w type = 1 or 2: v.conj() b v = I type = 3 : v.conj() inv(b) v = I Raises LinAlgError if eigenvalue computation does not converge, an error occurred, or b matrix is not definite positive. Note that if input matrices are not symmetric or hermitian, no error is reported but results will be wrong. See Also -------- eig : eigenvalues and right eigenvectors for non-symmetric arrays """ a1 = asarray_chkfinite(a) if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]: raise ValueError('expected square matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) if iscomplexobj(a1): cplx = True else: cplx = False if b is not None: b1 = asarray_chkfinite(b) overwrite_b = overwrite_b or _datanotshared(b1, b) if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]: raise ValueError('expected square matrix') if b1.shape != a1.shape: raise ValueError("wrong b dimensions %s, should " "be %s" % (str(b1.shape), str(a1.shape))) if iscomplexobj(b1): cplx = True else: cplx = cplx or False else: b1 = None # Set job for fortran routines _job = (eigvals_only and 'N') or 'V' # port eigenvalue range from python to fortran convention if eigvals is not None: lo, hi = eigvals if lo < 0 or hi >= a1.shape[0]: raise ValueError('The eigenvalue range specified is not valid.\n' 'Valid range is [%s,%s]' % (0, a1.shape[0]-1)) lo += 1 hi += 1 eigvals = (lo, hi) # set lower if lower: uplo = 'L' else: uplo = 'U' # fix prefix for lapack routines if cplx: pfx = 'he' else: pfx = 'sy' # Standard Eigenvalue Problem # Use '*evr' routines # FIXME: implement calculation of optimal lwork # for all lapack routines if b1 is None: (evr,) = get_lapack_funcs((pfx+'evr',), (a1,)) if eigvals is None: w, v, info = evr(a1, uplo=uplo, jobz=_job, range="A", il=1, iu=a1.shape[0], overwrite_a=overwrite_a) else: (lo, hi)= eigvals w_tot, v, info = evr(a1, uplo=uplo, jobz=_job, range="I", il=lo, iu=hi, overwrite_a=overwrite_a) w = w_tot[0:hi-lo+1] # Generalized Eigenvalue Problem else: # Use '*gvx' routines if range is specified if eigvals is not None: (gvx,) = get_lapack_funcs((pfx+'gvx',), (a1,b1)) (lo, hi) = eigvals w_tot, v, ifail, info = gvx(a1, b1, uplo=uplo, iu=hi, itype=type,jobz=_job, il=lo, overwrite_a=overwrite_a, overwrite_b=overwrite_b) w = w_tot[0:hi-lo+1] # Use '*gvd' routine if turbo is on and no eigvals are specified elif turbo: (gvd,) = get_lapack_funcs((pfx+'gvd',), (a1,b1)) v, w, info = gvd(a1, b1, uplo=uplo, itype=type, jobz=_job, overwrite_a=overwrite_a, overwrite_b=overwrite_b) # Use '*gv' routine if turbo is off and no eigvals are specified else: (gv,) = get_lapack_funcs((pfx+'gv',), (a1,b1)) v, w, info = gv(a1, b1, uplo=uplo, itype= type, jobz=_job, overwrite_a=overwrite_a, overwrite_b=overwrite_b) # Check if we had a successful exit if info == 0: if eigvals_only: return w else: return w, v elif info < 0: raise LinAlgError("illegal value in %i-th argument of internal" " fortran routine." % (-info)) elif info > 0 and b1 is None: raise LinAlgError("unrecoverable internal error.") # The algorithm failed to converge. elif info > 0 and info <= b1.shape[0]: if eigvals is not None: raise LinAlgError("the eigenvectors %s failed to" " converge." % nonzero(ifail)-1) else: raise LinAlgError("internal fortran routine failed to converge: " "%i off-diagonal elements of an " "intermediate tridiagonal form did not converge" " to zero." % info) # This occurs when b is not positive definite else: raise LinAlgError("the leading minor of order %i" " of 'b' is not positive definite. The" " factorization of 'b' could not be completed" " and no eigenvalues or eigenvectors were" " computed." % (info-b1.shape[0]))
def svd(a, full_matrices=True, compute_uv=True, overwrite_a=False): """Singular Value Decomposition. Factorizes the matrix a into two unitary matrices U and Vh and an 1d-array s of singular values (real, non-negative) such that a == U S Vh if S is an suitably shaped matrix of zeros whose main diagonal is s. Parameters ---------- a : array, shape (M, N) Matrix to decompose full_matrices : boolean If true, U, Vh are shaped (M,M), (N,N) If false, the shapes are (M,K), (K,N) where K = min(M,N) compute_uv : boolean Whether to compute also U, Vh in addition to s (Default: true) overwrite_a : boolean Whether data in a is overwritten (may improve performance) Returns ------- U: array, shape (M,M) or (M,K) depending on full_matrices s: array, shape (K,) The singular values, sorted so that s[i] >= s[i+1]. K = min(M, N) Vh: array, 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 Examples -------- >>> from scipy import random, linalg, allclose, dot >>> a = random.randn(9, 6) + 1j*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) >>> allclose(a, dot(U, dot(S, Vh))) True >>> s2 = linalg.svd(a, compute_uv=False) >>> allclose(s, s2) True See also -------- svdvals : return singular values of a matrix diagsvd : return the Sigma matrix, given the vector s """ # A hack until full_matrices == 0 support is fixed here. if full_matrices == 0: import numpy.linalg return numpy.linalg.svd(a, full_matrices=0, compute_uv=compute_uv) a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError('expected matrix') m,n = a1.shape overwrite_a = overwrite_a or (_datanotshared(a1, a)) gesdd, = get_lapack_funcs(('gesdd',), (a1,)) if gesdd.module_name[:7] == 'flapack': lwork = calc_lwork.gesdd(gesdd.prefix, m, n, compute_uv)[1] u,s,v,info = gesdd(a1,compute_uv = compute_uv, lwork = lwork, overwrite_a = overwrite_a) else: # 'clapack' raise NotImplementedError('calling gesdd from %s' % gesdd.module_name) 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 eig(a, b=None, left=False, right=True, overwrite_a=False, overwrite_b=False): """Solve an ordinary or generalized eigenvalue problem of a square matrix. Find eigenvalues w and right or left eigenvectors of a general matrix:: a vr[:,i] = w[i] b vr[:,i] a.H vl[:,i] = w[i].conj() b.H vl[:,i] where .H is the Hermitean conjugation. Parameters ---------- a : array, shape (M, M) A complex or real matrix whose eigenvalues and eigenvectors will be computed. b : array, shape (M, M) Right-hand side matrix in a generalized eigenvalue problem. If omitted, identity matrix is assumed. left : boolean Whether to calculate and return left eigenvectors right : boolean Whether to calculate and return right eigenvectors overwrite_a : boolean Whether to overwrite data in a (may improve performance) overwrite_b : boolean Whether to overwrite data in b (may improve performance) Returns ------- w : double or complex array, shape (M,) The eigenvalues, each repeated according to its multiplicity. (if left == True) vl : double or complex array, shape (M, M) The normalized left eigenvector corresponding to the eigenvalue w[i] is the column v[:,i]. (if right == True) vr : double or complex array, shape (M, M) The normalized right eigenvector corresponding to the eigenvalue w[i] is the column vr[:,i]. Raises LinAlgError if eigenvalue computation does not converge See Also -------- eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays """ a1 = asarray_chkfinite(a) if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]: raise ValueError('expected square matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) if b is not None: b = asarray_chkfinite(b) if b.shape != a1.shape: raise ValueError('a and b must have the same shape') return _geneig(a1, b, left, right, overwrite_a, overwrite_b) geev, = get_lapack_funcs(('geev', ), (a1, )) compute_vl, compute_vr = left, right if geev.module_name[:7] == 'flapack': lwork = calc_lwork.geev(geev.prefix, a1.shape[0], compute_vl, compute_vr)[1] if geev.prefix in 'cz': w, vl, vr, info = geev(a1, lwork=lwork, compute_vl=compute_vl, compute_vr=compute_vr, overwrite_a=overwrite_a) else: wr, wi, vl, vr, info = geev(a1, lwork=lwork, compute_vl=compute_vl, compute_vr=compute_vr, overwrite_a=overwrite_a) t = {'f': 'F', 'd': 'D'}[wr.dtype.char] w = wr + _I * wi else: # 'clapack' if geev.prefix in 'cz': w, vl, vr, info = geev(a1, compute_vl=compute_vl, compute_vr=compute_vr, overwrite_a=overwrite_a) else: wr, wi, vl, vr, info = geev(a1, compute_vl=compute_vl, compute_vr=compute_vr, overwrite_a=overwrite_a) t = {'f': 'F', 'd': 'D'}[wr.dtype.char] w = wr + _I * wi if info < 0: raise ValueError('illegal value in %d-th argument of internal geev' % -info) if info > 0: raise LinAlgError("eig algorithm did not converge (only eigenvalues " "with order >= %d have converged)" % info) only_real = numpy.logical_and.reduce(numpy.equal(w.imag, 0.0)) if not (geev.prefix in 'cz' or only_real): t = w.dtype.char if left: vl = _make_complex_eigvecs(w, vl, t) if right: vr = _make_complex_eigvecs(w, vr, t) if not (left or right): return w if left: if right: return w, vl, vr return w, vl return w, vr
def qr(a, overwrite_a=False, lwork=None, mode='full'): """Compute QR decomposition of a matrix. Calculate the decomposition :lm:`A = Q R` where Q is unitary/orthogonal and R upper triangular. Parameters ---------- a : array, shape (M, N) Matrix to be decomposed overwrite_a : bool, optional Whether data in a is overwritten (may improve performance) lwork : int, optional Work array size, lwork >= a.shape[1]. If None or -1, an optimal size is computed. mode : {'full', 'r', 'economic'} Determines what information is to be returned: either both Q and R ('full', default), only R ('r') or both Q and R but computed in economy-size ('economic', see Notes). Returns ------- Q : double or complex ndarray Of shape (M, M), or (M, K) for ``mode='economic'``. Not returned if ``mode='r'``. R : double or complex ndarray Of shape (M, N), or (K, N) for ``mode='economic'``. ``K = min(M, N)``. Raises LinAlgError if decomposition fails Notes ----- This is an interface to the LAPACK routines dgeqrf, zgeqrf, dorgqr, and zungqr. If ``mode=economic``, the shapes of Q and R are (M, K) and (K, N) instead of (M,M) and (M,N), with ``K=min(M,N)``. Examples -------- >>> from scipy import random, linalg, dot >>> a = random.randn(9, 6) >>> q, r = linalg.qr(a) >>> allclose(a, dot(q, r)) True >>> q.shape, r.shape ((9, 9), (9, 6)) >>> r2 = linalg.qr(a, mode='r') >>> allclose(r, r2) >>> q3, r3 = linalg.qr(a, mode='economic') >>> q3.shape, r3.shape ((9, 6), (6, 6)) """ if mode == 'qr': # 'qr' was the old default, equivalent to 'full'. Neither 'full' nor # 'qr' are used below, but set to 'full' anyway to be sure mode = 'full' if not mode in ['full', 'qr', 'r', 'economic']: raise ValueError(\ "Mode argument should be one of ['full', 'r', 'economic']") a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError("expected 2D array") M, N = a1.shape overwrite_a = overwrite_a or (_datanotshared(a1, a)) geqrf, = get_lapack_funcs(('geqrf',), (a1,)) if lwork is None or lwork == -1: # get optimal work array qr, tau, work, info = geqrf(a1, lwork=-1, overwrite_a=1) lwork = work[0].real.astype(numpy.int) qr, tau, work, info = geqrf(a1, lwork=lwork, overwrite_a=overwrite_a) if info < 0: raise ValueError("illegal value in %d-th argument of internal geqrf" % -info) if not mode == 'economic' or M < N: R = special_matrices.triu(qr) else: R = special_matrices.triu(qr[0:N, 0:N]) if mode == 'r': return R if find_best_lapack_type((a1,))[0] == 's' or \ find_best_lapack_type((a1,))[0] == 'd': gor_un_gqr, = get_lapack_funcs(('orgqr',), (qr,)) else: gor_un_gqr, = get_lapack_funcs(('ungqr',), (qr,)) if M < N: # get optimal work array Q, work, info = gor_un_gqr(qr[:,0:M], tau, lwork=-1, overwrite_a=1) lwork = work[0].real.astype(numpy.int) Q, work, info = gor_un_gqr(qr[:,0:M], tau, lwork=lwork, overwrite_a=1) elif mode == 'economic': # get optimal work array Q, work, info = gor_un_gqr(qr, tau, lwork=-1, overwrite_a=1) lwork = work[0].real.astype(numpy.int) Q, work, info = gor_un_gqr(qr, tau, lwork=lwork, overwrite_a=1) else: t = qr.dtype.char qqr = numpy.empty((M, M), dtype=t) qqr[:,0:N] = qr # get optimal work array Q, work, info = gor_un_gqr(qqr, tau, lwork=-1, overwrite_a=1) lwork = work[0].real.astype(numpy.int) Q, work, info = gor_un_gqr(qqr, tau, lwork=lwork, overwrite_a=1) if info < 0: raise ValueError("illegal value in %d-th argument of internal gorgqr" % -info) return Q, R
def eigh(a, b=None, lower=True, eigvals_only=False, overwrite_a=False, overwrite_b=False, turbo=True, eigvals=None, type=1): """Solve an ordinary or generalized eigenvalue problem for a complex Hermitian or real symmetric matrix. Find eigenvalues w and optionally eigenvectors v of matrix a, where b is positive definite:: a v[:,i] = w[i] b v[:,i] v[i,:].conj() a v[:,i] = w[i] v[i,:].conj() b v[:,i] = 1 Parameters ---------- a : array, shape (M, M) A complex Hermitian or real symmetric matrix whose eigenvalues and eigenvectors will be computed. b : array, shape (M, M) A complex Hermitian or real symmetric definite positive matrix in. If omitted, identity matrix is assumed. lower : boolean Whether the pertinent array data is taken from the lower or upper triangle of a. (Default: lower) eigvals_only : boolean Whether to calculate only eigenvalues and no eigenvectors. (Default: both are calculated) turbo : boolean Use divide and conquer algorithm (faster but expensive in memory, only for generalized eigenvalue problem and if eigvals=None) eigvals : tuple (lo, hi) Indexes of the smallest and largest (in ascending order) eigenvalues and corresponding eigenvectors to be returned: 0 <= lo < hi <= M-1. If omitted, all eigenvalues and eigenvectors are returned. type: integer Specifies the problem type to be solved: type = 1: a v[:,i] = w[i] b v[:,i] type = 2: a b v[:,i] = w[i] v[:,i] type = 3: b a v[:,i] = w[i] v[:,i] overwrite_a : boolean Whether to overwrite data in a (may improve performance) overwrite_b : boolean Whether to overwrite data in b (may improve performance) Returns ------- w : real array, shape (N,) The N (1<=N<=M) selected eigenvalues, in ascending order, each repeated according to its multiplicity. (if eigvals_only == False) v : complex array, shape (M, N) The normalized selected eigenvector corresponding to the eigenvalue w[i] is the column v[:,i]. Normalization: type 1 and 3: v.conj() a v = w type 2: inv(v).conj() a inv(v) = w type = 1 or 2: v.conj() b v = I type = 3 : v.conj() inv(b) v = I Raises LinAlgError if eigenvalue computation does not converge, an error occurred, or b matrix is not definite positive. Note that if input matrices are not symmetric or hermitian, no error is reported but results will be wrong. See Also -------- eig : eigenvalues and right eigenvectors for non-symmetric arrays """ a1 = asarray_chkfinite(a) if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]: raise ValueError('expected square matrix') overwrite_a = overwrite_a or (_datanotshared(a1, a)) if iscomplexobj(a1): cplx = True else: cplx = False if b is not None: b1 = asarray_chkfinite(b) overwrite_b = overwrite_b or _datanotshared(b1, b) if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]: raise ValueError('expected square matrix') if b1.shape != a1.shape: raise ValueError("wrong b dimensions %s, should " "be %s" % (str(b1.shape), str(a1.shape))) if iscomplexobj(b1): cplx = True else: cplx = cplx or False else: b1 = None # Set job for fortran routines _job = (eigvals_only and 'N') or 'V' # port eigenvalue range from python to fortran convention if eigvals is not None: lo, hi = eigvals if lo < 0 or hi >= a1.shape[0]: raise ValueError('The eigenvalue range specified is not valid.\n' 'Valid range is [%s,%s]' % (0, a1.shape[0] - 1)) lo += 1 hi += 1 eigvals = (lo, hi) # set lower if lower: uplo = 'L' else: uplo = 'U' # fix prefix for lapack routines if cplx: pfx = 'he' else: pfx = 'sy' # Standard Eigenvalue Problem # Use '*evr' routines # FIXME: implement calculation of optimal lwork # for all lapack routines if b1 is None: (evr, ) = get_lapack_funcs((pfx + 'evr', ), (a1, )) if eigvals is None: w, v, info = evr(a1, uplo=uplo, jobz=_job, range="A", il=1, iu=a1.shape[0], overwrite_a=overwrite_a) else: (lo, hi) = eigvals w_tot, v, info = evr(a1, uplo=uplo, jobz=_job, range="I", il=lo, iu=hi, overwrite_a=overwrite_a) w = w_tot[0:hi - lo + 1] # Generalized Eigenvalue Problem else: # Use '*gvx' routines if range is specified if eigvals is not None: (gvx, ) = get_lapack_funcs((pfx + 'gvx', ), (a1, b1)) (lo, hi) = eigvals w_tot, v, ifail, info = gvx(a1, b1, uplo=uplo, iu=hi, itype=type, jobz=_job, il=lo, overwrite_a=overwrite_a, overwrite_b=overwrite_b) w = w_tot[0:hi - lo + 1] # Use '*gvd' routine if turbo is on and no eigvals are specified elif turbo: (gvd, ) = get_lapack_funcs((pfx + 'gvd', ), (a1, b1)) v, w, info = gvd(a1, b1, uplo=uplo, itype=type, jobz=_job, overwrite_a=overwrite_a, overwrite_b=overwrite_b) # Use '*gv' routine if turbo is off and no eigvals are specified else: (gv, ) = get_lapack_funcs((pfx + 'gv', ), (a1, b1)) v, w, info = gv(a1, b1, uplo=uplo, itype=type, jobz=_job, overwrite_a=overwrite_a, overwrite_b=overwrite_b) # Check if we had a successful exit if info == 0: if eigvals_only: return w else: return w, v elif info < 0: raise LinAlgError("illegal value in %i-th argument of internal" " fortran routine." % (-info)) elif info > 0 and b1 is None: raise LinAlgError("unrecoverable internal error.") # The algorithm failed to converge. elif info > 0 and info <= b1.shape[0]: if eigvals is not None: raise LinAlgError("the eigenvectors %s failed to" " converge." % nonzero(ifail) - 1) else: raise LinAlgError("internal fortran routine failed to converge: " "%i off-diagonal elements of an " "intermediate tridiagonal form did not converge" " to zero." % info) # This occurs when b is not positive definite else: raise LinAlgError("the leading minor of order %i" " of 'b' is not positive definite. The" " factorization of 'b' could not be completed" " and no eigenvalues or eigenvectors were" " computed." % (info - b1.shape[0]))
def eig_banded(a_band, lower=False, eigvals_only=False, overwrite_a_band=False, select='a', select_range=None, max_ev=0): """Solve real symmetric or complex hermitian band matrix eigenvalue problem. Find eigenvalues w and optionally right eigenvectors v of a:: a v[:,i] = w[i] v[:,i] v.H v = identity The matrix a is stored in ab either in lower diagonal or upper diagonal ordered form: ab[u + i - j, j] == a[i,j] (if upper form; i <= j) ab[ i - j, j] == a[i,j] (if lower form; i >= j) Example of ab (shape of a is (6,6), u=2):: upper form: * * a02 a13 a24 a35 * a01 a12 a23 a34 a45 a00 a11 a22 a33 a44 a55 lower form: a00 a11 a22 a33 a44 a55 a10 a21 a32 a43 a54 * a20 a31 a42 a53 * * Cells marked with * are not used. Parameters ---------- a_band : array, shape (M, u+1) Banded matrix whose eigenvalues to calculate lower : boolean Is the matrix in the lower form. (Default is upper form) eigvals_only : boolean Compute only the eigenvalues and no eigenvectors. (Default: calculate also eigenvectors) overwrite_a_band: Discard data in a_band (may enhance performance) select: {'a', 'v', 'i'} Which eigenvalues to calculate ====== ======================================== select calculated ====== ======================================== 'a' All eigenvalues 'v' Eigenvalues in the interval (min, max] 'i' Eigenvalues with indices min <= i <= max ====== ======================================== select_range : (min, max) Range of selected eigenvalues max_ev : integer For select=='v', maximum number of eigenvalues expected. For other values of select, has no meaning. In doubt, leave this parameter untouched. Returns ------- w : array, shape (M,) The eigenvalues, in ascending order, each repeated according to its multiplicity. v : double or complex double array, shape (M, M) The normalized eigenvector corresponding to the eigenvalue w[i] is the column v[:,i]. Raises LinAlgError if eigenvalue computation does not converge """ if eigvals_only or overwrite_a_band: a1 = asarray_chkfinite(a_band) overwrite_a_band = overwrite_a_band or (_datanotshared(a1, a_band)) else: a1 = array(a_band) if issubclass(a1.dtype.type, inexact) and not isfinite(a1).all(): raise ValueError("array must not contain infs or NaNs") overwrite_a_band = 1 if len(a1.shape) != 2: raise ValueError('expected two-dimensional array') if select.lower() not in [0, 1, 2, 'a', 'v', 'i', 'all', 'value', 'index']: raise ValueError('invalid argument for select') if select.lower() in [0, 'a', 'all']: if a1.dtype.char in 'GFD': bevd, = get_lapack_funcs(('hbevd', ), (a1, )) # FIXME: implement this somewhen, for now go with builtin values # FIXME: calc optimal lwork by calling ?hbevd(lwork=-1) # or by using calc_lwork.f ??? # lwork = calc_lwork.hbevd(bevd.prefix, a1.shape[0], lower) internal_name = 'hbevd' else: # a1.dtype.char in 'fd': bevd, = get_lapack_funcs(('sbevd', ), (a1, )) # FIXME: implement this somewhen, for now go with builtin values # see above # lwork = calc_lwork.sbevd(bevd.prefix, a1.shape[0], lower) internal_name = 'sbevd' w, v, info = bevd(a1, compute_v=not eigvals_only, lower=lower, overwrite_ab=overwrite_a_band) if select.lower() in [1, 2, 'i', 'v', 'index', 'value']: # calculate certain range only if select.lower() in [2, 'i', 'index']: select = 2 vl, vu, il, iu = 0.0, 0.0, min(select_range), max(select_range) if min(il, iu) < 0 or max(il, iu) >= a1.shape[1]: raise ValueError('select_range out of bounds') max_ev = iu - il + 1 else: # 1, 'v', 'value' select = 1 vl, vu, il, iu = min(select_range), max(select_range), 0, 0 if max_ev == 0: max_ev = a_band.shape[1] if eigvals_only: max_ev = 1 # calculate optimal abstol for dsbevx (see manpage) if a1.dtype.char in 'fF': # single precision lamch, = get_lapack_funcs(('lamch', ), (array(0, dtype='f'), )) else: lamch, = get_lapack_funcs(('lamch', ), (array(0, dtype='d'), )) abstol = 2 * lamch('s') if a1.dtype.char in 'GFD': bevx, = get_lapack_funcs(('hbevx', ), (a1, )) internal_name = 'hbevx' else: # a1.dtype.char in 'gfd' bevx, = get_lapack_funcs(('sbevx', ), (a1, )) internal_name = 'sbevx' # il+1, iu+1: translate python indexing (0 ... N-1) into Fortran # indexing (1 ... N) w, v, m, ifail, info = bevx(a1, vl, vu, il + 1, iu + 1, compute_v=not eigvals_only, mmax=max_ev, range=select, lower=lower, overwrite_ab=overwrite_a_band, abstol=abstol) # crop off w and v w = w[:m] if not eigvals_only: v = v[:, :m] if info < 0: raise ValueError('illegal value in %d-th argument of internal %s' % (-info, internal_name)) if info > 0: raise LinAlgError("eig algorithm did not converge") if eigvals_only: return w return w, v
def svd(a, full_matrices=True, compute_uv=True, overwrite_a=False): """Singular Value Decomposition. Factorizes the matrix a into two unitary matrices U and Vh and an 1d-array s of singular values (real, non-negative) such that a == U S Vh if S is an suitably shaped matrix of zeros whose main diagonal is s. Parameters ---------- a : array, shape (M, N) Matrix to decompose full_matrices : boolean If true, U, Vh are shaped (M,M), (N,N) If false, the shapes are (M,K), (K,N) where K = min(M,N) compute_uv : boolean Whether to compute also U, Vh in addition to s (Default: true) overwrite_a : boolean Whether data in a is overwritten (may improve performance) Returns ------- U: array, shape (M,M) or (M,K) depending on full_matrices s: array, shape (K,) The singular values, sorted so that s[i] >= s[i+1]. K = min(M, N) Vh: array, 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 Examples -------- >>> from scipy import random, linalg, allclose, dot >>> a = random.randn(9, 6) + 1j*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) >>> allclose(a, dot(U, dot(S, Vh))) True >>> s2 = linalg.svd(a, compute_uv=False) >>> allclose(s, s2) True See also -------- svdvals : return singular values of a matrix diagsvd : return the Sigma matrix, given the vector s """ # A hack until full_matrices == 0 support is fixed here. if full_matrices == 0: import numpy.linalg return numpy.linalg.svd(a, full_matrices=0, compute_uv=compute_uv) a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError('expected matrix') m, n = a1.shape overwrite_a = overwrite_a or (_datanotshared(a1, a)) gesdd, = get_lapack_funcs(('gesdd', ), (a1, )) if gesdd.module_name[:7] == 'flapack': lwork = calc_lwork.gesdd(gesdd.prefix, m, n, compute_uv)[1] u, s, v, info = gesdd(a1, compute_uv=compute_uv, lwork=lwork, overwrite_a=overwrite_a) else: # 'clapack' raise NotImplementedError('calling gesdd from %s' % gesdd.module_name) 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 qr(a, overwrite_a=False, lwork=None, econ=None, mode='qr'): """Compute QR decomposition of a matrix. Calculate the decomposition :lm:`A = Q R` where Q is unitary/orthogonal and R upper triangular. Parameters ---------- a : array, shape (M, N) Matrix to be decomposed overwrite_a : boolean Whether data in a is overwritten (may improve performance) lwork : integer Work array size, lwork >= a.shape[1]. If None or -1, an optimal size is computed. econ : boolean Whether to compute the economy-size QR decomposition, making shapes of Q and R (M, K) and (K, N) instead of (M,M) and (M,N). K=min(M,N). Default is False. mode : {'qr', 'r'} Determines what information is to be returned: either both Q and R or only R. Returns ------- (if mode == 'qr') Q : double or complex array, shape (M, M) or (M, K) for econ==True (for any mode) R : double or complex array, shape (M, N) or (K, N) for econ==True Size K = min(M, N) Raises LinAlgError if decomposition fails Notes ----- This is an interface to the LAPACK routines dgeqrf, zgeqrf, dorgqr, and zungqr. Examples -------- >>> from scipy import random, linalg, dot >>> a = random.randn(9, 6) >>> q, r = linalg.qr(a) >>> allclose(a, dot(q, r)) True >>> q.shape, r.shape ((9, 9), (9, 6)) >>> r2 = linalg.qr(a, mode='r') >>> allclose(r, r2) >>> q3, r3 = linalg.qr(a, econ=True) >>> q3.shape, r3.shape ((9, 6), (6, 6)) """ if econ is None: econ = False else: warn("qr econ argument will be removed after scipy 0.7. " "The economy transform will then be available through " "the mode='economic' argument.", DeprecationWarning) a1 = asarray_chkfinite(a) if len(a1.shape) != 2: raise ValueError("expected 2D array") M, N = a1.shape overwrite_a = overwrite_a or (_datanotshared(a1, a)) geqrf, = get_lapack_funcs(('geqrf',), (a1,)) if lwork is None or lwork == -1: # get optimal work array qr, tau, work, info = geqrf(a1, lwork=-1, overwrite_a=1) lwork = work[0] qr, tau, work, info = geqrf(a1, lwork=lwork, overwrite_a=overwrite_a) if info < 0: raise ValueError("illegal value in %d-th argument of internal geqrf" % -info) if not econ or M < N: R = special_matrices.triu(qr) else: R = special_matrices.triu(qr[0:N, 0:N]) if mode == 'r': return R if find_best_lapack_type((a1,))[0] == 's' or \ find_best_lapack_type((a1,))[0] == 'd': gor_un_gqr, = get_lapack_funcs(('orgqr',), (qr,)) else: gor_un_gqr, = get_lapack_funcs(('ungqr',), (qr,)) if M < N: # get optimal work array Q, work, info = gor_un_gqr(qr[:,0:M], tau, lwork=-1, overwrite_a=1) lwork = work[0] Q, work, info = gor_un_gqr(qr[:,0:M], tau, lwork=lwork, overwrite_a=1) elif econ: # get optimal work array Q, work, info = gor_un_gqr(qr, tau, lwork=-1, overwrite_a=1) lwork = work[0] Q, work, info = gor_un_gqr(qr, tau, lwork=lwork, overwrite_a=1) else: t = qr.dtype.char qqr = numpy.empty((M, M), dtype=t) qqr[:,0:N] = qr # get optimal work array Q, work, info = gor_un_gqr(qqr, tau, lwork=-1, overwrite_a=1) lwork = work[0] Q, work, info = gor_un_gqr(qqr, tau, lwork=lwork, overwrite_a=1) if info < 0: raise ValueError("illegal value in %d-th argument of internal gorgqr" % -info) return Q, R