diff options
Diffstat (limited to 'numpy/linalg/linalg.py')
-rw-r--r-- | numpy/linalg/linalg.py | 748 |
1 files changed, 554 insertions, 194 deletions
diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py index f762cf72d..287b38d9b 100644 --- a/numpy/linalg/linalg.py +++ b/numpy/linalg/linalg.py @@ -26,6 +26,32 @@ fortran_int = intc # Error object class LinAlgError(Exception): + """ + Generic Python-exception-derived object raised by linalg functions. + + General purpose exception class, derived from Python's exception.Exception + class, programmatically raised in linalg functions when a Linear + Algebra-related condition would prevent further correct execution of the + function. + + Parameters + ---------- + None + + Examples + -------- + >>> from numpy import linalg as LA + >>> LA.inv(np.zeros((2,2))) + Traceback (most recent call last): + File "<stdin>", line 1, in <module> + File "...linalg.py", line 350, + in inv return wrap(solve(a, identity(a.shape[0], dtype=a.dtype))) + File "...linalg.py", line 249, + in solve + raise LinAlgError, 'Singular matrix' + numpy.linalg.linalg.LinAlgError: Singular matrix + + """ pass def _makearray(a): @@ -127,32 +153,44 @@ def _assertNonEmpty(*arrays): def tensorsolve(a, b, axes=None): """ - Solve the tensor equation a x = b for x + Solve the tensor equation ``a x = b`` for x. - It is assumed that all indices of x are summed over in the product, - together with the rightmost indices of a, similarly as in - tensordot(a, x, axes=len(b.shape)). + It is assumed that all indices of `x` are summed over in the product, + together with the rightmost indices of `a`, as is done in, for example, + ``tensordot(a, x, axes=len(b.shape))``. Parameters ---------- - a : array_like, shape b.shape+Q - Coefficient tensor. Shape Q of the rightmost indices of a must - be such that a is 'square', ie., prod(Q) == prod(b.shape). - b : array_like, any shape - Right-hand tensor. - axes : tuple of integers - Axes in a to reorder to the right, before inversion. + a : array_like + Coefficient tensor, of shape ``b.shape + Q``. `Q`, a tuple, equals + the shape of that sub-tensor of `a` consisting of the appropriate + number of its rightmost indices, and must be such that + ``prod(Q) == prod(b.shape)`` (in which sense `a` is said to be + 'square'). + b : array_like + Right-hand tensor, which can be of any shape. + axes : tuple of ints, optional + Axes in `a` to reorder to the right, before inversion. If None (default), no reordering is done. Returns ------- - x : array, shape Q + x : ndarray, shape Q + + Raises + ------ + LinAlgError + If `a` is singular or not 'square' (in the above sense). + + See Also + -------- + tensordot, tensorinv Examples -------- >>> a = np.eye(2*3*4) - >>> a.shape = (2*3,4, 2,3,4) - >>> b = np.random.randn(2*3,4) + >>> a.shape = (2*3, 4, 2, 3, 4) + >>> b = np.random.randn(2*3, 4) >>> x = np.linalg.tensorsolve(a, b) >>> x.shape (2, 3, 4) @@ -184,18 +222,21 @@ def tensorsolve(a, b, axes=None): def solve(a, b): """ - Solve the equation ``a x = b`` for ``x``. + Solve a linear matrix equation, or system of linear scalar equations. + + Computes the "exact" solution, `x`, of the well-determined, i.e., full + rank, linear matrix equation `ax = b`. Parameters ---------- a : array_like, shape (M, M) - Input equation coefficients. + Coefficient matrix. b : array_like, shape (M,) - Equation target values. + Ordinate or "dependent variable" values. Returns ------- - x : array, shape (M,) + x : ndarray, shape (M,) Raises ------ @@ -204,16 +245,26 @@ def solve(a, b): Notes ----- - - ``linalg.solve`` is a wrapper to the LAPACK http://www.netlib.org/lapack - routines `dgesv`_ and `zgesv`_. The solution to the system of linear - equations is computed using an LU decomposition with partial pivoting and + `solve` is a wrapper for the LAPACK routines `dgesv`_ and + `zgesv`_, the former being used if `a` is real-valued, the latter if + it is complex-valued. The solution to the system of linear equations + is computed using an LU decomposition [1]_ with partial pivoting and row interchanges. .. _dgesv: http://www.netlib.org/lapack/double/dgesv.f .. _zgesv: http://www.netlib.org/lapack/complex16/zgesv.f + `a` must be square and of full-rank, i.e., all rows (or, equivalently, + columns) must be linearly independent; if either is not true, use + `lstsq` for the least-squares best "solution" of the + system/equation. + + References + ---------- + .. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando, + FL, Academic Press, Inc., 1980, pg. 22. + Examples -------- Solve the system of equations ``3 * x0 + x1 = 9`` and ``x0 + 2 * x1 = 8``: @@ -260,43 +311,49 @@ def solve(a, b): def tensorinv(a, ind=2): """ - Find the 'inverse' of a N-d array + Compute the 'inverse' of an N-dimensional array. - The result is an inverse corresponding to the operation - tensordot(a, b, ind), ie., - - x == tensordot(tensordot(tensorinv(a), a, ind), x, ind) - == tensordot(tensordot(a, tensorinv(a), ind), x, ind) - - for all x (up to floating-point accuracy). + The result is an inverse for `a` relative to the tensordot operation + ``tensordot(a, b, ind)``, i. e., up to floating-point accuracy, + ``tensordot(tensorinv(a), a, ind)`` is the "identity" tensor for the + tensordot operation. Parameters ---------- a : array_like - Tensor to 'invert'. Its shape must 'square', ie., - prod(a.shape[:ind]) == prod(a.shape[ind:]) - ind : integer > 0 - How many of the first indices are involved in the inverse sum. + Tensor to 'invert'. Its shape must be 'square', i. e., + ``prod(a.shape[:ind]) == prod(a.shape[ind:])``. + ind : int, optional + Number of first indices that are involved in the inverse sum. + Must be a positive integer, default is 2. Returns ------- - b : array, shape a.shape[:ind]+a.shape[ind:] + b : ndarray + `a`'s tensordot inverse, shape ``a.shape[:ind] + a.shape[ind:]``. + + Raises + ------ + LinAlgError + If `a` is singular or not 'square' (in the above sense). - Raises LinAlgError if a is singular or not square + See Also + -------- + tensordot, tensorsolve Examples -------- >>> a = np.eye(4*6) - >>> a.shape = (4,6,8,3) + >>> a.shape = (4, 6, 8, 3) >>> ainv = np.linalg.tensorinv(a, ind=2) >>> ainv.shape (8, 3, 4, 6) - >>> b = np.random.randn(4,6) + >>> b = np.random.randn(4, 6) >>> np.allclose(np.tensordot(ainv, b), np.linalg.tensorsolve(a, b)) True >>> a = np.eye(4*6) - >>> a.shape = (24,8,3) + >>> a.shape = (24, 8, 3) >>> ainv = np.linalg.tensorinv(a, ind=1) >>> ainv.shape (8, 3, 24) @@ -323,17 +380,20 @@ def tensorinv(a, ind=2): def inv(a): """ - Compute the inverse of a matrix. + Compute the (multiplicative) inverse of a matrix. + + Given a square matrix `a`, return the matrix `ainv` satisfying + ``dot(a, ainv) = dot(ainv, a) = eye(a.shape[0])``. Parameters ---------- a : array_like, shape (M, M) - Matrix to be inverted + Matrix to be inverted. Returns ------- - ainv : ndarray, shape (M, M) - Inverse of the matrix `a` + ainv : ndarray or matrix, shape (M, M) + (Multiplicative) inverse of the matrix `a`. Raises ------ @@ -342,13 +402,20 @@ def inv(a): Examples -------- + >>> from numpy import linalg as LA >>> a = np.array([[1., 2.], [3., 4.]]) - >>> np.linalg.inv(a) - array([[-2. , 1. ], - [ 1.5, -0.5]]) - >>> np.dot(a, np.linalg.inv(a)) - array([[ 1., 0.], - [ 0., 1.]]) + >>> ainv = LA.inv(a) + >>> np.allclose(np.dot(a, ainv), np.eye(2)) + True + >>> np.allclose(np.dot(ainv, a), np.eye(2)) + True + + If a is a matrix object, then the return value is a matrix as well: + + >>> ainv = LA.inv(np.matrix(a)) + >>> ainv + matrix([[-2. , 1. ], + [ 1.5, -0.5]]) """ a, wrap = _makearray(a) @@ -447,56 +514,96 @@ def cholesky(a): def qr(a, mode='full'): """ - Compute QR decomposition of a matrix. + Compute the qr factorization of a matrix. - Calculate the decomposition :math:`A = Q R` where Q is orthonormal - and R upper triangular. + Factor the matrix `a` as `qr`, where `q` is orthonormal + (:math:`dot( q_{:,i}, q_{:,j}) = \\delta_{ij}`, the Kronecker delta) and + `r` is upper-triangular. Parameters ---------- a : array_like, shape (M, N) - Matrix to be decomposed + Matrix to be factored. mode : {'full', 'r', 'economic'} - Determines what information is to be returned. 'full' is the default. - Economic mode is slightly faster if only R is needed. + Specifies the information to be returned. 'full' is the default. + mode='r' returns a "true" `r`, while 'economic' returns a "polluted" + `r` (albeit slightly faster; see Returns below). Returns ------- mode = 'full' - Q : double or complex array, shape (M, K) - R : double or complex array, shape (K, N) - Size K = min(M, N) + q : double or complex array, shape (M, K) + + r : double or complex array, shape (K, N) + + Size K = min(M, N) mode = 'r' - R : double or complex array, shape (K, N) + r : double or complex array, shape (K, N) mode = 'economic' - A2 : double or complex array, shape (M, N) - The diagonal and the upper triangle of A2 contains R, - while the rest of the matrix is undefined. + a2 : double or complex array, shape (M, N) - If a is a matrix, so are all the return values. + The diagonal and the upper triangle of a2 contains r, + while the rest of the matrix is undefined. - Raises LinAlgError if decomposition fails + If `a` is a matrix, so are all the return values. + + Raises + ------ + LinAlgError : if factoring fails Notes ----- This is an interface to the LAPACK routines dgeqrf, zgeqrf, dorgqr, and zungqr. + For more information on the qr factorization, see for example: + http://en.wikipedia.org/wiki/QR_factorization + + Examples -------- >>> a = np.random.randn(9, 6) >>> q, r = np.linalg.qr(a) - >>> np.allclose(a, np.dot(q, r)) + >>> np.allclose(a, np.dot(q, r)) # a does equal qr True >>> r2 = np.linalg.qr(a, mode='r') >>> r3 = np.linalg.qr(a, mode='economic') - >>> np.allclose(r, r2) + >>> np.allclose(r, r2) # mode='r' returns the same r as mode='full' True + >>> # But only triu parts are guaranteed equal when mode='economic' >>> np.allclose(r, np.triu(r3[:6,:6], k=0)) True + Example illustrating a common use of `qr`: solving of least squares + problems + + What are the least-squares-best `m` and `y0` in ``y = y0 + mx`` for + the following data: {(0,1), (1,0), (1,2), (2,1)}. (Graph the points + and you'll see that it should be y0 = 0, m = 1.) The answer is provided + by solving the over-determined matrix equation ``Ax = b``, where: + + A = array([[0, 1], [1, 1], [1, 1], [2, 1]]) + + x = array([[y0], [m]]) b = array([[1], [0], [2], [1]]) + + If A = qr such that q is orthonormal (which is always possible via + Gram-Schmidt), then ``x = inv(r) * (q.T) * b``. (In numpy practice, + however, we simply use `lstsq`.) + + >>> A = np.array([[0, 1], [1, 1], [1, 1], [2, 1]]) + >>> A + array([[0, 1], + [1, 1], + [1, 1], + [2, 1]]) + >>> b = np.array([1, 0, 2, 1]) + >>> q, r = LA.qr(A) + >>> p = np.dot(q.T, b) + >>> np.dot(LA.inv(r), p) + array([ 1.1e-16, 1.0e+00]) + """ a, wrap = _makearray(a) _assertRank2(a) @@ -577,11 +684,13 @@ def eigvals(a): """ Compute the eigenvalues of a general matrix. + Main difference between `eigvals` and `eig`: the eigenvectors aren't + returned. + Parameters ---------- a : array_like, shape (M, M) - A complex or real matrix whose eigenvalues and eigenvectors - will be computed. + A complex- or real-valued matrix whose eigenvalues will be computed. Returns ------- @@ -598,19 +707,39 @@ def eigvals(a): See Also -------- eig : eigenvalues and right eigenvectors of general arrays - eigvalsh : eigenvalues of symmetric or Hemitiean arrays. - eigh : eigenvalues and eigenvectors of symmetric/Hermitean arrays. + eigvalsh : eigenvalues of symmetric or Hermitian arrays. + eigh : eigenvalues and eigenvectors of symmetric/Hermitian arrays. Notes ----- This is a simple interface to the LAPACK routines dgeev and zgeev - that sets the flags to return only the eigenvalues of general real - and complex arrays respectively. + that sets those routines' flags to return only the eigenvalues of + general real and complex arrays, respectively. - The number w is an eigenvalue of a if there exists a vector v - satisfying the equation dot(a,v) = w*v. Alternately, if w is a root of - the characteristic equation det(a - w[i]*I) = 0, where det is the - determinant and I is the identity matrix. + Examples + -------- + Illustration, using the fact that the eigenvalues of a diagonal matrix + are its diagonal elements, that multiplying a matrix on the left + by an orthogonal matrix, `Q`, and on the right by `Q.T` (the transpose + of `Q`), preserves the eigenvalues of the "middle" matrix. In other words, + if `Q` is orthogonal, then ``Q * A * Q.T`` has the same eigenvalues as + ``A``: + + >>> from numpy import linalg as LA + >>> x = np.random.random() + >>> Q = np.array([[np.cos(x), -np.sin(x)], [np.sin(x), np.cos(x)]]) + >>> LA.norm(Q[0, :]), LA.norm(Q[1, :]), np.dot(Q[0, :],Q[1, :]) + (1.0, 1.0, 0.0) + + Now multiply a diagonal matrix by Q on one side and by Q.T on the other: + + >>> D = np.diag((-1,1)) + >>> LA.eigvals(D) + array([-1., 1.]) + >>> A = np.dot(Q, D) + >>> A = np.dot(A, Q.T) + >>> LA.eigvals(A) + array([ 1., -1.]) """ a, wrap = _makearray(a) @@ -659,23 +788,24 @@ def eigvals(a): def eigvalsh(a, UPLO='L'): """ - Compute the eigenvalues of a Hermitean or real symmetric matrix. + Compute the eigenvalues of a Hermitian or real symmetric matrix. + + Main difference from eigh: the eigenvectors are not computed. Parameters ---------- a : array_like, shape (M, M) - A complex or real matrix whose eigenvalues and eigenvectors - will be computed. + A complex- or real-valued matrix whose eigenvalues are to be + computed. UPLO : {'L', 'U'}, optional - Specifies whether the calculation is done with data from the - lower triangular part of `a` ('L', default) or the upper triangular - part ('U'). + Specifies whether the calculation is done with the lower triangular + part of `a` ('L', default) or the upper triangular part ('U'). Returns ------- w : ndarray, shape (M,) - The eigenvalues, each repeated according to its multiplicity. - They are not necessarily ordered. + The eigenvalues, not necessarily ordered, each repeated according to + its multiplicity. Raises ------ @@ -684,20 +814,23 @@ def eigvalsh(a, UPLO='L'): See Also -------- - eigh : eigenvalues and eigenvectors of symmetric/Hermitean arrays. + eigh : eigenvalues and eigenvectors of symmetric/Hermitian arrays. eigvals : eigenvalues of general real or complex arrays. - eig : eigenvalues and eigenvectors of general real or complex arrays. + eig : eigenvalues and right eigenvectors of general real or complex + arrays. Notes ----- - This is a simple interface to the LAPACK routines dsyevd and - zheevd that sets the flags to return only the eigenvalues of real - symmetric and complex Hermetian arrays respectively. + This is a simple interface to the LAPACK routines dsyevd and zheevd + that sets those routines' flags to return only the eigenvalues of + real symmetric and complex Hermitian arrays, respectively. - The number w is an eigenvalue of a if there exists a vector v - satisfying the equation dot(a,v) = w*v. Alternately, if w is a root of - the characteristic equation det(a - w[i]*I) = 0, where det is the - determinant and I is the identity matrix. + Examples + -------- + >>> from numpy import linalg as LA + >>> a = np.array([[1, -2j], [2j, 5]]) + >>> LA.eigvalsh(a) + array([ 0.17157288+0.j, 5.82842712+0.j]) """ a, wrap = _makearray(a) @@ -750,22 +883,25 @@ def _convertarray(a): def eig(a): """ - Compute eigenvalues and right eigenvectors of an array. + Compute the eigenvalues and right eigenvectors of a square array. Parameters ---------- a : array_like, shape (M, M) - A complex or real 2-D array. + A square array of real or complex elements. Returns ------- w : ndarray, shape (M,) The eigenvalues, each repeated according to its multiplicity. The eigenvalues are not necessarily ordered, nor are they - necessarily real for real matrices. + necessarily real for real arrays (though for real arrays + complex-valued eigenvalues should occur in conjugate pairs). + v : ndarray, shape (M, M) - The normalized eigenvector corresponding to the eigenvalue ``w[i]`` is - the column ``v[:,i]``. + The normalized (unit "length") eigenvectors, such that the + column ``v[:,i]`` is the eigenvector corresponding to the + eigenvalue ``w[i]``. Raises ------ @@ -774,31 +910,83 @@ def eig(a): See Also -------- - eigvalsh : eigenvalues of symmetric or Hemitiean arrays. - eig : eigenvalues and right eigenvectors for non-symmetric arrays - eigvals : eigenvalues of non-symmetric array. + eigvalsh : eigenvalues of a symmetric or Hermitian (conjugate symmetric) + array. + + eigvals : eigenvalues of a non-symmetric array. Notes ----- This is a simple interface to the LAPACK routines dgeev and zgeev - that compute the eigenvalues and eigenvectors of general real and - complex arrays respectively. + which compute the eigenvalues and eigenvectors of, respectively, + general real- and complex-valued square arrays. - The number `w` is an eigenvalue of a if there exists a vector `v` - satisfying the equation ``dot(a,v) = w*v``. Alternately, if `w` is - a root of the characteristic equation ``det(a - w[i]*I) = 0``, where - `det` is the determinant and `I` is the identity matrix. The arrays - `a`, `w`, and `v` satisfy the equation ``dot(a,v[i]) = w[i]*v[:,i]``. + The number `w` is an eigenvalue of `a` if there exists a vector + `v` such that ``dot(a,v) = w * v``. Thus, the arrays `a`, `w`, and + `v` satisfy the equations ``dot(a[i,:], v[i]) = w[i] * v[:,i]`` + for :math:`i \\in \\{0,...,M-1\\}`. The array `v` of eigenvectors may not be of maximum rank, that is, some - of the columns may be dependent, although roundoff error may + of the columns may be linearly dependent, although round-off error may obscure that fact. If the eigenvalues are all different, then theoretically - the eigenvectors are independent. Likewise, the matrix of eigenvectors - is unitary if the matrix `a` is normal, i.e., if - ``dot(a, a.H) = dot(a.H, a)``. + the eigenvectors are linearly independent. Likewise, the (complex-valued) + matrix of eigenvectors `v` is unitary if the matrix `a` is normal, i.e., + if ``dot(a, a.H) = dot(a.H, a)``, where `a.H` denotes the conjugate + transpose of `a`. + + Finally, it is emphasized that `v` consists of the *right* (as in + right-hand side) eigenvectors of `a`. A vector `y` satisfying + ``dot(y.T, a) = z * y.T`` for some number `z` is called a *left* + eigenvector of `a`, and, in general, the left and right eigenvectors + of a matrix are not necessarily the (perhaps conjugate) transposes + of each other. + + References + ---------- + G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando, FL, + Academic Press, Inc., 1980, Various pp. - The left and right eigenvectors are not necessarily the (Hermitian) - transposes of each other. + Examples + -------- + >>> from numpy import linalg as LA + + (Almost) trivial example with real e-values and e-vectors. + + >>> w, v = LA.eig(np.diag((1, 2, 3))) + >>> w; v + array([ 1., 2., 3.]) + array([[ 1., 0., 0.], + [ 0., 1., 0.], + [ 0., 0., 1.]]) + + Real matrix possessing complex e-values and e-vectors; note that the + e-values are complex conjugates of each other. + + >>> w, v = LA.eig(np.array([[1, -1], [1, 1]])) + >>> w; v + array([ 1. + 1.j, 1. - 1.j]) + array([[ 0.70710678+0.j , 0.70710678+0.j ], + [ 0.00000000-0.70710678j, 0.00000000+0.70710678j]]) + + Complex-valued matrix with real e-values (but complex-valued e-vectors); + note that a.conj().T = a, i.e., a is Hermitian. + + >>> a = np.array([[1, 1j], [-1j, 1]]) + >>> w, v = LA.eig(a) + >>> w; v + array([ 2.00000000e+00+0.j, 5.98651912e-36+0.j]) # i.e., {2, 0} + array([[ 0.00000000+0.70710678j, 0.70710678+0.j ], + [ 0.70710678+0.j , 0.00000000+0.70710678j]]) + + Be careful about round-off error! + + >>> a = np.array([[1 + 1e-9, 0], [0, 1 - 1e-9]]) + >>> # Theor. e-values are 1 +/- 1e-9 + >>> w, v = LA.eig(a) + >>> w; v + array([ 1., 1.]) + array([[ 1., 0.], + [ 0., 1.]]) """ a, wrap = _makearray(a) @@ -857,24 +1045,27 @@ def eig(a): def eigh(a, UPLO='L'): """ - Eigenvalues and eigenvectors of a Hermitian or real symmetric matrix. + Return the eigenvalues and eigenvectors of a Hermitian or symmetric matrix. + + Returns two objects, a 1-D array containing the eigenvalues of `a`, and + a 2-D square array or matrix (depending on the input type) of the + corresponding eigenvectors (in columns). Parameters ---------- a : array_like, shape (M, M) - A complex Hermitian or symmetric real matrix. + A complex Hermitian or real symmetric matrix. UPLO : {'L', 'U'}, optional - Specifies whether the calculation is done with data from the - lower triangular part of `a` ('L', default) or the upper triangular - part ('U'). + Specifies whether the calculation is done with the lower triangular + part of `a` ('L', default) or the upper triangular part ('U'). Returns ------- w : ndarray, shape (M,) - The eigenvalues. The eigenvalues are not necessarily ordered. - v : ndarray, shape (M, M) - The normalized eigenvector corresponding to the eigenvalue w[i] is - the column v[:,i]. + The eigenvalues, not necessarily ordered. + v : ndarray, or matrix object if `a` is, shape (M, M) + The column ``v[:, i]`` is the normalized eigenvector corresponding + to the eigenvalue ``w[i]``. Raises ------ @@ -883,23 +1074,53 @@ def eigh(a, UPLO='L'): See Also -------- - eigvalsh : eigenvalues of symmetric or Hemitiean arrays. - eig : eigenvalues and right eigenvectors for non-symmetric arrays - eigvals : eigenvalues of non-symmetric array. + eigvalsh : eigenvalues of symmetric or Hermitian arrays. + eig : eigenvalues and right eigenvectors for non-symmetric arrays. + eigvals : eigenvalues of non-symmetric arrays. Notes ----- - A simple interface to the LAPACK routines dsyevd and zheevd that compute - the eigenvalues and eigenvectors of real symmetric and complex Hermitian - arrays respectively. - - The number w is an eigenvalue of a if there exists a vector v - satisfying the equation dot(a,v) = w*v. Alternately, if w is a root of - the characteristic equation det(a - w[i]*I) = 0, where det is the - determinant and I is the identity matrix. The eigenvalues of real - symmetric or complex Hermitean matrices are always real. The array v - of eigenvectors is unitary and a, w, and v satisfy the equation - dot(a,v[i]) = w[i]*v[:,i]. + This is a simple interface to the LAPACK routines dsyevd and zheevd, + which compute the eigenvalues and eigenvectors of real symmetric and + complex Hermitian arrays, respectively. + + The eigenvalues of real symmetric or complex Hermitian matrices are + always real. [1]_ The array `v` of (column) eigenvectors is unitary + and `a`, `w`, and `v` satisfy the equations + ``dot(a, v[:, i]) = w[i] * v[:, i]``. + + References + ---------- + .. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando, + FL, Academic Press, Inc., 1980, pg. 222. + + Examples + -------- + >>> from numpy import linalg as LA + >>> a = np.array([[1, -2j], [2j, 5]]) + >>> a + array([[ 1.+0.j, 0.-2.j], + [ 0.+2.j, 5.+0.j]]) + >>> w, v = LA.eigh(a) + >>> w; v + array([ 0.17157288, 5.82842712]) + array([[-0.92387953+0.j , -0.38268343+0.j ], + [ 0.00000000+0.38268343j, 0.00000000-0.92387953j]]) + + >>> np.dot(a, v[:, 0]) - w[0] * v[:, 0] # verify 1st e-val/vec pair + array([2.77555756e-17 + 0.j, 0. + 1.38777878e-16j]) + >>> np.dot(a, v[:, 1]) - w[1] * v[:, 1] # verify 2nd e-val/vec pair + array([ 0.+0.j, 0.+0.j]) + + >>> A = np.matrix(a) # what happens if input is a matrix object + >>> A + matrix([[ 1.+0.j, 0.-2.j], + [ 0.+2.j, 5.+0.j]]) + >>> w, v = LA.eigh(A) + >>> w; v + array([ 0.17157288, 5.82842712]) + matrix([[-0.92387953+0.j , -0.38268343+0.j ], + [ 0.00000000+0.38268343j, 0.00000000-0.92387953j]]) """ a, wrap = _makearray(a) @@ -949,31 +1170,34 @@ def svd(a, full_matrices=1, compute_uv=1): """ Singular Value Decomposition. - Factorizes the matrix `a` into two unitary matrices, ``U`` and ``Vh``, - and a 1-dimensional array of singular values, ``s`` (real, non-negative), - such that ``a == U S Vh``, where ``S`` is the diagonal - matrix ``np.diag(s)``. + Factors the matrix `a` into ``u * np.diag(s) * v.H``, where `u` and `v` + are unitary (i.e., ``u.H = inv(u)`` and similarly for `v`), ``.H`` is the + conjugate transpose operator (which is the ordinary transpose for + real-valued matrices), and `s` is a 1-D array of `a`'s singular values. Parameters ---------- - a : array_like, shape (M, N) - Matrix to decompose - full_matrices : boolean, optional - If True (default), ``U`` and ``Vh`` are shaped - ``(M,M)`` and ``(N,N)``. Otherwise, the shapes are - ``(M,K)`` and ``(K,N)``, where ``K = min(M,N)``. - compute_uv : boolean - Whether to compute ``U`` and ``Vh`` in addition to ``s``. + a : array_like + Matrix of shape ``(M, N)`` to decompose. + full_matrices : bool, optional + If True (default), ``u`` and ``v.H`` have the shapes + ``(M, M)`` and ``(N, N)``, respectively. Otherwise, the shapes + are ``(M, K)`` and ``(K, N)``, resp., where ``K = min(M, N)``. + compute_uv : bool, optional + Whether or not to compute ``u`` and ``v.H`` in addition to ``s``. True by default. Returns ------- - U : ndarray, shape (M, M) or (M, K) depending on `full_matrices` - Unitary matrix. - s : ndarray, shape (K,) where ``K = min(M, N)`` + u : ndarray + Unitary matrix. The shape of `U` is ``(M, M)`` or ``(M, K)`` + depending on value of `full_matrices`. + s : ndarray The singular values, sorted so that ``s[i] >= s[i+1]``. - Vh : ndarray, shape (N,N) or (K,N) depending on `full_matrices` - Unitary matrix. + `S` is a 1-D array of length ``min(M, N)`` + v.H : ndarray + Unitary matrix of shape ``(N, N)`` or ``(K, N)``, depending + on `full_matrices`. Raises ------ @@ -982,7 +1206,7 @@ def svd(a, full_matrices=1, compute_uv=1): Notes ----- - If `a` is a matrix (in contrast to an ndarray), then so are all + If `a` is a matrix object (as opposed to an `ndarray`), then so are all the return values. Examples @@ -1066,21 +1290,21 @@ def cond(x, p=None): """ Compute the condition number of a matrix. - The condition number of `x` is the norm of `x` times the norm - of the inverse of `x`. The norm can be the usual L2 - (root-of-sum-of-squares) norm or a number of other matrix norms. + This function is capable of returning the condition number using + one of seven different norms, depending on the value of `p` (see + Parameters below). Parameters ---------- x : array_like, shape (M, N) The matrix whose condition number is sought. - p : {None, 1, -1, 2, -2, inf, -inf, 'fro'} + p : {None, 1, -1, 2, -2, inf, -inf, 'fro'}, optional Order of the norm: ===== ============================ p norm for matrices ===== ============================ - None 2-norm, computed directly using the SVD + None 2-norm, computed directly using the ``SVD`` 'fro' Frobenius norm inf max(sum(abs(x), axis=1)) -inf min(sum(abs(x), axis=1)) @@ -1090,11 +1314,56 @@ def cond(x, p=None): -2 smallest singular value ===== ============================ + inf means the numpy.inf object, and the Frobenius norm is + the root-of-sum-of-squares norm. + Returns ------- - c : float + c : {float, inf} The condition number of the matrix. May be infinite. + See Also + -------- + numpy.linalg.linalg.norm + + Notes + ----- + The condition number of `x` is defined as the norm of `x` times the + norm of the inverse of `x` [1]_; the norm can be the usual L2-norm + (root-of-sum-of-squares) or one of a number of other matrix norms. + + References + ---------- + .. [1] G. Strang, *Linear Algebra and Its Applications*, Orlando, FL, + Academic Press, Inc., 1980, pg. 285. + + Examples + -------- + >>> from numpy import linalg as LA + >>> a = np.array([[1, 0, -1], [0, 1, 0], [1, 0, 1]]) + >>> a + array([[ 1, 0, -1], + [ 0, 1, 0], + [ 1, 0, 1]]) + >>> LA.cond(a) + 1.4142135623730951 + >>> LA.cond(a, 'fro') + 3.1622776601683795 + >>> LA.cond(a, np.inf) + 2.0 + >>> LA.cond(a, -np.inf) + 1.0 + >>> LA.cond(a, 1) + 2.0 + >>> LA.cond(a, -1) + 1.0 + >>> LA.cond(a, 2) + 1.4142135623730951 + >>> LA.cond(a, -2) + 0.70710678118654746 + >>> min(LA.svd(a, compute_uv=0))*min(LA.svd(LA.inv(a), compute_uv=0)) + 0.70710678118654746 + """ x = asarray(x) # in case we have a matrix if p is None: @@ -1111,31 +1380,55 @@ def pinv(a, rcond=1e-15 ): Calculate the generalized inverse of a matrix using its singular-value decomposition (SVD) and including all - `large` singular values. + *large* singular values. Parameters ---------- - a : array_like (M, N) + a : array_like, shape (M, N) Matrix to be pseudo-inverted. rcond : float - Cutoff for `small` singular values. - Singular values smaller than rcond*largest_singular_value are - considered zero. + Cutoff for small singular values. + Singular values smaller (in modulus) than + `rcond` * largest_singular_value (again, in modulus) + are set to zero. Returns ------- - B : ndarray (N, M) - The pseudo-inverse of `a`. If `a` is an np.matrix instance, then so + B : ndarray, shape (N, M) + The pseudo-inverse of `a`. If `a` is a `matrix` instance, then so is `B`. - Raises ------ LinAlgError - In case SVD computation does not converge. + If the SVD computation does not converge. + + Notes + ----- + The pseudo-inverse of a matrix A, denoted :math:`A^+`, is + defined as: "the matrix that 'solves' [the least-squares problem] + :math:`Ax = b`," i.e., if :math:`\\bar{x}` is said solution, then + :math:`A^+` is that matrix such that :math:`\\bar{x} = A^+b`. + + It can be shown that if :math:`Q_1 \\Sigma Q_2^T = A` is the singular + value decomposition of A, then + :math:`A^+ = Q_2 \\Sigma^+ Q_1^T`, where :math:`Q_{1,2}` are + orthogonal matrices, :math:`\\Sigma` is a diagonal matrix consisting + of A's so-called singular values, (followed, typically, by + zeros), and then :math:`\\Sigma^+` is simply the diagonal matrix + consisting of the reciprocals of A's singular values + (again, followed by zeros). [1]_ + + References + ---------- + .. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando, + FL, Academic Press, Inc., 1980, pp. 139-142. Examples -------- + The following example checks that ``a * a+ * a == a`` and + ``a+ * a * a+ == a+``: + >>> a = np.random.randn(9, 6) >>> B = np.linalg.pinv(a) >>> np.allclose(a, np.dot(a, np.dot(B, a))) @@ -1214,37 +1507,42 @@ def det(a): def lstsq(a, b, rcond=-1): """ - Return the least-squares solution to an equation. + Return the least-squares solution to a linear matrix equation. Solves the equation `a x = b` by computing a vector `x` that minimizes - the norm `|| b - a x ||`. + the norm `|| b - a x ||`. The equation may be under-, well-, or over- + determined (i.e., the number of linearly independent rows of `a` can be + less than, equal to, or greater than its number of linearly independent + columns). If `a` is square and of full rank, then `x` (but for round-off + error) is the "exact" solution of the equation. Parameters ---------- a : array_like, shape (M, N) - Input equation coefficients. + "Coefficient" matrix. b : array_like, shape (M,) or (M, K) - Equation target values. If `b` is two-dimensional, the least - squares solution is calculated for each of the `K` target sets. + Ordinate or "dependent variable" values. If `b` is two-dimensional, + the least-squares solution is calculated for each of the `K` columns + of `b`. rcond : float, optional - Cutoff for ``small`` singular values of `a`. - Singular values smaller than `rcond` times the largest singular - value are considered zero. + Cut-off ratio for small singular values of `a`. + Singular values are set to zero if they are smaller than `rcond` + times the largest singular value of `a`. Returns ------- - x : ndarray, shape(N,) or (N, K) - Least squares solution. The shape of `x` depends on the shape of - `b`. - residues : ndarray, shape(), (1,), or (K,) - Sums of residues; squared Euclidian norm for each column in - `b - a x`. + x : ndarray, shape (N,) or (N, K) + Least-squares solution. The shape of `x` depends on the shape of + `b`. + residues : ndarray, shape (), (1,), or (K,) + Sums of residues; squared Euclidean norm for each column in + ``b - a*x``. If the rank of `a` is < N or > M, this is an empty array. If `b` is 1-dimensional, this is a (1,) shape array. Otherwise the shape is (K,). - rank : integer + rank : int Rank of matrix `a`. - s : ndarray, shape(min(M,N),) + s : ndarray, shape (min(M,N),) Singular values of `a`. Raises @@ -1254,8 +1552,7 @@ def lstsq(a, b, rcond=-1): Notes ----- - If `b` is a matrix, then all array results are returned as - matrices. + If `b` is a matrix, then all array results are returned as matrices. Examples -------- @@ -1265,7 +1562,7 @@ def lstsq(a, b, rcond=-1): >>> y = np.array([-1, 0.2, 0.9, 2.1]) By examining the coefficients, we see that the line should have a - gradient of roughly 1 and cuts the y-axis at more-or-less -1. + gradient of roughly 1 and cut the y-axis at, more or less, -1. We can rewrite the line equation as ``y = Ap``, where ``A = [[x 1]]`` and ``p = [[m], [c]]``. Now use `lstsq` to solve for `p`: @@ -1358,22 +1655,27 @@ def norm(x, ord=None): """ Matrix or vector norm. + This function is able to return one of seven different matrix norms, + or one of an infinite number of vector norms (described below), depending + on the value of the ``ord`` parameter. + Parameters ---------- x : array_like, shape (M,) or (M, N) Input array. - ord : {2, int, inf, -inf, 'fro'} - Order of the norm (see table under ``Notes``). + ord : {non-zero int, inf, -inf, 'fro'}, optional + Order of the norm (see table under ``Notes``). inf means numpy's + `inf` object. Returns ------- n : float - Norm of the matrix or vector + Norm of the matrix or vector. Notes ----- - For values ord < 0, the result is, strictly speaking, not a - mathematical 'norm', but it may still be useful for numerical + For values of ``ord < 0``, the result is, strictly speaking, not a + mathematical 'norm', but it may still be useful for various numerical purposes. The following norms can be calculated: @@ -1392,6 +1694,64 @@ def norm(x, ord=None): other -- sum(abs(x)**ord)**(1./ord) ===== ============================ ========================== + The Frobenius norm is given by [1]_: + + :math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}` + + References + ---------- + .. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*, + Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15 + + Examples + -------- + >>> from numpy import linalg as LA + >>> a = np.arange(9) - 4 + >>> a + array([-4, -3, -2, -1, 0, 1, 2, 3, 4]) + >>> b = a.reshape((3, 3)) + >>> b + array([[-4, -3, -2], + [-1, 0, 1], + [ 2, 3, 4]]) + + >>> LA.norm(a) + 7.745966692414834 + >>> LA.norm(b) + 7.745966692414834 + >>> LA.norm(b, 'fro') + 7.745966692414834 + >>> LA.norm(a, np.inf) + 4 + >>> LA.norm(b, np.inf) + 9 + >>> LA.norm(a, -np.inf) + 0 + >>> LA.norm(b, -np.inf) + 2 + + >>> LA.norm(a, 1) + 20 + >>> LA.norm(b, 1) + 7 + >>> LA.norm(a, -1) + -4.6566128774142013e-010 + >>> LA.norm(b, -1) + 6 + >>> LA.norm(a, 2) + 7.745966692414834 + >>> LA.norm(b, 2) + 7.3484692283495345 + + >>> LA.norm(a, -2) + nan + >>> LA.norm(b, -2) + 1.8570331885190563e-016 + >>> LA.norm(a, 3) + 5.8480354764257312 + >>> LA.norm(a, -3) + nan + """ x = asarray(x) nd = len(x.shape) |