Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/numpy/linalg/linalg.py
7771 views
1
"""Lite version of scipy.linalg.
2
3
Notes
4
-----
5
This module is a lite version of the linalg.py module in SciPy which
6
contains high-level Python interface to the LAPACK library. The lite
7
version only accesses the following LAPACK functions: dgesv, zgesv,
8
dgeev, zgeev, dgesdd, zgesdd, dgelsd, zgelsd, dsyevd, zheevd, dgetrf,
9
zgetrf, 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', 'eig', 'eigh', 'lstsq', 'norm', 'qr', 'cond', 'matrix_rank',
15
'LinAlgError', 'multi_dot']
16
17
import functools
18
import operator
19
import warnings
20
21
from numpy.core import (
22
array, asarray, zeros, empty, empty_like, intc, single, double,
23
csingle, cdouble, inexact, complexfloating, newaxis, all, Inf, dot,
24
add, multiply, sqrt, fastCopyAndTranspose, sum, isfinite,
25
finfo, errstate, geterrobj, moveaxis, amin, amax, product, abs,
26
atleast_2d, intp, asanyarray, object_, matmul,
27
swapaxes, divide, count_nonzero, isnan, sign, argsort, sort
28
)
29
from numpy.core.multiarray import normalize_axis_index
30
from numpy.core.overrides import set_module
31
from numpy.core import overrides
32
from numpy.lib.twodim_base import triu, eye
33
from numpy.linalg import _umath_linalg
34
35
36
array_function_dispatch = functools.partial(
37
overrides.array_function_dispatch, module='numpy.linalg')
38
39
40
fortran_int = intc
41
42
43
@set_module('numpy.linalg')
44
class LinAlgError(Exception):
45
"""
46
Generic Python-exception-derived object raised by linalg functions.
47
48
General purpose exception class, derived from Python's exception.Exception
49
class, programmatically raised in linalg functions when a Linear
50
Algebra-related condition would prevent further correct execution of the
51
function.
52
53
Parameters
54
----------
55
None
56
57
Examples
58
--------
59
>>> from numpy import linalg as LA
60
>>> LA.inv(np.zeros((2,2)))
61
Traceback (most recent call last):
62
File "<stdin>", line 1, in <module>
63
File "...linalg.py", line 350,
64
in inv return wrap(solve(a, identity(a.shape[0], dtype=a.dtype)))
65
File "...linalg.py", line 249,
66
in solve
67
raise LinAlgError('Singular matrix')
68
numpy.linalg.LinAlgError: Singular matrix
69
70
"""
71
72
73
def _determine_error_states():
74
errobj = geterrobj()
75
bufsize = errobj[0]
76
77
with errstate(invalid='call', over='ignore',
78
divide='ignore', under='ignore'):
79
invalid_call_errmask = geterrobj()[1]
80
81
return [bufsize, invalid_call_errmask, None]
82
83
# Dealing with errors in _umath_linalg
84
_linalg_error_extobj = _determine_error_states()
85
del _determine_error_states
86
87
def _raise_linalgerror_singular(err, flag):
88
raise LinAlgError("Singular matrix")
89
90
def _raise_linalgerror_nonposdef(err, flag):
91
raise LinAlgError("Matrix is not positive definite")
92
93
def _raise_linalgerror_eigenvalues_nonconvergence(err, flag):
94
raise LinAlgError("Eigenvalues did not converge")
95
96
def _raise_linalgerror_svd_nonconvergence(err, flag):
97
raise LinAlgError("SVD did not converge")
98
99
def _raise_linalgerror_lstsq(err, flag):
100
raise LinAlgError("SVD did not converge in Linear Least Squares")
101
102
def _raise_linalgerror_qr(err, flag):
103
raise LinAlgError("Incorrect argument found while performing "
104
"QR factorization")
105
106
def get_linalg_error_extobj(callback):
107
extobj = list(_linalg_error_extobj) # make a copy
108
extobj[2] = callback
109
return extobj
110
111
def _makearray(a):
112
new = asarray(a)
113
wrap = getattr(a, "__array_prepare__", new.__array_wrap__)
114
return new, wrap
115
116
def isComplexType(t):
117
return issubclass(t, complexfloating)
118
119
_real_types_map = {single : single,
120
double : double,
121
csingle : single,
122
cdouble : double}
123
124
_complex_types_map = {single : csingle,
125
double : cdouble,
126
csingle : csingle,
127
cdouble : cdouble}
128
129
def _realType(t, default=double):
130
return _real_types_map.get(t, default)
131
132
def _complexType(t, default=cdouble):
133
return _complex_types_map.get(t, default)
134
135
def _commonType(*arrays):
136
# in lite version, use higher precision (always double or cdouble)
137
result_type = single
138
is_complex = False
139
for a in arrays:
140
if issubclass(a.dtype.type, inexact):
141
if isComplexType(a.dtype.type):
142
is_complex = True
143
rt = _realType(a.dtype.type, default=None)
144
if rt is None:
145
# unsupported inexact scalar
146
raise TypeError("array type %s is unsupported in linalg" %
147
(a.dtype.name,))
148
else:
149
rt = double
150
if rt is double:
151
result_type = double
152
if is_complex:
153
t = cdouble
154
result_type = _complex_types_map[result_type]
155
else:
156
t = double
157
return t, result_type
158
159
160
# _fastCopyAndTranpose assumes the input is 2D (as all the calls in here are).
161
162
_fastCT = fastCopyAndTranspose
163
164
def _to_native_byte_order(*arrays):
165
ret = []
166
for arr in arrays:
167
if arr.dtype.byteorder not in ('=', '|'):
168
ret.append(asarray(arr, dtype=arr.dtype.newbyteorder('=')))
169
else:
170
ret.append(arr)
171
if len(ret) == 1:
172
return ret[0]
173
else:
174
return ret
175
176
def _fastCopyAndTranspose(type, *arrays):
177
cast_arrays = ()
178
for a in arrays:
179
if a.dtype.type is not type:
180
a = a.astype(type)
181
cast_arrays = cast_arrays + (_fastCT(a),)
182
if len(cast_arrays) == 1:
183
return cast_arrays[0]
184
else:
185
return cast_arrays
186
187
def _assert_2d(*arrays):
188
for a in arrays:
189
if a.ndim != 2:
190
raise LinAlgError('%d-dimensional array given. Array must be '
191
'two-dimensional' % a.ndim)
192
193
def _assert_stacked_2d(*arrays):
194
for a in arrays:
195
if a.ndim < 2:
196
raise LinAlgError('%d-dimensional array given. Array must be '
197
'at least two-dimensional' % a.ndim)
198
199
def _assert_stacked_square(*arrays):
200
for a in arrays:
201
m, n = a.shape[-2:]
202
if m != n:
203
raise LinAlgError('Last 2 dimensions of the array must be square')
204
205
def _assert_finite(*arrays):
206
for a in arrays:
207
if not isfinite(a).all():
208
raise LinAlgError("Array must not contain infs or NaNs")
209
210
def _is_empty_2d(arr):
211
# check size first for efficiency
212
return arr.size == 0 and product(arr.shape[-2:]) == 0
213
214
215
def transpose(a):
216
"""
217
Transpose each matrix in a stack of matrices.
218
219
Unlike np.transpose, this only swaps the last two axes, rather than all of
220
them
221
222
Parameters
223
----------
224
a : (...,M,N) array_like
225
226
Returns
227
-------
228
aT : (...,N,M) ndarray
229
"""
230
return swapaxes(a, -1, -2)
231
232
# Linear equations
233
234
def _tensorsolve_dispatcher(a, b, axes=None):
235
return (a, b)
236
237
238
@array_function_dispatch(_tensorsolve_dispatcher)
239
def tensorsolve(a, b, axes=None):
240
"""
241
Solve the tensor equation ``a x = b`` for x.
242
243
It is assumed that all indices of `x` are summed over in the product,
244
together with the rightmost indices of `a`, as is done in, for example,
245
``tensordot(a, x, axes=b.ndim)``.
246
247
Parameters
248
----------
249
a : array_like
250
Coefficient tensor, of shape ``b.shape + Q``. `Q`, a tuple, equals
251
the shape of that sub-tensor of `a` consisting of the appropriate
252
number of its rightmost indices, and must be such that
253
``prod(Q) == prod(b.shape)`` (in which sense `a` is said to be
254
'square').
255
b : array_like
256
Right-hand tensor, which can be of any shape.
257
axes : tuple of ints, optional
258
Axes in `a` to reorder to the right, before inversion.
259
If None (default), no reordering is done.
260
261
Returns
262
-------
263
x : ndarray, shape Q
264
265
Raises
266
------
267
LinAlgError
268
If `a` is singular or not 'square' (in the above sense).
269
270
See Also
271
--------
272
numpy.tensordot, tensorinv, numpy.einsum
273
274
Examples
275
--------
276
>>> a = np.eye(2*3*4)
277
>>> a.shape = (2*3, 4, 2, 3, 4)
278
>>> b = np.random.randn(2*3, 4)
279
>>> x = np.linalg.tensorsolve(a, b)
280
>>> x.shape
281
(2, 3, 4)
282
>>> np.allclose(np.tensordot(a, x, axes=3), b)
283
True
284
285
"""
286
a, wrap = _makearray(a)
287
b = asarray(b)
288
an = a.ndim
289
290
if axes is not None:
291
allaxes = list(range(0, an))
292
for k in axes:
293
allaxes.remove(k)
294
allaxes.insert(an, k)
295
a = a.transpose(allaxes)
296
297
oldshape = a.shape[-(an-b.ndim):]
298
prod = 1
299
for k in oldshape:
300
prod *= k
301
302
a = a.reshape(-1, prod)
303
b = b.ravel()
304
res = wrap(solve(a, b))
305
res.shape = oldshape
306
return res
307
308
309
def _solve_dispatcher(a, b):
310
return (a, b)
311
312
313
@array_function_dispatch(_solve_dispatcher)
314
def solve(a, b):
315
"""
316
Solve a linear matrix equation, or system of linear scalar equations.
317
318
Computes the "exact" solution, `x`, of the well-determined, i.e., full
319
rank, linear matrix equation `ax = b`.
320
321
Parameters
322
----------
323
a : (..., M, M) array_like
324
Coefficient matrix.
325
b : {(..., M,), (..., M, K)}, array_like
326
Ordinate or "dependent variable" values.
327
328
Returns
329
-------
330
x : {(..., M,), (..., M, K)} ndarray
331
Solution to the system a x = b. Returned shape is identical to `b`.
332
333
Raises
334
------
335
LinAlgError
336
If `a` is singular or not square.
337
338
See Also
339
--------
340
scipy.linalg.solve : Similar function in SciPy.
341
342
Notes
343
-----
344
345
.. versionadded:: 1.8.0
346
347
Broadcasting rules apply, see the `numpy.linalg` documentation for
348
details.
349
350
The solutions are computed using LAPACK routine ``_gesv``.
351
352
`a` must be square and of full-rank, i.e., all rows (or, equivalently,
353
columns) must be linearly independent; if either is not true, use
354
`lstsq` for the least-squares best "solution" of the
355
system/equation.
356
357
References
358
----------
359
.. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando,
360
FL, Academic Press, Inc., 1980, pg. 22.
361
362
Examples
363
--------
364
Solve the system of equations ``x0 + 2 * x1 = 1`` and ``3 * x0 + 5 * x1 = 2``:
365
366
>>> a = np.array([[1, 2], [3, 5]])
367
>>> b = np.array([1, 2])
368
>>> x = np.linalg.solve(a, b)
369
>>> x
370
array([-1., 1.])
371
372
Check that the solution is correct:
373
374
>>> np.allclose(np.dot(a, x), b)
375
True
376
377
"""
378
a, _ = _makearray(a)
379
_assert_stacked_2d(a)
380
_assert_stacked_square(a)
381
b, wrap = _makearray(b)
382
t, result_t = _commonType(a, b)
383
384
# We use the b = (..., M,) logic, only if the number of extra dimensions
385
# match exactly
386
if b.ndim == a.ndim - 1:
387
gufunc = _umath_linalg.solve1
388
else:
389
gufunc = _umath_linalg.solve
390
391
signature = 'DD->D' if isComplexType(t) else 'dd->d'
392
extobj = get_linalg_error_extobj(_raise_linalgerror_singular)
393
r = gufunc(a, b, signature=signature, extobj=extobj)
394
395
return wrap(r.astype(result_t, copy=False))
396
397
398
def _tensorinv_dispatcher(a, ind=None):
399
return (a,)
400
401
402
@array_function_dispatch(_tensorinv_dispatcher)
403
def tensorinv(a, ind=2):
404
"""
405
Compute the 'inverse' of an N-dimensional array.
406
407
The result is an inverse for `a` relative to the tensordot operation
408
``tensordot(a, b, ind)``, i. e., up to floating-point accuracy,
409
``tensordot(tensorinv(a), a, ind)`` is the "identity" tensor for the
410
tensordot operation.
411
412
Parameters
413
----------
414
a : array_like
415
Tensor to 'invert'. Its shape must be 'square', i. e.,
416
``prod(a.shape[:ind]) == prod(a.shape[ind:])``.
417
ind : int, optional
418
Number of first indices that are involved in the inverse sum.
419
Must be a positive integer, default is 2.
420
421
Returns
422
-------
423
b : ndarray
424
`a`'s tensordot inverse, shape ``a.shape[ind:] + a.shape[:ind]``.
425
426
Raises
427
------
428
LinAlgError
429
If `a` is singular or not 'square' (in the above sense).
430
431
See Also
432
--------
433
numpy.tensordot, tensorsolve
434
435
Examples
436
--------
437
>>> a = np.eye(4*6)
438
>>> a.shape = (4, 6, 8, 3)
439
>>> ainv = np.linalg.tensorinv(a, ind=2)
440
>>> ainv.shape
441
(8, 3, 4, 6)
442
>>> b = np.random.randn(4, 6)
443
>>> np.allclose(np.tensordot(ainv, b), np.linalg.tensorsolve(a, b))
444
True
445
446
>>> a = np.eye(4*6)
447
>>> a.shape = (24, 8, 3)
448
>>> ainv = np.linalg.tensorinv(a, ind=1)
449
>>> ainv.shape
450
(8, 3, 24)
451
>>> b = np.random.randn(24)
452
>>> np.allclose(np.tensordot(ainv, b, 1), np.linalg.tensorsolve(a, b))
453
True
454
455
"""
456
a = asarray(a)
457
oldshape = a.shape
458
prod = 1
459
if ind > 0:
460
invshape = oldshape[ind:] + oldshape[:ind]
461
for k in oldshape[ind:]:
462
prod *= k
463
else:
464
raise ValueError("Invalid ind argument.")
465
a = a.reshape(prod, -1)
466
ia = inv(a)
467
return ia.reshape(*invshape)
468
469
470
# Matrix inversion
471
472
def _unary_dispatcher(a):
473
return (a,)
474
475
476
@array_function_dispatch(_unary_dispatcher)
477
def inv(a):
478
"""
479
Compute the (multiplicative) inverse of a matrix.
480
481
Given a square matrix `a`, return the matrix `ainv` satisfying
482
``dot(a, ainv) = dot(ainv, a) = eye(a.shape[0])``.
483
484
Parameters
485
----------
486
a : (..., M, M) array_like
487
Matrix to be inverted.
488
489
Returns
490
-------
491
ainv : (..., M, M) ndarray or matrix
492
(Multiplicative) inverse of the matrix `a`.
493
494
Raises
495
------
496
LinAlgError
497
If `a` is not square or inversion fails.
498
499
See Also
500
--------
501
scipy.linalg.inv : Similar function in SciPy.
502
503
Notes
504
-----
505
506
.. versionadded:: 1.8.0
507
508
Broadcasting rules apply, see the `numpy.linalg` documentation for
509
details.
510
511
Examples
512
--------
513
>>> from numpy.linalg import inv
514
>>> a = np.array([[1., 2.], [3., 4.]])
515
>>> ainv = inv(a)
516
>>> np.allclose(np.dot(a, ainv), np.eye(2))
517
True
518
>>> np.allclose(np.dot(ainv, a), np.eye(2))
519
True
520
521
If a is a matrix object, then the return value is a matrix as well:
522
523
>>> ainv = inv(np.matrix(a))
524
>>> ainv
525
matrix([[-2. , 1. ],
526
[ 1.5, -0.5]])
527
528
Inverses of several matrices can be computed at once:
529
530
>>> a = np.array([[[1., 2.], [3., 4.]], [[1, 3], [3, 5]]])
531
>>> inv(a)
532
array([[[-2. , 1. ],
533
[ 1.5 , -0.5 ]],
534
[[-1.25, 0.75],
535
[ 0.75, -0.25]]])
536
537
"""
538
a, wrap = _makearray(a)
539
_assert_stacked_2d(a)
540
_assert_stacked_square(a)
541
t, result_t = _commonType(a)
542
543
signature = 'D->D' if isComplexType(t) else 'd->d'
544
extobj = get_linalg_error_extobj(_raise_linalgerror_singular)
545
ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
546
return wrap(ainv.astype(result_t, copy=False))
547
548
549
def _matrix_power_dispatcher(a, n):
550
return (a,)
551
552
553
@array_function_dispatch(_matrix_power_dispatcher)
554
def matrix_power(a, n):
555
"""
556
Raise a square matrix to the (integer) power `n`.
557
558
For positive integers `n`, the power is computed by repeated matrix
559
squarings and matrix multiplications. If ``n == 0``, the identity matrix
560
of the same shape as M is returned. If ``n < 0``, the inverse
561
is computed and then raised to the ``abs(n)``.
562
563
.. note:: Stacks of object matrices are not currently supported.
564
565
Parameters
566
----------
567
a : (..., M, M) array_like
568
Matrix to be "powered".
569
n : int
570
The exponent can be any integer or long integer, positive,
571
negative, or zero.
572
573
Returns
574
-------
575
a**n : (..., M, M) ndarray or matrix object
576
The return value is the same shape and type as `M`;
577
if the exponent is positive or zero then the type of the
578
elements is the same as those of `M`. If the exponent is
579
negative the elements are floating-point.
580
581
Raises
582
------
583
LinAlgError
584
For matrices that are not square or that (for negative powers) cannot
585
be inverted numerically.
586
587
Examples
588
--------
589
>>> from numpy.linalg import matrix_power
590
>>> i = np.array([[0, 1], [-1, 0]]) # matrix equiv. of the imaginary unit
591
>>> matrix_power(i, 3) # should = -i
592
array([[ 0, -1],
593
[ 1, 0]])
594
>>> matrix_power(i, 0)
595
array([[1, 0],
596
[0, 1]])
597
>>> matrix_power(i, -3) # should = 1/(-i) = i, but w/ f.p. elements
598
array([[ 0., 1.],
599
[-1., 0.]])
600
601
Somewhat more sophisticated example
602
603
>>> q = np.zeros((4, 4))
604
>>> q[0:2, 0:2] = -i
605
>>> q[2:4, 2:4] = i
606
>>> q # one of the three quaternion units not equal to 1
607
array([[ 0., -1., 0., 0.],
608
[ 1., 0., 0., 0.],
609
[ 0., 0., 0., 1.],
610
[ 0., 0., -1., 0.]])
611
>>> matrix_power(q, 2) # = -np.eye(4)
612
array([[-1., 0., 0., 0.],
613
[ 0., -1., 0., 0.],
614
[ 0., 0., -1., 0.],
615
[ 0., 0., 0., -1.]])
616
617
"""
618
a = asanyarray(a)
619
_assert_stacked_2d(a)
620
_assert_stacked_square(a)
621
622
try:
623
n = operator.index(n)
624
except TypeError as e:
625
raise TypeError("exponent must be an integer") from e
626
627
# Fall back on dot for object arrays. Object arrays are not supported by
628
# the current implementation of matmul using einsum
629
if a.dtype != object:
630
fmatmul = matmul
631
elif a.ndim == 2:
632
fmatmul = dot
633
else:
634
raise NotImplementedError(
635
"matrix_power not supported for stacks of object arrays")
636
637
if n == 0:
638
a = empty_like(a)
639
a[...] = eye(a.shape[-2], dtype=a.dtype)
640
return a
641
642
elif n < 0:
643
a = inv(a)
644
n = abs(n)
645
646
# short-cuts.
647
if n == 1:
648
return a
649
650
elif n == 2:
651
return fmatmul(a, a)
652
653
elif n == 3:
654
return fmatmul(fmatmul(a, a), a)
655
656
# Use binary decomposition to reduce the number of matrix multiplications.
657
# Here, we iterate over the bits of n, from LSB to MSB, raise `a` to
658
# increasing powers of 2, and multiply into the result as needed.
659
z = result = None
660
while n > 0:
661
z = a if z is None else fmatmul(z, z)
662
n, bit = divmod(n, 2)
663
if bit:
664
result = z if result is None else fmatmul(result, z)
665
666
return result
667
668
669
# Cholesky decomposition
670
671
672
@array_function_dispatch(_unary_dispatcher)
673
def cholesky(a):
674
"""
675
Cholesky decomposition.
676
677
Return the Cholesky decomposition, `L * L.H`, of the square matrix `a`,
678
where `L` is lower-triangular and .H is the conjugate transpose operator
679
(which is the ordinary transpose if `a` is real-valued). `a` must be
680
Hermitian (symmetric if real-valued) and positive-definite. No
681
checking is performed to verify whether `a` is Hermitian or not.
682
In addition, only the lower-triangular and diagonal elements of `a`
683
are used. Only `L` is actually returned.
684
685
Parameters
686
----------
687
a : (..., M, M) array_like
688
Hermitian (symmetric if all elements are real), positive-definite
689
input matrix.
690
691
Returns
692
-------
693
L : (..., M, M) array_like
694
Upper or lower-triangular Cholesky factor of `a`. Returns a
695
matrix object if `a` is a matrix object.
696
697
Raises
698
------
699
LinAlgError
700
If the decomposition fails, for example, if `a` is not
701
positive-definite.
702
703
See Also
704
--------
705
scipy.linalg.cholesky : Similar function in SciPy.
706
scipy.linalg.cholesky_banded : Cholesky decompose a banded Hermitian
707
positive-definite matrix.
708
scipy.linalg.cho_factor : Cholesky decomposition of a matrix, to use in
709
`scipy.linalg.cho_solve`.
710
711
Notes
712
-----
713
714
.. versionadded:: 1.8.0
715
716
Broadcasting rules apply, see the `numpy.linalg` documentation for
717
details.
718
719
The Cholesky decomposition is often used as a fast way of solving
720
721
.. math:: A \\mathbf{x} = \\mathbf{b}
722
723
(when `A` is both Hermitian/symmetric and positive-definite).
724
725
First, we solve for :math:`\\mathbf{y}` in
726
727
.. math:: L \\mathbf{y} = \\mathbf{b},
728
729
and then for :math:`\\mathbf{x}` in
730
731
.. math:: L.H \\mathbf{x} = \\mathbf{y}.
732
733
Examples
734
--------
735
>>> A = np.array([[1,-2j],[2j,5]])
736
>>> A
737
array([[ 1.+0.j, -0.-2.j],
738
[ 0.+2.j, 5.+0.j]])
739
>>> L = np.linalg.cholesky(A)
740
>>> L
741
array([[1.+0.j, 0.+0.j],
742
[0.+2.j, 1.+0.j]])
743
>>> np.dot(L, L.T.conj()) # verify that L * L.H = A
744
array([[1.+0.j, 0.-2.j],
745
[0.+2.j, 5.+0.j]])
746
>>> A = [[1,-2j],[2j,5]] # what happens if A is only array_like?
747
>>> np.linalg.cholesky(A) # an ndarray object is returned
748
array([[1.+0.j, 0.+0.j],
749
[0.+2.j, 1.+0.j]])
750
>>> # But a matrix object is returned if A is a matrix object
751
>>> np.linalg.cholesky(np.matrix(A))
752
matrix([[ 1.+0.j, 0.+0.j],
753
[ 0.+2.j, 1.+0.j]])
754
755
"""
756
extobj = get_linalg_error_extobj(_raise_linalgerror_nonposdef)
757
gufunc = _umath_linalg.cholesky_lo
758
a, wrap = _makearray(a)
759
_assert_stacked_2d(a)
760
_assert_stacked_square(a)
761
t, result_t = _commonType(a)
762
signature = 'D->D' if isComplexType(t) else 'd->d'
763
r = gufunc(a, signature=signature, extobj=extobj)
764
return wrap(r.astype(result_t, copy=False))
765
766
767
# QR decomposition
768
769
def _qr_dispatcher(a, mode=None):
770
return (a,)
771
772
773
@array_function_dispatch(_qr_dispatcher)
774
def qr(a, mode='reduced'):
775
"""
776
Compute the qr factorization of a matrix.
777
778
Factor the matrix `a` as *qr*, where `q` is orthonormal and `r` is
779
upper-triangular.
780
781
Parameters
782
----------
783
a : array_like, shape (..., M, N)
784
An array-like object with the dimensionality of at least 2.
785
mode : {'reduced', 'complete', 'r', 'raw'}, optional
786
If K = min(M, N), then
787
788
* 'reduced' : returns q, r with dimensions
789
(..., M, K), (..., K, N) (default)
790
* 'complete' : returns q, r with dimensions (..., M, M), (..., M, N)
791
* 'r' : returns r only with dimensions (..., K, N)
792
* 'raw' : returns h, tau with dimensions (..., N, M), (..., K,)
793
794
The options 'reduced', 'complete, and 'raw' are new in numpy 1.8,
795
see the notes for more information. The default is 'reduced', and to
796
maintain backward compatibility with earlier versions of numpy both
797
it and the old default 'full' can be omitted. Note that array h
798
returned in 'raw' mode is transposed for calling Fortran. The
799
'economic' mode is deprecated. The modes 'full' and 'economic' may
800
be passed using only the first letter for backwards compatibility,
801
but all others must be spelled out. See the Notes for more
802
explanation.
803
804
805
Returns
806
-------
807
q : ndarray of float or complex, optional
808
A matrix with orthonormal columns. When mode = 'complete' the
809
result is an orthogonal/unitary matrix depending on whether or not
810
a is real/complex. The determinant may be either +/- 1 in that
811
case. In case the number of dimensions in the input array is
812
greater than 2 then a stack of the matrices with above properties
813
is returned.
814
r : ndarray of float or complex, optional
815
The upper-triangular matrix or a stack of upper-triangular
816
matrices if the number of dimensions in the input array is greater
817
than 2.
818
(h, tau) : ndarrays of np.double or np.cdouble, optional
819
The array h contains the Householder reflectors that generate q
820
along with r. The tau array contains scaling factors for the
821
reflectors. In the deprecated 'economic' mode only h is returned.
822
823
Raises
824
------
825
LinAlgError
826
If factoring fails.
827
828
See Also
829
--------
830
scipy.linalg.qr : Similar function in SciPy.
831
scipy.linalg.rq : Compute RQ decomposition of a matrix.
832
833
Notes
834
-----
835
This is an interface to the LAPACK routines ``dgeqrf``, ``zgeqrf``,
836
``dorgqr``, and ``zungqr``.
837
838
For more information on the qr factorization, see for example:
839
https://en.wikipedia.org/wiki/QR_factorization
840
841
Subclasses of `ndarray` are preserved except for the 'raw' mode. So if
842
`a` is of type `matrix`, all the return values will be matrices too.
843
844
New 'reduced', 'complete', and 'raw' options for mode were added in
845
NumPy 1.8.0 and the old option 'full' was made an alias of 'reduced'. In
846
addition the options 'full' and 'economic' were deprecated. Because
847
'full' was the previous default and 'reduced' is the new default,
848
backward compatibility can be maintained by letting `mode` default.
849
The 'raw' option was added so that LAPACK routines that can multiply
850
arrays by q using the Householder reflectors can be used. Note that in
851
this case the returned arrays are of type np.double or np.cdouble and
852
the h array is transposed to be FORTRAN compatible. No routines using
853
the 'raw' return are currently exposed by numpy, but some are available
854
in lapack_lite and just await the necessary work.
855
856
Examples
857
--------
858
>>> a = np.random.randn(9, 6)
859
>>> q, r = np.linalg.qr(a)
860
>>> np.allclose(a, np.dot(q, r)) # a does equal qr
861
True
862
>>> r2 = np.linalg.qr(a, mode='r')
863
>>> np.allclose(r, r2) # mode='r' returns the same r as mode='full'
864
True
865
>>> a = np.random.normal(size=(3, 2, 2)) # Stack of 2 x 2 matrices as input
866
>>> q, r = np.linalg.qr(a)
867
>>> q.shape
868
(3, 2, 2)
869
>>> r.shape
870
(3, 2, 2)
871
>>> np.allclose(a, np.matmul(q, r))
872
True
873
874
Example illustrating a common use of `qr`: solving of least squares
875
problems
876
877
What are the least-squares-best `m` and `y0` in ``y = y0 + mx`` for
878
the following data: {(0,1), (1,0), (1,2), (2,1)}. (Graph the points
879
and you'll see that it should be y0 = 0, m = 1.) The answer is provided
880
by solving the over-determined matrix equation ``Ax = b``, where::
881
882
A = array([[0, 1], [1, 1], [1, 1], [2, 1]])
883
x = array([[y0], [m]])
884
b = array([[1], [0], [2], [1]])
885
886
If A = qr such that q is orthonormal (which is always possible via
887
Gram-Schmidt), then ``x = inv(r) * (q.T) * b``. (In numpy practice,
888
however, we simply use `lstsq`.)
889
890
>>> A = np.array([[0, 1], [1, 1], [1, 1], [2, 1]])
891
>>> A
892
array([[0, 1],
893
[1, 1],
894
[1, 1],
895
[2, 1]])
896
>>> b = np.array([1, 0, 2, 1])
897
>>> q, r = np.linalg.qr(A)
898
>>> p = np.dot(q.T, b)
899
>>> np.dot(np.linalg.inv(r), p)
900
array([ 1.1e-16, 1.0e+00])
901
902
"""
903
if mode not in ('reduced', 'complete', 'r', 'raw'):
904
if mode in ('f', 'full'):
905
# 2013-04-01, 1.8
906
msg = "".join((
907
"The 'full' option is deprecated in favor of 'reduced'.\n",
908
"For backward compatibility let mode default."))
909
warnings.warn(msg, DeprecationWarning, stacklevel=3)
910
mode = 'reduced'
911
elif mode in ('e', 'economic'):
912
# 2013-04-01, 1.8
913
msg = "The 'economic' option is deprecated."
914
warnings.warn(msg, DeprecationWarning, stacklevel=3)
915
mode = 'economic'
916
else:
917
raise ValueError(f"Unrecognized mode '{mode}'")
918
919
a, wrap = _makearray(a)
920
_assert_stacked_2d(a)
921
m, n = a.shape[-2:]
922
t, result_t = _commonType(a)
923
a = a.astype(t, copy=True)
924
a = _to_native_byte_order(a)
925
mn = min(m, n)
926
927
if m <= n:
928
gufunc = _umath_linalg.qr_r_raw_m
929
else:
930
gufunc = _umath_linalg.qr_r_raw_n
931
932
signature = 'D->D' if isComplexType(t) else 'd->d'
933
extobj = get_linalg_error_extobj(_raise_linalgerror_qr)
934
tau = gufunc(a, signature=signature, extobj=extobj)
935
936
# handle modes that don't return q
937
if mode == 'r':
938
r = triu(a[..., :mn, :])
939
r = r.astype(result_t, copy=False)
940
return wrap(r)
941
942
if mode == 'raw':
943
q = transpose(a)
944
q = q.astype(result_t, copy=False)
945
tau = tau.astype(result_t, copy=False)
946
return wrap(q), tau
947
948
if mode == 'economic':
949
a = a.astype(result_t, copy=False)
950
return wrap(a)
951
952
# mc is the number of columns in the resulting q
953
# matrix. If the mode is complete then it is
954
# same as number of rows, and if the mode is reduced,
955
# then it is the minimum of number of rows and columns.
956
if mode == 'complete' and m > n:
957
mc = m
958
gufunc = _umath_linalg.qr_complete
959
else:
960
mc = mn
961
gufunc = _umath_linalg.qr_reduced
962
963
signature = 'DD->D' if isComplexType(t) else 'dd->d'
964
extobj = get_linalg_error_extobj(_raise_linalgerror_qr)
965
q = gufunc(a, tau, signature=signature, extobj=extobj)
966
r = triu(a[..., :mc, :])
967
968
q = q.astype(result_t, copy=False)
969
r = r.astype(result_t, copy=False)
970
971
return wrap(q), wrap(r)
972
973
# Eigenvalues
974
975
976
@array_function_dispatch(_unary_dispatcher)
977
def eigvals(a):
978
"""
979
Compute the eigenvalues of a general matrix.
980
981
Main difference between `eigvals` and `eig`: the eigenvectors aren't
982
returned.
983
984
Parameters
985
----------
986
a : (..., M, M) array_like
987
A complex- or real-valued matrix whose eigenvalues will be computed.
988
989
Returns
990
-------
991
w : (..., M,) ndarray
992
The eigenvalues, each repeated according to its multiplicity.
993
They are not necessarily ordered, nor are they necessarily
994
real for real matrices.
995
996
Raises
997
------
998
LinAlgError
999
If the eigenvalue computation does not converge.
1000
1001
See Also
1002
--------
1003
eig : eigenvalues and right eigenvectors of general arrays
1004
eigvalsh : eigenvalues of real symmetric or complex Hermitian
1005
(conjugate symmetric) arrays.
1006
eigh : eigenvalues and eigenvectors of real symmetric or complex
1007
Hermitian (conjugate symmetric) arrays.
1008
scipy.linalg.eigvals : Similar function in SciPy.
1009
1010
Notes
1011
-----
1012
1013
.. versionadded:: 1.8.0
1014
1015
Broadcasting rules apply, see the `numpy.linalg` documentation for
1016
details.
1017
1018
This is implemented using the ``_geev`` LAPACK routines which compute
1019
the eigenvalues and eigenvectors of general square arrays.
1020
1021
Examples
1022
--------
1023
Illustration, using the fact that the eigenvalues of a diagonal matrix
1024
are its diagonal elements, that multiplying a matrix on the left
1025
by an orthogonal matrix, `Q`, and on the right by `Q.T` (the transpose
1026
of `Q`), preserves the eigenvalues of the "middle" matrix. In other words,
1027
if `Q` is orthogonal, then ``Q * A * Q.T`` has the same eigenvalues as
1028
``A``:
1029
1030
>>> from numpy import linalg as LA
1031
>>> x = np.random.random()
1032
>>> Q = np.array([[np.cos(x), -np.sin(x)], [np.sin(x), np.cos(x)]])
1033
>>> LA.norm(Q[0, :]), LA.norm(Q[1, :]), np.dot(Q[0, :],Q[1, :])
1034
(1.0, 1.0, 0.0)
1035
1036
Now multiply a diagonal matrix by ``Q`` on one side and by ``Q.T`` on the other:
1037
1038
>>> D = np.diag((-1,1))
1039
>>> LA.eigvals(D)
1040
array([-1., 1.])
1041
>>> A = np.dot(Q, D)
1042
>>> A = np.dot(A, Q.T)
1043
>>> LA.eigvals(A)
1044
array([ 1., -1.]) # random
1045
1046
"""
1047
a, wrap = _makearray(a)
1048
_assert_stacked_2d(a)
1049
_assert_stacked_square(a)
1050
_assert_finite(a)
1051
t, result_t = _commonType(a)
1052
1053
extobj = get_linalg_error_extobj(
1054
_raise_linalgerror_eigenvalues_nonconvergence)
1055
signature = 'D->D' if isComplexType(t) else 'd->D'
1056
w = _umath_linalg.eigvals(a, signature=signature, extobj=extobj)
1057
1058
if not isComplexType(t):
1059
if all(w.imag == 0):
1060
w = w.real
1061
result_t = _realType(result_t)
1062
else:
1063
result_t = _complexType(result_t)
1064
1065
return w.astype(result_t, copy=False)
1066
1067
1068
def _eigvalsh_dispatcher(a, UPLO=None):
1069
return (a,)
1070
1071
1072
@array_function_dispatch(_eigvalsh_dispatcher)
1073
def eigvalsh(a, UPLO='L'):
1074
"""
1075
Compute the eigenvalues of a complex Hermitian or real symmetric matrix.
1076
1077
Main difference from eigh: the eigenvectors are not computed.
1078
1079
Parameters
1080
----------
1081
a : (..., M, M) array_like
1082
A complex- or real-valued matrix whose eigenvalues are to be
1083
computed.
1084
UPLO : {'L', 'U'}, optional
1085
Specifies whether the calculation is done with the lower triangular
1086
part of `a` ('L', default) or the upper triangular part ('U').
1087
Irrespective of this value only the real parts of the diagonal will
1088
be considered in the computation to preserve the notion of a Hermitian
1089
matrix. It therefore follows that the imaginary part of the diagonal
1090
will always be treated as zero.
1091
1092
Returns
1093
-------
1094
w : (..., M,) ndarray
1095
The eigenvalues in ascending order, each repeated according to
1096
its multiplicity.
1097
1098
Raises
1099
------
1100
LinAlgError
1101
If the eigenvalue computation does not converge.
1102
1103
See Also
1104
--------
1105
eigh : eigenvalues and eigenvectors of real symmetric or complex Hermitian
1106
(conjugate symmetric) arrays.
1107
eigvals : eigenvalues of general real or complex arrays.
1108
eig : eigenvalues and right eigenvectors of general real or complex
1109
arrays.
1110
scipy.linalg.eigvalsh : Similar function in SciPy.
1111
1112
Notes
1113
-----
1114
1115
.. versionadded:: 1.8.0
1116
1117
Broadcasting rules apply, see the `numpy.linalg` documentation for
1118
details.
1119
1120
The eigenvalues are computed using LAPACK routines ``_syevd``, ``_heevd``.
1121
1122
Examples
1123
--------
1124
>>> from numpy import linalg as LA
1125
>>> a = np.array([[1, -2j], [2j, 5]])
1126
>>> LA.eigvalsh(a)
1127
array([ 0.17157288, 5.82842712]) # may vary
1128
1129
>>> # demonstrate the treatment of the imaginary part of the diagonal
1130
>>> a = np.array([[5+2j, 9-2j], [0+2j, 2-1j]])
1131
>>> a
1132
array([[5.+2.j, 9.-2.j],
1133
[0.+2.j, 2.-1.j]])
1134
>>> # with UPLO='L' this is numerically equivalent to using LA.eigvals()
1135
>>> # with:
1136
>>> b = np.array([[5.+0.j, 0.-2.j], [0.+2.j, 2.-0.j]])
1137
>>> b
1138
array([[5.+0.j, 0.-2.j],
1139
[0.+2.j, 2.+0.j]])
1140
>>> wa = LA.eigvalsh(a)
1141
>>> wb = LA.eigvals(b)
1142
>>> wa; wb
1143
array([1., 6.])
1144
array([6.+0.j, 1.+0.j])
1145
1146
"""
1147
UPLO = UPLO.upper()
1148
if UPLO not in ('L', 'U'):
1149
raise ValueError("UPLO argument must be 'L' or 'U'")
1150
1151
extobj = get_linalg_error_extobj(
1152
_raise_linalgerror_eigenvalues_nonconvergence)
1153
if UPLO == 'L':
1154
gufunc = _umath_linalg.eigvalsh_lo
1155
else:
1156
gufunc = _umath_linalg.eigvalsh_up
1157
1158
a, wrap = _makearray(a)
1159
_assert_stacked_2d(a)
1160
_assert_stacked_square(a)
1161
t, result_t = _commonType(a)
1162
signature = 'D->d' if isComplexType(t) else 'd->d'
1163
w = gufunc(a, signature=signature, extobj=extobj)
1164
return w.astype(_realType(result_t), copy=False)
1165
1166
def _convertarray(a):
1167
t, result_t = _commonType(a)
1168
a = _fastCT(a.astype(t))
1169
return a, t, result_t
1170
1171
1172
# Eigenvectors
1173
1174
1175
@array_function_dispatch(_unary_dispatcher)
1176
def eig(a):
1177
"""
1178
Compute the eigenvalues and right eigenvectors of a square array.
1179
1180
Parameters
1181
----------
1182
a : (..., M, M) array
1183
Matrices for which the eigenvalues and right eigenvectors will
1184
be computed
1185
1186
Returns
1187
-------
1188
w : (..., M) array
1189
The eigenvalues, each repeated according to its multiplicity.
1190
The eigenvalues are not necessarily ordered. The resulting
1191
array will be of complex type, unless the imaginary part is
1192
zero in which case it will be cast to a real type. When `a`
1193
is real the resulting eigenvalues will be real (0 imaginary
1194
part) or occur in conjugate pairs
1195
1196
v : (..., M, M) array
1197
The normalized (unit "length") eigenvectors, such that the
1198
column ``v[:,i]`` is the eigenvector corresponding to the
1199
eigenvalue ``w[i]``.
1200
1201
Raises
1202
------
1203
LinAlgError
1204
If the eigenvalue computation does not converge.
1205
1206
See Also
1207
--------
1208
eigvals : eigenvalues of a non-symmetric array.
1209
eigh : eigenvalues and eigenvectors of a real symmetric or complex
1210
Hermitian (conjugate symmetric) array.
1211
eigvalsh : eigenvalues of a real symmetric or complex Hermitian
1212
(conjugate symmetric) array.
1213
scipy.linalg.eig : Similar function in SciPy that also solves the
1214
generalized eigenvalue problem.
1215
scipy.linalg.schur : Best choice for unitary and other non-Hermitian
1216
normal matrices.
1217
1218
Notes
1219
-----
1220
1221
.. versionadded:: 1.8.0
1222
1223
Broadcasting rules apply, see the `numpy.linalg` documentation for
1224
details.
1225
1226
This is implemented using the ``_geev`` LAPACK routines which compute
1227
the eigenvalues and eigenvectors of general square arrays.
1228
1229
The number `w` is an eigenvalue of `a` if there exists a vector
1230
`v` such that ``a @ v = w * v``. Thus, the arrays `a`, `w`, and
1231
`v` satisfy the equations ``a @ v[:,i] = w[i] * v[:,i]``
1232
for :math:`i \\in \\{0,...,M-1\\}`.
1233
1234
The array `v` of eigenvectors may not be of maximum rank, that is, some
1235
of the columns may be linearly dependent, although round-off error may
1236
obscure that fact. If the eigenvalues are all different, then theoretically
1237
the eigenvectors are linearly independent and `a` can be diagonalized by
1238
a similarity transformation using `v`, i.e, ``inv(v) @ a @ v`` is diagonal.
1239
1240
For non-Hermitian normal matrices the SciPy function `scipy.linalg.schur`
1241
is preferred because the matrix `v` is guaranteed to be unitary, which is
1242
not the case when using `eig`. The Schur factorization produces an
1243
upper triangular matrix rather than a diagonal matrix, but for normal
1244
matrices only the diagonal of the upper triangular matrix is needed, the
1245
rest is roundoff error.
1246
1247
Finally, it is emphasized that `v` consists of the *right* (as in
1248
right-hand side) eigenvectors of `a`. A vector `y` satisfying
1249
``y.T @ a = z * y.T`` for some number `z` is called a *left*
1250
eigenvector of `a`, and, in general, the left and right eigenvectors
1251
of a matrix are not necessarily the (perhaps conjugate) transposes
1252
of each other.
1253
1254
References
1255
----------
1256
G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando, FL,
1257
Academic Press, Inc., 1980, Various pp.
1258
1259
Examples
1260
--------
1261
>>> from numpy import linalg as LA
1262
1263
(Almost) trivial example with real e-values and e-vectors.
1264
1265
>>> w, v = LA.eig(np.diag((1, 2, 3)))
1266
>>> w; v
1267
array([1., 2., 3.])
1268
array([[1., 0., 0.],
1269
[0., 1., 0.],
1270
[0., 0., 1.]])
1271
1272
Real matrix possessing complex e-values and e-vectors; note that the
1273
e-values are complex conjugates of each other.
1274
1275
>>> w, v = LA.eig(np.array([[1, -1], [1, 1]]))
1276
>>> w; v
1277
array([1.+1.j, 1.-1.j])
1278
array([[0.70710678+0.j , 0.70710678-0.j ],
1279
[0. -0.70710678j, 0. +0.70710678j]])
1280
1281
Complex-valued matrix with real e-values (but complex-valued e-vectors);
1282
note that ``a.conj().T == a``, i.e., `a` is Hermitian.
1283
1284
>>> a = np.array([[1, 1j], [-1j, 1]])
1285
>>> w, v = LA.eig(a)
1286
>>> w; v
1287
array([2.+0.j, 0.+0.j])
1288
array([[ 0. +0.70710678j, 0.70710678+0.j ], # may vary
1289
[ 0.70710678+0.j , -0. +0.70710678j]])
1290
1291
Be careful about round-off error!
1292
1293
>>> a = np.array([[1 + 1e-9, 0], [0, 1 - 1e-9]])
1294
>>> # Theor. e-values are 1 +/- 1e-9
1295
>>> w, v = LA.eig(a)
1296
>>> w; v
1297
array([1., 1.])
1298
array([[1., 0.],
1299
[0., 1.]])
1300
1301
"""
1302
a, wrap = _makearray(a)
1303
_assert_stacked_2d(a)
1304
_assert_stacked_square(a)
1305
_assert_finite(a)
1306
t, result_t = _commonType(a)
1307
1308
extobj = get_linalg_error_extobj(
1309
_raise_linalgerror_eigenvalues_nonconvergence)
1310
signature = 'D->DD' if isComplexType(t) else 'd->DD'
1311
w, vt = _umath_linalg.eig(a, signature=signature, extobj=extobj)
1312
1313
if not isComplexType(t) and all(w.imag == 0.0):
1314
w = w.real
1315
vt = vt.real
1316
result_t = _realType(result_t)
1317
else:
1318
result_t = _complexType(result_t)
1319
1320
vt = vt.astype(result_t, copy=False)
1321
return w.astype(result_t, copy=False), wrap(vt)
1322
1323
1324
@array_function_dispatch(_eigvalsh_dispatcher)
1325
def eigh(a, UPLO='L'):
1326
"""
1327
Return the eigenvalues and eigenvectors of a complex Hermitian
1328
(conjugate symmetric) or a real symmetric matrix.
1329
1330
Returns two objects, a 1-D array containing the eigenvalues of `a`, and
1331
a 2-D square array or matrix (depending on the input type) of the
1332
corresponding eigenvectors (in columns).
1333
1334
Parameters
1335
----------
1336
a : (..., M, M) array
1337
Hermitian or real symmetric matrices whose eigenvalues and
1338
eigenvectors are to be computed.
1339
UPLO : {'L', 'U'}, optional
1340
Specifies whether the calculation is done with the lower triangular
1341
part of `a` ('L', default) or the upper triangular part ('U').
1342
Irrespective of this value only the real parts of the diagonal will
1343
be considered in the computation to preserve the notion of a Hermitian
1344
matrix. It therefore follows that the imaginary part of the diagonal
1345
will always be treated as zero.
1346
1347
Returns
1348
-------
1349
w : (..., M) ndarray
1350
The eigenvalues in ascending order, each repeated according to
1351
its multiplicity.
1352
v : {(..., M, M) ndarray, (..., M, M) matrix}
1353
The column ``v[:, i]`` is the normalized eigenvector corresponding
1354
to the eigenvalue ``w[i]``. Will return a matrix object if `a` is
1355
a matrix object.
1356
1357
Raises
1358
------
1359
LinAlgError
1360
If the eigenvalue computation does not converge.
1361
1362
See Also
1363
--------
1364
eigvalsh : eigenvalues of real symmetric or complex Hermitian
1365
(conjugate symmetric) arrays.
1366
eig : eigenvalues and right eigenvectors for non-symmetric arrays.
1367
eigvals : eigenvalues of non-symmetric arrays.
1368
scipy.linalg.eigh : Similar function in SciPy (but also solves the
1369
generalized eigenvalue problem).
1370
1371
Notes
1372
-----
1373
1374
.. versionadded:: 1.8.0
1375
1376
Broadcasting rules apply, see the `numpy.linalg` documentation for
1377
details.
1378
1379
The eigenvalues/eigenvectors are computed using LAPACK routines ``_syevd``,
1380
``_heevd``.
1381
1382
The eigenvalues of real symmetric or complex Hermitian matrices are
1383
always real. [1]_ The array `v` of (column) eigenvectors is unitary
1384
and `a`, `w`, and `v` satisfy the equations
1385
``dot(a, v[:, i]) = w[i] * v[:, i]``.
1386
1387
References
1388
----------
1389
.. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando,
1390
FL, Academic Press, Inc., 1980, pg. 222.
1391
1392
Examples
1393
--------
1394
>>> from numpy import linalg as LA
1395
>>> a = np.array([[1, -2j], [2j, 5]])
1396
>>> a
1397
array([[ 1.+0.j, -0.-2.j],
1398
[ 0.+2.j, 5.+0.j]])
1399
>>> w, v = LA.eigh(a)
1400
>>> w; v
1401
array([0.17157288, 5.82842712])
1402
array([[-0.92387953+0.j , -0.38268343+0.j ], # may vary
1403
[ 0. +0.38268343j, 0. -0.92387953j]])
1404
1405
>>> np.dot(a, v[:, 0]) - w[0] * v[:, 0] # verify 1st e-val/vec pair
1406
array([5.55111512e-17+0.0000000e+00j, 0.00000000e+00+1.2490009e-16j])
1407
>>> np.dot(a, v[:, 1]) - w[1] * v[:, 1] # verify 2nd e-val/vec pair
1408
array([0.+0.j, 0.+0.j])
1409
1410
>>> A = np.matrix(a) # what happens if input is a matrix object
1411
>>> A
1412
matrix([[ 1.+0.j, -0.-2.j],
1413
[ 0.+2.j, 5.+0.j]])
1414
>>> w, v = LA.eigh(A)
1415
>>> w; v
1416
array([0.17157288, 5.82842712])
1417
matrix([[-0.92387953+0.j , -0.38268343+0.j ], # may vary
1418
[ 0. +0.38268343j, 0. -0.92387953j]])
1419
1420
>>> # demonstrate the treatment of the imaginary part of the diagonal
1421
>>> a = np.array([[5+2j, 9-2j], [0+2j, 2-1j]])
1422
>>> a
1423
array([[5.+2.j, 9.-2.j],
1424
[0.+2.j, 2.-1.j]])
1425
>>> # with UPLO='L' this is numerically equivalent to using LA.eig() with:
1426
>>> b = np.array([[5.+0.j, 0.-2.j], [0.+2.j, 2.-0.j]])
1427
>>> b
1428
array([[5.+0.j, 0.-2.j],
1429
[0.+2.j, 2.+0.j]])
1430
>>> wa, va = LA.eigh(a)
1431
>>> wb, vb = LA.eig(b)
1432
>>> wa; wb
1433
array([1., 6.])
1434
array([6.+0.j, 1.+0.j])
1435
>>> va; vb
1436
array([[-0.4472136 +0.j , -0.89442719+0.j ], # may vary
1437
[ 0. +0.89442719j, 0. -0.4472136j ]])
1438
array([[ 0.89442719+0.j , -0. +0.4472136j],
1439
[-0. +0.4472136j, 0.89442719+0.j ]])
1440
"""
1441
UPLO = UPLO.upper()
1442
if UPLO not in ('L', 'U'):
1443
raise ValueError("UPLO argument must be 'L' or 'U'")
1444
1445
a, wrap = _makearray(a)
1446
_assert_stacked_2d(a)
1447
_assert_stacked_square(a)
1448
t, result_t = _commonType(a)
1449
1450
extobj = get_linalg_error_extobj(
1451
_raise_linalgerror_eigenvalues_nonconvergence)
1452
if UPLO == 'L':
1453
gufunc = _umath_linalg.eigh_lo
1454
else:
1455
gufunc = _umath_linalg.eigh_up
1456
1457
signature = 'D->dD' if isComplexType(t) else 'd->dd'
1458
w, vt = gufunc(a, signature=signature, extobj=extobj)
1459
w = w.astype(_realType(result_t), copy=False)
1460
vt = vt.astype(result_t, copy=False)
1461
return w, wrap(vt)
1462
1463
1464
# Singular value decomposition
1465
1466
def _svd_dispatcher(a, full_matrices=None, compute_uv=None, hermitian=None):
1467
return (a,)
1468
1469
1470
@array_function_dispatch(_svd_dispatcher)
1471
def svd(a, full_matrices=True, compute_uv=True, hermitian=False):
1472
"""
1473
Singular Value Decomposition.
1474
1475
When `a` is a 2D array, it is factorized as ``u @ np.diag(s) @ vh
1476
= (u * s) @ vh``, where `u` and `vh` are 2D unitary arrays and `s` is a 1D
1477
array of `a`'s singular values. When `a` is higher-dimensional, SVD is
1478
applied in stacked mode as explained below.
1479
1480
Parameters
1481
----------
1482
a : (..., M, N) array_like
1483
A real or complex array with ``a.ndim >= 2``.
1484
full_matrices : bool, optional
1485
If True (default), `u` and `vh` have the shapes ``(..., M, M)`` and
1486
``(..., N, N)``, respectively. Otherwise, the shapes are
1487
``(..., M, K)`` and ``(..., K, N)``, respectively, where
1488
``K = min(M, N)``.
1489
compute_uv : bool, optional
1490
Whether or not to compute `u` and `vh` in addition to `s`. True
1491
by default.
1492
hermitian : bool, optional
1493
If True, `a` is assumed to be Hermitian (symmetric if real-valued),
1494
enabling a more efficient method for finding singular values.
1495
Defaults to False.
1496
1497
.. versionadded:: 1.17.0
1498
1499
Returns
1500
-------
1501
u : { (..., M, M), (..., M, K) } array
1502
Unitary array(s). The first ``a.ndim - 2`` dimensions have the same
1503
size as those of the input `a`. The size of the last two dimensions
1504
depends on the value of `full_matrices`. Only returned when
1505
`compute_uv` is True.
1506
s : (..., K) array
1507
Vector(s) with the singular values, within each vector sorted in
1508
descending order. The first ``a.ndim - 2`` dimensions have the same
1509
size as those of the input `a`.
1510
vh : { (..., N, N), (..., K, N) } array
1511
Unitary array(s). The first ``a.ndim - 2`` dimensions have the same
1512
size as those of the input `a`. The size of the last two dimensions
1513
depends on the value of `full_matrices`. Only returned when
1514
`compute_uv` is True.
1515
1516
Raises
1517
------
1518
LinAlgError
1519
If SVD computation does not converge.
1520
1521
See Also
1522
--------
1523
scipy.linalg.svd : Similar function in SciPy.
1524
scipy.linalg.svdvals : Compute singular values of a matrix.
1525
1526
Notes
1527
-----
1528
1529
.. versionchanged:: 1.8.0
1530
Broadcasting rules apply, see the `numpy.linalg` documentation for
1531
details.
1532
1533
The decomposition is performed using LAPACK routine ``_gesdd``.
1534
1535
SVD is usually described for the factorization of a 2D matrix :math:`A`.
1536
The higher-dimensional case will be discussed below. In the 2D case, SVD is
1537
written as :math:`A = U S V^H`, where :math:`A = a`, :math:`U= u`,
1538
:math:`S= \\mathtt{np.diag}(s)` and :math:`V^H = vh`. The 1D array `s`
1539
contains the singular values of `a` and `u` and `vh` are unitary. The rows
1540
of `vh` are the eigenvectors of :math:`A^H A` and the columns of `u` are
1541
the eigenvectors of :math:`A A^H`. In both cases the corresponding
1542
(possibly non-zero) eigenvalues are given by ``s**2``.
1543
1544
If `a` has more than two dimensions, then broadcasting rules apply, as
1545
explained in :ref:`routines.linalg-broadcasting`. This means that SVD is
1546
working in "stacked" mode: it iterates over all indices of the first
1547
``a.ndim - 2`` dimensions and for each combination SVD is applied to the
1548
last two indices. The matrix `a` can be reconstructed from the
1549
decomposition with either ``(u * s[..., None, :]) @ vh`` or
1550
``u @ (s[..., None] * vh)``. (The ``@`` operator can be replaced by the
1551
function ``np.matmul`` for python versions below 3.5.)
1552
1553
If `a` is a ``matrix`` object (as opposed to an ``ndarray``), then so are
1554
all the return values.
1555
1556
Examples
1557
--------
1558
>>> a = np.random.randn(9, 6) + 1j*np.random.randn(9, 6)
1559
>>> b = np.random.randn(2, 7, 8, 3) + 1j*np.random.randn(2, 7, 8, 3)
1560
1561
Reconstruction based on full SVD, 2D case:
1562
1563
>>> u, s, vh = np.linalg.svd(a, full_matrices=True)
1564
>>> u.shape, s.shape, vh.shape
1565
((9, 9), (6,), (6, 6))
1566
>>> np.allclose(a, np.dot(u[:, :6] * s, vh))
1567
True
1568
>>> smat = np.zeros((9, 6), dtype=complex)
1569
>>> smat[:6, :6] = np.diag(s)
1570
>>> np.allclose(a, np.dot(u, np.dot(smat, vh)))
1571
True
1572
1573
Reconstruction based on reduced SVD, 2D case:
1574
1575
>>> u, s, vh = np.linalg.svd(a, full_matrices=False)
1576
>>> u.shape, s.shape, vh.shape
1577
((9, 6), (6,), (6, 6))
1578
>>> np.allclose(a, np.dot(u * s, vh))
1579
True
1580
>>> smat = np.diag(s)
1581
>>> np.allclose(a, np.dot(u, np.dot(smat, vh)))
1582
True
1583
1584
Reconstruction based on full SVD, 4D case:
1585
1586
>>> u, s, vh = np.linalg.svd(b, full_matrices=True)
1587
>>> u.shape, s.shape, vh.shape
1588
((2, 7, 8, 8), (2, 7, 3), (2, 7, 3, 3))
1589
>>> np.allclose(b, np.matmul(u[..., :3] * s[..., None, :], vh))
1590
True
1591
>>> np.allclose(b, np.matmul(u[..., :3], s[..., None] * vh))
1592
True
1593
1594
Reconstruction based on reduced SVD, 4D case:
1595
1596
>>> u, s, vh = np.linalg.svd(b, full_matrices=False)
1597
>>> u.shape, s.shape, vh.shape
1598
((2, 7, 8, 3), (2, 7, 3), (2, 7, 3, 3))
1599
>>> np.allclose(b, np.matmul(u * s[..., None, :], vh))
1600
True
1601
>>> np.allclose(b, np.matmul(u, s[..., None] * vh))
1602
True
1603
1604
"""
1605
import numpy as _nx
1606
a, wrap = _makearray(a)
1607
1608
if hermitian:
1609
# note: lapack svd returns eigenvalues with s ** 2 sorted descending,
1610
# but eig returns s sorted ascending, so we re-order the eigenvalues
1611
# and related arrays to have the correct order
1612
if compute_uv:
1613
s, u = eigh(a)
1614
sgn = sign(s)
1615
s = abs(s)
1616
sidx = argsort(s)[..., ::-1]
1617
sgn = _nx.take_along_axis(sgn, sidx, axis=-1)
1618
s = _nx.take_along_axis(s, sidx, axis=-1)
1619
u = _nx.take_along_axis(u, sidx[..., None, :], axis=-1)
1620
# singular values are unsigned, move the sign into v
1621
vt = transpose(u * sgn[..., None, :]).conjugate()
1622
return wrap(u), s, wrap(vt)
1623
else:
1624
s = eigvalsh(a)
1625
s = s[..., ::-1]
1626
s = abs(s)
1627
return sort(s)[..., ::-1]
1628
1629
_assert_stacked_2d(a)
1630
t, result_t = _commonType(a)
1631
1632
extobj = get_linalg_error_extobj(_raise_linalgerror_svd_nonconvergence)
1633
1634
m, n = a.shape[-2:]
1635
if compute_uv:
1636
if full_matrices:
1637
if m < n:
1638
gufunc = _umath_linalg.svd_m_f
1639
else:
1640
gufunc = _umath_linalg.svd_n_f
1641
else:
1642
if m < n:
1643
gufunc = _umath_linalg.svd_m_s
1644
else:
1645
gufunc = _umath_linalg.svd_n_s
1646
1647
signature = 'D->DdD' if isComplexType(t) else 'd->ddd'
1648
u, s, vh = gufunc(a, signature=signature, extobj=extobj)
1649
u = u.astype(result_t, copy=False)
1650
s = s.astype(_realType(result_t), copy=False)
1651
vh = vh.astype(result_t, copy=False)
1652
return wrap(u), s, wrap(vh)
1653
else:
1654
if m < n:
1655
gufunc = _umath_linalg.svd_m
1656
else:
1657
gufunc = _umath_linalg.svd_n
1658
1659
signature = 'D->d' if isComplexType(t) else 'd->d'
1660
s = gufunc(a, signature=signature, extobj=extobj)
1661
s = s.astype(_realType(result_t), copy=False)
1662
return s
1663
1664
1665
def _cond_dispatcher(x, p=None):
1666
return (x,)
1667
1668
1669
@array_function_dispatch(_cond_dispatcher)
1670
def cond(x, p=None):
1671
"""
1672
Compute the condition number of a matrix.
1673
1674
This function is capable of returning the condition number using
1675
one of seven different norms, depending on the value of `p` (see
1676
Parameters below).
1677
1678
Parameters
1679
----------
1680
x : (..., M, N) array_like
1681
The matrix whose condition number is sought.
1682
p : {None, 1, -1, 2, -2, inf, -inf, 'fro'}, optional
1683
Order of the norm used in the condition number computation:
1684
1685
===== ============================
1686
p norm for matrices
1687
===== ============================
1688
None 2-norm, computed directly using the ``SVD``
1689
'fro' Frobenius norm
1690
inf max(sum(abs(x), axis=1))
1691
-inf min(sum(abs(x), axis=1))
1692
1 max(sum(abs(x), axis=0))
1693
-1 min(sum(abs(x), axis=0))
1694
2 2-norm (largest sing. value)
1695
-2 smallest singular value
1696
===== ============================
1697
1698
inf means the `numpy.inf` object, and the Frobenius norm is
1699
the root-of-sum-of-squares norm.
1700
1701
Returns
1702
-------
1703
c : {float, inf}
1704
The condition number of the matrix. May be infinite.
1705
1706
See Also
1707
--------
1708
numpy.linalg.norm
1709
1710
Notes
1711
-----
1712
The condition number of `x` is defined as the norm of `x` times the
1713
norm of the inverse of `x` [1]_; the norm can be the usual L2-norm
1714
(root-of-sum-of-squares) or one of a number of other matrix norms.
1715
1716
References
1717
----------
1718
.. [1] G. Strang, *Linear Algebra and Its Applications*, Orlando, FL,
1719
Academic Press, Inc., 1980, pg. 285.
1720
1721
Examples
1722
--------
1723
>>> from numpy import linalg as LA
1724
>>> a = np.array([[1, 0, -1], [0, 1, 0], [1, 0, 1]])
1725
>>> a
1726
array([[ 1, 0, -1],
1727
[ 0, 1, 0],
1728
[ 1, 0, 1]])
1729
>>> LA.cond(a)
1730
1.4142135623730951
1731
>>> LA.cond(a, 'fro')
1732
3.1622776601683795
1733
>>> LA.cond(a, np.inf)
1734
2.0
1735
>>> LA.cond(a, -np.inf)
1736
1.0
1737
>>> LA.cond(a, 1)
1738
2.0
1739
>>> LA.cond(a, -1)
1740
1.0
1741
>>> LA.cond(a, 2)
1742
1.4142135623730951
1743
>>> LA.cond(a, -2)
1744
0.70710678118654746 # may vary
1745
>>> min(LA.svd(a, compute_uv=False))*min(LA.svd(LA.inv(a), compute_uv=False))
1746
0.70710678118654746 # may vary
1747
1748
"""
1749
x = asarray(x) # in case we have a matrix
1750
if _is_empty_2d(x):
1751
raise LinAlgError("cond is not defined on empty arrays")
1752
if p is None or p == 2 or p == -2:
1753
s = svd(x, compute_uv=False)
1754
with errstate(all='ignore'):
1755
if p == -2:
1756
r = s[..., -1] / s[..., 0]
1757
else:
1758
r = s[..., 0] / s[..., -1]
1759
else:
1760
# Call inv(x) ignoring errors. The result array will
1761
# contain nans in the entries where inversion failed.
1762
_assert_stacked_2d(x)
1763
_assert_stacked_square(x)
1764
t, result_t = _commonType(x)
1765
signature = 'D->D' if isComplexType(t) else 'd->d'
1766
with errstate(all='ignore'):
1767
invx = _umath_linalg.inv(x, signature=signature)
1768
r = norm(x, p, axis=(-2, -1)) * norm(invx, p, axis=(-2, -1))
1769
r = r.astype(result_t, copy=False)
1770
1771
# Convert nans to infs unless the original array had nan entries
1772
r = asarray(r)
1773
nan_mask = isnan(r)
1774
if nan_mask.any():
1775
nan_mask &= ~isnan(x).any(axis=(-2, -1))
1776
if r.ndim > 0:
1777
r[nan_mask] = Inf
1778
elif nan_mask:
1779
r[()] = Inf
1780
1781
# Convention is to return scalars instead of 0d arrays
1782
if r.ndim == 0:
1783
r = r[()]
1784
1785
return r
1786
1787
1788
def _matrix_rank_dispatcher(A, tol=None, hermitian=None):
1789
return (A,)
1790
1791
1792
@array_function_dispatch(_matrix_rank_dispatcher)
1793
def matrix_rank(A, tol=None, hermitian=False):
1794
"""
1795
Return matrix rank of array using SVD method
1796
1797
Rank of the array is the number of singular values of the array that are
1798
greater than `tol`.
1799
1800
.. versionchanged:: 1.14
1801
Can now operate on stacks of matrices
1802
1803
Parameters
1804
----------
1805
A : {(M,), (..., M, N)} array_like
1806
Input vector or stack of matrices.
1807
tol : (...) array_like, float, optional
1808
Threshold below which SVD values are considered zero. If `tol` is
1809
None, and ``S`` is an array with singular values for `M`, and
1810
``eps`` is the epsilon value for datatype of ``S``, then `tol` is
1811
set to ``S.max() * max(M, N) * eps``.
1812
1813
.. versionchanged:: 1.14
1814
Broadcasted against the stack of matrices
1815
hermitian : bool, optional
1816
If True, `A` is assumed to be Hermitian (symmetric if real-valued),
1817
enabling a more efficient method for finding singular values.
1818
Defaults to False.
1819
1820
.. versionadded:: 1.14
1821
1822
Returns
1823
-------
1824
rank : (...) array_like
1825
Rank of A.
1826
1827
Notes
1828
-----
1829
The default threshold to detect rank deficiency is a test on the magnitude
1830
of the singular values of `A`. By default, we identify singular values less
1831
than ``S.max() * max(M, N) * eps`` as indicating rank deficiency (with
1832
the symbols defined above). This is the algorithm MATLAB uses [1]. It also
1833
appears in *Numerical recipes* in the discussion of SVD solutions for linear
1834
least squares [2].
1835
1836
This default threshold is designed to detect rank deficiency accounting for
1837
the numerical errors of the SVD computation. Imagine that there is a column
1838
in `A` that is an exact (in floating point) linear combination of other
1839
columns in `A`. Computing the SVD on `A` will not produce a singular value
1840
exactly equal to 0 in general: any difference of the smallest SVD value from
1841
0 will be caused by numerical imprecision in the calculation of the SVD.
1842
Our threshold for small SVD values takes this numerical imprecision into
1843
account, and the default threshold will detect such numerical rank
1844
deficiency. The threshold may declare a matrix `A` rank deficient even if
1845
the linear combination of some columns of `A` is not exactly equal to
1846
another column of `A` but only numerically very close to another column of
1847
`A`.
1848
1849
We chose our default threshold because it is in wide use. Other thresholds
1850
are possible. For example, elsewhere in the 2007 edition of *Numerical
1851
recipes* there is an alternative threshold of ``S.max() *
1852
np.finfo(A.dtype).eps / 2. * np.sqrt(m + n + 1.)``. The authors describe
1853
this threshold as being based on "expected roundoff error" (p 71).
1854
1855
The thresholds above deal with floating point roundoff error in the
1856
calculation of the SVD. However, you may have more information about the
1857
sources of error in `A` that would make you consider other tolerance values
1858
to detect *effective* rank deficiency. The most useful measure of the
1859
tolerance depends on the operations you intend to use on your matrix. For
1860
example, if your data come from uncertain measurements with uncertainties
1861
greater than floating point epsilon, choosing a tolerance near that
1862
uncertainty may be preferable. The tolerance may be absolute if the
1863
uncertainties are absolute rather than relative.
1864
1865
References
1866
----------
1867
.. [1] MATLAB reference documentation, "Rank"
1868
https://www.mathworks.com/help/techdoc/ref/rank.html
1869
.. [2] W. H. Press, S. A. Teukolsky, W. T. Vetterling and B. P. Flannery,
1870
"Numerical Recipes (3rd edition)", Cambridge University Press, 2007,
1871
page 795.
1872
1873
Examples
1874
--------
1875
>>> from numpy.linalg import matrix_rank
1876
>>> matrix_rank(np.eye(4)) # Full rank matrix
1877
4
1878
>>> I=np.eye(4); I[-1,-1] = 0. # rank deficient matrix
1879
>>> matrix_rank(I)
1880
3
1881
>>> matrix_rank(np.ones((4,))) # 1 dimension - rank 1 unless all 0
1882
1
1883
>>> matrix_rank(np.zeros((4,)))
1884
0
1885
"""
1886
A = asarray(A)
1887
if A.ndim < 2:
1888
return int(not all(A==0))
1889
S = svd(A, compute_uv=False, hermitian=hermitian)
1890
if tol is None:
1891
tol = S.max(axis=-1, keepdims=True) * max(A.shape[-2:]) * finfo(S.dtype).eps
1892
else:
1893
tol = asarray(tol)[..., newaxis]
1894
return count_nonzero(S > tol, axis=-1)
1895
1896
1897
# Generalized inverse
1898
1899
def _pinv_dispatcher(a, rcond=None, hermitian=None):
1900
return (a,)
1901
1902
1903
@array_function_dispatch(_pinv_dispatcher)
1904
def pinv(a, rcond=1e-15, hermitian=False):
1905
"""
1906
Compute the (Moore-Penrose) pseudo-inverse of a matrix.
1907
1908
Calculate the generalized inverse of a matrix using its
1909
singular-value decomposition (SVD) and including all
1910
*large* singular values.
1911
1912
.. versionchanged:: 1.14
1913
Can now operate on stacks of matrices
1914
1915
Parameters
1916
----------
1917
a : (..., M, N) array_like
1918
Matrix or stack of matrices to be pseudo-inverted.
1919
rcond : (...) array_like of float
1920
Cutoff for small singular values.
1921
Singular values less than or equal to
1922
``rcond * largest_singular_value`` are set to zero.
1923
Broadcasts against the stack of matrices.
1924
hermitian : bool, optional
1925
If True, `a` is assumed to be Hermitian (symmetric if real-valued),
1926
enabling a more efficient method for finding singular values.
1927
Defaults to False.
1928
1929
.. versionadded:: 1.17.0
1930
1931
Returns
1932
-------
1933
B : (..., N, M) ndarray
1934
The pseudo-inverse of `a`. If `a` is a `matrix` instance, then so
1935
is `B`.
1936
1937
Raises
1938
------
1939
LinAlgError
1940
If the SVD computation does not converge.
1941
1942
See Also
1943
--------
1944
scipy.linalg.pinv : Similar function in SciPy.
1945
scipy.linalg.pinv2 : Similar function in SciPy (SVD-based).
1946
scipy.linalg.pinvh : Compute the (Moore-Penrose) pseudo-inverse of a
1947
Hermitian matrix.
1948
1949
Notes
1950
-----
1951
The pseudo-inverse of a matrix A, denoted :math:`A^+`, is
1952
defined as: "the matrix that 'solves' [the least-squares problem]
1953
:math:`Ax = b`," i.e., if :math:`\\bar{x}` is said solution, then
1954
:math:`A^+` is that matrix such that :math:`\\bar{x} = A^+b`.
1955
1956
It can be shown that if :math:`Q_1 \\Sigma Q_2^T = A` is the singular
1957
value decomposition of A, then
1958
:math:`A^+ = Q_2 \\Sigma^+ Q_1^T`, where :math:`Q_{1,2}` are
1959
orthogonal matrices, :math:`\\Sigma` is a diagonal matrix consisting
1960
of A's so-called singular values, (followed, typically, by
1961
zeros), and then :math:`\\Sigma^+` is simply the diagonal matrix
1962
consisting of the reciprocals of A's singular values
1963
(again, followed by zeros). [1]_
1964
1965
References
1966
----------
1967
.. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando,
1968
FL, Academic Press, Inc., 1980, pp. 139-142.
1969
1970
Examples
1971
--------
1972
The following example checks that ``a * a+ * a == a`` and
1973
``a+ * a * a+ == a+``:
1974
1975
>>> a = np.random.randn(9, 6)
1976
>>> B = np.linalg.pinv(a)
1977
>>> np.allclose(a, np.dot(a, np.dot(B, a)))
1978
True
1979
>>> np.allclose(B, np.dot(B, np.dot(a, B)))
1980
True
1981
1982
"""
1983
a, wrap = _makearray(a)
1984
rcond = asarray(rcond)
1985
if _is_empty_2d(a):
1986
m, n = a.shape[-2:]
1987
res = empty(a.shape[:-2] + (n, m), dtype=a.dtype)
1988
return wrap(res)
1989
a = a.conjugate()
1990
u, s, vt = svd(a, full_matrices=False, hermitian=hermitian)
1991
1992
# discard small singular values
1993
cutoff = rcond[..., newaxis] * amax(s, axis=-1, keepdims=True)
1994
large = s > cutoff
1995
s = divide(1, s, where=large, out=s)
1996
s[~large] = 0
1997
1998
res = matmul(transpose(vt), multiply(s[..., newaxis], transpose(u)))
1999
return wrap(res)
2000
2001
2002
# Determinant
2003
2004
2005
@array_function_dispatch(_unary_dispatcher)
2006
def slogdet(a):
2007
"""
2008
Compute the sign and (natural) logarithm of the determinant of an array.
2009
2010
If an array has a very small or very large determinant, then a call to
2011
`det` may overflow or underflow. This routine is more robust against such
2012
issues, because it computes the logarithm of the determinant rather than
2013
the determinant itself.
2014
2015
Parameters
2016
----------
2017
a : (..., M, M) array_like
2018
Input array, has to be a square 2-D array.
2019
2020
Returns
2021
-------
2022
sign : (...) array_like
2023
A number representing the sign of the determinant. For a real matrix,
2024
this is 1, 0, or -1. For a complex matrix, this is a complex number
2025
with absolute value 1 (i.e., it is on the unit circle), or else 0.
2026
logdet : (...) array_like
2027
The natural log of the absolute value of the determinant.
2028
2029
If the determinant is zero, then `sign` will be 0 and `logdet` will be
2030
-Inf. In all cases, the determinant is equal to ``sign * np.exp(logdet)``.
2031
2032
See Also
2033
--------
2034
det
2035
2036
Notes
2037
-----
2038
2039
.. versionadded:: 1.8.0
2040
2041
Broadcasting rules apply, see the `numpy.linalg` documentation for
2042
details.
2043
2044
.. versionadded:: 1.6.0
2045
2046
The determinant is computed via LU factorization using the LAPACK
2047
routine ``z/dgetrf``.
2048
2049
2050
Examples
2051
--------
2052
The determinant of a 2-D array ``[[a, b], [c, d]]`` is ``ad - bc``:
2053
2054
>>> a = np.array([[1, 2], [3, 4]])
2055
>>> (sign, logdet) = np.linalg.slogdet(a)
2056
>>> (sign, logdet)
2057
(-1, 0.69314718055994529) # may vary
2058
>>> sign * np.exp(logdet)
2059
-2.0
2060
2061
Computing log-determinants for a stack of matrices:
2062
2063
>>> a = np.array([ [[1, 2], [3, 4]], [[1, 2], [2, 1]], [[1, 3], [3, 1]] ])
2064
>>> a.shape
2065
(3, 2, 2)
2066
>>> sign, logdet = np.linalg.slogdet(a)
2067
>>> (sign, logdet)
2068
(array([-1., -1., -1.]), array([ 0.69314718, 1.09861229, 2.07944154]))
2069
>>> sign * np.exp(logdet)
2070
array([-2., -3., -8.])
2071
2072
This routine succeeds where ordinary `det` does not:
2073
2074
>>> np.linalg.det(np.eye(500) * 0.1)
2075
0.0
2076
>>> np.linalg.slogdet(np.eye(500) * 0.1)
2077
(1, -1151.2925464970228)
2078
2079
"""
2080
a = asarray(a)
2081
_assert_stacked_2d(a)
2082
_assert_stacked_square(a)
2083
t, result_t = _commonType(a)
2084
real_t = _realType(result_t)
2085
signature = 'D->Dd' if isComplexType(t) else 'd->dd'
2086
sign, logdet = _umath_linalg.slogdet(a, signature=signature)
2087
sign = sign.astype(result_t, copy=False)
2088
logdet = logdet.astype(real_t, copy=False)
2089
return sign, logdet
2090
2091
2092
@array_function_dispatch(_unary_dispatcher)
2093
def det(a):
2094
"""
2095
Compute the determinant of an array.
2096
2097
Parameters
2098
----------
2099
a : (..., M, M) array_like
2100
Input array to compute determinants for.
2101
2102
Returns
2103
-------
2104
det : (...) array_like
2105
Determinant of `a`.
2106
2107
See Also
2108
--------
2109
slogdet : Another way to represent the determinant, more suitable
2110
for large matrices where underflow/overflow may occur.
2111
scipy.linalg.det : Similar function in SciPy.
2112
2113
Notes
2114
-----
2115
2116
.. versionadded:: 1.8.0
2117
2118
Broadcasting rules apply, see the `numpy.linalg` documentation for
2119
details.
2120
2121
The determinant is computed via LU factorization using the LAPACK
2122
routine ``z/dgetrf``.
2123
2124
Examples
2125
--------
2126
The determinant of a 2-D array [[a, b], [c, d]] is ad - bc:
2127
2128
>>> a = np.array([[1, 2], [3, 4]])
2129
>>> np.linalg.det(a)
2130
-2.0 # may vary
2131
2132
Computing determinants for a stack of matrices:
2133
2134
>>> a = np.array([ [[1, 2], [3, 4]], [[1, 2], [2, 1]], [[1, 3], [3, 1]] ])
2135
>>> a.shape
2136
(3, 2, 2)
2137
>>> np.linalg.det(a)
2138
array([-2., -3., -8.])
2139
2140
"""
2141
a = asarray(a)
2142
_assert_stacked_2d(a)
2143
_assert_stacked_square(a)
2144
t, result_t = _commonType(a)
2145
signature = 'D->D' if isComplexType(t) else 'd->d'
2146
r = _umath_linalg.det(a, signature=signature)
2147
r = r.astype(result_t, copy=False)
2148
return r
2149
2150
2151
# Linear Least Squares
2152
2153
def _lstsq_dispatcher(a, b, rcond=None):
2154
return (a, b)
2155
2156
2157
@array_function_dispatch(_lstsq_dispatcher)
2158
def lstsq(a, b, rcond="warn"):
2159
r"""
2160
Return the least-squares solution to a linear matrix equation.
2161
2162
Computes the vector `x` that approximately solves the equation
2163
``a @ x = b``. The equation may be under-, well-, or over-determined
2164
(i.e., the number of linearly independent rows of `a` can be less than,
2165
equal to, or greater than its number of linearly independent columns).
2166
If `a` is square and of full rank, then `x` (but for round-off error)
2167
is the "exact" solution of the equation. Else, `x` minimizes the
2168
Euclidean 2-norm :math:`||b - ax||`. If there are multiple minimizing
2169
solutions, the one with the smallest 2-norm :math:`||x||` is returned.
2170
2171
Parameters
2172
----------
2173
a : (M, N) array_like
2174
"Coefficient" matrix.
2175
b : {(M,), (M, K)} array_like
2176
Ordinate or "dependent variable" values. If `b` is two-dimensional,
2177
the least-squares solution is calculated for each of the `K` columns
2178
of `b`.
2179
rcond : float, optional
2180
Cut-off ratio for small singular values of `a`.
2181
For the purposes of rank determination, singular values are treated
2182
as zero if they are smaller than `rcond` times the largest singular
2183
value of `a`.
2184
2185
.. versionchanged:: 1.14.0
2186
If not set, a FutureWarning is given. The previous default
2187
of ``-1`` will use the machine precision as `rcond` parameter,
2188
the new default will use the machine precision times `max(M, N)`.
2189
To silence the warning and use the new default, use ``rcond=None``,
2190
to keep using the old behavior, use ``rcond=-1``.
2191
2192
Returns
2193
-------
2194
x : {(N,), (N, K)} ndarray
2195
Least-squares solution. If `b` is two-dimensional,
2196
the solutions are in the `K` columns of `x`.
2197
residuals : {(1,), (K,), (0,)} ndarray
2198
Sums of squared residuals: Squared Euclidean 2-norm for each column in
2199
``b - a @ x``.
2200
If the rank of `a` is < N or M <= N, this is an empty array.
2201
If `b` is 1-dimensional, this is a (1,) shape array.
2202
Otherwise the shape is (K,).
2203
rank : int
2204
Rank of matrix `a`.
2205
s : (min(M, N),) ndarray
2206
Singular values of `a`.
2207
2208
Raises
2209
------
2210
LinAlgError
2211
If computation does not converge.
2212
2213
See Also
2214
--------
2215
scipy.linalg.lstsq : Similar function in SciPy.
2216
2217
Notes
2218
-----
2219
If `b` is a matrix, then all array results are returned as matrices.
2220
2221
Examples
2222
--------
2223
Fit a line, ``y = mx + c``, through some noisy data-points:
2224
2225
>>> x = np.array([0, 1, 2, 3])
2226
>>> y = np.array([-1, 0.2, 0.9, 2.1])
2227
2228
By examining the coefficients, we see that the line should have a
2229
gradient of roughly 1 and cut the y-axis at, more or less, -1.
2230
2231
We can rewrite the line equation as ``y = Ap``, where ``A = [[x 1]]``
2232
and ``p = [[m], [c]]``. Now use `lstsq` to solve for `p`:
2233
2234
>>> A = np.vstack([x, np.ones(len(x))]).T
2235
>>> A
2236
array([[ 0., 1.],
2237
[ 1., 1.],
2238
[ 2., 1.],
2239
[ 3., 1.]])
2240
2241
>>> m, c = np.linalg.lstsq(A, y, rcond=None)[0]
2242
>>> m, c
2243
(1.0 -0.95) # may vary
2244
2245
Plot the data along with the fitted line:
2246
2247
>>> import matplotlib.pyplot as plt
2248
>>> _ = plt.plot(x, y, 'o', label='Original data', markersize=10)
2249
>>> _ = plt.plot(x, m*x + c, 'r', label='Fitted line')
2250
>>> _ = plt.legend()
2251
>>> plt.show()
2252
2253
"""
2254
a, _ = _makearray(a)
2255
b, wrap = _makearray(b)
2256
is_1d = b.ndim == 1
2257
if is_1d:
2258
b = b[:, newaxis]
2259
_assert_2d(a, b)
2260
m, n = a.shape[-2:]
2261
m2, n_rhs = b.shape[-2:]
2262
if m != m2:
2263
raise LinAlgError('Incompatible dimensions')
2264
2265
t, result_t = _commonType(a, b)
2266
result_real_t = _realType(result_t)
2267
2268
# Determine default rcond value
2269
if rcond == "warn":
2270
# 2017-08-19, 1.14.0
2271
warnings.warn("`rcond` parameter will change to the default of "
2272
"machine precision times ``max(M, N)`` where M and N "
2273
"are the input matrix dimensions.\n"
2274
"To use the future default and silence this warning "
2275
"we advise to pass `rcond=None`, to keep using the old, "
2276
"explicitly pass `rcond=-1`.",
2277
FutureWarning, stacklevel=3)
2278
rcond = -1
2279
if rcond is None:
2280
rcond = finfo(t).eps * max(n, m)
2281
2282
if m <= n:
2283
gufunc = _umath_linalg.lstsq_m
2284
else:
2285
gufunc = _umath_linalg.lstsq_n
2286
2287
signature = 'DDd->Ddid' if isComplexType(t) else 'ddd->ddid'
2288
extobj = get_linalg_error_extobj(_raise_linalgerror_lstsq)
2289
if n_rhs == 0:
2290
# lapack can't handle n_rhs = 0 - so allocate the array one larger in that axis
2291
b = zeros(b.shape[:-2] + (m, n_rhs + 1), dtype=b.dtype)
2292
x, resids, rank, s = gufunc(a, b, rcond, signature=signature, extobj=extobj)
2293
if m == 0:
2294
x[...] = 0
2295
if n_rhs == 0:
2296
# remove the item we added
2297
x = x[..., :n_rhs]
2298
resids = resids[..., :n_rhs]
2299
2300
# remove the axis we added
2301
if is_1d:
2302
x = x.squeeze(axis=-1)
2303
# we probably should squeeze resids too, but we can't
2304
# without breaking compatibility.
2305
2306
# as documented
2307
if rank != n or m <= n:
2308
resids = array([], result_real_t)
2309
2310
# coerce output arrays
2311
s = s.astype(result_real_t, copy=False)
2312
resids = resids.astype(result_real_t, copy=False)
2313
x = x.astype(result_t, copy=True) # Copying lets the memory in r_parts be freed
2314
return wrap(x), wrap(resids), rank, s
2315
2316
2317
def _multi_svd_norm(x, row_axis, col_axis, op):
2318
"""Compute a function of the singular values of the 2-D matrices in `x`.
2319
2320
This is a private utility function used by `numpy.linalg.norm()`.
2321
2322
Parameters
2323
----------
2324
x : ndarray
2325
row_axis, col_axis : int
2326
The axes of `x` that hold the 2-D matrices.
2327
op : callable
2328
This should be either numpy.amin or `numpy.amax` or `numpy.sum`.
2329
2330
Returns
2331
-------
2332
result : float or ndarray
2333
If `x` is 2-D, the return values is a float.
2334
Otherwise, it is an array with ``x.ndim - 2`` dimensions.
2335
The return values are either the minimum or maximum or sum of the
2336
singular values of the matrices, depending on whether `op`
2337
is `numpy.amin` or `numpy.amax` or `numpy.sum`.
2338
2339
"""
2340
y = moveaxis(x, (row_axis, col_axis), (-2, -1))
2341
result = op(svd(y, compute_uv=False), axis=-1)
2342
return result
2343
2344
2345
def _norm_dispatcher(x, ord=None, axis=None, keepdims=None):
2346
return (x,)
2347
2348
2349
@array_function_dispatch(_norm_dispatcher)
2350
def norm(x, ord=None, axis=None, keepdims=False):
2351
"""
2352
Matrix or vector norm.
2353
2354
This function is able to return one of eight different matrix norms,
2355
or one of an infinite number of vector norms (described below), depending
2356
on the value of the ``ord`` parameter.
2357
2358
Parameters
2359
----------
2360
x : array_like
2361
Input array. If `axis` is None, `x` must be 1-D or 2-D, unless `ord`
2362
is None. If both `axis` and `ord` are None, the 2-norm of
2363
``x.ravel`` will be returned.
2364
ord : {non-zero int, inf, -inf, 'fro', 'nuc'}, optional
2365
Order of the norm (see table under ``Notes``). inf means numpy's
2366
`inf` object. The default is None.
2367
axis : {None, int, 2-tuple of ints}, optional.
2368
If `axis` is an integer, it specifies the axis of `x` along which to
2369
compute the vector norms. If `axis` is a 2-tuple, it specifies the
2370
axes that hold 2-D matrices, and the matrix norms of these matrices
2371
are computed. If `axis` is None then either a vector norm (when `x`
2372
is 1-D) or a matrix norm (when `x` is 2-D) is returned. The default
2373
is None.
2374
2375
.. versionadded:: 1.8.0
2376
2377
keepdims : bool, optional
2378
If this is set to True, the axes which are normed over are left in the
2379
result as dimensions with size one. With this option the result will
2380
broadcast correctly against the original `x`.
2381
2382
.. versionadded:: 1.10.0
2383
2384
Returns
2385
-------
2386
n : float or ndarray
2387
Norm of the matrix or vector(s).
2388
2389
See Also
2390
--------
2391
scipy.linalg.norm : Similar function in SciPy.
2392
2393
Notes
2394
-----
2395
For values of ``ord < 1``, the result is, strictly speaking, not a
2396
mathematical 'norm', but it may still be useful for various numerical
2397
purposes.
2398
2399
The following norms can be calculated:
2400
2401
===== ============================ ==========================
2402
ord norm for matrices norm for vectors
2403
===== ============================ ==========================
2404
None Frobenius norm 2-norm
2405
'fro' Frobenius norm --
2406
'nuc' nuclear norm --
2407
inf max(sum(abs(x), axis=1)) max(abs(x))
2408
-inf min(sum(abs(x), axis=1)) min(abs(x))
2409
0 -- sum(x != 0)
2410
1 max(sum(abs(x), axis=0)) as below
2411
-1 min(sum(abs(x), axis=0)) as below
2412
2 2-norm (largest sing. value) as below
2413
-2 smallest singular value as below
2414
other -- sum(abs(x)**ord)**(1./ord)
2415
===== ============================ ==========================
2416
2417
The Frobenius norm is given by [1]_:
2418
2419
:math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}`
2420
2421
The nuclear norm is the sum of the singular values.
2422
2423
Both the Frobenius and nuclear norm orders are only defined for
2424
matrices and raise a ValueError when ``x.ndim != 2``.
2425
2426
References
2427
----------
2428
.. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*,
2429
Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15
2430
2431
Examples
2432
--------
2433
>>> from numpy import linalg as LA
2434
>>> a = np.arange(9) - 4
2435
>>> a
2436
array([-4, -3, -2, ..., 2, 3, 4])
2437
>>> b = a.reshape((3, 3))
2438
>>> b
2439
array([[-4, -3, -2],
2440
[-1, 0, 1],
2441
[ 2, 3, 4]])
2442
2443
>>> LA.norm(a)
2444
7.745966692414834
2445
>>> LA.norm(b)
2446
7.745966692414834
2447
>>> LA.norm(b, 'fro')
2448
7.745966692414834
2449
>>> LA.norm(a, np.inf)
2450
4.0
2451
>>> LA.norm(b, np.inf)
2452
9.0
2453
>>> LA.norm(a, -np.inf)
2454
0.0
2455
>>> LA.norm(b, -np.inf)
2456
2.0
2457
2458
>>> LA.norm(a, 1)
2459
20.0
2460
>>> LA.norm(b, 1)
2461
7.0
2462
>>> LA.norm(a, -1)
2463
-4.6566128774142013e-010
2464
>>> LA.norm(b, -1)
2465
6.0
2466
>>> LA.norm(a, 2)
2467
7.745966692414834
2468
>>> LA.norm(b, 2)
2469
7.3484692283495345
2470
2471
>>> LA.norm(a, -2)
2472
0.0
2473
>>> LA.norm(b, -2)
2474
1.8570331885190563e-016 # may vary
2475
>>> LA.norm(a, 3)
2476
5.8480354764257312 # may vary
2477
>>> LA.norm(a, -3)
2478
0.0
2479
2480
Using the `axis` argument to compute vector norms:
2481
2482
>>> c = np.array([[ 1, 2, 3],
2483
... [-1, 1, 4]])
2484
>>> LA.norm(c, axis=0)
2485
array([ 1.41421356, 2.23606798, 5. ])
2486
>>> LA.norm(c, axis=1)
2487
array([ 3.74165739, 4.24264069])
2488
>>> LA.norm(c, ord=1, axis=1)
2489
array([ 6., 6.])
2490
2491
Using the `axis` argument to compute matrix norms:
2492
2493
>>> m = np.arange(8).reshape(2,2,2)
2494
>>> LA.norm(m, axis=(1,2))
2495
array([ 3.74165739, 11.22497216])
2496
>>> LA.norm(m[0, :, :]), LA.norm(m[1, :, :])
2497
(3.7416573867739413, 11.224972160321824)
2498
2499
"""
2500
x = asarray(x)
2501
2502
if not issubclass(x.dtype.type, (inexact, object_)):
2503
x = x.astype(float)
2504
2505
# Immediately handle some default, simple, fast, and common cases.
2506
if axis is None:
2507
ndim = x.ndim
2508
if ((ord is None) or
2509
(ord in ('f', 'fro') and ndim == 2) or
2510
(ord == 2 and ndim == 1)):
2511
2512
x = x.ravel(order='K')
2513
if isComplexType(x.dtype.type):
2514
sqnorm = dot(x.real, x.real) + dot(x.imag, x.imag)
2515
else:
2516
sqnorm = dot(x, x)
2517
ret = sqrt(sqnorm)
2518
if keepdims:
2519
ret = ret.reshape(ndim*[1])
2520
return ret
2521
2522
# Normalize the `axis` argument to a tuple.
2523
nd = x.ndim
2524
if axis is None:
2525
axis = tuple(range(nd))
2526
elif not isinstance(axis, tuple):
2527
try:
2528
axis = int(axis)
2529
except Exception as e:
2530
raise TypeError("'axis' must be None, an integer or a tuple of integers") from e
2531
axis = (axis,)
2532
2533
if len(axis) == 1:
2534
if ord == Inf:
2535
return abs(x).max(axis=axis, keepdims=keepdims)
2536
elif ord == -Inf:
2537
return abs(x).min(axis=axis, keepdims=keepdims)
2538
elif ord == 0:
2539
# Zero norm
2540
return (x != 0).astype(x.real.dtype).sum(axis=axis, keepdims=keepdims)
2541
elif ord == 1:
2542
# special case for speedup
2543
return add.reduce(abs(x), axis=axis, keepdims=keepdims)
2544
elif ord is None or ord == 2:
2545
# special case for speedup
2546
s = (x.conj() * x).real
2547
return sqrt(add.reduce(s, axis=axis, keepdims=keepdims))
2548
# None of the str-type keywords for ord ('fro', 'nuc')
2549
# are valid for vectors
2550
elif isinstance(ord, str):
2551
raise ValueError(f"Invalid norm order '{ord}' for vectors")
2552
else:
2553
absx = abs(x)
2554
absx **= ord
2555
ret = add.reduce(absx, axis=axis, keepdims=keepdims)
2556
ret **= (1 / ord)
2557
return ret
2558
elif len(axis) == 2:
2559
row_axis, col_axis = axis
2560
row_axis = normalize_axis_index(row_axis, nd)
2561
col_axis = normalize_axis_index(col_axis, nd)
2562
if row_axis == col_axis:
2563
raise ValueError('Duplicate axes given.')
2564
if ord == 2:
2565
ret = _multi_svd_norm(x, row_axis, col_axis, amax)
2566
elif ord == -2:
2567
ret = _multi_svd_norm(x, row_axis, col_axis, amin)
2568
elif ord == 1:
2569
if col_axis > row_axis:
2570
col_axis -= 1
2571
ret = add.reduce(abs(x), axis=row_axis).max(axis=col_axis)
2572
elif ord == Inf:
2573
if row_axis > col_axis:
2574
row_axis -= 1
2575
ret = add.reduce(abs(x), axis=col_axis).max(axis=row_axis)
2576
elif ord == -1:
2577
if col_axis > row_axis:
2578
col_axis -= 1
2579
ret = add.reduce(abs(x), axis=row_axis).min(axis=col_axis)
2580
elif ord == -Inf:
2581
if row_axis > col_axis:
2582
row_axis -= 1
2583
ret = add.reduce(abs(x), axis=col_axis).min(axis=row_axis)
2584
elif ord in [None, 'fro', 'f']:
2585
ret = sqrt(add.reduce((x.conj() * x).real, axis=axis))
2586
elif ord == 'nuc':
2587
ret = _multi_svd_norm(x, row_axis, col_axis, sum)
2588
else:
2589
raise ValueError("Invalid norm order for matrices.")
2590
if keepdims:
2591
ret_shape = list(x.shape)
2592
ret_shape[axis[0]] = 1
2593
ret_shape[axis[1]] = 1
2594
ret = ret.reshape(ret_shape)
2595
return ret
2596
else:
2597
raise ValueError("Improper number of dimensions to norm.")
2598
2599
2600
# multi_dot
2601
2602
def _multidot_dispatcher(arrays, *, out=None):
2603
yield from arrays
2604
yield out
2605
2606
2607
@array_function_dispatch(_multidot_dispatcher)
2608
def multi_dot(arrays, *, out=None):
2609
"""
2610
Compute the dot product of two or more arrays in a single function call,
2611
while automatically selecting the fastest evaluation order.
2612
2613
`multi_dot` chains `numpy.dot` and uses optimal parenthesization
2614
of the matrices [1]_ [2]_. Depending on the shapes of the matrices,
2615
this can speed up the multiplication a lot.
2616
2617
If the first argument is 1-D it is treated as a row vector.
2618
If the last argument is 1-D it is treated as a column vector.
2619
The other arguments must be 2-D.
2620
2621
Think of `multi_dot` as::
2622
2623
def multi_dot(arrays): return functools.reduce(np.dot, arrays)
2624
2625
2626
Parameters
2627
----------
2628
arrays : sequence of array_like
2629
If the first argument is 1-D it is treated as row vector.
2630
If the last argument is 1-D it is treated as column vector.
2631
The other arguments must be 2-D.
2632
out : ndarray, optional
2633
Output argument. This must have the exact kind that would be returned
2634
if it was not used. In particular, it must have the right type, must be
2635
C-contiguous, and its dtype must be the dtype that would be returned
2636
for `dot(a, b)`. This is a performance feature. Therefore, if these
2637
conditions are not met, an exception is raised, instead of attempting
2638
to be flexible.
2639
2640
.. versionadded:: 1.19.0
2641
2642
Returns
2643
-------
2644
output : ndarray
2645
Returns the dot product of the supplied arrays.
2646
2647
See Also
2648
--------
2649
numpy.dot : dot multiplication with two arguments.
2650
2651
References
2652
----------
2653
2654
.. [1] Cormen, "Introduction to Algorithms", Chapter 15.2, p. 370-378
2655
.. [2] https://en.wikipedia.org/wiki/Matrix_chain_multiplication
2656
2657
Examples
2658
--------
2659
`multi_dot` allows you to write::
2660
2661
>>> from numpy.linalg import multi_dot
2662
>>> # Prepare some data
2663
>>> A = np.random.random((10000, 100))
2664
>>> B = np.random.random((100, 1000))
2665
>>> C = np.random.random((1000, 5))
2666
>>> D = np.random.random((5, 333))
2667
>>> # the actual dot multiplication
2668
>>> _ = multi_dot([A, B, C, D])
2669
2670
instead of::
2671
2672
>>> _ = np.dot(np.dot(np.dot(A, B), C), D)
2673
>>> # or
2674
>>> _ = A.dot(B).dot(C).dot(D)
2675
2676
Notes
2677
-----
2678
The cost for a matrix multiplication can be calculated with the
2679
following function::
2680
2681
def cost(A, B):
2682
return A.shape[0] * A.shape[1] * B.shape[1]
2683
2684
Assume we have three matrices
2685
:math:`A_{10x100}, B_{100x5}, C_{5x50}`.
2686
2687
The costs for the two different parenthesizations are as follows::
2688
2689
cost((AB)C) = 10*100*5 + 10*5*50 = 5000 + 2500 = 7500
2690
cost(A(BC)) = 10*100*50 + 100*5*50 = 50000 + 25000 = 75000
2691
2692
"""
2693
n = len(arrays)
2694
# optimization only makes sense for len(arrays) > 2
2695
if n < 2:
2696
raise ValueError("Expecting at least two arrays.")
2697
elif n == 2:
2698
return dot(arrays[0], arrays[1], out=out)
2699
2700
arrays = [asanyarray(a) for a in arrays]
2701
2702
# save original ndim to reshape the result array into the proper form later
2703
ndim_first, ndim_last = arrays[0].ndim, arrays[-1].ndim
2704
# Explicitly convert vectors to 2D arrays to keep the logic of the internal
2705
# _multi_dot_* functions as simple as possible.
2706
if arrays[0].ndim == 1:
2707
arrays[0] = atleast_2d(arrays[0])
2708
if arrays[-1].ndim == 1:
2709
arrays[-1] = atleast_2d(arrays[-1]).T
2710
_assert_2d(*arrays)
2711
2712
# _multi_dot_three is much faster than _multi_dot_matrix_chain_order
2713
if n == 3:
2714
result = _multi_dot_three(arrays[0], arrays[1], arrays[2], out=out)
2715
else:
2716
order = _multi_dot_matrix_chain_order(arrays)
2717
result = _multi_dot(arrays, order, 0, n - 1, out=out)
2718
2719
# return proper shape
2720
if ndim_first == 1 and ndim_last == 1:
2721
return result[0, 0] # scalar
2722
elif ndim_first == 1 or ndim_last == 1:
2723
return result.ravel() # 1-D
2724
else:
2725
return result
2726
2727
2728
def _multi_dot_three(A, B, C, out=None):
2729
"""
2730
Find the best order for three arrays and do the multiplication.
2731
2732
For three arguments `_multi_dot_three` is approximately 15 times faster
2733
than `_multi_dot_matrix_chain_order`
2734
2735
"""
2736
a0, a1b0 = A.shape
2737
b1c0, c1 = C.shape
2738
# cost1 = cost((AB)C) = a0*a1b0*b1c0 + a0*b1c0*c1
2739
cost1 = a0 * b1c0 * (a1b0 + c1)
2740
# cost2 = cost(A(BC)) = a1b0*b1c0*c1 + a0*a1b0*c1
2741
cost2 = a1b0 * c1 * (a0 + b1c0)
2742
2743
if cost1 < cost2:
2744
return dot(dot(A, B), C, out=out)
2745
else:
2746
return dot(A, dot(B, C), out=out)
2747
2748
2749
def _multi_dot_matrix_chain_order(arrays, return_costs=False):
2750
"""
2751
Return a np.array that encodes the optimal order of mutiplications.
2752
2753
The optimal order array is then used by `_multi_dot()` to do the
2754
multiplication.
2755
2756
Also return the cost matrix if `return_costs` is `True`
2757
2758
The implementation CLOSELY follows Cormen, "Introduction to Algorithms",
2759
Chapter 15.2, p. 370-378. Note that Cormen uses 1-based indices.
2760
2761
cost[i, j] = min([
2762
cost[prefix] + cost[suffix] + cost_mult(prefix, suffix)
2763
for k in range(i, j)])
2764
2765
"""
2766
n = len(arrays)
2767
# p stores the dimensions of the matrices
2768
# Example for p: A_{10x100}, B_{100x5}, C_{5x50} --> p = [10, 100, 5, 50]
2769
p = [a.shape[0] for a in arrays] + [arrays[-1].shape[1]]
2770
# m is a matrix of costs of the subproblems
2771
# m[i,j]: min number of scalar multiplications needed to compute A_{i..j}
2772
m = zeros((n, n), dtype=double)
2773
# s is the actual ordering
2774
# s[i, j] is the value of k at which we split the product A_i..A_j
2775
s = empty((n, n), dtype=intp)
2776
2777
for l in range(1, n):
2778
for i in range(n - l):
2779
j = i + l
2780
m[i, j] = Inf
2781
for k in range(i, j):
2782
q = m[i, k] + m[k+1, j] + p[i]*p[k+1]*p[j+1]
2783
if q < m[i, j]:
2784
m[i, j] = q
2785
s[i, j] = k # Note that Cormen uses 1-based index
2786
2787
return (s, m) if return_costs else s
2788
2789
2790
def _multi_dot(arrays, order, i, j, out=None):
2791
"""Actually do the multiplication with the given order."""
2792
if i == j:
2793
# the initial call with non-None out should never get here
2794
assert out is None
2795
2796
return arrays[i]
2797
else:
2798
return dot(_multi_dot(arrays, order, i, order[i, j]),
2799
_multi_dot(arrays, order, order[i, j] + 1, j),
2800
out=out)
2801
2802