Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_linalg.py3658 linesDownload Raw Back to linalg
1"""Lite version of scipy.linalg.
2
3Notes
4-----
5This module is a lite version of the linalg.py module in SciPy which
6contains high-level Python interface to the LAPACK library.  The lite
7version only accesses the following LAPACK functions: dgesv, zgesv,
8dgeev, zgeev, dgesdd, zgesdd, dgelsd, zgelsd, dsyevd, zheevd, dgetrf,
9zgetrf, dpotrf, zpotrf, dgeqrf, zgeqrf, zungqr, dorgqr.
10"""
11
12__all__ = ['matrix_power', 'solve', 'tensorsolve', 'tensorinv', 'inv',
13           'cholesky', 'eigvals', 'eigvalsh', 'pinv', 'slogdet', 'det',
14           'svd', 'svdvals', 'eig', 'eigh', 'lstsq', 'norm', 'qr', 'cond',
15           'matrix_rank', 'LinAlgError', 'multi_dot', 'trace', 'diagonal',
16           'cross', 'outer', 'tensordot', 'matmul', 'matrix_transpose',
17           'matrix_norm', 'vector_norm', 'vecdot']
18
19import functools
20import operator
21import warnings
22from typing import Any, NamedTuple
23
24from numpy._core import (
25    abs,
26    add,
27    all,
28    amax,
29    amin,
30    argsort,
31    array,
32    asanyarray,
33    asarray,
34    atleast_2d,
35    cdouble,
36    complexfloating,
37    count_nonzero,
38    cross as _core_cross,
39    csingle,
40    diagonal as _core_diagonal,
41    divide,
42    dot,
43    double,
44    empty,
45    empty_like,
46    errstate,
47    finfo,
48    inexact,
49    inf,
50    intc,
51    intp,
52    isfinite,
53    isnan,
54    matmul as _core_matmul,
55    matrix_transpose as _core_matrix_transpose,
56    moveaxis,
57    multiply,
58    newaxis,
59    object_,
60    outer as _core_outer,
61    overrides,
62    prod,
63    reciprocal,
64    sign,
65    single,
66    sort,
67    sqrt,
68    sum,
69    swapaxes,
70    tensordot as _core_tensordot,
71    trace as _core_trace,
72    transpose as _core_transpose,
73    vecdot as _core_vecdot,
74    zeros,
75)
76from numpy._globals import _NoValue
77from numpy._typing import NDArray
78from numpy._utils import set_module
79from numpy.lib._twodim_base_impl import eye, triu
80from numpy.lib.array_utils import normalize_axis_index, normalize_axis_tuple
81from numpy.linalg import _umath_linalg
82
83
84class EigResult(NamedTuple):
85    eigenvalues: NDArray[Any]
86    eigenvectors: NDArray[Any]
87
88class EighResult(NamedTuple):
89    eigenvalues: NDArray[Any]
90    eigenvectors: NDArray[Any]
91
92class QRResult(NamedTuple):
93    Q: NDArray[Any]
94    R: NDArray[Any]
95
96class SlogdetResult(NamedTuple):
97    sign: NDArray[Any]
98    logabsdet: NDArray[Any]
99
100class SVDResult(NamedTuple):
101    U: NDArray[Any]
102    S: NDArray[Any]
103    Vh: NDArray[Any]
104
105
106array_function_dispatch = functools.partial(
107    overrides.array_function_dispatch, module='numpy.linalg'
108)
109
110
111fortran_int = intc
112
113
114@set_module('numpy.linalg')
115class LinAlgError(ValueError):
116    """
117    Generic Python-exception-derived object raised by linalg functions.
118
119    General purpose exception class, derived from Python's ValueError
120    class, programmatically raised in linalg functions when a Linear
121    Algebra-related condition would prevent further correct execution of the
122    function.
123
124    Parameters
125    ----------
126    None
127
128    Examples
129    --------
130    >>> from numpy import linalg as LA
131    >>> LA.inv(np.zeros((2,2)))
132    Traceback (most recent call last):
133      File "<stdin>", line 1, in <module>
134      File "...linalg.py", line 350,
135        in inv return wrap(solve(a, identity(a.shape[0], dtype=a.dtype)))
136      File "...linalg.py", line 249,
137        in solve
138        raise LinAlgError('Singular matrix')
139    numpy.linalg.LinAlgError: Singular matrix
140
141    """
142
143
144def _raise_linalgerror_singular(err, flag):
145    raise LinAlgError("Singular matrix")
146
147def _raise_linalgerror_nonposdef(err, flag):
148    raise LinAlgError("Matrix is not positive definite")
149
150def _raise_linalgerror_eigenvalues_nonconvergence(err, flag):
151    raise LinAlgError("Eigenvalues did not converge")
152
153def _raise_linalgerror_svd_nonconvergence(err, flag):
154    raise LinAlgError("SVD did not converge")
155
156def _raise_linalgerror_lstsq(err, flag):
157    raise LinAlgError("SVD did not converge in Linear Least Squares")
158
159def _raise_linalgerror_qr(err, flag):
160    raise LinAlgError("Incorrect argument found while performing "
161                      "QR factorization")
162
163
164def _makearray(a):
165    new = asarray(a)
166    wrap = getattr(a, "__array_wrap__", new.__array_wrap__)
167    return new, wrap
168
169def isComplexType(t):
170    return issubclass(t, complexfloating)
171
172
173_real_types_map = {single: single,
174                   double: double,
175                   csingle: single,
176                   cdouble: double}
177
178_complex_types_map = {single: csingle,
179                      double: cdouble,
180                      csingle: csingle,
181                      cdouble: cdouble}
182
183def _realType(t, default=double):
184    return _real_types_map.get(t, default)
185
186def _complexType(t, default=cdouble):
187    return _complex_types_map.get(t, default)
188
189def _commonType(*arrays):
190    # in lite version, use higher precision (always double or cdouble)
191    result_type = single
192    is_complex = False
193    for a in arrays:
194        type_ = a.dtype.type
195        if issubclass(type_, inexact):
196            if isComplexType(type_):
197                is_complex = True
198            rt = _realType(type_, default=None)
199            if rt is double:
200                result_type = double
201            elif rt is None:
202                # unsupported inexact scalar
203                raise TypeError(f"array type {a.dtype.name} is unsupported in linalg")
204        else:
205            result_type = double
206    if is_complex:
207        result_type = _complex_types_map[result_type]
208        return cdouble, result_type
209    else:
210        return double, result_type
211
212
213def _to_native_byte_order(*arrays):
214    ret = []
215    for arr in arrays:
216        if arr.dtype.byteorder not in ('=', '|'):
217            ret.append(asarray(arr, dtype=arr.dtype.newbyteorder('=')))
218        else:
219            ret.append(arr)
220    if len(ret) == 1:
221        return ret[0]
222    else:
223        return ret
224
225
226def _assert_2d(*arrays):
227    for a in arrays:
228        if a.ndim != 2:
229            raise LinAlgError('%d-dimensional array given. Array must be '
230                    'two-dimensional' % a.ndim)
231
232def _assert_stacked_2d(*arrays):
233    for a in arrays:
234        if a.ndim < 2:
235            raise LinAlgError('%d-dimensional array given. Array must be '
236                    'at least two-dimensional' % a.ndim)
237
238def _assert_stacked_square(*arrays):
239    for a in arrays:
240        try:
241            m, n = a.shape[-2:]
242        except ValueError:
243            raise LinAlgError('%d-dimensional array given. Array must be '
244                    'at least two-dimensional' % a.ndim)
245        if m != n:
246            raise LinAlgError('Last 2 dimensions of the array must be square')
247
248def _assert_finite(*arrays):
249    for a in arrays:
250        if not isfinite(a).all():
251            raise LinAlgError("Array must not contain infs or NaNs")
252
253def _is_empty_2d(arr):
254    # check size first for efficiency
255    return arr.size == 0 and prod(arr.shape[-2:]) == 0
256
257
258def transpose(a):
259    """
260    Transpose each matrix in a stack of matrices.
261
262    Unlike np.transpose, this only swaps the last two axes, rather than all of
263    them
264
265    Parameters
266    ----------
267    a : (...,M,N) array_like
268
269    Returns
270    -------
271    aT : (...,N,M) ndarray
272    """
273    return swapaxes(a, -1, -2)
274
275# Linear equations
276
277def _tensorsolve_dispatcher(a, b, axes=None):
278    return (a, b)
279
280
281@array_function_dispatch(_tensorsolve_dispatcher)
282def tensorsolve(a, b, axes=None):
283    """
284    Solve the tensor equation ``a x = b`` for x.
285
286    It is assumed that all indices of `x` are summed over in the product,
287    together with the rightmost indices of `a`, as is done in, for example,
288    ``tensordot(a, x, axes=x.ndim)``.
289
290    Parameters
291    ----------
292    a : array_like
293        Coefficient tensor, of shape ``b.shape + Q``. `Q`, a tuple, equals
294        the shape of that sub-tensor of `a` consisting of the appropriate
295        number of its rightmost indices, and must be such that
296        ``prod(Q) == prod(b.shape)`` (in which sense `a` is said to be
297        'square').
298    b : array_like
299        Right-hand tensor, which can be of any shape.
300    axes : tuple of ints, optional
301        Axes in `a` to reorder to the right, before inversion.
302        If None (default), no reordering is done.
303
304    Returns
305    -------
306    x : ndarray, shape Q
307
308    Raises
309    ------
310    LinAlgError
311        If `a` is singular or not 'square' (in the above sense).
312
313    See Also
314    --------
315    numpy.tensordot, tensorinv, numpy.einsum
316
317    Examples
318    --------
319    >>> import numpy as np
320    >>> a = np.eye(2*3*4).reshape((2*3, 4, 2, 3, 4))
321    >>> rng = np.random.default_rng()
322    >>> b = rng.normal(size=(2*3, 4))
323    >>> x = np.linalg.tensorsolve(a, b)
324    >>> x.shape
325    (2, 3, 4)
326    >>> np.allclose(np.tensordot(a, x, axes=3), b)
327    True
328
329    """
330    a, wrap = _makearray(a)
331    b = asarray(b)
332    an = a.ndim
333
334    if axes is not None:
335        allaxes = list(range(an))
336        for k in axes:
337            allaxes.remove(k)
338            allaxes.insert(an, k)
339        a = a.transpose(allaxes)
340
341    oldshape = a.shape[-(an - b.ndim):]
342    prod = 1
343    for k in oldshape:
344        prod *= k
345
346    if a.size != prod ** 2:
347        raise LinAlgError(
348            "Input arrays must satisfy the requirement \
349            prod(a.shape[b.ndim:]) == prod(a.shape[:b.ndim])"
350        )
351
352    a = a.reshape(prod, prod)
353    b = b.ravel()
354    res = wrap(solve(a, b))
355    res.shape = oldshape
356    return res
357
358
359def _solve_dispatcher(a, b):
360    return (a, b)
361
362
363@array_function_dispatch(_solve_dispatcher)
364def solve(a, b):
365    """
366    Solve a linear matrix equation, or system of linear scalar equations.
367
368    Computes the "exact" solution, `x`, of the well-determined, i.e., full
369    rank, linear matrix equation `ax = b`.
370
371    Parameters
372    ----------
373    a : (..., M, M) array_like
374        Coefficient matrix.
375    b : {(M,), (..., M, K)}, array_like
376        Ordinate or "dependent variable" values.
377
378    Returns
379    -------
380    x : {(..., M,), (..., M, K)} ndarray
381        Solution to the system a x = b.  Returned shape is (..., M) if b is
382        shape (M,) and (..., M, K) if b is (..., M, K), where the "..." part is
383        broadcasted between a and b.
384
385    Raises
386    ------
387    LinAlgError
388        If `a` is singular or not square.
389
390    See Also
391    --------
392    scipy.linalg.solve : Similar function in SciPy.
393
394    Notes
395    -----
396    Broadcasting rules apply, see the `numpy.linalg` documentation for
397    details.
398
399    The solutions are computed using LAPACK routine ``_gesv``.
400
401    `a` must be square and of full-rank, i.e., all rows (or, equivalently,
402    columns) must be linearly independent; if either is not true, use
403    `lstsq` for the least-squares best "solution" of the
404    system/equation.
405
406    .. versionchanged:: 2.0
407
408       The b array is only treated as a shape (M,) column vector if it is
409       exactly 1-dimensional. In all other instances it is treated as a stack
410       of (M, K) matrices. Previously b would be treated as a stack of (M,)
411       vectors if b.ndim was equal to a.ndim - 1.
412
413    References
414    ----------
415    .. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando,
416           FL, Academic Press, Inc., 1980, pg. 22.
417
418    Examples
419    --------
420    Solve the system of equations:
421    ``x0 + 2 * x1 = 1`` and
422    ``3 * x0 + 5 * x1 = 2``:
423
424    >>> import numpy as np
425    >>> a = np.array([[1, 2], [3, 5]])
426    >>> b = np.array([1, 2])
427    >>> x = np.linalg.solve(a, b)
428    >>> x
429    array([-1.,  1.])
430
431    Check that the solution is correct:
432
433    >>> np.allclose(np.dot(a, x), b)
434    True
435
436    """
437    a, _ = _makearray(a)
438    _assert_stacked_square(a)
439    b, wrap = _makearray(b)
440    t, result_t = _commonType(a, b)
441
442    # We use the b = (..., M,) logic, only if the number of extra dimensions
443    # match exactly
444    if b.ndim == 1:
445        gufunc = _umath_linalg.solve1
446    else:
447        gufunc = _umath_linalg.solve
448
449    signature = 'DD->D' if isComplexType(t) else 'dd->d'
450    with errstate(call=_raise_linalgerror_singular, invalid='call',
451                  over='ignore', divide='ignore', under='ignore'):
452        r = gufunc(a, b, signature=signature)
453
454    return wrap(r.astype(result_t, copy=False))
455
456
457def _tensorinv_dispatcher(a, ind=None):
458    return (a,)
459
460
461@array_function_dispatch(_tensorinv_dispatcher)
462def tensorinv(a, ind=2):
463    """
464    Compute the 'inverse' of an N-dimensional array.
465
466    The result is an inverse for `a` relative to the tensordot operation
467    ``tensordot(a, b, ind)``, i. e., up to floating-point accuracy,
468    ``tensordot(tensorinv(a), a, ind)`` is the "identity" tensor for the
469    tensordot operation.
470
471    Parameters
472    ----------
473    a : array_like
474        Tensor to 'invert'. Its shape must be 'square', i. e.,
475        ``prod(a.shape[:ind]) == prod(a.shape[ind:])``.
476    ind : int, optional
477        Number of first indices that are involved in the inverse sum.
478        Must be a positive integer, default is 2.
479
480    Returns
481    -------
482    b : ndarray
483        `a`'s tensordot inverse, shape ``a.shape[ind:] + a.shape[:ind]``.
484
485    Raises
486    ------
487    LinAlgError
488        If `a` is singular or not 'square' (in the above sense).
489
490    See Also
491    --------
492    numpy.tensordot, tensorsolve
493
494    Examples
495    --------
496    >>> import numpy as np
497    >>> a = np.eye(4*6).reshape((4, 6, 8, 3))
498    >>> ainv = np.linalg.tensorinv(a, ind=2)
499    >>> ainv.shape
500    (8, 3, 4, 6)
501    >>> rng = np.random.default_rng()
502    >>> b = rng.normal(size=(4, 6))
503    >>> np.allclose(np.tensordot(ainv, b), np.linalg.tensorsolve(a, b))
504    True
505
506    >>> a = np.eye(4*6).reshape((24, 8, 3))
507    >>> ainv = np.linalg.tensorinv(a, ind=1)
508    >>> ainv.shape
509    (8, 3, 24)
510    >>> rng = np.random.default_rng()
511    >>> b = rng.normal(size=24)
512    >>> np.allclose(np.tensordot(ainv, b, 1), np.linalg.tensorsolve(a, b))
513    True
514
515    """
516    a = asarray(a)
517    oldshape = a.shape
518    prod = 1
519    if ind > 0:
520        invshape = oldshape[ind:] + oldshape[:ind]
521        for k in oldshape[ind:]:
522            prod *= k
523    else:
524        raise ValueError("Invalid ind argument.")
525    a = a.reshape(prod, -1)
526    ia = inv(a)
527    return ia.reshape(*invshape)
528
529
530# Matrix inversion
531
532def _unary_dispatcher(a):
533    return (a,)
534
535
536@array_function_dispatch(_unary_dispatcher)
537def inv(a):
538    """
539    Compute the inverse of a matrix.
540
541    Given a square matrix `a`, return the matrix `ainv` satisfying
542    ``a @ ainv = ainv @ a = eye(a.shape[0])``.
543
544    Parameters
545    ----------
546    a : (..., M, M) array_like
547        Matrix to be inverted.
548
549    Returns
550    -------
551    ainv : (..., M, M) ndarray or matrix
552        Inverse of the matrix `a`.
553
554    Raises
555    ------
556    LinAlgError
557        If `a` is not square or inversion fails.
558
559    See Also
560    --------
561    scipy.linalg.inv : Similar function in SciPy.
562    numpy.linalg.cond : Compute the condition number of a matrix.
563    numpy.linalg.svd : Compute the singular value decomposition of a matrix.
564
565    Notes
566    -----
567    Broadcasting rules apply, see the `numpy.linalg` documentation for
568    details.
569
570    If `a` is detected to be singular, a `LinAlgError` is raised. If `a` is
571    ill-conditioned, a `LinAlgError` may or may not be raised, and results may
572    be inaccurate due to floating-point errors.
573
574    References
575    ----------
576    .. [1] Wikipedia, "Condition number",
577           https://en.wikipedia.org/wiki/Condition_number
578
579    Examples
580    --------
581    >>> import numpy as np
582    >>> from numpy.linalg import inv
583    >>> a = np.array([[1., 2.], [3., 4.]])
584    >>> ainv = inv(a)
585    >>> np.allclose(a @ ainv, np.eye(2))
586    True
587    >>> np.allclose(ainv @ a, np.eye(2))
588    True
589
590    If a is a matrix object, then the return value is a matrix as well:
591
592    >>> ainv = inv(np.matrix(a))
593    >>> ainv
594    matrix([[-2. ,  1. ],
595            [ 1.5, -0.5]])
596
597    Inverses of several matrices can be computed at once:
598
599    >>> a = np.array([[[1., 2.], [3., 4.]], [[1, 3], [3, 5]]])
600    >>> inv(a)
601    array([[[-2.  ,  1.  ],
602            [ 1.5 , -0.5 ]],
603           [[-1.25,  0.75],
604            [ 0.75, -0.25]]])
605
606    If a matrix is close to singular, the computed inverse may not satisfy
607    ``a @ ainv = ainv @ a = eye(a.shape[0])`` even if a `LinAlgError`
608    is not raised:
609
610    >>> a = np.array([[2,4,6],[2,0,2],[6,8,14]])
611    >>> inv(a)  # No errors raised
612    array([[-1.12589991e+15, -5.62949953e+14,  5.62949953e+14],
613       [-1.12589991e+15, -5.62949953e+14,  5.62949953e+14],
614       [ 1.12589991e+15,  5.62949953e+14, -5.62949953e+14]])
615    >>> a @ inv(a)
616    array([[ 0.   , -0.5  ,  0.   ],  # may vary
617           [-0.5  ,  0.625,  0.25 ],
618           [ 0.   ,  0.   ,  1.   ]])
619
620    To detect ill-conditioned matrices, you can use `numpy.linalg.cond` to
621    compute its *condition number* [1]_. The larger the condition number, the
622    more ill-conditioned the matrix is. As a rule of thumb, if the condition
623    number ``cond(a) = 10**k``, then you may lose up to ``k`` digits of
624    accuracy on top of what would be lost to the numerical method due to loss
625    of precision from arithmetic methods.
626
627    >>> from numpy.linalg import cond
628    >>> cond(a)
629    np.float64(8.659885634118668e+17)  # may vary
630
631    It is also possible to detect ill-conditioning by inspecting the matrix's
632    singular values directly. The ratio between the largest and the smallest
633    singular value is the condition number:
634
635    >>> from numpy.linalg import svd
636    >>> sigma = svd(a, compute_uv=False)  # Do not compute singular vectors
637    >>> sigma.max()/sigma.min()
638    8.659885634118668e+17  # may vary
639
640    """
641    a, wrap = _makearray(a)
642    _assert_stacked_square(a)
643    t, result_t = _commonType(a)
644
645    signature = 'D->D' if isComplexType(t) else 'd->d'
646    with errstate(call=_raise_linalgerror_singular, invalid='call',
647                  over='ignore', divide='ignore', under='ignore'):
648        ainv = _umath_linalg.inv(a, signature=signature)
649    return wrap(ainv.astype(result_t, copy=False))
650
651
652def _matrix_power_dispatcher(a, n):
653    return (a,)
654
655
656@array_function_dispatch(_matrix_power_dispatcher)
657def matrix_power(a, n):
658    """
659    Raise a square matrix to the (integer) power `n`.
660
661    For positive integers `n`, the power is computed by repeated matrix
662    squarings and matrix multiplications. If ``n == 0``, the identity matrix
663    of the same shape as M is returned. If ``n < 0``, the inverse
664    is computed and then raised to the ``abs(n)``.
665
666    .. note:: Stacks of object matrices are not currently supported.
667
668    Parameters
669    ----------
670    a : (..., M, M) array_like
671        Matrix to be "powered".
672    n : int
673        The exponent can be any integer or long integer, positive,
674        negative, or zero.
675
676    Returns
677    -------
678    a**n : (..., M, M) ndarray or matrix object
679        The return value is the same shape and type as `M`;
680        if the exponent is positive or zero then the type of the
681        elements is the same as those of `M`. If the exponent is
682        negative the elements are floating-point.
683
684    Raises
685    ------
686    LinAlgError
687        For matrices that are not square or that (for negative powers) cannot
688        be inverted numerically.
689
690    Examples
691    --------
692    >>> import numpy as np
693    >>> from numpy.linalg import matrix_power
694    >>> i = np.array([[0, 1], [-1, 0]]) # matrix equiv. of the imaginary unit
695    >>> matrix_power(i, 3) # should = -i
696    array([[ 0, -1],
697           [ 1,  0]])
698    >>> matrix_power(i, 0)
699    array([[1, 0],
700           [0, 1]])
701    >>> matrix_power(i, -3) # should = 1/(-i) = i, but w/ f.p. elements
702    array([[ 0.,  1.],
703           [-1.,  0.]])
704
705    Somewhat more sophisticated example
706
707    >>> q = np.zeros((4, 4))
708    >>> q[0:2, 0:2] = -i
709    >>> q[2:4, 2:4] = i
710    >>> q # one of the three quaternion units not equal to 1
711    array([[ 0., -1.,  0.,  0.],
712           [ 1.,  0.,  0.,  0.],
713           [ 0.,  0.,  0.,  1.],
714           [ 0.,  0., -1.,  0.]])
715    >>> matrix_power(q, 2) # = -np.eye(4)
716    array([[-1.,  0.,  0.,  0.],
717           [ 0., -1.,  0.,  0.],
718           [ 0.,  0., -1.,  0.],
719           [ 0.,  0.,  0., -1.]])
720
721    """
722    a = asanyarray(a)
723    _assert_stacked_square(a)
724
725    try:
726        n = operator.index(n)
727    except TypeError as e:
728        raise TypeError("exponent must be an integer") from e
729
730    # Fall back on dot for object arrays. Object arrays are not supported by
731    # the current implementation of matmul using einsum
732    if a.dtype != object:
733        fmatmul = matmul
734    elif a.ndim == 2:
735        fmatmul = dot
736    else:
737        raise NotImplementedError(
738            "matrix_power not supported for stacks of object arrays")
739
740    if n == 0:
741        a = empty_like(a)
742        a[...] = eye(a.shape[-2], dtype=a.dtype)
743        return a
744
745    elif n < 0:
746        a = inv(a)
747        n = abs(n)
748
749    # short-cuts.
750    if n == 1:
751        return a
752
753    elif n == 2:
754        return fmatmul(a, a)
755
756    elif n == 3:
757        return fmatmul(fmatmul(a, a), a)
758
759    # Use binary decomposition to reduce the number of matrix multiplications.
760    # Here, we iterate over the bits of n, from LSB to MSB, raise `a` to
761    # increasing powers of 2, and multiply into the result as needed.
762    z = result = None
763    while n > 0:
764        z = a if z is None else fmatmul(z, z)
765        n, bit = divmod(n, 2)
766        if bit:
767            result = z if result is None else fmatmul(result, z)
768
769    return result
770
771
772# Cholesky decomposition
773
774def _cholesky_dispatcher(a, /, *, upper=None):
775    return (a,)
776
777
778@array_function_dispatch(_cholesky_dispatcher)
779def cholesky(a, /, *, upper=False):
780    """
781    Cholesky decomposition.
782
783    Return the lower or upper Cholesky decomposition, ``L * L.H`` or
784    ``U.H * U``, of the square matrix ``a``, where ``L`` is lower-triangular,
785    ``U`` is upper-triangular, and ``.H`` is the conjugate transpose operator
786    (which is the ordinary transpose if ``a`` is real-valued). ``a`` must be
787    Hermitian (symmetric if real-valued) and positive-definite. No checking is
788    performed to verify whether ``a`` is Hermitian or not. In addition, only
789    the lower or upper-triangular and diagonal elements of ``a`` are used.
790    Only ``L`` or ``U`` is actually returned.
791
792    Parameters
793    ----------
794    a : (..., M, M) array_like
795        Hermitian (symmetric if all elements are real), positive-definite
796        input matrix.
797    upper : bool
798        If ``True``, the result must be the upper-triangular Cholesky factor.
799        If ``False``, the result must be the lower-triangular Cholesky factor.
800        Default: ``False``.
801
802    Returns
803    -------
804    L : (..., M, M) array_like
805        Lower or upper-triangular Cholesky factor of `a`. Returns a matrix
806        object if `a` is a matrix object.
807
808    Raises
809    ------
810    LinAlgError
811       If the decomposition fails, for example, if `a` is not
812       positive-definite.
813
814    See Also
815    --------
816    scipy.linalg.cholesky : Similar function in SciPy.
817    scipy.linalg.cholesky_banded : Cholesky decompose a banded Hermitian
818                                   positive-definite matrix.
819    scipy.linalg.cho_factor : Cholesky decomposition of a matrix, to use in
820                              `scipy.linalg.cho_solve`.
821
822    Notes
823    -----
824    Broadcasting rules apply, see the `numpy.linalg` documentation for
825    details.
826
827    The Cholesky decomposition is often used as a fast way of solving
828
829    .. math:: A \\mathbf{x} = \\mathbf{b}
830
831    (when `A` is both Hermitian/symmetric and positive-definite).
832
833    First, we solve for :math:`\\mathbf{y}` in
834
835    .. math:: L \\mathbf{y} = \\mathbf{b},
836
837    and then for :math:`\\mathbf{x}` in
838
839    .. math:: L^{H} \\mathbf{x} = \\mathbf{y}.
840
841    Examples
842    --------
843    >>> import numpy as np
844    >>> A = np.array([[1,-2j],[2j,5]])
845    >>> A
846    array([[ 1.+0.j, -0.-2.j],
847           [ 0.+2.j,  5.+0.j]])
848    >>> L = np.linalg.cholesky(A)
849    >>> L
850    array([[1.+0.j, 0.+0.j],
851           [0.+2.j, 1.+0.j]])
852    >>> np.dot(L, L.T.conj()) # verify that L * L.H = A
853    array([[1.+0.j, 0.-2.j],
854           [0.+2.j, 5.+0.j]])
855    >>> A = [[1,-2j],[2j,5]] # what happens if A is only array_like?
856    >>> np.linalg.cholesky(A) # an ndarray object is returned
857    array([[1.+0.j, 0.+0.j],
858           [0.+2.j, 1.+0.j]])
859    >>> # But a matrix object is returned if A is a matrix object
860    >>> np.linalg.cholesky(np.matrix(A))
861    matrix([[ 1.+0.j,  0.+0.j],
862            [ 0.+2.j,  1.+0.j]])
863    >>> # The upper-triangular Cholesky factor can also be obtained.
864    >>> np.linalg.cholesky(A, upper=True)
865    array([[1.-0.j, 0.-2.j],
866           [0.-0.j, 1.-0.j]])
867
868    """
869    gufunc = _umath_linalg.cholesky_up if upper else _umath_linalg.cholesky_lo
870    a, wrap = _makearray(a)
871    _assert_stacked_square(a)
872    t, result_t = _commonType(a)
873    signature = 'D->D' if isComplexType(t) else 'd->d'
874    with errstate(call=_raise_linalgerror_nonposdef, invalid='call',
875                  over='ignore', divide='ignore', under='ignore'):
876        r = gufunc(a, signature=signature)
877    return wrap(r.astype(result_t, copy=False))
878
879
880# outer product
881
882
883def _outer_dispatcher(x1, x2):
884    return (x1, x2)
885
886
887@array_function_dispatch(_outer_dispatcher)
888def outer(x1, x2, /):
889    """
890    Compute the outer product of two vectors.
891
892    This function is Array API compatible. Compared to ``np.outer``
893    it accepts 1-dimensional inputs only.
894
895    Parameters
896    ----------
897    x1 : (M,) array_like
898        One-dimensional input array of size ``N``.
899        Must have a numeric data type.
900    x2 : (N,) array_like
901        One-dimensional input array of size ``M``.
902        Must have a numeric data type.
903
904    Returns
905    -------
906    out : (M, N) ndarray
907        ``out[i, j] = a[i] * b[j]``
908
909    See also
910    --------
911    outer
912
913    Examples
914    --------
915    Make a (*very* coarse) grid for computing a Mandelbrot set:
916
917    >>> rl = np.linalg.outer(np.ones((5,)), np.linspace(-2, 2, 5))
918    >>> rl
919    array([[-2., -1.,  0.,  1.,  2.],
920           [-2., -1.,  0.,  1.,  2.],
921           [-2., -1.,  0.,  1.,  2.],
922           [-2., -1.,  0.,  1.,  2.],
923           [-2., -1.,  0.,  1.,  2.]])
924    >>> im = np.linalg.outer(1j*np.linspace(2, -2, 5), np.ones((5,)))
925    >>> im
926    array([[0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j],
927           [0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j],
928           [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
929           [0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j],
930           [0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j]])
931    >>> grid = rl + im
932    >>> grid
933    array([[-2.+2.j, -1.+2.j,  0.+2.j,  1.+2.j,  2.+2.j],
934           [-2.+1.j, -1.+1.j,  0.+1.j,  1.+1.j,  2.+1.j],
935           [-2.+0.j, -1.+0.j,  0.+0.j,  1.+0.j,  2.+0.j],
936           [-2.-1.j, -1.-1.j,  0.-1.j,  1.-1.j,  2.-1.j],
937           [-2.-2.j, -1.-2.j,  0.-2.j,  1.-2.j,  2.-2.j]])
938
939    An example using a "vector" of letters:
940
941    >>> x = np.array(['a', 'b', 'c'], dtype=object)
942    >>> np.linalg.outer(x, [1, 2, 3])
943    array([['a', 'aa', 'aaa'],
944           ['b', 'bb', 'bbb'],
945           ['c', 'cc', 'ccc']], dtype=object)
946
947    """
948    x1 = asanyarray(x1)
949    x2 = asanyarray(x2)
950    if x1.ndim != 1 or x2.ndim != 1:
951        raise ValueError(
952            "Input arrays must be one-dimensional, but they are "
953            f"{x1.ndim=} and {x2.ndim=}."
954        )
955    return _core_outer(x1, x2, out=None)
956
957
958# QR decomposition
959
960
961def _qr_dispatcher(a, mode=None):
962    return (a,)
963
964
965@array_function_dispatch(_qr_dispatcher)
966def qr(a, mode='reduced'):
967    """
968    Compute the qr factorization of a matrix.
969
970    Factor the matrix `a` as *qr*, where `q` is orthonormal and `r` is
971    upper-triangular.
972
973    Parameters
974    ----------
975    a : array_like, shape (..., M, N)
976        An array-like object with the dimensionality of at least 2.
977    mode : {'reduced', 'complete', 'r', 'raw'}, optional, default: 'reduced'
978        If K = min(M, N), then
979
980        * 'reduced'  : returns Q, R with dimensions (..., M, K), (..., K, N)
981        * 'complete' : returns Q, R with dimensions (..., M, M), (..., M, N)
982        * 'r'        : returns R only with dimensions (..., K, N)
983        * 'raw'      : returns h, tau with dimensions (..., N, M), (..., K,)
984
985        The options 'reduced', 'complete, and 'raw' are new in numpy 1.8,
986        see the notes for more information. The default is 'reduced', and to
987        maintain backward compatibility with earlier versions of numpy both
988        it and the old default 'full' can be omitted. Note that array h
989        returned in 'raw' mode is transposed for calling Fortran. The
990        'economic' mode is deprecated.  The modes 'full' and 'economic' may
991        be passed using only the first letter for backwards compatibility,
992        but all others must be spelled out. See the Notes for more
993        explanation.
994
995
996    Returns
997    -------
998    Q : ndarray of float or complex, optional
999        A matrix with orthonormal columns. When mode = 'complete' the
1000        result is an orthogonal/unitary matrix depending on whether or not
1001        a is real/complex. The determinant may be either +/- 1 in that
1002        case. In case the number of dimensions in the input array is
1003        greater than 2 then a stack of the matrices with above properties
1004        is returned.
1005    R : ndarray of float or complex, optional
1006        The upper-triangular matrix or a stack of upper-triangular
1007        matrices if the number of dimensions in the input array is greater
1008        than 2.
1009    (h, tau) : ndarrays of np.double or np.cdouble, optional
1010        The array h contains the Householder reflectors that generate q
1011        along with r. The tau array contains scaling factors for the
1012        reflectors. In the deprecated  'economic' mode only h is returned.
1013
1014    Raises
1015    ------
1016    LinAlgError
1017        If factoring fails.
1018
1019    See Also
1020    --------
1021    scipy.linalg.qr : Similar function in SciPy.
1022    scipy.linalg.rq : Compute RQ decomposition of a matrix.
1023
1024    Notes
1025    -----
1026    When mode is 'reduced' or 'complete', the result will be a namedtuple with
1027    the attributes ``Q`` and ``R``.
1028
1029    This is an interface to the LAPACK routines ``dgeqrf``, ``zgeqrf``,
1030    ``dorgqr``, and ``zungqr``.
1031
1032    For more information on the qr factorization, see for example:
1033    https://en.wikipedia.org/wiki/QR_factorization
1034
1035    Subclasses of `ndarray` are preserved except for the 'raw' mode. So if
1036    `a` is of type `matrix`, all the return values will be matrices too.
1037
1038    New 'reduced', 'complete', and 'raw' options for mode were added in
1039    NumPy 1.8.0 and the old option 'full' was made an alias of 'reduced'.  In
1040    addition the options 'full' and 'economic' were deprecated.  Because
1041    'full' was the previous default and 'reduced' is the new default,
1042    backward compatibility can be maintained by letting `mode` default.
1043    The 'raw' option was added so that LAPACK routines that can multiply
1044    arrays by q using the Householder reflectors can be used. Note that in
1045    this case the returned arrays are of type np.double or np.cdouble and
1046    the h array is transposed to be FORTRAN compatible.  No routines using
1047    the 'raw' return are currently exposed by numpy, but some are available
1048    in lapack_lite and just await the necessary work.
1049
1050    Examples
1051    --------
1052    >>> import numpy as np
1053    >>> rng = np.random.default_rng()
1054    >>> a = rng.normal(size=(9, 6))
1055    >>> Q, R = np.linalg.qr(a)
1056    >>> np.allclose(a, np.dot(Q, R))  # a does equal QR
1057    True
1058    >>> R2 = np.linalg.qr(a, mode='r')
1059    >>> np.allclose(R, R2)  # mode='r' returns the same R as mode='full'
1060    True
1061    >>> a = np.random.normal(size=(3, 2, 2)) # Stack of 2 x 2 matrices as input
1062    >>> Q, R = np.linalg.qr(a)
1063    >>> Q.shape
1064    (3, 2, 2)
1065    >>> R.shape
1066    (3, 2, 2)
1067    >>> np.allclose(a, np.matmul(Q, R))
1068    True
1069
1070    Example illustrating a common use of `qr`: solving of least squares
1071    problems
1072
1073    What are the least-squares-best `m` and `y0` in ``y = y0 + mx`` for
1074    the following data: {(0,1), (1,0), (1,2), (2,1)}. (Graph the points
1075    and you'll see that it should be y0 = 0, m = 1.)  The answer is provided
1076    by solving the over-determined matrix equation ``Ax = b``, where::
1077
1078      A = array([[0, 1], [1, 1], [1, 1], [2, 1]])
1079      x = array([[y0], [m]])
1080      b = array([[1], [0], [2], [1]])
1081
1082    If A = QR such that Q is orthonormal (which is always possible via
1083    Gram-Schmidt), then ``x = inv(R) * (Q.T) * b``.  (In numpy practice,
1084    however, we simply use `lstsq`.)
1085
1086    >>> A = np.array([[0, 1], [1, 1], [1, 1], [2, 1]])
1087    >>> A
1088    array([[0, 1],
1089           [1, 1],
1090           [1, 1],
1091           [2, 1]])
1092    >>> b = np.array([1, 2, 2, 3])
1093    >>> Q, R = np.linalg.qr(A)
1094    >>> p = np.dot(Q.T, b)
1095    >>> np.dot(np.linalg.inv(R), p)
1096    array([  1.,   1.])
1097
1098    """
1099    if mode not in ('reduced', 'complete', 'r', 'raw'):
1100        if mode in ('f', 'full'):
1101            # 2013-04-01, 1.8
1102            msg = (
1103                "The 'full' option is deprecated in favor of 'reduced'.\n"
1104                "For backward compatibility let mode default."
1105            )
1106            warnings.warn(msg, DeprecationWarning, stacklevel=2)
1107            mode = 'reduced'
1108        elif mode in ('e', 'economic'):
1109            # 2013-04-01, 1.8
1110            msg = "The 'economic' option is deprecated."
1111            warnings.warn(msg, DeprecationWarning, stacklevel=2)
1112            mode = 'economic'
1113        else:
1114            raise ValueError(f"Unrecognized mode '{mode}'")
1115
1116    a, wrap = _makearray(a)
1117    _assert_stacked_2d(a)
1118    m, n = a.shape[-2:]
1119    t, result_t = _commonType(a)
1120    a = a.astype(t, copy=True)
1121    a = _to_native_byte_order(a)
1122    mn = min(m, n)
1123
1124    signature = 'D->D' if isComplexType(t) else 'd->d'
1125    with errstate(call=_raise_linalgerror_qr, invalid='call',
1126                  over='ignore', divide='ignore', under='ignore'):
1127        tau = _umath_linalg.qr_r_raw(a, signature=signature)
1128
1129    # handle modes that don't return q
1130    if mode == 'r':
1131        r = triu(a[..., :mn, :])
1132        r = r.astype(result_t, copy=False)
1133        return wrap(r)
1134
1135    if mode == 'raw':
1136        q = transpose(a)
1137        q = q.astype(result_t, copy=False)
1138        tau = tau.astype(result_t, copy=False)
1139        return wrap(q), tau
1140
1141    if mode == 'economic':
1142        a = a.astype(result_t, copy=False)
1143        return wrap(a)
1144
1145    # mc is the number of columns in the resulting q
1146    # matrix. If the mode is complete then it is
1147    # same as number of rows, and if the mode is reduced,
1148    # then it is the minimum of number of rows and columns.
1149    if mode == 'complete' and m > n:
1150        mc = m
1151        gufunc = _umath_linalg.qr_complete
1152    else:
1153        mc = mn
1154        gufunc = _umath_linalg.qr_reduced
1155
1156    signature = 'DD->D' if isComplexType(t) else 'dd->d'
1157    with errstate(call=_raise_linalgerror_qr, invalid='call',
1158                  over='ignore', divide='ignore', under='ignore'):
1159        q = gufunc(a, tau, signature=signature)
1160    r = triu(a[..., :mc, :])
1161
1162    q = q.astype(result_t, copy=False)
1163    r = r.astype(result_t, copy=False)
1164
1165    return QRResult(wrap(q), wrap(r))
1166
1167# Eigenvalues
1168
1169
1170@array_function_dispatch(_unary_dispatcher)
1171def eigvals(a):
1172    """
1173    Compute the eigenvalues of a general matrix.
1174
1175    Main difference between `eigvals` and `eig`: the eigenvectors aren't
1176    returned.
1177
1178    Parameters
1179    ----------
1180    a : (..., M, M) array_like
1181        A complex- or real-valued matrix whose eigenvalues will be computed.
1182
1183    Returns
1184    -------
1185    w : (..., M,) ndarray
1186        The eigenvalues, each repeated according to its multiplicity.
1187        They are not necessarily ordered, nor are they necessarily
1188        real for real matrices.
1189
1190    Raises
1191    ------
1192    LinAlgError
1193        If the eigenvalue computation does not converge.
1194
1195    See Also
1196    --------
1197    eig : eigenvalues and right eigenvectors of general arrays
1198    eigvalsh : eigenvalues of real symmetric or complex Hermitian
1199               (conjugate symmetric) arrays.
1200    eigh : eigenvalues and eigenvectors of real symmetric or complex

Showing the first 1,200 of 3658 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai