Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scipy/linalg/_basic.py: 7%
402 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-12 06:31 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-12 06:31 +0000
1#
2# Author: Pearu Peterson, March 2002
3#
4# w/ additions by Travis Oliphant, March 2002
5# and Jake Vanderplas, August 2012
7from warnings import warn
8import numpy as np
9from numpy import atleast_1d, atleast_2d
10from ._flinalg_py import get_flinalg_funcs
11from .lapack import get_lapack_funcs, _compute_lwork
12from ._misc import LinAlgError, _datacopied, LinAlgWarning
13from ._decomp import _asarray_validated
14from . import _decomp, _decomp_svd
15from ._solve_toeplitz import levinson
17__all__ = ['solve', 'solve_triangular', 'solveh_banded', 'solve_banded',
18 'solve_toeplitz', 'solve_circulant', 'inv', 'det', 'lstsq',
19 'pinv', 'pinvh', 'matrix_balance', 'matmul_toeplitz']
22# Linear equations
23def _solve_check(n, info, lamch=None, rcond=None):
24 """ Check arguments during the different steps of the solution phase """
25 if info < 0:
26 raise ValueError('LAPACK reported an illegal value in {}-th argument'
27 '.'.format(-info))
28 elif 0 < info:
29 raise LinAlgError('Matrix is singular.')
31 if lamch is None:
32 return
33 E = lamch('E')
34 if rcond < E:
35 warn('Ill-conditioned matrix (rcond={:.6g}): '
36 'result may not be accurate.'.format(rcond),
37 LinAlgWarning, stacklevel=3)
40def solve(a, b, sym_pos=False, lower=False, overwrite_a=False,
41 overwrite_b=False, check_finite=True, assume_a='gen',
42 transposed=False):
43 """
44 Solves the linear equation set ``a @ x == b`` for the unknown ``x``
45 for square `a` matrix.
47 If the data matrix is known to be a particular type then supplying the
48 corresponding string to ``assume_a`` key chooses the dedicated solver.
49 The available options are
51 =================== ========
52 generic matrix 'gen'
53 symmetric 'sym'
54 hermitian 'her'
55 positive definite 'pos'
56 =================== ========
58 If omitted, ``'gen'`` is the default structure.
60 The datatype of the arrays define which solver is called regardless
61 of the values. In other words, even when the complex array entries have
62 precisely zero imaginary parts, the complex solver will be called based
63 on the data type of the array.
65 Parameters
66 ----------
67 a : (N, N) array_like
68 Square input data
69 b : (N, NRHS) array_like
70 Input data for the right hand side.
71 sym_pos : bool, default: False, deprecated
72 Assume `a` is symmetric and positive definite.
74 .. deprecated:: 0.19.0
75 This keyword is deprecated and should be replaced by using
76 ``assume_a = 'pos'``. `sym_pos` will be removed in SciPy 1.11.0.
78 lower : bool, default: False
79 Ignored if ``assume_a == 'gen'`` (the default). If True, the
80 calculation uses only the data in the lower triangle of `a`;
81 entries above the diagonal are ignored. If False (default), the
82 calculation uses only the data in the upper triangle of `a`; entries
83 below the diagonal are ignored.
84 overwrite_a : bool, default: False
85 Allow overwriting data in `a` (may enhance performance).
86 overwrite_b : bool, default: False
87 Allow overwriting data in `b` (may enhance performance).
88 check_finite : bool, default: True
89 Whether to check that the input matrices contain only finite numbers.
90 Disabling may give a performance gain, but may result in problems
91 (crashes, non-termination) if the inputs do contain infinities or NaNs.
92 assume_a : str, {'gen', 'sym', 'her', 'pos'}
93 Valid entries are explained above.
94 transposed : bool, default: False
95 If True, solve ``a.T @ x == b``. Raises `NotImplementedError`
96 for complex `a`.
98 Returns
99 -------
100 x : (N, NRHS) ndarray
101 The solution array.
103 Raises
104 ------
105 ValueError
106 If size mismatches detected or input a is not square.
107 LinAlgError
108 If the matrix is singular.
109 LinAlgWarning
110 If an ill-conditioned input a is detected.
111 NotImplementedError
112 If transposed is True and input a is a complex matrix.
114 Notes
115 -----
116 If the input b matrix is a 1-D array with N elements, when supplied
117 together with an NxN input a, it is assumed as a valid column vector
118 despite the apparent size mismatch. This is compatible with the
119 numpy.dot() behavior and the returned result is still 1-D array.
121 The generic, symmetric, Hermitian and positive definite solutions are
122 obtained via calling ?GESV, ?SYSV, ?HESV, and ?POSV routines of
123 LAPACK respectively.
125 Examples
126 --------
127 Given `a` and `b`, solve for `x`:
129 >>> import numpy as np
130 >>> a = np.array([[3, 2, 0], [1, -1, 0], [0, 5, 1]])
131 >>> b = np.array([2, 4, -1])
132 >>> from scipy import linalg
133 >>> x = linalg.solve(a, b)
134 >>> x
135 array([ 2., -2., 9.])
136 >>> np.dot(a, x) == b
137 array([ True, True, True], dtype=bool)
139 """
140 # Flags for 1-D or N-D right-hand side
141 b_is_1D = False
143 a1 = atleast_2d(_asarray_validated(a, check_finite=check_finite))
144 b1 = atleast_1d(_asarray_validated(b, check_finite=check_finite))
145 n = a1.shape[0]
147 overwrite_a = overwrite_a or _datacopied(a1, a)
148 overwrite_b = overwrite_b or _datacopied(b1, b)
150 if a1.shape[0] != a1.shape[1]:
151 raise ValueError('Input a needs to be a square matrix.')
153 if n != b1.shape[0]:
154 # Last chance to catch 1x1 scalar a and 1-D b arrays
155 if not (n == 1 and b1.size != 0):
156 raise ValueError('Input b has to have same number of rows as '
157 'input a')
159 # accommodate empty arrays
160 if b1.size == 0:
161 return np.asfortranarray(b1.copy())
163 # regularize 1-D b arrays to 2D
164 if b1.ndim == 1:
165 if n == 1:
166 b1 = b1[None, :]
167 else:
168 b1 = b1[:, None]
169 b_is_1D = True
171 # Backwards compatibility - old keyword.
172 if sym_pos:
173 message = ("The 'sym_pos' keyword is deprecated and should be "
174 "replaced by using 'assume_a = \"pos\"'. 'sym_pos' will be"
175 " removed in SciPy 1.11.0.")
176 warn(message, DeprecationWarning, stacklevel=2)
177 assume_a = 'pos'
179 if assume_a not in ('gen', 'sym', 'her', 'pos'):
180 raise ValueError('{} is not a recognized matrix structure'
181 ''.format(assume_a))
183 # for a real matrix, describe it as "symmetric", not "hermitian"
184 # (lapack doesn't know what to do with real hermitian matrices)
185 if assume_a == 'her' and not np.iscomplexobj(a1):
186 assume_a = 'sym'
188 # Get the correct lamch function.
189 # The LAMCH functions only exists for S and D
190 # So for complex values we have to convert to real/double.
191 if a1.dtype.char in 'fF': # single precision
192 lamch = get_lapack_funcs('lamch', dtype='f')
193 else:
194 lamch = get_lapack_funcs('lamch', dtype='d')
196 # Currently we do not have the other forms of the norm calculators
197 # lansy, lanpo, lanhe.
198 # However, in any case they only reduce computations slightly...
199 lange = get_lapack_funcs('lange', (a1,))
201 # Since the I-norm and 1-norm are the same for symmetric matrices
202 # we can collect them all in this one call
203 # Note however, that when issuing 'gen' and form!='none', then
204 # the I-norm should be used
205 if transposed:
206 trans = 1
207 norm = 'I'
208 if np.iscomplexobj(a1):
209 raise NotImplementedError('scipy.linalg.solve can currently '
210 'not solve a^T x = b or a^H x = b '
211 'for complex matrices.')
212 else:
213 trans = 0
214 norm = '1'
216 anorm = lange(norm, a1)
218 # Generalized case 'gesv'
219 if assume_a == 'gen':
220 gecon, getrf, getrs = get_lapack_funcs(('gecon', 'getrf', 'getrs'),
221 (a1, b1))
222 lu, ipvt, info = getrf(a1, overwrite_a=overwrite_a)
223 _solve_check(n, info)
224 x, info = getrs(lu, ipvt, b1,
225 trans=trans, overwrite_b=overwrite_b)
226 _solve_check(n, info)
227 rcond, info = gecon(lu, anorm, norm=norm)
228 # Hermitian case 'hesv'
229 elif assume_a == 'her':
230 hecon, hesv, hesv_lw = get_lapack_funcs(('hecon', 'hesv',
231 'hesv_lwork'), (a1, b1))
232 lwork = _compute_lwork(hesv_lw, n, lower)
233 lu, ipvt, x, info = hesv(a1, b1, lwork=lwork,
234 lower=lower,
235 overwrite_a=overwrite_a,
236 overwrite_b=overwrite_b)
237 _solve_check(n, info)
238 rcond, info = hecon(lu, ipvt, anorm)
239 # Symmetric case 'sysv'
240 elif assume_a == 'sym':
241 sycon, sysv, sysv_lw = get_lapack_funcs(('sycon', 'sysv',
242 'sysv_lwork'), (a1, b1))
243 lwork = _compute_lwork(sysv_lw, n, lower)
244 lu, ipvt, x, info = sysv(a1, b1, lwork=lwork,
245 lower=lower,
246 overwrite_a=overwrite_a,
247 overwrite_b=overwrite_b)
248 _solve_check(n, info)
249 rcond, info = sycon(lu, ipvt, anorm)
250 # Positive definite case 'posv'
251 else:
252 pocon, posv = get_lapack_funcs(('pocon', 'posv'),
253 (a1, b1))
254 lu, x, info = posv(a1, b1, lower=lower,
255 overwrite_a=overwrite_a,
256 overwrite_b=overwrite_b)
257 _solve_check(n, info)
258 rcond, info = pocon(lu, anorm)
260 _solve_check(n, info, lamch, rcond)
262 if b_is_1D:
263 x = x.ravel()
265 return x
268def solve_triangular(a, b, trans=0, lower=False, unit_diagonal=False,
269 overwrite_b=False, check_finite=True):
270 """
271 Solve the equation `a x = b` for `x`, assuming a is a triangular matrix.
273 Parameters
274 ----------
275 a : (M, M) array_like
276 A triangular matrix
277 b : (M,) or (M, N) array_like
278 Right-hand side matrix in `a x = b`
279 lower : bool, optional
280 Use only data contained in the lower triangle of `a`.
281 Default is to use upper triangle.
282 trans : {0, 1, 2, 'N', 'T', 'C'}, optional
283 Type of system to solve:
285 ======== =========
286 trans system
287 ======== =========
288 0 or 'N' a x = b
289 1 or 'T' a^T x = b
290 2 or 'C' a^H x = b
291 ======== =========
292 unit_diagonal : bool, optional
293 If True, diagonal elements of `a` are assumed to be 1 and
294 will not be referenced.
295 overwrite_b : bool, optional
296 Allow overwriting data in `b` (may enhance performance)
297 check_finite : bool, optional
298 Whether to check that the input matrices contain only finite numbers.
299 Disabling may give a performance gain, but may result in problems
300 (crashes, non-termination) if the inputs do contain infinities or NaNs.
302 Returns
303 -------
304 x : (M,) or (M, N) ndarray
305 Solution to the system `a x = b`. Shape of return matches `b`.
307 Raises
308 ------
309 LinAlgError
310 If `a` is singular
312 Notes
313 -----
314 .. versionadded:: 0.9.0
316 Examples
317 --------
318 Solve the lower triangular system a x = b, where::
320 [3 0 0 0] [4]
321 a = [2 1 0 0] b = [2]
322 [1 0 1 0] [4]
323 [1 1 1 1] [2]
325 >>> import numpy as np
326 >>> from scipy.linalg import solve_triangular
327 >>> a = np.array([[3, 0, 0, 0], [2, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 1]])
328 >>> b = np.array([4, 2, 4, 2])
329 >>> x = solve_triangular(a, b, lower=True)
330 >>> x
331 array([ 1.33333333, -0.66666667, 2.66666667, -1.33333333])
332 >>> a.dot(x) # Check the result
333 array([ 4., 2., 4., 2.])
335 """
337 a1 = _asarray_validated(a, check_finite=check_finite)
338 b1 = _asarray_validated(b, check_finite=check_finite)
339 if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
340 raise ValueError('expected square matrix')
341 if a1.shape[0] != b1.shape[0]:
342 raise ValueError('shapes of a {} and b {} are incompatible'
343 .format(a1.shape, b1.shape))
344 overwrite_b = overwrite_b or _datacopied(b1, b)
346 trans = {'N': 0, 'T': 1, 'C': 2}.get(trans, trans)
347 trtrs, = get_lapack_funcs(('trtrs',), (a1, b1))
348 if a1.flags.f_contiguous or trans == 2:
349 x, info = trtrs(a1, b1, overwrite_b=overwrite_b, lower=lower,
350 trans=trans, unitdiag=unit_diagonal)
351 else:
352 # transposed system is solved since trtrs expects Fortran ordering
353 x, info = trtrs(a1.T, b1, overwrite_b=overwrite_b, lower=not lower,
354 trans=not trans, unitdiag=unit_diagonal)
356 if info == 0:
357 return x
358 if info > 0:
359 raise LinAlgError("singular matrix: resolution failed at diagonal %d" %
360 (info-1))
361 raise ValueError('illegal value in %dth argument of internal trtrs' %
362 (-info))
365def solve_banded(l_and_u, ab, b, overwrite_ab=False, overwrite_b=False,
366 check_finite=True):
367 """
368 Solve the equation a x = b for x, assuming a is banded matrix.
370 The matrix a is stored in `ab` using the matrix diagonal ordered form::
372 ab[u + i - j, j] == a[i,j]
374 Example of `ab` (shape of a is (6,6), `u` =1, `l` =2)::
376 * a01 a12 a23 a34 a45
377 a00 a11 a22 a33 a44 a55
378 a10 a21 a32 a43 a54 *
379 a20 a31 a42 a53 * *
381 Parameters
382 ----------
383 (l, u) : (integer, integer)
384 Number of non-zero lower and upper diagonals
385 ab : (`l` + `u` + 1, M) array_like
386 Banded matrix
387 b : (M,) or (M, K) array_like
388 Right-hand side
389 overwrite_ab : bool, optional
390 Discard data in `ab` (may enhance performance)
391 overwrite_b : bool, optional
392 Discard data in `b` (may enhance performance)
393 check_finite : bool, optional
394 Whether to check that the input matrices contain only finite numbers.
395 Disabling may give a performance gain, but may result in problems
396 (crashes, non-termination) if the inputs do contain infinities or NaNs.
398 Returns
399 -------
400 x : (M,) or (M, K) ndarray
401 The solution to the system a x = b. Returned shape depends on the
402 shape of `b`.
404 Examples
405 --------
406 Solve the banded system a x = b, where::
408 [5 2 -1 0 0] [0]
409 [1 4 2 -1 0] [1]
410 a = [0 1 3 2 -1] b = [2]
411 [0 0 1 2 2] [2]
412 [0 0 0 1 1] [3]
414 There is one nonzero diagonal below the main diagonal (l = 1), and
415 two above (u = 2). The diagonal banded form of the matrix is::
417 [* * -1 -1 -1]
418 ab = [* 2 2 2 2]
419 [5 4 3 2 1]
420 [1 1 1 1 *]
422 >>> import numpy as np
423 >>> from scipy.linalg import solve_banded
424 >>> ab = np.array([[0, 0, -1, -1, -1],
425 ... [0, 2, 2, 2, 2],
426 ... [5, 4, 3, 2, 1],
427 ... [1, 1, 1, 1, 0]])
428 >>> b = np.array([0, 1, 2, 2, 3])
429 >>> x = solve_banded((1, 2), ab, b)
430 >>> x
431 array([-2.37288136, 3.93220339, -4. , 4.3559322 , -1.3559322 ])
433 """
435 a1 = _asarray_validated(ab, check_finite=check_finite, as_inexact=True)
436 b1 = _asarray_validated(b, check_finite=check_finite, as_inexact=True)
437 # Validate shapes.
438 if a1.shape[-1] != b1.shape[0]:
439 raise ValueError("shapes of ab and b are not compatible.")
440 (nlower, nupper) = l_and_u
441 if nlower + nupper + 1 != a1.shape[0]:
442 raise ValueError("invalid values for the number of lower and upper "
443 "diagonals: l+u+1 (%d) does not equal ab.shape[0] "
444 "(%d)" % (nlower + nupper + 1, ab.shape[0]))
446 overwrite_b = overwrite_b or _datacopied(b1, b)
447 if a1.shape[-1] == 1:
448 b2 = np.array(b1, copy=(not overwrite_b))
449 b2 /= a1[1, 0]
450 return b2
451 if nlower == nupper == 1:
452 overwrite_ab = overwrite_ab or _datacopied(a1, ab)
453 gtsv, = get_lapack_funcs(('gtsv',), (a1, b1))
454 du = a1[0, 1:]
455 d = a1[1, :]
456 dl = a1[2, :-1]
457 du2, d, du, x, info = gtsv(dl, d, du, b1, overwrite_ab, overwrite_ab,
458 overwrite_ab, overwrite_b)
459 else:
460 gbsv, = get_lapack_funcs(('gbsv',), (a1, b1))
461 a2 = np.zeros((2*nlower + nupper + 1, a1.shape[1]), dtype=gbsv.dtype)
462 a2[nlower:, :] = a1
463 lu, piv, x, info = gbsv(nlower, nupper, a2, b1, overwrite_ab=True,
464 overwrite_b=overwrite_b)
465 if info == 0:
466 return x
467 if info > 0:
468 raise LinAlgError("singular matrix")
469 raise ValueError('illegal value in %d-th argument of internal '
470 'gbsv/gtsv' % -info)
473def solveh_banded(ab, b, overwrite_ab=False, overwrite_b=False, lower=False,
474 check_finite=True):
475 """
476 Solve equation a x = b. a is Hermitian positive-definite banded matrix.
478 Uses Thomas' Algorithm, which is more efficient than standard LU
479 factorization, but should only be used for Hermitian positive-definite
480 matrices.
482 The matrix ``a`` is stored in `ab` either in lower diagonal or upper
483 diagonal ordered form:
485 ab[u + i - j, j] == a[i,j] (if upper form; i <= j)
486 ab[ i - j, j] == a[i,j] (if lower form; i >= j)
488 Example of `ab` (shape of ``a`` is (6, 6), number of upper diagonals,
489 ``u`` =2)::
491 upper form:
492 * * a02 a13 a24 a35
493 * a01 a12 a23 a34 a45
494 a00 a11 a22 a33 a44 a55
496 lower form:
497 a00 a11 a22 a33 a44 a55
498 a10 a21 a32 a43 a54 *
499 a20 a31 a42 a53 * *
501 Cells marked with * are not used.
503 Parameters
504 ----------
505 ab : (``u`` + 1, M) array_like
506 Banded matrix
507 b : (M,) or (M, K) array_like
508 Right-hand side
509 overwrite_ab : bool, optional
510 Discard data in `ab` (may enhance performance)
511 overwrite_b : bool, optional
512 Discard data in `b` (may enhance performance)
513 lower : bool, optional
514 Is the matrix in the lower form. (Default is upper form)
515 check_finite : bool, optional
516 Whether to check that the input matrices contain only finite numbers.
517 Disabling may give a performance gain, but may result in problems
518 (crashes, non-termination) if the inputs do contain infinities or NaNs.
520 Returns
521 -------
522 x : (M,) or (M, K) ndarray
523 The solution to the system ``a x = b``. Shape of return matches shape
524 of `b`.
526 Notes
527 -----
528 In the case of a non-positive definite matrix ``a``, the solver
529 `solve_banded` may be used.
531 Examples
532 --------
533 Solve the banded system ``A x = b``, where::
535 [ 4 2 -1 0 0 0] [1]
536 [ 2 5 2 -1 0 0] [2]
537 A = [-1 2 6 2 -1 0] b = [2]
538 [ 0 -1 2 7 2 -1] [3]
539 [ 0 0 -1 2 8 2] [3]
540 [ 0 0 0 -1 2 9] [3]
542 >>> import numpy as np
543 >>> from scipy.linalg import solveh_banded
545 ``ab`` contains the main diagonal and the nonzero diagonals below the
546 main diagonal. That is, we use the lower form:
548 >>> ab = np.array([[ 4, 5, 6, 7, 8, 9],
549 ... [ 2, 2, 2, 2, 2, 0],
550 ... [-1, -1, -1, -1, 0, 0]])
551 >>> b = np.array([1, 2, 2, 3, 3, 3])
552 >>> x = solveh_banded(ab, b, lower=True)
553 >>> x
554 array([ 0.03431373, 0.45938375, 0.05602241, 0.47759104, 0.17577031,
555 0.34733894])
558 Solve the Hermitian banded system ``H x = b``, where::
560 [ 8 2-1j 0 0 ] [ 1 ]
561 H = [2+1j 5 1j 0 ] b = [1+1j]
562 [ 0 -1j 9 -2-1j] [1-2j]
563 [ 0 0 -2+1j 6 ] [ 0 ]
565 In this example, we put the upper diagonals in the array ``hb``:
567 >>> hb = np.array([[0, 2-1j, 1j, -2-1j],
568 ... [8, 5, 9, 6 ]])
569 >>> b = np.array([1, 1+1j, 1-2j, 0])
570 >>> x = solveh_banded(hb, b)
571 >>> x
572 array([ 0.07318536-0.02939412j, 0.11877624+0.17696461j,
573 0.10077984-0.23035393j, -0.00479904-0.09358128j])
575 """
576 a1 = _asarray_validated(ab, check_finite=check_finite)
577 b1 = _asarray_validated(b, check_finite=check_finite)
578 # Validate shapes.
579 if a1.shape[-1] != b1.shape[0]:
580 raise ValueError("shapes of ab and b are not compatible.")
582 overwrite_b = overwrite_b or _datacopied(b1, b)
583 overwrite_ab = overwrite_ab or _datacopied(a1, ab)
585 if a1.shape[0] == 2:
586 ptsv, = get_lapack_funcs(('ptsv',), (a1, b1))
587 if lower:
588 d = a1[0, :].real
589 e = a1[1, :-1]
590 else:
591 d = a1[1, :].real
592 e = a1[0, 1:].conj()
593 d, du, x, info = ptsv(d, e, b1, overwrite_ab, overwrite_ab,
594 overwrite_b)
595 else:
596 pbsv, = get_lapack_funcs(('pbsv',), (a1, b1))
597 c, x, info = pbsv(a1, b1, lower=lower, overwrite_ab=overwrite_ab,
598 overwrite_b=overwrite_b)
599 if info > 0:
600 raise LinAlgError("%dth leading minor not positive definite" % info)
601 if info < 0:
602 raise ValueError('illegal value in %dth argument of internal '
603 'pbsv' % -info)
604 return x
607def solve_toeplitz(c_or_cr, b, check_finite=True):
608 """Solve a Toeplitz system using Levinson Recursion
610 The Toeplitz matrix has constant diagonals, with c as its first column
611 and r as its first row. If r is not given, ``r == conjugate(c)`` is
612 assumed.
614 Parameters
615 ----------
616 c_or_cr : array_like or tuple of (array_like, array_like)
617 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
618 actual shape of ``c``, it will be converted to a 1-D array. If not
619 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
620 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
621 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
622 of ``r``, it will be converted to a 1-D array.
623 b : (M,) or (M, K) array_like
624 Right-hand side in ``T x = b``.
625 check_finite : bool, optional
626 Whether to check that the input matrices contain only finite numbers.
627 Disabling may give a performance gain, but may result in problems
628 (result entirely NaNs) if the inputs do contain infinities or NaNs.
630 Returns
631 -------
632 x : (M,) or (M, K) ndarray
633 The solution to the system ``T x = b``. Shape of return matches shape
634 of `b`.
636 See Also
637 --------
638 toeplitz : Toeplitz matrix
640 Notes
641 -----
642 The solution is computed using Levinson-Durbin recursion, which is faster
643 than generic least-squares methods, but can be less numerically stable.
645 Examples
646 --------
647 Solve the Toeplitz system T x = b, where::
649 [ 1 -1 -2 -3] [1]
650 T = [ 3 1 -1 -2] b = [2]
651 [ 6 3 1 -1] [2]
652 [10 6 3 1] [5]
654 To specify the Toeplitz matrix, only the first column and the first
655 row are needed.
657 >>> import numpy as np
658 >>> c = np.array([1, 3, 6, 10]) # First column of T
659 >>> r = np.array([1, -1, -2, -3]) # First row of T
660 >>> b = np.array([1, 2, 2, 5])
662 >>> from scipy.linalg import solve_toeplitz, toeplitz
663 >>> x = solve_toeplitz((c, r), b)
664 >>> x
665 array([ 1.66666667, -1. , -2.66666667, 2.33333333])
667 Check the result by creating the full Toeplitz matrix and
668 multiplying it by `x`. We should get `b`.
670 >>> T = toeplitz(c, r)
671 >>> T.dot(x)
672 array([ 1., 2., 2., 5.])
674 """
675 # If numerical stability of this algorithm is a problem, a future
676 # developer might consider implementing other O(N^2) Toeplitz solvers,
677 # such as GKO (https://www.jstor.org/stable/2153371) or Bareiss.
679 r, c, b, dtype, b_shape = _validate_args_for_toeplitz_ops(
680 c_or_cr, b, check_finite, keep_b_shape=True)
682 # Form a 1-D array of values to be used in the matrix, containing a
683 # reversed copy of r[1:], followed by c.
684 vals = np.concatenate((r[-1:0:-1], c))
685 if b is None:
686 raise ValueError('illegal value, `b` is a required argument')
688 if b.ndim == 1:
689 x, _ = levinson(vals, np.ascontiguousarray(b))
690 else:
691 x = np.column_stack([levinson(vals, np.ascontiguousarray(b[:, i]))[0]
692 for i in range(b.shape[1])])
693 x = x.reshape(*b_shape)
695 return x
698def _get_axis_len(aname, a, axis):
699 ax = axis
700 if ax < 0:
701 ax += a.ndim
702 if 0 <= ax < a.ndim:
703 return a.shape[ax]
704 raise ValueError("'%saxis' entry is out of bounds" % (aname,))
707def solve_circulant(c, b, singular='raise', tol=None,
708 caxis=-1, baxis=0, outaxis=0):
709 """Solve C x = b for x, where C is a circulant matrix.
711 `C` is the circulant matrix associated with the vector `c`.
713 The system is solved by doing division in Fourier space. The
714 calculation is::
716 x = ifft(fft(b) / fft(c))
718 where `fft` and `ifft` are the fast Fourier transform and its inverse,
719 respectively. For a large vector `c`, this is *much* faster than
720 solving the system with the full circulant matrix.
722 Parameters
723 ----------
724 c : array_like
725 The coefficients of the circulant matrix.
726 b : array_like
727 Right-hand side matrix in ``a x = b``.
728 singular : str, optional
729 This argument controls how a near singular circulant matrix is
730 handled. If `singular` is "raise" and the circulant matrix is
731 near singular, a `LinAlgError` is raised. If `singular` is
732 "lstsq", the least squares solution is returned. Default is "raise".
733 tol : float, optional
734 If any eigenvalue of the circulant matrix has an absolute value
735 that is less than or equal to `tol`, the matrix is considered to be
736 near singular. If not given, `tol` is set to::
738 tol = abs_eigs.max() * abs_eigs.size * np.finfo(np.float64).eps
740 where `abs_eigs` is the array of absolute values of the eigenvalues
741 of the circulant matrix.
742 caxis : int
743 When `c` has dimension greater than 1, it is viewed as a collection
744 of circulant vectors. In this case, `caxis` is the axis of `c` that
745 holds the vectors of circulant coefficients.
746 baxis : int
747 When `b` has dimension greater than 1, it is viewed as a collection
748 of vectors. In this case, `baxis` is the axis of `b` that holds the
749 right-hand side vectors.
750 outaxis : int
751 When `c` or `b` are multidimensional, the value returned by
752 `solve_circulant` is multidimensional. In this case, `outaxis` is
753 the axis of the result that holds the solution vectors.
755 Returns
756 -------
757 x : ndarray
758 Solution to the system ``C x = b``.
760 Raises
761 ------
762 LinAlgError
763 If the circulant matrix associated with `c` is near singular.
765 See Also
766 --------
767 circulant : circulant matrix
769 Notes
770 -----
771 For a 1-D vector `c` with length `m`, and an array `b`
772 with shape ``(m, ...)``,
774 solve_circulant(c, b)
776 returns the same result as
778 solve(circulant(c), b)
780 where `solve` and `circulant` are from `scipy.linalg`.
782 .. versionadded:: 0.16.0
784 Examples
785 --------
786 >>> import numpy as np
787 >>> from scipy.linalg import solve_circulant, solve, circulant, lstsq
789 >>> c = np.array([2, 2, 4])
790 >>> b = np.array([1, 2, 3])
791 >>> solve_circulant(c, b)
792 array([ 0.75, -0.25, 0.25])
794 Compare that result to solving the system with `scipy.linalg.solve`:
796 >>> solve(circulant(c), b)
797 array([ 0.75, -0.25, 0.25])
799 A singular example:
801 >>> c = np.array([1, 1, 0, 0])
802 >>> b = np.array([1, 2, 3, 4])
804 Calling ``solve_circulant(c, b)`` will raise a `LinAlgError`. For the
805 least square solution, use the option ``singular='lstsq'``:
807 >>> solve_circulant(c, b, singular='lstsq')
808 array([ 0.25, 1.25, 2.25, 1.25])
810 Compare to `scipy.linalg.lstsq`:
812 >>> x, resid, rnk, s = lstsq(circulant(c), b)
813 >>> x
814 array([ 0.25, 1.25, 2.25, 1.25])
816 A broadcasting example:
818 Suppose we have the vectors of two circulant matrices stored in an array
819 with shape (2, 5), and three `b` vectors stored in an array with shape
820 (3, 5). For example,
822 >>> c = np.array([[1.5, 2, 3, 0, 0], [1, 1, 4, 3, 2]])
823 >>> b = np.arange(15).reshape(-1, 5)
825 We want to solve all combinations of circulant matrices and `b` vectors,
826 with the result stored in an array with shape (2, 3, 5). When we
827 disregard the axes of `c` and `b` that hold the vectors of coefficients,
828 the shapes of the collections are (2,) and (3,), respectively, which are
829 not compatible for broadcasting. To have a broadcast result with shape
830 (2, 3), we add a trivial dimension to `c`: ``c[:, np.newaxis, :]`` has
831 shape (2, 1, 5). The last dimension holds the coefficients of the
832 circulant matrices, so when we call `solve_circulant`, we can use the
833 default ``caxis=-1``. The coefficients of the `b` vectors are in the last
834 dimension of the array `b`, so we use ``baxis=-1``. If we use the
835 default `outaxis`, the result will have shape (5, 2, 3), so we'll use
836 ``outaxis=-1`` to put the solution vectors in the last dimension.
838 >>> x = solve_circulant(c[:, np.newaxis, :], b, baxis=-1, outaxis=-1)
839 >>> x.shape
840 (2, 3, 5)
841 >>> np.set_printoptions(precision=3) # For compact output of numbers.
842 >>> x
843 array([[[-0.118, 0.22 , 1.277, -0.142, 0.302],
844 [ 0.651, 0.989, 2.046, 0.627, 1.072],
845 [ 1.42 , 1.758, 2.816, 1.396, 1.841]],
846 [[ 0.401, 0.304, 0.694, -0.867, 0.377],
847 [ 0.856, 0.758, 1.149, -0.412, 0.831],
848 [ 1.31 , 1.213, 1.603, 0.042, 1.286]]])
850 Check by solving one pair of `c` and `b` vectors (cf. ``x[1, 1, :]``):
852 >>> solve_circulant(c[1], b[1, :])
853 array([ 0.856, 0.758, 1.149, -0.412, 0.831])
855 """
856 c = np.atleast_1d(c)
857 nc = _get_axis_len("c", c, caxis)
858 b = np.atleast_1d(b)
859 nb = _get_axis_len("b", b, baxis)
860 if nc != nb:
861 raise ValueError('Shapes of c {} and b {} are incompatible'
862 .format(c.shape, b.shape))
864 fc = np.fft.fft(np.moveaxis(c, caxis, -1), axis=-1)
865 abs_fc = np.abs(fc)
866 if tol is None:
867 # This is the same tolerance as used in np.linalg.matrix_rank.
868 tol = abs_fc.max(axis=-1) * nc * np.finfo(np.float64).eps
869 if tol.shape != ():
870 tol.shape = tol.shape + (1,)
871 else:
872 tol = np.atleast_1d(tol)
874 near_zeros = abs_fc <= tol
875 is_near_singular = np.any(near_zeros)
876 if is_near_singular:
877 if singular == 'raise':
878 raise LinAlgError("near singular circulant matrix.")
879 else:
880 # Replace the small values with 1 to avoid errors in the
881 # division fb/fc below.
882 fc[near_zeros] = 1
884 fb = np.fft.fft(np.moveaxis(b, baxis, -1), axis=-1)
886 q = fb / fc
888 if is_near_singular:
889 # `near_zeros` is a boolean array, same shape as `c`, that is
890 # True where `fc` is (near) zero. `q` is the broadcasted result
891 # of fb / fc, so to set the values of `q` to 0 where `fc` is near
892 # zero, we use a mask that is the broadcast result of an array
893 # of True values shaped like `b` with `near_zeros`.
894 mask = np.ones_like(b, dtype=bool) & near_zeros
895 q[mask] = 0
897 x = np.fft.ifft(q, axis=-1)
898 if not (np.iscomplexobj(c) or np.iscomplexobj(b)):
899 x = x.real
900 if outaxis != -1:
901 x = np.moveaxis(x, -1, outaxis)
902 return x
905# matrix inversion
906def inv(a, overwrite_a=False, check_finite=True):
907 """
908 Compute the inverse of a matrix.
910 Parameters
911 ----------
912 a : array_like
913 Square matrix to be inverted.
914 overwrite_a : bool, optional
915 Discard data in `a` (may improve performance). Default is False.
916 check_finite : bool, optional
917 Whether to check that the input matrix contains only finite numbers.
918 Disabling may give a performance gain, but may result in problems
919 (crashes, non-termination) if the inputs do contain infinities or NaNs.
921 Returns
922 -------
923 ainv : ndarray
924 Inverse of the matrix `a`.
926 Raises
927 ------
928 LinAlgError
929 If `a` is singular.
930 ValueError
931 If `a` is not square, or not 2D.
933 Examples
934 --------
935 >>> import numpy as np
936 >>> from scipy import linalg
937 >>> a = np.array([[1., 2.], [3., 4.]])
938 >>> linalg.inv(a)
939 array([[-2. , 1. ],
940 [ 1.5, -0.5]])
941 >>> np.dot(a, linalg.inv(a))
942 array([[ 1., 0.],
943 [ 0., 1.]])
945 """
946 a1 = _asarray_validated(a, check_finite=check_finite)
947 if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
948 raise ValueError('expected square matrix')
949 overwrite_a = overwrite_a or _datacopied(a1, a)
950 # XXX: I found no advantage or disadvantage of using finv.
951# finv, = get_flinalg_funcs(('inv',),(a1,))
952# if finv is not None:
953# a_inv,info = finv(a1,overwrite_a=overwrite_a)
954# if info==0:
955# return a_inv
956# if info>0: raise LinAlgError, "singular matrix"
957# if info<0: raise ValueError('illegal value in %d-th argument of '
958# 'internal inv.getrf|getri'%(-info))
959 getrf, getri, getri_lwork = get_lapack_funcs(('getrf', 'getri',
960 'getri_lwork'),
961 (a1,))
962 lu, piv, info = getrf(a1, overwrite_a=overwrite_a)
963 if info == 0:
964 lwork = _compute_lwork(getri_lwork, a1.shape[0])
966 # XXX: the following line fixes curious SEGFAULT when
967 # benchmarking 500x500 matrix inverse. This seems to
968 # be a bug in LAPACK ?getri routine because if lwork is
969 # minimal (when using lwork[0] instead of lwork[1]) then
970 # all tests pass. Further investigation is required if
971 # more such SEGFAULTs occur.
972 lwork = int(1.01 * lwork)
973 inv_a, info = getri(lu, piv, lwork=lwork, overwrite_lu=1)
974 if info > 0:
975 raise LinAlgError("singular matrix")
976 if info < 0:
977 raise ValueError('illegal value in %d-th argument of internal '
978 'getrf|getri' % -info)
979 return inv_a
982# Determinant
984def det(a, overwrite_a=False, check_finite=True):
985 """
986 Compute the determinant of a matrix
988 The determinant of a square matrix is a value derived arithmetically
989 from the coefficients of the matrix.
991 The determinant for a 3x3 matrix, for example, is computed as follows::
993 a b c
994 d e f = A
995 g h i
997 det(A) = a*e*i + b*f*g + c*d*h - c*e*g - b*d*i - a*f*h
999 Parameters
1000 ----------
1001 a : (M, M) array_like
1002 A square matrix.
1003 overwrite_a : bool, optional
1004 Allow overwriting data in a (may enhance performance).
1005 check_finite : bool, optional
1006 Whether to check that the input matrix contains only finite numbers.
1007 Disabling may give a performance gain, but may result in problems
1008 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1010 Returns
1011 -------
1012 det : float or complex
1013 Determinant of `a`.
1015 Notes
1016 -----
1017 The determinant is computed via LU factorization, LAPACK routine z/dgetrf.
1019 Examples
1020 --------
1021 >>> import numpy as np
1022 >>> from scipy import linalg
1023 >>> a = np.array([[1,2,3], [4,5,6], [7,8,9]])
1024 >>> linalg.det(a)
1025 0.0
1026 >>> a = np.array([[0,2,3], [4,5,6], [7,8,9]])
1027 >>> linalg.det(a)
1028 3.0
1030 """
1031 a1 = _asarray_validated(a, check_finite=check_finite)
1032 if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
1033 raise ValueError('expected square matrix')
1034 overwrite_a = overwrite_a or _datacopied(a1, a)
1035 fdet, = get_flinalg_funcs(('det',), (a1,))
1036 a_det, info = fdet(a1, overwrite_a=overwrite_a)
1037 if info < 0:
1038 raise ValueError('illegal value in %d-th argument of internal '
1039 'det.getrf' % -info)
1040 return a_det
1043# Linear Least Squares
1044def lstsq(a, b, cond=None, overwrite_a=False, overwrite_b=False,
1045 check_finite=True, lapack_driver=None):
1046 """
1047 Compute least-squares solution to equation Ax = b.
1049 Compute a vector x such that the 2-norm ``|b - A x|`` is minimized.
1051 Parameters
1052 ----------
1053 a : (M, N) array_like
1054 Left-hand side array
1055 b : (M,) or (M, K) array_like
1056 Right hand side array
1057 cond : float, optional
1058 Cutoff for 'small' singular values; used to determine effective
1059 rank of a. Singular values smaller than
1060 ``cond * largest_singular_value`` are considered zero.
1061 overwrite_a : bool, optional
1062 Discard data in `a` (may enhance performance). Default is False.
1063 overwrite_b : bool, optional
1064 Discard data in `b` (may enhance performance). Default is False.
1065 check_finite : bool, optional
1066 Whether to check that the input matrices contain only finite numbers.
1067 Disabling may give a performance gain, but may result in problems
1068 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1069 lapack_driver : str, optional
1070 Which LAPACK driver is used to solve the least-squares problem.
1071 Options are ``'gelsd'``, ``'gelsy'``, ``'gelss'``. Default
1072 (``'gelsd'``) is a good choice. However, ``'gelsy'`` can be slightly
1073 faster on many problems. ``'gelss'`` was used historically. It is
1074 generally slow but uses less memory.
1076 .. versionadded:: 0.17.0
1078 Returns
1079 -------
1080 x : (N,) or (N, K) ndarray
1081 Least-squares solution.
1082 residues : (K,) ndarray or float
1083 Square of the 2-norm for each column in ``b - a x``, if ``M > N`` and
1084 ``ndim(A) == n`` (returns a scalar if ``b`` is 1-D). Otherwise a
1085 (0,)-shaped array is returned.
1086 rank : int
1087 Effective rank of `a`.
1088 s : (min(M, N),) ndarray or None
1089 Singular values of `a`. The condition number of ``a`` is
1090 ``s[0] / s[-1]``.
1092 Raises
1093 ------
1094 LinAlgError
1095 If computation does not converge.
1097 ValueError
1098 When parameters are not compatible.
1100 See Also
1101 --------
1102 scipy.optimize.nnls : linear least squares with non-negativity constraint
1104 Notes
1105 -----
1106 When ``'gelsy'`` is used as a driver, `residues` is set to a (0,)-shaped
1107 array and `s` is always ``None``.
1109 Examples
1110 --------
1111 >>> import numpy as np
1112 >>> from scipy.linalg import lstsq
1113 >>> import matplotlib.pyplot as plt
1115 Suppose we have the following data:
1117 >>> x = np.array([1, 2.5, 3.5, 4, 5, 7, 8.5])
1118 >>> y = np.array([0.3, 1.1, 1.5, 2.0, 3.2, 6.6, 8.6])
1120 We want to fit a quadratic polynomial of the form ``y = a + b*x**2``
1121 to this data. We first form the "design matrix" M, with a constant
1122 column of 1s and a column containing ``x**2``:
1124 >>> M = x[:, np.newaxis]**[0, 2]
1125 >>> M
1126 array([[ 1. , 1. ],
1127 [ 1. , 6.25],
1128 [ 1. , 12.25],
1129 [ 1. , 16. ],
1130 [ 1. , 25. ],
1131 [ 1. , 49. ],
1132 [ 1. , 72.25]])
1134 We want to find the least-squares solution to ``M.dot(p) = y``,
1135 where ``p`` is a vector with length 2 that holds the parameters
1136 ``a`` and ``b``.
1138 >>> p, res, rnk, s = lstsq(M, y)
1139 >>> p
1140 array([ 0.20925829, 0.12013861])
1142 Plot the data and the fitted curve.
1144 >>> plt.plot(x, y, 'o', label='data')
1145 >>> xx = np.linspace(0, 9, 101)
1146 >>> yy = p[0] + p[1]*xx**2
1147 >>> plt.plot(xx, yy, label='least squares fit, $y = a + bx^2$')
1148 >>> plt.xlabel('x')
1149 >>> plt.ylabel('y')
1150 >>> plt.legend(framealpha=1, shadow=True)
1151 >>> plt.grid(alpha=0.25)
1152 >>> plt.show()
1154 """
1155 a1 = _asarray_validated(a, check_finite=check_finite)
1156 b1 = _asarray_validated(b, check_finite=check_finite)
1157 if len(a1.shape) != 2:
1158 raise ValueError('Input array a should be 2D')
1159 m, n = a1.shape
1160 if len(b1.shape) == 2:
1161 nrhs = b1.shape[1]
1162 else:
1163 nrhs = 1
1164 if m != b1.shape[0]:
1165 raise ValueError('Shape mismatch: a and b should have the same number'
1166 ' of rows ({} != {}).'.format(m, b1.shape[0]))
1167 if m == 0 or n == 0: # Zero-sized problem, confuses LAPACK
1168 x = np.zeros((n,) + b1.shape[1:], dtype=np.common_type(a1, b1))
1169 if n == 0:
1170 residues = np.linalg.norm(b1, axis=0)**2
1171 else:
1172 residues = np.empty((0,))
1173 return x, residues, 0, np.empty((0,))
1175 driver = lapack_driver
1176 if driver is None:
1177 driver = lstsq.default_lapack_driver
1178 if driver not in ('gelsd', 'gelsy', 'gelss'):
1179 raise ValueError('LAPACK driver "%s" is not found' % driver)
1181 lapack_func, lapack_lwork = get_lapack_funcs((driver,
1182 '%s_lwork' % driver),
1183 (a1, b1))
1184 real_data = True if (lapack_func.dtype.kind == 'f') else False
1186 if m < n:
1187 # need to extend b matrix as it will be filled with
1188 # a larger solution matrix
1189 if len(b1.shape) == 2:
1190 b2 = np.zeros((n, nrhs), dtype=lapack_func.dtype)
1191 b2[:m, :] = b1
1192 else:
1193 b2 = np.zeros(n, dtype=lapack_func.dtype)
1194 b2[:m] = b1
1195 b1 = b2
1197 overwrite_a = overwrite_a or _datacopied(a1, a)
1198 overwrite_b = overwrite_b or _datacopied(b1, b)
1200 if cond is None:
1201 cond = np.finfo(lapack_func.dtype).eps
1203 if driver in ('gelss', 'gelsd'):
1204 if driver == 'gelss':
1205 lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1206 v, x, s, rank, work, info = lapack_func(a1, b1, cond, lwork,
1207 overwrite_a=overwrite_a,
1208 overwrite_b=overwrite_b)
1210 elif driver == 'gelsd':
1211 if real_data:
1212 lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1213 x, s, rank, info = lapack_func(a1, b1, lwork,
1214 iwork, cond, False, False)
1215 else: # complex data
1216 lwork, rwork, iwork = _compute_lwork(lapack_lwork, m, n,
1217 nrhs, cond)
1218 x, s, rank, info = lapack_func(a1, b1, lwork, rwork, iwork,
1219 cond, False, False)
1220 if info > 0:
1221 raise LinAlgError("SVD did not converge in Linear Least Squares")
1222 if info < 0:
1223 raise ValueError('illegal value in %d-th argument of internal %s'
1224 % (-info, lapack_driver))
1225 resids = np.asarray([], dtype=x.dtype)
1226 if m > n:
1227 x1 = x[:n]
1228 if rank == n:
1229 resids = np.sum(np.abs(x[n:])**2, axis=0)
1230 x = x1
1231 return x, resids, rank, s
1233 elif driver == 'gelsy':
1234 lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1235 jptv = np.zeros((a1.shape[1], 1), dtype=np.int32)
1236 v, x, j, rank, info = lapack_func(a1, b1, jptv, cond,
1237 lwork, False, False)
1238 if info < 0:
1239 raise ValueError("illegal value in %d-th argument of internal "
1240 "gelsy" % -info)
1241 if m > n:
1242 x1 = x[:n]
1243 x = x1
1244 return x, np.array([], x.dtype), rank, None
1247lstsq.default_lapack_driver = 'gelsd'
1250def pinv(a, atol=None, rtol=None, return_rank=False, check_finite=True,
1251 cond=None, rcond=None):
1252 """
1253 Compute the (Moore-Penrose) pseudo-inverse of a matrix.
1255 Calculate a generalized inverse of a matrix using its
1256 singular-value decomposition ``U @ S @ V`` in the economy mode and picking
1257 up only the columns/rows that are associated with significant singular
1258 values.
1260 If ``s`` is the maximum singular value of ``a``, then the
1261 significance cut-off value is determined by ``atol + rtol * s``. Any
1262 singular value below this value is assumed insignificant.
1264 Parameters
1265 ----------
1266 a : (M, N) array_like
1267 Matrix to be pseudo-inverted.
1268 atol : float, optional
1269 Absolute threshold term, default value is 0.
1271 .. versionadded:: 1.7.0
1273 rtol : float, optional
1274 Relative threshold term, default value is ``max(M, N) * eps`` where
1275 ``eps`` is the machine precision value of the datatype of ``a``.
1277 .. versionadded:: 1.7.0
1279 return_rank : bool, optional
1280 If True, return the effective rank of the matrix.
1281 check_finite : bool, optional
1282 Whether to check that the input matrix contains only finite numbers.
1283 Disabling may give a performance gain, but may result in problems
1284 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1285 cond, rcond : float, optional
1286 In older versions, these values were meant to be used as ``atol`` with
1287 ``rtol=0``. If both were given ``rcond`` overwrote ``cond`` and hence
1288 the code was not correct. Thus using these are strongly discouraged and
1289 the tolerances above are recommended instead. In fact, if provided,
1290 atol, rtol takes precedence over these keywords.
1292 .. versionchanged:: 1.7.0
1293 Deprecated in favor of ``rtol`` and ``atol`` parameters above and
1294 will be removed in future versions of SciPy.
1296 .. versionchanged:: 1.3.0
1297 Previously the default cutoff value was just ``eps*f`` where ``f``
1298 was ``1e3`` for single precision and ``1e6`` for double precision.
1300 Returns
1301 -------
1302 B : (N, M) ndarray
1303 The pseudo-inverse of matrix `a`.
1304 rank : int
1305 The effective rank of the matrix. Returned if `return_rank` is True.
1307 Raises
1308 ------
1309 LinAlgError
1310 If SVD computation does not converge.
1312 Examples
1313 --------
1314 >>> import numpy as np
1315 >>> from scipy import linalg
1316 >>> rng = np.random.default_rng()
1317 >>> a = rng.standard_normal((9, 6))
1318 >>> B = linalg.pinv(a)
1319 >>> np.allclose(a, a @ B @ a)
1320 True
1321 >>> np.allclose(B, B @ a @ B)
1322 True
1324 """
1325 a = _asarray_validated(a, check_finite=check_finite)
1326 u, s, vh = _decomp_svd.svd(a, full_matrices=False, check_finite=False)
1327 t = u.dtype.char.lower()
1328 maxS = np.max(s)
1330 if rcond or cond:
1331 warn('Use of the "cond" and "rcond" keywords are deprecated and '
1332 'will be removed in future versions of SciPy. Use "atol" and '
1333 '"rtol" keywords instead', DeprecationWarning, stacklevel=2)
1335 # backwards compatible only atol and rtol are both missing
1336 if (rcond or cond) and (atol is None) and (rtol is None):
1337 atol = rcond or cond
1338 rtol = 0.
1340 atol = 0. if atol is None else atol
1341 rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
1343 if (atol < 0.) or (rtol < 0.):
1344 raise ValueError("atol and rtol values must be positive.")
1346 val = atol + maxS * rtol
1347 rank = np.sum(s > val)
1349 u = u[:, :rank]
1350 u /= s[:rank]
1351 B = (u @ vh[:rank]).conj().T
1353 if return_rank:
1354 return B, rank
1355 else:
1356 return B
1359def pinvh(a, atol=None, rtol=None, lower=True, return_rank=False,
1360 check_finite=True):
1361 """
1362 Compute the (Moore-Penrose) pseudo-inverse of a Hermitian matrix.
1364 Calculate a generalized inverse of a complex Hermitian/real symmetric
1365 matrix using its eigenvalue decomposition and including all eigenvalues
1366 with 'large' absolute value.
1368 Parameters
1369 ----------
1370 a : (N, N) array_like
1371 Real symmetric or complex hermetian matrix to be pseudo-inverted
1373 atol : float, optional
1374 Absolute threshold term, default value is 0.
1376 .. versionadded:: 1.7.0
1378 rtol : float, optional
1379 Relative threshold term, default value is ``N * eps`` where
1380 ``eps`` is the machine precision value of the datatype of ``a``.
1382 .. versionadded:: 1.7.0
1384 lower : bool, optional
1385 Whether the pertinent array data is taken from the lower or upper
1386 triangle of `a`. (Default: lower)
1387 return_rank : bool, optional
1388 If True, return the effective rank of the matrix.
1389 check_finite : bool, optional
1390 Whether to check that the input matrix contains only finite numbers.
1391 Disabling may give a performance gain, but may result in problems
1392 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1394 Returns
1395 -------
1396 B : (N, N) ndarray
1397 The pseudo-inverse of matrix `a`.
1398 rank : int
1399 The effective rank of the matrix. Returned if `return_rank` is True.
1401 Raises
1402 ------
1403 LinAlgError
1404 If eigenvalue algorithm does not converge.
1406 Examples
1407 --------
1408 >>> import numpy as np
1409 >>> from scipy.linalg import pinvh
1410 >>> rng = np.random.default_rng()
1411 >>> a = rng.standard_normal((9, 6))
1412 >>> a = np.dot(a, a.T)
1413 >>> B = pinvh(a)
1414 >>> np.allclose(a, a @ B @ a)
1415 True
1416 >>> np.allclose(B, B @ a @ B)
1417 True
1419 """
1420 a = _asarray_validated(a, check_finite=check_finite)
1421 s, u = _decomp.eigh(a, lower=lower, check_finite=False)
1422 t = u.dtype.char.lower()
1423 maxS = np.max(np.abs(s))
1425 atol = 0. if atol is None else atol
1426 rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
1428 if (atol < 0.) or (rtol < 0.):
1429 raise ValueError("atol and rtol values must be positive.")
1431 val = atol + maxS * rtol
1432 above_cutoff = (abs(s) > val)
1434 psigma_diag = 1.0 / s[above_cutoff]
1435 u = u[:, above_cutoff]
1437 B = (u * psigma_diag) @ u.conj().T
1439 if return_rank:
1440 return B, len(psigma_diag)
1441 else:
1442 return B
1445def matrix_balance(A, permute=True, scale=True, separate=False,
1446 overwrite_a=False):
1447 """
1448 Compute a diagonal similarity transformation for row/column balancing.
1450 The balancing tries to equalize the row and column 1-norms by applying
1451 a similarity transformation such that the magnitude variation of the
1452 matrix entries is reflected to the scaling matrices.
1454 Moreover, if enabled, the matrix is first permuted to isolate the upper
1455 triangular parts of the matrix and, again if scaling is also enabled,
1456 only the remaining subblocks are subjected to scaling.
1458 The balanced matrix satisfies the following equality
1460 .. math::
1462 B = T^{-1} A T
1464 The scaling coefficients are approximated to the nearest power of 2
1465 to avoid round-off errors.
1467 Parameters
1468 ----------
1469 A : (n, n) array_like
1470 Square data matrix for the balancing.
1471 permute : bool, optional
1472 The selector to define whether permutation of A is also performed
1473 prior to scaling.
1474 scale : bool, optional
1475 The selector to turn on and off the scaling. If False, the matrix
1476 will not be scaled.
1477 separate : bool, optional
1478 This switches from returning a full matrix of the transformation
1479 to a tuple of two separate 1-D permutation and scaling arrays.
1480 overwrite_a : bool, optional
1481 This is passed to xGEBAL directly. Essentially, overwrites the result
1482 to the data. It might increase the space efficiency. See LAPACK manual
1483 for details. This is False by default.
1485 Returns
1486 -------
1487 B : (n, n) ndarray
1488 Balanced matrix
1489 T : (n, n) ndarray
1490 A possibly permuted diagonal matrix whose nonzero entries are
1491 integer powers of 2 to avoid numerical truncation errors.
1492 scale, perm : (n,) ndarray
1493 If ``separate`` keyword is set to True then instead of the array
1494 ``T`` above, the scaling and the permutation vectors are given
1495 separately as a tuple without allocating the full array ``T``.
1497 Notes
1498 -----
1499 This algorithm is particularly useful for eigenvalue and matrix
1500 decompositions and in many cases it is already called by various
1501 LAPACK routines.
1503 The algorithm is based on the well-known technique of [1]_ and has
1504 been modified to account for special cases. See [2]_ for details
1505 which have been implemented since LAPACK v3.5.0. Before this version
1506 there are corner cases where balancing can actually worsen the
1507 conditioning. See [3]_ for such examples.
1509 The code is a wrapper around LAPACK's xGEBAL routine family for matrix
1510 balancing.
1512 .. versionadded:: 0.19.0
1514 References
1515 ----------
1516 .. [1] B.N. Parlett and C. Reinsch, "Balancing a Matrix for
1517 Calculation of Eigenvalues and Eigenvectors", Numerische Mathematik,
1518 Vol.13(4), 1969, :doi:`10.1007/BF02165404`
1519 .. [2] R. James, J. Langou, B.R. Lowery, "On matrix balancing and
1520 eigenvector computation", 2014, :arxiv:`1401.5766`
1521 .. [3] D.S. Watkins. A case where balancing is harmful.
1522 Electron. Trans. Numer. Anal, Vol.23, 2006.
1524 Examples
1525 --------
1526 >>> import numpy as np
1527 >>> from scipy import linalg
1528 >>> x = np.array([[1,2,0], [9,1,0.01], [1,2,10*np.pi]])
1530 >>> y, permscale = linalg.matrix_balance(x)
1531 >>> np.abs(x).sum(axis=0) / np.abs(x).sum(axis=1)
1532 array([ 3.66666667, 0.4995005 , 0.91312162])
1534 >>> np.abs(y).sum(axis=0) / np.abs(y).sum(axis=1)
1535 array([ 1.2 , 1.27041742, 0.92658316]) # may vary
1537 >>> permscale # only powers of 2 (0.5 == 2^(-1))
1538 array([[ 0.5, 0. , 0. ], # may vary
1539 [ 0. , 1. , 0. ],
1540 [ 0. , 0. , 1. ]])
1542 """
1544 A = np.atleast_2d(_asarray_validated(A, check_finite=True))
1546 if not np.equal(*A.shape):
1547 raise ValueError('The data matrix for balancing should be square.')
1549 gebal = get_lapack_funcs(('gebal'), (A,))
1550 B, lo, hi, ps, info = gebal(A, scale=scale, permute=permute,
1551 overwrite_a=overwrite_a)
1553 if info < 0:
1554 raise ValueError('xGEBAL exited with the internal error '
1555 '"illegal value in argument number {}.". See '
1556 'LAPACK documentation for the xGEBAL error codes.'
1557 ''.format(-info))
1559 # Separate the permutations from the scalings and then convert to int
1560 scaling = np.ones_like(ps, dtype=float)
1561 scaling[lo:hi+1] = ps[lo:hi+1]
1563 # gebal uses 1-indexing
1564 ps = ps.astype(int, copy=False) - 1
1565 n = A.shape[0]
1566 perm = np.arange(n)
1568 # LAPACK permutes with the ordering n --> hi, then 0--> lo
1569 if hi < n:
1570 for ind, x in enumerate(ps[hi+1:][::-1], 1):
1571 if n-ind == x:
1572 continue
1573 perm[[x, n-ind]] = perm[[n-ind, x]]
1575 if lo > 0:
1576 for ind, x in enumerate(ps[:lo]):
1577 if ind == x:
1578 continue
1579 perm[[x, ind]] = perm[[ind, x]]
1581 if separate:
1582 return B, (scaling, perm)
1584 # get the inverse permutation
1585 iperm = np.empty_like(perm)
1586 iperm[perm] = np.arange(n)
1588 return B, np.diag(scaling)[iperm, :]
1591def _validate_args_for_toeplitz_ops(c_or_cr, b, check_finite, keep_b_shape,
1592 enforce_square=True):
1593 """Validate arguments and format inputs for toeplitz functions
1595 Parameters
1596 ----------
1597 c_or_cr : array_like or tuple of (array_like, array_like)
1598 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
1599 actual shape of ``c``, it will be converted to a 1-D array. If not
1600 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
1601 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
1602 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
1603 of ``r``, it will be converted to a 1-D array.
1604 b : (M,) or (M, K) array_like
1605 Right-hand side in ``T x = b``.
1606 check_finite : bool
1607 Whether to check that the input matrices contain only finite numbers.
1608 Disabling may give a performance gain, but may result in problems
1609 (result entirely NaNs) if the inputs do contain infinities or NaNs.
1610 keep_b_shape : bool
1611 Whether to convert a (M,) dimensional b into a (M, 1) dimensional
1612 matrix.
1613 enforce_square : bool, optional
1614 If True (default), this verifies that the Toeplitz matrix is square.
1616 Returns
1617 -------
1618 r : array
1619 1d array corresponding to the first row of the Toeplitz matrix.
1620 c: array
1621 1d array corresponding to the first column of the Toeplitz matrix.
1622 b: array
1623 (M,), (M, 1) or (M, K) dimensional array, post validation,
1624 corresponding to ``b``.
1625 dtype: numpy datatype
1626 ``dtype`` stores the datatype of ``r``, ``c`` and ``b``. If any of
1627 ``r``, ``c`` or ``b`` are complex, ``dtype`` is ``np.complex128``,
1628 otherwise, it is ``np.float``.
1629 b_shape: tuple
1630 Shape of ``b`` after passing it through ``_asarray_validated``.
1632 """
1634 if isinstance(c_or_cr, tuple):
1635 c, r = c_or_cr
1636 c = _asarray_validated(c, check_finite=check_finite).ravel()
1637 r = _asarray_validated(r, check_finite=check_finite).ravel()
1638 else:
1639 c = _asarray_validated(c_or_cr, check_finite=check_finite).ravel()
1640 r = c.conjugate()
1642 if b is None:
1643 raise ValueError('`b` must be an array, not None.')
1645 b = _asarray_validated(b, check_finite=check_finite)
1646 b_shape = b.shape
1648 is_not_square = r.shape[0] != c.shape[0]
1649 if (enforce_square and is_not_square) or b.shape[0] != r.shape[0]:
1650 raise ValueError('Incompatible dimensions.')
1652 is_cmplx = np.iscomplexobj(r) or np.iscomplexobj(c) or np.iscomplexobj(b)
1653 dtype = np.complex128 if is_cmplx else np.double
1654 r, c, b = (np.asarray(i, dtype=dtype) for i in (r, c, b))
1656 if b.ndim == 1 and not keep_b_shape:
1657 b = b.reshape(-1, 1)
1658 elif b.ndim != 1:
1659 b = b.reshape(b.shape[0], -1)
1661 return r, c, b, dtype, b_shape
1664def matmul_toeplitz(c_or_cr, x, check_finite=False, workers=None):
1665 """Efficient Toeplitz Matrix-Matrix Multiplication using FFT
1667 This function returns the matrix multiplication between a Toeplitz
1668 matrix and a dense matrix.
1670 The Toeplitz matrix has constant diagonals, with c as its first column
1671 and r as its first row. If r is not given, ``r == conjugate(c)`` is
1672 assumed.
1674 Parameters
1675 ----------
1676 c_or_cr : array_like or tuple of (array_like, array_like)
1677 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
1678 actual shape of ``c``, it will be converted to a 1-D array. If not
1679 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
1680 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
1681 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
1682 of ``r``, it will be converted to a 1-D array.
1683 x : (M,) or (M, K) array_like
1684 Matrix with which to multiply.
1685 check_finite : bool, optional
1686 Whether to check that the input matrices contain only finite numbers.
1687 Disabling may give a performance gain, but may result in problems
1688 (result entirely NaNs) if the inputs do contain infinities or NaNs.
1689 workers : int, optional
1690 To pass to scipy.fft.fft and ifft. Maximum number of workers to use
1691 for parallel computation. If negative, the value wraps around from
1692 ``os.cpu_count()``. See scipy.fft.fft for more details.
1694 Returns
1695 -------
1696 T @ x : (M,) or (M, K) ndarray
1697 The result of the matrix multiplication ``T @ x``. Shape of return
1698 matches shape of `x`.
1700 See Also
1701 --------
1702 toeplitz : Toeplitz matrix
1703 solve_toeplitz : Solve a Toeplitz system using Levinson Recursion
1705 Notes
1706 -----
1707 The Toeplitz matrix is embedded in a circulant matrix and the FFT is used
1708 to efficiently calculate the matrix-matrix product.
1710 Because the computation is based on the FFT, integer inputs will
1711 result in floating point outputs. This is unlike NumPy's `matmul`,
1712 which preserves the data type of the input.
1714 This is partly based on the implementation that can be found in [1]_,
1715 licensed under the MIT license. More information about the method can be
1716 found in reference [2]_. References [3]_ and [4]_ have more reference
1717 implementations in Python.
1719 .. versionadded:: 1.6.0
1721 References
1722 ----------
1723 .. [1] Jacob R Gardner, Geoff Pleiss, David Bindel, Kilian
1724 Q Weinberger, Andrew Gordon Wilson, "GPyTorch: Blackbox Matrix-Matrix
1725 Gaussian Process Inference with GPU Acceleration" with contributions
1726 from Max Balandat and Ruihan Wu. Available online:
1727 https://github.com/cornellius-gp/gpytorch
1729 .. [2] J. Demmel, P. Koev, and X. Li, "A Brief Survey of Direct Linear
1730 Solvers". In Z. Bai, J. Demmel, J. Dongarra, A. Ruhe, and H. van der
1731 Vorst, editors. Templates for the Solution of Algebraic Eigenvalue
1732 Problems: A Practical Guide. SIAM, Philadelphia, 2000. Available at:
1733 http://www.netlib.org/utk/people/JackDongarra/etemplates/node384.html
1735 .. [3] R. Scheibler, E. Bezzam, I. Dokmanic, Pyroomacoustics: A Python
1736 package for audio room simulations and array processing algorithms,
1737 Proc. IEEE ICASSP, Calgary, CA, 2018.
1738 https://github.com/LCAV/pyroomacoustics/blob/pypi-release/
1739 pyroomacoustics/adaptive/util.py
1741 .. [4] Marano S, Edwards B, Ferrari G and Fah D (2017), "Fitting
1742 Earthquake Spectra: Colored Noise and Incomplete Data", Bulletin of
1743 the Seismological Society of America., January, 2017. Vol. 107(1),
1744 pp. 276-291.
1746 Examples
1747 --------
1748 Multiply the Toeplitz matrix T with matrix x::
1750 [ 1 -1 -2 -3] [1 10]
1751 T = [ 3 1 -1 -2] x = [2 11]
1752 [ 6 3 1 -1] [2 11]
1753 [10 6 3 1] [5 19]
1755 To specify the Toeplitz matrix, only the first column and the first
1756 row are needed.
1758 >>> import numpy as np
1759 >>> c = np.array([1, 3, 6, 10]) # First column of T
1760 >>> r = np.array([1, -1, -2, -3]) # First row of T
1761 >>> x = np.array([[1, 10], [2, 11], [2, 11], [5, 19]])
1763 >>> from scipy.linalg import toeplitz, matmul_toeplitz
1764 >>> matmul_toeplitz((c, r), x)
1765 array([[-20., -80.],
1766 [ -7., -8.],
1767 [ 9., 85.],
1768 [ 33., 218.]])
1770 Check the result by creating the full Toeplitz matrix and
1771 multiplying it by ``x``.
1773 >>> toeplitz(c, r) @ x
1774 array([[-20, -80],
1775 [ -7, -8],
1776 [ 9, 85],
1777 [ 33, 218]])
1779 The full matrix is never formed explicitly, so this routine
1780 is suitable for very large Toeplitz matrices.
1782 >>> n = 1000000
1783 >>> matmul_toeplitz([1] + [0]*(n-1), np.ones(n))
1784 array([1., 1., 1., ..., 1., 1., 1.])
1786 """
1788 from ..fft import fft, ifft, rfft, irfft
1790 r, c, x, dtype, x_shape = _validate_args_for_toeplitz_ops(
1791 c_or_cr, x, check_finite, keep_b_shape=False, enforce_square=False)
1792 n, m = x.shape
1794 T_nrows = len(c)
1795 T_ncols = len(r)
1796 p = T_nrows + T_ncols - 1 # equivalent to len(embedded_col)
1798 embedded_col = np.concatenate((c, r[-1:0:-1]))
1800 if np.iscomplexobj(embedded_col) or np.iscomplexobj(x):
1801 fft_mat = fft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
1802 fft_x = fft(x, n=p, axis=0, workers=workers)
1804 mat_times_x = ifft(fft_mat*fft_x, axis=0,
1805 workers=workers)[:T_nrows, :]
1806 else:
1807 # Real inputs; using rfft is faster
1808 fft_mat = rfft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
1809 fft_x = rfft(x, n=p, axis=0, workers=workers)
1811 mat_times_x = irfft(fft_mat*fft_x, axis=0,
1812 workers=workers, n=p)[:T_nrows, :]
1814 return_shape = (T_nrows,) if len(x_shape) == 1 else (T_nrows, m)
1815 return mat_times_x.reshape(*return_shape)