Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/scipy/linalg/_basic.py: 7%

430 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-14 06:37 +0000

1# 

2# Author: Pearu Peterson, March 2002 

3# 

4# w/ additions by Travis Oliphant, March 2002 

5# and Jake Vanderplas, August 2012 

6 

7from warnings import warn 

8from itertools import product 

9import numpy as np 

10from numpy import atleast_1d, atleast_2d 

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 

16from ._cythonized_array_utils import find_det_from_lu 

17from scipy._lib.deprecation import _NoValue, _deprecate_positional_args 

18 

19__all__ = ['solve', 'solve_triangular', 'solveh_banded', 'solve_banded', 

20 'solve_toeplitz', 'solve_circulant', 'inv', 'det', 'lstsq', 

21 'pinv', 'pinvh', 'matrix_balance', 'matmul_toeplitz'] 

22 

23 

24# The numpy facilities for type-casting checks are too slow for small sized 

25# arrays and eat away the time budget for the checkups. Here we set a 

26# precomputed dict container of the numpy.can_cast() table. 

27 

28# It can be used to determine quickly what a dtype can be cast to LAPACK 

29# compatible types, i.e., 'float32, float64, complex64, complex128'. 

30# Then it can be checked via "casting_dict[arr.dtype.char]" 

31lapack_cast_dict = {x: ''.join([y for y in 'fdFD' if np.can_cast(x, y)]) 

32 for x in np.typecodes['All']} 

33 

34 

35# Linear equations 

36def _solve_check(n, info, lamch=None, rcond=None): 

37 """ Check arguments during the different steps of the solution phase """ 

38 if info < 0: 

39 raise ValueError(f'LAPACK reported an illegal value in {-info}-th argument.') 

40 elif 0 < info: 

41 raise LinAlgError('Matrix is singular.') 

42 

43 if lamch is None: 

44 return 

45 E = lamch('E') 

46 if rcond < E: 

47 warn(f'Ill-conditioned matrix (rcond={rcond:.6g}): ' 

48 'result may not be accurate.', 

49 LinAlgWarning, stacklevel=3) 

50 

51 

52def solve(a, b, lower=False, overwrite_a=False, 

53 overwrite_b=False, check_finite=True, assume_a='gen', 

54 transposed=False): 

55 """ 

56 Solves the linear equation set ``a @ x == b`` for the unknown ``x`` 

57 for square `a` matrix. 

58 

59 If the data matrix is known to be a particular type then supplying the 

60 corresponding string to ``assume_a`` key chooses the dedicated solver. 

61 The available options are 

62 

63 =================== ======== 

64 generic matrix 'gen' 

65 symmetric 'sym' 

66 hermitian 'her' 

67 positive definite 'pos' 

68 =================== ======== 

69 

70 If omitted, ``'gen'`` is the default structure. 

71 

72 The datatype of the arrays define which solver is called regardless 

73 of the values. In other words, even when the complex array entries have 

74 precisely zero imaginary parts, the complex solver will be called based 

75 on the data type of the array. 

76 

77 Parameters 

78 ---------- 

79 a : (N, N) array_like 

80 Square input data 

81 b : (N, NRHS) array_like 

82 Input data for the right hand side. 

83 lower : bool, default: False 

84 Ignored if ``assume_a == 'gen'`` (the default). If True, the 

85 calculation uses only the data in the lower triangle of `a`; 

86 entries above the diagonal are ignored. If False (default), the 

87 calculation uses only the data in the upper triangle of `a`; entries 

88 below the diagonal are ignored. 

89 overwrite_a : bool, default: False 

90 Allow overwriting data in `a` (may enhance performance). 

91 overwrite_b : bool, default: False 

92 Allow overwriting data in `b` (may enhance performance). 

93 check_finite : bool, default: True 

94 Whether to check that the input matrices contain only finite numbers. 

95 Disabling may give a performance gain, but may result in problems 

96 (crashes, non-termination) if the inputs do contain infinities or NaNs. 

97 assume_a : str, {'gen', 'sym', 'her', 'pos'} 

98 Valid entries are explained above. 

99 transposed : bool, default: False 

100 If True, solve ``a.T @ x == b``. Raises `NotImplementedError` 

101 for complex `a`. 

102 

103 Returns 

104 ------- 

105 x : (N, NRHS) ndarray 

106 The solution array. 

107 

108 Raises 

109 ------ 

110 ValueError 

111 If size mismatches detected or input a is not square. 

112 LinAlgError 

113 If the matrix is singular. 

114 LinAlgWarning 

115 If an ill-conditioned input a is detected. 

116 NotImplementedError 

117 If transposed is True and input a is a complex matrix. 

118 

119 Notes 

120 ----- 

121 If the input b matrix is a 1-D array with N elements, when supplied 

122 together with an NxN input a, it is assumed as a valid column vector 

123 despite the apparent size mismatch. This is compatible with the 

124 numpy.dot() behavior and the returned result is still 1-D array. 

125 

126 The generic, symmetric, Hermitian and positive definite solutions are 

127 obtained via calling ?GESV, ?SYSV, ?HESV, and ?POSV routines of 

128 LAPACK respectively. 

129 

130 Examples 

131 -------- 

132 Given `a` and `b`, solve for `x`: 

133 

134 >>> import numpy as np 

135 >>> a = np.array([[3, 2, 0], [1, -1, 0], [0, 5, 1]]) 

136 >>> b = np.array([2, 4, -1]) 

137 >>> from scipy import linalg 

138 >>> x = linalg.solve(a, b) 

139 >>> x 

140 array([ 2., -2., 9.]) 

141 >>> np.dot(a, x) == b 

142 array([ True, True, True], dtype=bool) 

143 

144 """ 

145 # Flags for 1-D or N-D right-hand side 

146 b_is_1D = False 

147 

148 a1 = atleast_2d(_asarray_validated(a, check_finite=check_finite)) 

149 b1 = atleast_1d(_asarray_validated(b, check_finite=check_finite)) 

150 n = a1.shape[0] 

151 

152 overwrite_a = overwrite_a or _datacopied(a1, a) 

153 overwrite_b = overwrite_b or _datacopied(b1, b) 

154 

155 if a1.shape[0] != a1.shape[1]: 

156 raise ValueError('Input a needs to be a square matrix.') 

157 

158 if n != b1.shape[0]: 

159 # Last chance to catch 1x1 scalar a and 1-D b arrays 

160 if not (n == 1 and b1.size != 0): 

161 raise ValueError('Input b has to have same number of rows as ' 

162 'input a') 

163 

164 # accommodate empty arrays 

165 if b1.size == 0: 

166 return np.asfortranarray(b1.copy()) 

167 

168 # regularize 1-D b arrays to 2D 

169 if b1.ndim == 1: 

170 if n == 1: 

171 b1 = b1[None, :] 

172 else: 

173 b1 = b1[:, None] 

174 b_is_1D = True 

175 

176 if assume_a not in ('gen', 'sym', 'her', 'pos'): 

177 raise ValueError(f'{assume_a} is not a recognized matrix structure') 

178 

179 # for a real matrix, describe it as "symmetric", not "hermitian" 

180 # (lapack doesn't know what to do with real hermitian matrices) 

181 if assume_a == 'her' and not np.iscomplexobj(a1): 

182 assume_a = 'sym' 

183 

184 # Get the correct lamch function. 

185 # The LAMCH functions only exists for S and D 

186 # So for complex values we have to convert to real/double. 

187 if a1.dtype.char in 'fF': # single precision 

188 lamch = get_lapack_funcs('lamch', dtype='f') 

189 else: 

190 lamch = get_lapack_funcs('lamch', dtype='d') 

191 

192 # Currently we do not have the other forms of the norm calculators 

193 # lansy, lanpo, lanhe. 

194 # However, in any case they only reduce computations slightly... 

195 lange = get_lapack_funcs('lange', (a1,)) 

196 

197 # Since the I-norm and 1-norm are the same for symmetric matrices 

198 # we can collect them all in this one call 

199 # Note however, that when issuing 'gen' and form!='none', then 

200 # the I-norm should be used 

201 if transposed: 

202 trans = 1 

203 norm = 'I' 

204 if np.iscomplexobj(a1): 

205 raise NotImplementedError('scipy.linalg.solve can currently ' 

206 'not solve a^T x = b or a^H x = b ' 

207 'for complex matrices.') 

208 else: 

209 trans = 0 

210 norm = '1' 

211 

212 anorm = lange(norm, a1) 

213 

214 # Generalized case 'gesv' 

215 if assume_a == 'gen': 

216 gecon, getrf, getrs = get_lapack_funcs(('gecon', 'getrf', 'getrs'), 

217 (a1, b1)) 

218 lu, ipvt, info = getrf(a1, overwrite_a=overwrite_a) 

219 _solve_check(n, info) 

220 x, info = getrs(lu, ipvt, b1, 

221 trans=trans, overwrite_b=overwrite_b) 

222 _solve_check(n, info) 

223 rcond, info = gecon(lu, anorm, norm=norm) 

224 # Hermitian case 'hesv' 

225 elif assume_a == 'her': 

226 hecon, hesv, hesv_lw = get_lapack_funcs(('hecon', 'hesv', 

227 'hesv_lwork'), (a1, b1)) 

228 lwork = _compute_lwork(hesv_lw, n, lower) 

229 lu, ipvt, x, info = hesv(a1, b1, lwork=lwork, 

230 lower=lower, 

231 overwrite_a=overwrite_a, 

232 overwrite_b=overwrite_b) 

233 _solve_check(n, info) 

234 rcond, info = hecon(lu, ipvt, anorm) 

235 # Symmetric case 'sysv' 

236 elif assume_a == 'sym': 

237 sycon, sysv, sysv_lw = get_lapack_funcs(('sycon', 'sysv', 

238 'sysv_lwork'), (a1, b1)) 

239 lwork = _compute_lwork(sysv_lw, n, lower) 

240 lu, ipvt, x, info = sysv(a1, b1, lwork=lwork, 

241 lower=lower, 

242 overwrite_a=overwrite_a, 

243 overwrite_b=overwrite_b) 

244 _solve_check(n, info) 

245 rcond, info = sycon(lu, ipvt, anorm) 

246 # Positive definite case 'posv' 

247 else: 

248 pocon, posv = get_lapack_funcs(('pocon', 'posv'), 

249 (a1, b1)) 

250 lu, x, info = posv(a1, b1, lower=lower, 

251 overwrite_a=overwrite_a, 

252 overwrite_b=overwrite_b) 

253 _solve_check(n, info) 

254 rcond, info = pocon(lu, anorm) 

255 

256 _solve_check(n, info, lamch, rcond) 

257 

258 if b_is_1D: 

259 x = x.ravel() 

260 

261 return x 

262 

263 

264def solve_triangular(a, b, trans=0, lower=False, unit_diagonal=False, 

265 overwrite_b=False, check_finite=True): 

266 """ 

267 Solve the equation `a x = b` for `x`, assuming a is a triangular matrix. 

268 

269 Parameters 

270 ---------- 

271 a : (M, M) array_like 

272 A triangular matrix 

273 b : (M,) or (M, N) array_like 

274 Right-hand side matrix in `a x = b` 

275 lower : bool, optional 

276 Use only data contained in the lower triangle of `a`. 

277 Default is to use upper triangle. 

278 trans : {0, 1, 2, 'N', 'T', 'C'}, optional 

279 Type of system to solve: 

280 

281 ======== ========= 

282 trans system 

283 ======== ========= 

284 0 or 'N' a x = b 

285 1 or 'T' a^T x = b 

286 2 or 'C' a^H x = b 

287 ======== ========= 

288 unit_diagonal : bool, optional 

289 If True, diagonal elements of `a` are assumed to be 1 and 

290 will not be referenced. 

291 overwrite_b : bool, optional 

292 Allow overwriting data in `b` (may enhance performance) 

293 check_finite : bool, optional 

294 Whether to check that the input matrices contain only finite numbers. 

295 Disabling may give a performance gain, but may result in problems 

296 (crashes, non-termination) if the inputs do contain infinities or NaNs. 

297 

298 Returns 

299 ------- 

300 x : (M,) or (M, N) ndarray 

301 Solution to the system `a x = b`. Shape of return matches `b`. 

302 

303 Raises 

304 ------ 

305 LinAlgError 

306 If `a` is singular 

307 

308 Notes 

309 ----- 

310 .. versionadded:: 0.9.0 

311 

312 Examples 

313 -------- 

314 Solve the lower triangular system a x = b, where:: 

315 

316 [3 0 0 0] [4] 

317 a = [2 1 0 0] b = [2] 

318 [1 0 1 0] [4] 

319 [1 1 1 1] [2] 

320 

321 >>> import numpy as np 

322 >>> from scipy.linalg import solve_triangular 

323 >>> a = np.array([[3, 0, 0, 0], [2, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 1]]) 

324 >>> b = np.array([4, 2, 4, 2]) 

325 >>> x = solve_triangular(a, b, lower=True) 

326 >>> x 

327 array([ 1.33333333, -0.66666667, 2.66666667, -1.33333333]) 

328 >>> a.dot(x) # Check the result 

329 array([ 4., 2., 4., 2.]) 

330 

331 """ 

332 

333 a1 = _asarray_validated(a, check_finite=check_finite) 

334 b1 = _asarray_validated(b, check_finite=check_finite) 

335 if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]: 

336 raise ValueError('expected square matrix') 

337 if a1.shape[0] != b1.shape[0]: 

338 raise ValueError(f'shapes of a {a1.shape} and b {b1.shape} are incompatible') 

339 overwrite_b = overwrite_b or _datacopied(b1, b) 

340 

341 trans = {'N': 0, 'T': 1, 'C': 2}.get(trans, trans) 

342 trtrs, = get_lapack_funcs(('trtrs',), (a1, b1)) 

343 if a1.flags.f_contiguous or trans == 2: 

344 x, info = trtrs(a1, b1, overwrite_b=overwrite_b, lower=lower, 

345 trans=trans, unitdiag=unit_diagonal) 

346 else: 

347 # transposed system is solved since trtrs expects Fortran ordering 

348 x, info = trtrs(a1.T, b1, overwrite_b=overwrite_b, lower=not lower, 

349 trans=not trans, unitdiag=unit_diagonal) 

350 

351 if info == 0: 

352 return x 

353 if info > 0: 

354 raise LinAlgError("singular matrix: resolution failed at diagonal %d" % 

355 (info-1)) 

356 raise ValueError('illegal value in %dth argument of internal trtrs' % 

357 (-info)) 

358 

359 

360def solve_banded(l_and_u, ab, b, overwrite_ab=False, overwrite_b=False, 

361 check_finite=True): 

362 """ 

363 Solve the equation a x = b for x, assuming a is banded matrix. 

364 

365 The matrix a is stored in `ab` using the matrix diagonal ordered form:: 

366 

367 ab[u + i - j, j] == a[i,j] 

368 

369 Example of `ab` (shape of a is (6,6), `u` =1, `l` =2):: 

370 

371 * a01 a12 a23 a34 a45 

372 a00 a11 a22 a33 a44 a55 

373 a10 a21 a32 a43 a54 * 

374 a20 a31 a42 a53 * * 

375 

376 Parameters 

377 ---------- 

378 (l, u) : (integer, integer) 

379 Number of non-zero lower and upper diagonals 

380 ab : (`l` + `u` + 1, M) array_like 

381 Banded matrix 

382 b : (M,) or (M, K) array_like 

383 Right-hand side 

384 overwrite_ab : bool, optional 

385 Discard data in `ab` (may enhance performance) 

386 overwrite_b : bool, optional 

387 Discard data in `b` (may enhance performance) 

388 check_finite : bool, optional 

389 Whether to check that the input matrices contain only finite numbers. 

390 Disabling may give a performance gain, but may result in problems 

391 (crashes, non-termination) if the inputs do contain infinities or NaNs. 

392 

393 Returns 

394 ------- 

395 x : (M,) or (M, K) ndarray 

396 The solution to the system a x = b. Returned shape depends on the 

397 shape of `b`. 

398 

399 Examples 

400 -------- 

401 Solve the banded system a x = b, where:: 

402 

403 [5 2 -1 0 0] [0] 

404 [1 4 2 -1 0] [1] 

405 a = [0 1 3 2 -1] b = [2] 

406 [0 0 1 2 2] [2] 

407 [0 0 0 1 1] [3] 

408 

409 There is one nonzero diagonal below the main diagonal (l = 1), and 

410 two above (u = 2). The diagonal banded form of the matrix is:: 

411 

412 [* * -1 -1 -1] 

413 ab = [* 2 2 2 2] 

414 [5 4 3 2 1] 

415 [1 1 1 1 *] 

416 

417 >>> import numpy as np 

418 >>> from scipy.linalg import solve_banded 

419 >>> ab = np.array([[0, 0, -1, -1, -1], 

420 ... [0, 2, 2, 2, 2], 

421 ... [5, 4, 3, 2, 1], 

422 ... [1, 1, 1, 1, 0]]) 

423 >>> b = np.array([0, 1, 2, 2, 3]) 

424 >>> x = solve_banded((1, 2), ab, b) 

425 >>> x 

426 array([-2.37288136, 3.93220339, -4. , 4.3559322 , -1.3559322 ]) 

427 

428 """ 

429 

430 a1 = _asarray_validated(ab, check_finite=check_finite, as_inexact=True) 

431 b1 = _asarray_validated(b, check_finite=check_finite, as_inexact=True) 

432 # Validate shapes. 

433 if a1.shape[-1] != b1.shape[0]: 

434 raise ValueError("shapes of ab and b are not compatible.") 

435 (nlower, nupper) = l_and_u 

436 if nlower + nupper + 1 != a1.shape[0]: 

437 raise ValueError("invalid values for the number of lower and upper " 

438 "diagonals: l+u+1 (%d) does not equal ab.shape[0] " 

439 "(%d)" % (nlower + nupper + 1, ab.shape[0])) 

440 

441 overwrite_b = overwrite_b or _datacopied(b1, b) 

442 if a1.shape[-1] == 1: 

443 b2 = np.array(b1, copy=(not overwrite_b)) 

444 b2 /= a1[1, 0] 

445 return b2 

446 if nlower == nupper == 1: 

447 overwrite_ab = overwrite_ab or _datacopied(a1, ab) 

448 gtsv, = get_lapack_funcs(('gtsv',), (a1, b1)) 

449 du = a1[0, 1:] 

450 d = a1[1, :] 

451 dl = a1[2, :-1] 

452 du2, d, du, x, info = gtsv(dl, d, du, b1, overwrite_ab, overwrite_ab, 

453 overwrite_ab, overwrite_b) 

454 else: 

455 gbsv, = get_lapack_funcs(('gbsv',), (a1, b1)) 

456 a2 = np.zeros((2*nlower + nupper + 1, a1.shape[1]), dtype=gbsv.dtype) 

457 a2[nlower:, :] = a1 

458 lu, piv, x, info = gbsv(nlower, nupper, a2, b1, overwrite_ab=True, 

459 overwrite_b=overwrite_b) 

460 if info == 0: 

461 return x 

462 if info > 0: 

463 raise LinAlgError("singular matrix") 

464 raise ValueError('illegal value in %d-th argument of internal ' 

465 'gbsv/gtsv' % -info) 

466 

467 

468def solveh_banded(ab, b, overwrite_ab=False, overwrite_b=False, lower=False, 

469 check_finite=True): 

470 """ 

471 Solve equation a x = b. a is Hermitian positive-definite banded matrix. 

472 

473 Uses Thomas' Algorithm, which is more efficient than standard LU 

474 factorization, but should only be used for Hermitian positive-definite 

475 matrices. 

476 

477 The matrix ``a`` is stored in `ab` either in lower diagonal or upper 

478 diagonal ordered form: 

479 

480 ab[u + i - j, j] == a[i,j] (if upper form; i <= j) 

481 ab[ i - j, j] == a[i,j] (if lower form; i >= j) 

482 

483 Example of `ab` (shape of ``a`` is (6, 6), number of upper diagonals, 

484 ``u`` =2):: 

485 

486 upper form: 

487 * * a02 a13 a24 a35 

488 * a01 a12 a23 a34 a45 

489 a00 a11 a22 a33 a44 a55 

490 

491 lower form: 

492 a00 a11 a22 a33 a44 a55 

493 a10 a21 a32 a43 a54 * 

494 a20 a31 a42 a53 * * 

495 

496 Cells marked with * are not used. 

497 

498 Parameters 

499 ---------- 

500 ab : (``u`` + 1, M) array_like 

501 Banded matrix 

502 b : (M,) or (M, K) array_like 

503 Right-hand side 

504 overwrite_ab : bool, optional 

505 Discard data in `ab` (may enhance performance) 

506 overwrite_b : bool, optional 

507 Discard data in `b` (may enhance performance) 

508 lower : bool, optional 

509 Is the matrix in the lower form. (Default is upper form) 

510 check_finite : bool, optional 

511 Whether to check that the input matrices contain only finite numbers. 

512 Disabling may give a performance gain, but may result in problems 

513 (crashes, non-termination) if the inputs do contain infinities or NaNs. 

514 

515 Returns 

516 ------- 

517 x : (M,) or (M, K) ndarray 

518 The solution to the system ``a x = b``. Shape of return matches shape 

519 of `b`. 

520 

521 Notes 

522 ----- 

523 In the case of a non-positive definite matrix ``a``, the solver 

524 `solve_banded` may be used. 

525 

526 Examples 

527 -------- 

528 Solve the banded system ``A x = b``, where:: 

529 

530 [ 4 2 -1 0 0 0] [1] 

531 [ 2 5 2 -1 0 0] [2] 

532 A = [-1 2 6 2 -1 0] b = [2] 

533 [ 0 -1 2 7 2 -1] [3] 

534 [ 0 0 -1 2 8 2] [3] 

535 [ 0 0 0 -1 2 9] [3] 

536 

537 >>> import numpy as np 

538 >>> from scipy.linalg import solveh_banded 

539 

540 ``ab`` contains the main diagonal and the nonzero diagonals below the 

541 main diagonal. That is, we use the lower form: 

542 

543 >>> ab = np.array([[ 4, 5, 6, 7, 8, 9], 

544 ... [ 2, 2, 2, 2, 2, 0], 

545 ... [-1, -1, -1, -1, 0, 0]]) 

546 >>> b = np.array([1, 2, 2, 3, 3, 3]) 

547 >>> x = solveh_banded(ab, b, lower=True) 

548 >>> x 

549 array([ 0.03431373, 0.45938375, 0.05602241, 0.47759104, 0.17577031, 

550 0.34733894]) 

551 

552 

553 Solve the Hermitian banded system ``H x = b``, where:: 

554 

555 [ 8 2-1j 0 0 ] [ 1 ] 

556 H = [2+1j 5 1j 0 ] b = [1+1j] 

557 [ 0 -1j 9 -2-1j] [1-2j] 

558 [ 0 0 -2+1j 6 ] [ 0 ] 

559 

560 In this example, we put the upper diagonals in the array ``hb``: 

561 

562 >>> hb = np.array([[0, 2-1j, 1j, -2-1j], 

563 ... [8, 5, 9, 6 ]]) 

564 >>> b = np.array([1, 1+1j, 1-2j, 0]) 

565 >>> x = solveh_banded(hb, b) 

566 >>> x 

567 array([ 0.07318536-0.02939412j, 0.11877624+0.17696461j, 

568 0.10077984-0.23035393j, -0.00479904-0.09358128j]) 

569 

570 """ 

571 a1 = _asarray_validated(ab, check_finite=check_finite) 

572 b1 = _asarray_validated(b, check_finite=check_finite) 

573 # Validate shapes. 

574 if a1.shape[-1] != b1.shape[0]: 

575 raise ValueError("shapes of ab and b are not compatible.") 

576 

577 overwrite_b = overwrite_b or _datacopied(b1, b) 

578 overwrite_ab = overwrite_ab or _datacopied(a1, ab) 

579 

580 if a1.shape[0] == 2: 

581 ptsv, = get_lapack_funcs(('ptsv',), (a1, b1)) 

582 if lower: 

583 d = a1[0, :].real 

584 e = a1[1, :-1] 

585 else: 

586 d = a1[1, :].real 

587 e = a1[0, 1:].conj() 

588 d, du, x, info = ptsv(d, e, b1, overwrite_ab, overwrite_ab, 

589 overwrite_b) 

590 else: 

591 pbsv, = get_lapack_funcs(('pbsv',), (a1, b1)) 

592 c, x, info = pbsv(a1, b1, lower=lower, overwrite_ab=overwrite_ab, 

593 overwrite_b=overwrite_b) 

594 if info > 0: 

595 raise LinAlgError("%dth leading minor not positive definite" % info) 

596 if info < 0: 

597 raise ValueError('illegal value in %dth argument of internal ' 

598 'pbsv' % -info) 

599 return x 

600 

601 

602def solve_toeplitz(c_or_cr, b, check_finite=True): 

603 """Solve a Toeplitz system using Levinson Recursion 

604 

605 The Toeplitz matrix has constant diagonals, with c as its first column 

606 and r as its first row. If r is not given, ``r == conjugate(c)`` is 

607 assumed. 

608 

609 Parameters 

610 ---------- 

611 c_or_cr : array_like or tuple of (array_like, array_like) 

612 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the 

613 actual shape of ``c``, it will be converted to a 1-D array. If not 

614 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is 

615 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row 

616 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape 

617 of ``r``, it will be converted to a 1-D array. 

618 b : (M,) or (M, K) array_like 

619 Right-hand side in ``T x = b``. 

620 check_finite : bool, optional 

621 Whether to check that the input matrices contain only finite numbers. 

622 Disabling may give a performance gain, but may result in problems 

623 (result entirely NaNs) if the inputs do contain infinities or NaNs. 

624 

625 Returns 

626 ------- 

627 x : (M,) or (M, K) ndarray 

628 The solution to the system ``T x = b``. Shape of return matches shape 

629 of `b`. 

630 

631 See Also 

632 -------- 

633 toeplitz : Toeplitz matrix 

634 

635 Notes 

636 ----- 

637 The solution is computed using Levinson-Durbin recursion, which is faster 

638 than generic least-squares methods, but can be less numerically stable. 

639 

640 Examples 

641 -------- 

642 Solve the Toeplitz system T x = b, where:: 

643 

644 [ 1 -1 -2 -3] [1] 

645 T = [ 3 1 -1 -2] b = [2] 

646 [ 6 3 1 -1] [2] 

647 [10 6 3 1] [5] 

648 

649 To specify the Toeplitz matrix, only the first column and the first 

650 row are needed. 

651 

652 >>> import numpy as np 

653 >>> c = np.array([1, 3, 6, 10]) # First column of T 

654 >>> r = np.array([1, -1, -2, -3]) # First row of T 

655 >>> b = np.array([1, 2, 2, 5]) 

656 

657 >>> from scipy.linalg import solve_toeplitz, toeplitz 

658 >>> x = solve_toeplitz((c, r), b) 

659 >>> x 

660 array([ 1.66666667, -1. , -2.66666667, 2.33333333]) 

661 

662 Check the result by creating the full Toeplitz matrix and 

663 multiplying it by `x`. We should get `b`. 

664 

665 >>> T = toeplitz(c, r) 

666 >>> T.dot(x) 

667 array([ 1., 2., 2., 5.]) 

668 

669 """ 

670 # If numerical stability of this algorithm is a problem, a future 

671 # developer might consider implementing other O(N^2) Toeplitz solvers, 

672 # such as GKO (https://www.jstor.org/stable/2153371) or Bareiss. 

673 

674 r, c, b, dtype, b_shape = _validate_args_for_toeplitz_ops( 

675 c_or_cr, b, check_finite, keep_b_shape=True) 

676 

677 # Form a 1-D array of values to be used in the matrix, containing a 

678 # reversed copy of r[1:], followed by c. 

679 vals = np.concatenate((r[-1:0:-1], c)) 

680 if b is None: 

681 raise ValueError('illegal value, `b` is a required argument') 

682 

683 if b.ndim == 1: 

684 x, _ = levinson(vals, np.ascontiguousarray(b)) 

685 else: 

686 x = np.column_stack([levinson(vals, np.ascontiguousarray(b[:, i]))[0] 

687 for i in range(b.shape[1])]) 

688 x = x.reshape(*b_shape) 

689 

690 return x 

691 

692 

693def _get_axis_len(aname, a, axis): 

694 ax = axis 

695 if ax < 0: 

696 ax += a.ndim 

697 if 0 <= ax < a.ndim: 

698 return a.shape[ax] 

699 raise ValueError(f"'{aname}axis' entry is out of bounds") 

700 

701 

702def solve_circulant(c, b, singular='raise', tol=None, 

703 caxis=-1, baxis=0, outaxis=0): 

704 """Solve C x = b for x, where C is a circulant matrix. 

705 

706 `C` is the circulant matrix associated with the vector `c`. 

707 

708 The system is solved by doing division in Fourier space. The 

709 calculation is:: 

710 

711 x = ifft(fft(b) / fft(c)) 

712 

713 where `fft` and `ifft` are the fast Fourier transform and its inverse, 

714 respectively. For a large vector `c`, this is *much* faster than 

715 solving the system with the full circulant matrix. 

716 

717 Parameters 

718 ---------- 

719 c : array_like 

720 The coefficients of the circulant matrix. 

721 b : array_like 

722 Right-hand side matrix in ``a x = b``. 

723 singular : str, optional 

724 This argument controls how a near singular circulant matrix is 

725 handled. If `singular` is "raise" and the circulant matrix is 

726 near singular, a `LinAlgError` is raised. If `singular` is 

727 "lstsq", the least squares solution is returned. Default is "raise". 

728 tol : float, optional 

729 If any eigenvalue of the circulant matrix has an absolute value 

730 that is less than or equal to `tol`, the matrix is considered to be 

731 near singular. If not given, `tol` is set to:: 

732 

733 tol = abs_eigs.max() * abs_eigs.size * np.finfo(np.float64).eps 

734 

735 where `abs_eigs` is the array of absolute values of the eigenvalues 

736 of the circulant matrix. 

737 caxis : int 

738 When `c` has dimension greater than 1, it is viewed as a collection 

739 of circulant vectors. In this case, `caxis` is the axis of `c` that 

740 holds the vectors of circulant coefficients. 

741 baxis : int 

742 When `b` has dimension greater than 1, it is viewed as a collection 

743 of vectors. In this case, `baxis` is the axis of `b` that holds the 

744 right-hand side vectors. 

745 outaxis : int 

746 When `c` or `b` are multidimensional, the value returned by 

747 `solve_circulant` is multidimensional. In this case, `outaxis` is 

748 the axis of the result that holds the solution vectors. 

749 

750 Returns 

751 ------- 

752 x : ndarray 

753 Solution to the system ``C x = b``. 

754 

755 Raises 

756 ------ 

757 LinAlgError 

758 If the circulant matrix associated with `c` is near singular. 

759 

760 See Also 

761 -------- 

762 circulant : circulant matrix 

763 

764 Notes 

765 ----- 

766 For a 1-D vector `c` with length `m`, and an array `b` 

767 with shape ``(m, ...)``, 

768 

769 solve_circulant(c, b) 

770 

771 returns the same result as 

772 

773 solve(circulant(c), b) 

774 

775 where `solve` and `circulant` are from `scipy.linalg`. 

776 

777 .. versionadded:: 0.16.0 

778 

779 Examples 

780 -------- 

781 >>> import numpy as np 

782 >>> from scipy.linalg import solve_circulant, solve, circulant, lstsq 

783 

784 >>> c = np.array([2, 2, 4]) 

785 >>> b = np.array([1, 2, 3]) 

786 >>> solve_circulant(c, b) 

787 array([ 0.75, -0.25, 0.25]) 

788 

789 Compare that result to solving the system with `scipy.linalg.solve`: 

790 

791 >>> solve(circulant(c), b) 

792 array([ 0.75, -0.25, 0.25]) 

793 

794 A singular example: 

795 

796 >>> c = np.array([1, 1, 0, 0]) 

797 >>> b = np.array([1, 2, 3, 4]) 

798 

799 Calling ``solve_circulant(c, b)`` will raise a `LinAlgError`. For the 

800 least square solution, use the option ``singular='lstsq'``: 

801 

802 >>> solve_circulant(c, b, singular='lstsq') 

803 array([ 0.25, 1.25, 2.25, 1.25]) 

804 

805 Compare to `scipy.linalg.lstsq`: 

806 

807 >>> x, resid, rnk, s = lstsq(circulant(c), b) 

808 >>> x 

809 array([ 0.25, 1.25, 2.25, 1.25]) 

810 

811 A broadcasting example: 

812 

813 Suppose we have the vectors of two circulant matrices stored in an array 

814 with shape (2, 5), and three `b` vectors stored in an array with shape 

815 (3, 5). For example, 

816 

817 >>> c = np.array([[1.5, 2, 3, 0, 0], [1, 1, 4, 3, 2]]) 

818 >>> b = np.arange(15).reshape(-1, 5) 

819 

820 We want to solve all combinations of circulant matrices and `b` vectors, 

821 with the result stored in an array with shape (2, 3, 5). When we 

822 disregard the axes of `c` and `b` that hold the vectors of coefficients, 

823 the shapes of the collections are (2,) and (3,), respectively, which are 

824 not compatible for broadcasting. To have a broadcast result with shape 

825 (2, 3), we add a trivial dimension to `c`: ``c[:, np.newaxis, :]`` has 

826 shape (2, 1, 5). The last dimension holds the coefficients of the 

827 circulant matrices, so when we call `solve_circulant`, we can use the 

828 default ``caxis=-1``. The coefficients of the `b` vectors are in the last 

829 dimension of the array `b`, so we use ``baxis=-1``. If we use the 

830 default `outaxis`, the result will have shape (5, 2, 3), so we'll use 

831 ``outaxis=-1`` to put the solution vectors in the last dimension. 

832 

833 >>> x = solve_circulant(c[:, np.newaxis, :], b, baxis=-1, outaxis=-1) 

834 >>> x.shape 

835 (2, 3, 5) 

836 >>> np.set_printoptions(precision=3) # For compact output of numbers. 

837 >>> x 

838 array([[[-0.118, 0.22 , 1.277, -0.142, 0.302], 

839 [ 0.651, 0.989, 2.046, 0.627, 1.072], 

840 [ 1.42 , 1.758, 2.816, 1.396, 1.841]], 

841 [[ 0.401, 0.304, 0.694, -0.867, 0.377], 

842 [ 0.856, 0.758, 1.149, -0.412, 0.831], 

843 [ 1.31 , 1.213, 1.603, 0.042, 1.286]]]) 

844 

845 Check by solving one pair of `c` and `b` vectors (cf. ``x[1, 1, :]``): 

846 

847 >>> solve_circulant(c[1], b[1, :]) 

848 array([ 0.856, 0.758, 1.149, -0.412, 0.831]) 

849 

850 """ 

851 c = np.atleast_1d(c) 

852 nc = _get_axis_len("c", c, caxis) 

853 b = np.atleast_1d(b) 

854 nb = _get_axis_len("b", b, baxis) 

855 if nc != nb: 

856 raise ValueError(f'Shapes of c {c.shape} and b {b.shape} are incompatible') 

857 

858 fc = np.fft.fft(np.moveaxis(c, caxis, -1), axis=-1) 

859 abs_fc = np.abs(fc) 

860 if tol is None: 

861 # This is the same tolerance as used in np.linalg.matrix_rank. 

862 tol = abs_fc.max(axis=-1) * nc * np.finfo(np.float64).eps 

863 if tol.shape != (): 

864 tol.shape = tol.shape + (1,) 

865 else: 

866 tol = np.atleast_1d(tol) 

867 

868 near_zeros = abs_fc <= tol 

869 is_near_singular = np.any(near_zeros) 

870 if is_near_singular: 

871 if singular == 'raise': 

872 raise LinAlgError("near singular circulant matrix.") 

873 else: 

874 # Replace the small values with 1 to avoid errors in the 

875 # division fb/fc below. 

876 fc[near_zeros] = 1 

877 

878 fb = np.fft.fft(np.moveaxis(b, baxis, -1), axis=-1) 

879 

880 q = fb / fc 

881 

882 if is_near_singular: 

883 # `near_zeros` is a boolean array, same shape as `c`, that is 

884 # True where `fc` is (near) zero. `q` is the broadcasted result 

885 # of fb / fc, so to set the values of `q` to 0 where `fc` is near 

886 # zero, we use a mask that is the broadcast result of an array 

887 # of True values shaped like `b` with `near_zeros`. 

888 mask = np.ones_like(b, dtype=bool) & near_zeros 

889 q[mask] = 0 

890 

891 x = np.fft.ifft(q, axis=-1) 

892 if not (np.iscomplexobj(c) or np.iscomplexobj(b)): 

893 x = x.real 

894 if outaxis != -1: 

895 x = np.moveaxis(x, -1, outaxis) 

896 return x 

897 

898 

899# matrix inversion 

900def inv(a, overwrite_a=False, check_finite=True): 

901 """ 

902 Compute the inverse of a matrix. 

903 

904 Parameters 

905 ---------- 

906 a : array_like 

907 Square matrix to be inverted. 

908 overwrite_a : bool, optional 

909 Discard data in `a` (may improve performance). Default is False. 

910 check_finite : bool, optional 

911 Whether to check that the input matrix contains only finite numbers. 

912 Disabling may give a performance gain, but may result in problems 

913 (crashes, non-termination) if the inputs do contain infinities or NaNs. 

914 

915 Returns 

916 ------- 

917 ainv : ndarray 

918 Inverse of the matrix `a`. 

919 

920 Raises 

921 ------ 

922 LinAlgError 

923 If `a` is singular. 

924 ValueError 

925 If `a` is not square, or not 2D. 

926 

927 Examples 

928 -------- 

929 >>> import numpy as np 

930 >>> from scipy import linalg 

931 >>> a = np.array([[1., 2.], [3., 4.]]) 

932 >>> linalg.inv(a) 

933 array([[-2. , 1. ], 

934 [ 1.5, -0.5]]) 

935 >>> np.dot(a, linalg.inv(a)) 

936 array([[ 1., 0.], 

937 [ 0., 1.]]) 

938 

939 """ 

940 a1 = _asarray_validated(a, check_finite=check_finite) 

941 if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]: 

942 raise ValueError('expected square matrix') 

943 overwrite_a = overwrite_a or _datacopied(a1, a) 

944 getrf, getri, getri_lwork = get_lapack_funcs(('getrf', 'getri', 

945 'getri_lwork'), 

946 (a1,)) 

947 lu, piv, info = getrf(a1, overwrite_a=overwrite_a) 

948 if info == 0: 

949 lwork = _compute_lwork(getri_lwork, a1.shape[0]) 

950 

951 # XXX: the following line fixes curious SEGFAULT when 

952 # benchmarking 500x500 matrix inverse. This seems to 

953 # be a bug in LAPACK ?getri routine because if lwork is 

954 # minimal (when using lwork[0] instead of lwork[1]) then 

955 # all tests pass. Further investigation is required if 

956 # more such SEGFAULTs occur. 

957 lwork = int(1.01 * lwork) 

958 inv_a, info = getri(lu, piv, lwork=lwork, overwrite_lu=1) 

959 if info > 0: 

960 raise LinAlgError("singular matrix") 

961 if info < 0: 

962 raise ValueError('illegal value in %d-th argument of internal ' 

963 'getrf|getri' % -info) 

964 return inv_a 

965 

966 

967# Determinant 

968 

969def det(a, overwrite_a=False, check_finite=True): 

970 """ 

971 Compute the determinant of a matrix 

972 

973 The determinant is a scalar that is a function of the associated square 

974 matrix coefficients. The determinant value is zero for singular matrices. 

975 

976 Parameters 

977 ---------- 

978 a : (..., M, M) array_like 

979 Input array to compute determinants for. 

980 overwrite_a : bool, optional 

981 Allow overwriting data in a (may enhance performance). 

982 check_finite : bool, optional 

983 Whether to check that the input matrix contains only finite numbers. 

984 Disabling may give a performance gain, but may result in problems 

985 (crashes, non-termination) if the inputs do contain infinities or NaNs. 

986 

987 Returns 

988 ------- 

989 det : (...) float or complex 

990 Determinant of `a`. For stacked arrays, a scalar is returned for each 

991 (m, m) slice in the last two dimensions of the input. For example, an 

992 input of shape (p, q, m, m) will produce a result of shape (p, q). If 

993 all dimensions are 1 a scalar is returned regardless of ndim. 

994 

995 Notes 

996 ----- 

997 The determinant is computed by performing an LU factorization of the 

998 input with LAPACK routine 'getrf', and then calculating the product of 

999 diagonal entries of the U factor. 

1000 

1001 Even the input array is single precision (float32 or complex64), the result 

1002 will be returned in double precision (float64 or complex128) to prevent 

1003 overflows. 

1004 

1005 Examples 

1006 -------- 

1007 >>> import numpy as np 

1008 >>> from scipy import linalg 

1009 >>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) # A singular matrix 

1010 >>> linalg.det(a) 

1011 0.0 

1012 >>> b = np.array([[0,2,3], [4,5,6], [7,8,9]]) 

1013 >>> linalg.det(b) 

1014 3.0 

1015 >>> # An array with the shape (3, 2, 2, 2) 

1016 >>> c = np.array([[[[1., 2.], [3., 4.]], 

1017 ... [[5., 6.], [7., 8.]]], 

1018 ... [[[9., 10.], [11., 12.]], 

1019 ... [[13., 14.], [15., 16.]]], 

1020 ... [[[17., 18.], [19., 20.]], 

1021 ... [[21., 22.], [23., 24.]]]]) 

1022 >>> linalg.det(c) # The resulting shape is (3, 2) 

1023 array([[-2., -2.], 

1024 [-2., -2.], 

1025 [-2., -2.]]) 

1026 >>> linalg.det(c[0, 0]) # Confirm the (0, 0) slice, [[1, 2], [3, 4]] 

1027 -2.0 

1028 """ 

1029 # The goal is to end up with a writable contiguous array to pass to Cython 

1030 

1031 # First we check and make arrays. 

1032 a1 = np.asarray_chkfinite(a) if check_finite else np.asarray(a) 

1033 if a1.ndim < 2: 

1034 raise ValueError('The input array must be at least two-dimensional.') 

1035 if a1.shape[-1] != a1.shape[-2]: 

1036 raise ValueError('Last 2 dimensions of the array must be square' 

1037 f' but received shape {a1.shape}.') 

1038 

1039 # Also check if dtype is LAPACK compatible 

1040 if a1.dtype.char not in 'fdFD': 

1041 dtype_char = lapack_cast_dict[a1.dtype.char] 

1042 if not dtype_char: # No casting possible 

1043 raise TypeError(f'The dtype "{a1.dtype.name}" cannot be cast ' 

1044 'to float(32, 64) or complex(64, 128).') 

1045 

1046 a1 = a1.astype(dtype_char[0]) # makes a copy, free to scratch 

1047 overwrite_a = True 

1048 

1049 # Empty array has determinant 1 because math. 

1050 if min(*a1.shape) == 0: 

1051 if a1.ndim == 2: 

1052 return np.float64(1.) 

1053 else: 

1054 return np.ones(shape=a1.shape[:-2], dtype=np.float64) 

1055 

1056 # Scalar case 

1057 if a1.shape[-2:] == (1, 1): 

1058 # Either ndarray with spurious singletons or a single element 

1059 if max(*a1.shape) > 1: 

1060 temp = np.squeeze(a1) 

1061 if a1.dtype.char in 'dD': 

1062 return temp 

1063 else: 

1064 return (temp.astype('d') if a1.dtype.char == 'f' else 

1065 temp.astype('D')) 

1066 else: 

1067 return (np.float64(a1.item()) if a1.dtype.char in 'fd' else 

1068 np.complex128(a1.item())) 

1069 

1070 # Then check overwrite permission 

1071 if not _datacopied(a1, a): # "a" still alive through "a1" 

1072 if not overwrite_a: 

1073 # Data belongs to "a" so make a copy 

1074 a1 = a1.copy(order='C') 

1075 # else: Do nothing we'll use "a" if possible 

1076 # else: a1 has its own data thus free to scratch 

1077 

1078 # Then layout checks, might happen that overwrite is allowed but original 

1079 # array was read-only or non-C-contiguous. 

1080 if not (a1.flags['C_CONTIGUOUS'] and a1.flags['WRITEABLE']): 

1081 a1 = a1.copy(order='C') 

1082 

1083 if a1.ndim == 2: 

1084 det = find_det_from_lu(a1) 

1085 # Convert float, complex to to NumPy scalars 

1086 return (np.float64(det) if np.isrealobj(det) else np.complex128(det)) 

1087 

1088 # loop over the stacked array, and avoid overflows for single precision 

1089 # Cf. np.linalg.det(np.diag([1e+38, 1e+38]).astype(np.float32)) 

1090 dtype_char = a1.dtype.char 

1091 if dtype_char in 'fF': 

1092 dtype_char = 'd' if dtype_char.islower() else 'D' 

1093 

1094 det = np.empty(a1.shape[:-2], dtype=dtype_char) 

1095 for ind in product(*[range(x) for x in a1.shape[:-2]]): 

1096 det[ind] = find_det_from_lu(a1[ind]) 

1097 return det 

1098 

1099 

1100# Linear Least Squares 

1101def lstsq(a, b, cond=None, overwrite_a=False, overwrite_b=False, 

1102 check_finite=True, lapack_driver=None): 

1103 """ 

1104 Compute least-squares solution to equation Ax = b. 

1105 

1106 Compute a vector x such that the 2-norm ``|b - A x|`` is minimized. 

1107 

1108 Parameters 

1109 ---------- 

1110 a : (M, N) array_like 

1111 Left-hand side array 

1112 b : (M,) or (M, K) array_like 

1113 Right hand side array 

1114 cond : float, optional 

1115 Cutoff for 'small' singular values; used to determine effective 

1116 rank of a. Singular values smaller than 

1117 ``cond * largest_singular_value`` are considered zero. 

1118 overwrite_a : bool, optional 

1119 Discard data in `a` (may enhance performance). Default is False. 

1120 overwrite_b : bool, optional 

1121 Discard data in `b` (may enhance performance). Default is False. 

1122 check_finite : bool, optional 

1123 Whether to check that the input matrices contain only finite numbers. 

1124 Disabling may give a performance gain, but may result in problems 

1125 (crashes, non-termination) if the inputs do contain infinities or NaNs. 

1126 lapack_driver : str, optional 

1127 Which LAPACK driver is used to solve the least-squares problem. 

1128 Options are ``'gelsd'``, ``'gelsy'``, ``'gelss'``. Default 

1129 (``'gelsd'``) is a good choice. However, ``'gelsy'`` can be slightly 

1130 faster on many problems. ``'gelss'`` was used historically. It is 

1131 generally slow but uses less memory. 

1132 

1133 .. versionadded:: 0.17.0 

1134 

1135 Returns 

1136 ------- 

1137 x : (N,) or (N, K) ndarray 

1138 Least-squares solution. 

1139 residues : (K,) ndarray or float 

1140 Square of the 2-norm for each column in ``b - a x``, if ``M > N`` and 

1141 ``ndim(A) == n`` (returns a scalar if ``b`` is 1-D). Otherwise a 

1142 (0,)-shaped array is returned. 

1143 rank : int 

1144 Effective rank of `a`. 

1145 s : (min(M, N),) ndarray or None 

1146 Singular values of `a`. The condition number of ``a`` is 

1147 ``s[0] / s[-1]``. 

1148 

1149 Raises 

1150 ------ 

1151 LinAlgError 

1152 If computation does not converge. 

1153 

1154 ValueError 

1155 When parameters are not compatible. 

1156 

1157 See Also 

1158 -------- 

1159 scipy.optimize.nnls : linear least squares with non-negativity constraint 

1160 

1161 Notes 

1162 ----- 

1163 When ``'gelsy'`` is used as a driver, `residues` is set to a (0,)-shaped 

1164 array and `s` is always ``None``. 

1165 

1166 Examples 

1167 -------- 

1168 >>> import numpy as np 

1169 >>> from scipy.linalg import lstsq 

1170 >>> import matplotlib.pyplot as plt 

1171 

1172 Suppose we have the following data: 

1173 

1174 >>> x = np.array([1, 2.5, 3.5, 4, 5, 7, 8.5]) 

1175 >>> y = np.array([0.3, 1.1, 1.5, 2.0, 3.2, 6.6, 8.6]) 

1176 

1177 We want to fit a quadratic polynomial of the form ``y = a + b*x**2`` 

1178 to this data. We first form the "design matrix" M, with a constant 

1179 column of 1s and a column containing ``x**2``: 

1180 

1181 >>> M = x[:, np.newaxis]**[0, 2] 

1182 >>> M 

1183 array([[ 1. , 1. ], 

1184 [ 1. , 6.25], 

1185 [ 1. , 12.25], 

1186 [ 1. , 16. ], 

1187 [ 1. , 25. ], 

1188 [ 1. , 49. ], 

1189 [ 1. , 72.25]]) 

1190 

1191 We want to find the least-squares solution to ``M.dot(p) = y``, 

1192 where ``p`` is a vector with length 2 that holds the parameters 

1193 ``a`` and ``b``. 

1194 

1195 >>> p, res, rnk, s = lstsq(M, y) 

1196 >>> p 

1197 array([ 0.20925829, 0.12013861]) 

1198 

1199 Plot the data and the fitted curve. 

1200 

1201 >>> plt.plot(x, y, 'o', label='data') 

1202 >>> xx = np.linspace(0, 9, 101) 

1203 >>> yy = p[0] + p[1]*xx**2 

1204 >>> plt.plot(xx, yy, label='least squares fit, $y = a + bx^2$') 

1205 >>> plt.xlabel('x') 

1206 >>> plt.ylabel('y') 

1207 >>> plt.legend(framealpha=1, shadow=True) 

1208 >>> plt.grid(alpha=0.25) 

1209 >>> plt.show() 

1210 

1211 """ 

1212 a1 = _asarray_validated(a, check_finite=check_finite) 

1213 b1 = _asarray_validated(b, check_finite=check_finite) 

1214 if len(a1.shape) != 2: 

1215 raise ValueError('Input array a should be 2D') 

1216 m, n = a1.shape 

1217 if len(b1.shape) == 2: 

1218 nrhs = b1.shape[1] 

1219 else: 

1220 nrhs = 1 

1221 if m != b1.shape[0]: 

1222 raise ValueError('Shape mismatch: a and b should have the same number' 

1223 f' of rows ({m} != {b1.shape[0]}).') 

1224 if m == 0 or n == 0: # Zero-sized problem, confuses LAPACK 

1225 x = np.zeros((n,) + b1.shape[1:], dtype=np.common_type(a1, b1)) 

1226 if n == 0: 

1227 residues = np.linalg.norm(b1, axis=0)**2 

1228 else: 

1229 residues = np.empty((0,)) 

1230 return x, residues, 0, np.empty((0,)) 

1231 

1232 driver = lapack_driver 

1233 if driver is None: 

1234 driver = lstsq.default_lapack_driver 

1235 if driver not in ('gelsd', 'gelsy', 'gelss'): 

1236 raise ValueError('LAPACK driver "%s" is not found' % driver) 

1237 

1238 lapack_func, lapack_lwork = get_lapack_funcs((driver, 

1239 '%s_lwork' % driver), 

1240 (a1, b1)) 

1241 real_data = True if (lapack_func.dtype.kind == 'f') else False 

1242 

1243 if m < n: 

1244 # need to extend b matrix as it will be filled with 

1245 # a larger solution matrix 

1246 if len(b1.shape) == 2: 

1247 b2 = np.zeros((n, nrhs), dtype=lapack_func.dtype) 

1248 b2[:m, :] = b1 

1249 else: 

1250 b2 = np.zeros(n, dtype=lapack_func.dtype) 

1251 b2[:m] = b1 

1252 b1 = b2 

1253 

1254 overwrite_a = overwrite_a or _datacopied(a1, a) 

1255 overwrite_b = overwrite_b or _datacopied(b1, b) 

1256 

1257 if cond is None: 

1258 cond = np.finfo(lapack_func.dtype).eps 

1259 

1260 if driver in ('gelss', 'gelsd'): 

1261 if driver == 'gelss': 

1262 lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond) 

1263 v, x, s, rank, work, info = lapack_func(a1, b1, cond, lwork, 

1264 overwrite_a=overwrite_a, 

1265 overwrite_b=overwrite_b) 

1266 

1267 elif driver == 'gelsd': 

1268 if real_data: 

1269 lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond) 

1270 x, s, rank, info = lapack_func(a1, b1, lwork, 

1271 iwork, cond, False, False) 

1272 else: # complex data 

1273 lwork, rwork, iwork = _compute_lwork(lapack_lwork, m, n, 

1274 nrhs, cond) 

1275 x, s, rank, info = lapack_func(a1, b1, lwork, rwork, iwork, 

1276 cond, False, False) 

1277 if info > 0: 

1278 raise LinAlgError("SVD did not converge in Linear Least Squares") 

1279 if info < 0: 

1280 raise ValueError('illegal value in %d-th argument of internal %s' 

1281 % (-info, lapack_driver)) 

1282 resids = np.asarray([], dtype=x.dtype) 

1283 if m > n: 

1284 x1 = x[:n] 

1285 if rank == n: 

1286 resids = np.sum(np.abs(x[n:])**2, axis=0) 

1287 x = x1 

1288 return x, resids, rank, s 

1289 

1290 elif driver == 'gelsy': 

1291 lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond) 

1292 jptv = np.zeros((a1.shape[1], 1), dtype=np.int32) 

1293 v, x, j, rank, info = lapack_func(a1, b1, jptv, cond, 

1294 lwork, False, False) 

1295 if info < 0: 

1296 raise ValueError("illegal value in %d-th argument of internal " 

1297 "gelsy" % -info) 

1298 if m > n: 

1299 x1 = x[:n] 

1300 x = x1 

1301 return x, np.array([], x.dtype), rank, None 

1302 

1303 

1304lstsq.default_lapack_driver = 'gelsd' 

1305 

1306 

1307@_deprecate_positional_args(version="1.14") 

1308def pinv(a, *, atol=None, rtol=None, return_rank=False, check_finite=True, 

1309 cond=_NoValue, rcond=_NoValue): 

1310 """ 

1311 Compute the (Moore-Penrose) pseudo-inverse of a matrix. 

1312 

1313 Calculate a generalized inverse of a matrix using its 

1314 singular-value decomposition ``U @ S @ V`` in the economy mode and picking 

1315 up only the columns/rows that are associated with significant singular 

1316 values. 

1317 

1318 If ``s`` is the maximum singular value of ``a``, then the 

1319 significance cut-off value is determined by ``atol + rtol * s``. Any 

1320 singular value below this value is assumed insignificant. 

1321 

1322 Parameters 

1323 ---------- 

1324 a : (M, N) array_like 

1325 Matrix to be pseudo-inverted. 

1326 atol : float, optional 

1327 Absolute threshold term, default value is 0. 

1328 

1329 .. versionadded:: 1.7.0 

1330 

1331 rtol : float, optional 

1332 Relative threshold term, default value is ``max(M, N) * eps`` where 

1333 ``eps`` is the machine precision value of the datatype of ``a``. 

1334 

1335 .. versionadded:: 1.7.0 

1336 

1337 return_rank : bool, optional 

1338 If True, return the effective rank of the matrix. 

1339 check_finite : bool, optional 

1340 Whether to check that the input matrix contains only finite numbers. 

1341 Disabling may give a performance gain, but may result in problems 

1342 (crashes, non-termination) if the inputs do contain infinities or NaNs. 

1343 cond, rcond : float, optional 

1344 In older versions, these values were meant to be used as ``atol`` with 

1345 ``rtol=0``. If both were given ``rcond`` overwrote ``cond`` and hence 

1346 the code was not correct. Thus using these are strongly discouraged and 

1347 the tolerances above are recommended instead. In fact, if provided, 

1348 atol, rtol takes precedence over these keywords. 

1349 

1350 .. deprecated:: 1.7.0 

1351 Deprecated in favor of ``rtol`` and ``atol`` parameters above and 

1352 will be removed in SciPy 1.14.0. 

1353 

1354 .. versionchanged:: 1.3.0 

1355 Previously the default cutoff value was just ``eps*f`` where ``f`` 

1356 was ``1e3`` for single precision and ``1e6`` for double precision. 

1357 

1358 Returns 

1359 ------- 

1360 B : (N, M) ndarray 

1361 The pseudo-inverse of matrix `a`. 

1362 rank : int 

1363 The effective rank of the matrix. Returned if `return_rank` is True. 

1364 

1365 Raises 

1366 ------ 

1367 LinAlgError 

1368 If SVD computation does not converge. 

1369 

1370 See Also 

1371 -------- 

1372 pinvh : Moore-Penrose pseudoinverse of a hermitian matrix. 

1373 

1374 Notes 

1375 ----- 

1376 If ``A`` is invertible then the Moore-Penrose pseudoinverse is exactly 

1377 the inverse of ``A`` [1]_. If ``A`` is not invertible then the 

1378 Moore-Penrose pseudoinverse computes the ``x`` solution to ``Ax = b`` such 

1379 that ``||Ax - b||`` is minimized [1]_. 

1380 

1381 References 

1382 ---------- 

1383 .. [1] Penrose, R. (1956). On best approximate solutions of linear matrix 

1384 equations. Mathematical Proceedings of the Cambridge Philosophical 

1385 Society, 52(1), 17-19. doi:10.1017/S0305004100030929 

1386 

1387 Examples 

1388 -------- 

1389 

1390 Given an ``m x n`` matrix ``A`` and an ``n x m`` matrix ``B`` the four 

1391 Moore-Penrose conditions are: 

1392 

1393 1. ``ABA = A`` (``B`` is a generalized inverse of ``A``), 

1394 2. ``BAB = B`` (``A`` is a generalized inverse of ``B``), 

1395 3. ``(AB)* = AB`` (``AB`` is hermitian), 

1396 4. ``(BA)* = BA`` (``BA`` is hermitian) [1]_. 

1397 

1398 Here, ``A*`` denotes the conjugate transpose. The Moore-Penrose 

1399 pseudoinverse is a unique ``B`` that satisfies all four of these 

1400 conditions and exists for any ``A``. Note that, unlike the standard 

1401 matrix inverse, ``A`` does not have to be a square matrix or have 

1402 linearly independent columns/rows. 

1403 

1404 As an example, we can calculate the Moore-Penrose pseudoinverse of a 

1405 random non-square matrix and verify it satisfies the four conditions. 

1406 

1407 >>> import numpy as np 

1408 >>> from scipy import linalg 

1409 >>> rng = np.random.default_rng() 

1410 >>> A = rng.standard_normal((9, 6)) 

1411 >>> B = linalg.pinv(A) 

1412 >>> np.allclose(A @ B @ A, A) # Condition 1 

1413 True 

1414 >>> np.allclose(B @ A @ B, B) # Condition 2 

1415 True 

1416 >>> np.allclose((A @ B).conj().T, A @ B) # Condition 3 

1417 True 

1418 >>> np.allclose((B @ A).conj().T, B @ A) # Condition 4 

1419 True 

1420 

1421 """ 

1422 a = _asarray_validated(a, check_finite=check_finite) 

1423 u, s, vh = _decomp_svd.svd(a, full_matrices=False, check_finite=False) 

1424 t = u.dtype.char.lower() 

1425 maxS = np.max(s) 

1426 

1427 if rcond is not _NoValue or cond is not _NoValue: 

1428 warn('Use of the "cond" and "rcond" keywords are deprecated and ' 

1429 'will be removed in SciPy 1.14.0. Use "atol" and ' 

1430 '"rtol" keywords instead', DeprecationWarning, stacklevel=2) 

1431 

1432 # backwards compatible only atol and rtol are both missing 

1433 if ((rcond not in (_NoValue, None) or cond not in (_NoValue, None)) 

1434 and (atol is None) and (rtol is None)): 

1435 atol = rcond if rcond not in (_NoValue, None) else cond 

1436 rtol = 0. 

1437 

1438 atol = 0. if atol is None else atol 

1439 rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol 

1440 

1441 if (atol < 0.) or (rtol < 0.): 

1442 raise ValueError("atol and rtol values must be positive.") 

1443 

1444 val = atol + maxS * rtol 

1445 rank = np.sum(s > val) 

1446 

1447 u = u[:, :rank] 

1448 u /= s[:rank] 

1449 B = (u @ vh[:rank]).conj().T 

1450 

1451 if return_rank: 

1452 return B, rank 

1453 else: 

1454 return B 

1455 

1456 

1457def pinvh(a, atol=None, rtol=None, lower=True, return_rank=False, 

1458 check_finite=True): 

1459 """ 

1460 Compute the (Moore-Penrose) pseudo-inverse of a Hermitian matrix. 

1461 

1462 Calculate a generalized inverse of a complex Hermitian/real symmetric 

1463 matrix using its eigenvalue decomposition and including all eigenvalues 

1464 with 'large' absolute value. 

1465 

1466 Parameters 

1467 ---------- 

1468 a : (N, N) array_like 

1469 Real symmetric or complex hermetian matrix to be pseudo-inverted 

1470 

1471 atol : float, optional 

1472 Absolute threshold term, default value is 0. 

1473 

1474 .. versionadded:: 1.7.0 

1475 

1476 rtol : float, optional 

1477 Relative threshold term, default value is ``N * eps`` where 

1478 ``eps`` is the machine precision value of the datatype of ``a``. 

1479 

1480 .. versionadded:: 1.7.0 

1481 

1482 lower : bool, optional 

1483 Whether the pertinent array data is taken from the lower or upper 

1484 triangle of `a`. (Default: lower) 

1485 return_rank : bool, optional 

1486 If True, return the effective rank of the matrix. 

1487 check_finite : bool, optional 

1488 Whether to check that the input matrix contains only finite numbers. 

1489 Disabling may give a performance gain, but may result in problems 

1490 (crashes, non-termination) if the inputs do contain infinities or NaNs. 

1491 

1492 Returns 

1493 ------- 

1494 B : (N, N) ndarray 

1495 The pseudo-inverse of matrix `a`. 

1496 rank : int 

1497 The effective rank of the matrix. Returned if `return_rank` is True. 

1498 

1499 Raises 

1500 ------ 

1501 LinAlgError 

1502 If eigenvalue algorithm does not converge. 

1503 

1504 See Also 

1505 -------- 

1506 pinv : Moore-Penrose pseudoinverse of a matrix. 

1507 

1508 Examples 

1509 -------- 

1510 

1511 For a more detailed example see `pinv`. 

1512 

1513 >>> import numpy as np 

1514 >>> from scipy.linalg import pinvh 

1515 >>> rng = np.random.default_rng() 

1516 >>> a = rng.standard_normal((9, 6)) 

1517 >>> a = np.dot(a, a.T) 

1518 >>> B = pinvh(a) 

1519 >>> np.allclose(a, a @ B @ a) 

1520 True 

1521 >>> np.allclose(B, B @ a @ B) 

1522 True 

1523 

1524 """ 

1525 a = _asarray_validated(a, check_finite=check_finite) 

1526 s, u = _decomp.eigh(a, lower=lower, check_finite=False) 

1527 t = u.dtype.char.lower() 

1528 maxS = np.max(np.abs(s)) 

1529 

1530 atol = 0. if atol is None else atol 

1531 rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol 

1532 

1533 if (atol < 0.) or (rtol < 0.): 

1534 raise ValueError("atol and rtol values must be positive.") 

1535 

1536 val = atol + maxS * rtol 

1537 above_cutoff = (abs(s) > val) 

1538 

1539 psigma_diag = 1.0 / s[above_cutoff] 

1540 u = u[:, above_cutoff] 

1541 

1542 B = (u * psigma_diag) @ u.conj().T 

1543 

1544 if return_rank: 

1545 return B, len(psigma_diag) 

1546 else: 

1547 return B 

1548 

1549 

1550def matrix_balance(A, permute=True, scale=True, separate=False, 

1551 overwrite_a=False): 

1552 """ 

1553 Compute a diagonal similarity transformation for row/column balancing. 

1554 

1555 The balancing tries to equalize the row and column 1-norms by applying 

1556 a similarity transformation such that the magnitude variation of the 

1557 matrix entries is reflected to the scaling matrices. 

1558 

1559 Moreover, if enabled, the matrix is first permuted to isolate the upper 

1560 triangular parts of the matrix and, again if scaling is also enabled, 

1561 only the remaining subblocks are subjected to scaling. 

1562 

1563 The balanced matrix satisfies the following equality 

1564 

1565 .. math:: 

1566 

1567 B = T^{-1} A T 

1568 

1569 The scaling coefficients are approximated to the nearest power of 2 

1570 to avoid round-off errors. 

1571 

1572 Parameters 

1573 ---------- 

1574 A : (n, n) array_like 

1575 Square data matrix for the balancing. 

1576 permute : bool, optional 

1577 The selector to define whether permutation of A is also performed 

1578 prior to scaling. 

1579 scale : bool, optional 

1580 The selector to turn on and off the scaling. If False, the matrix 

1581 will not be scaled. 

1582 separate : bool, optional 

1583 This switches from returning a full matrix of the transformation 

1584 to a tuple of two separate 1-D permutation and scaling arrays. 

1585 overwrite_a : bool, optional 

1586 This is passed to xGEBAL directly. Essentially, overwrites the result 

1587 to the data. It might increase the space efficiency. See LAPACK manual 

1588 for details. This is False by default. 

1589 

1590 Returns 

1591 ------- 

1592 B : (n, n) ndarray 

1593 Balanced matrix 

1594 T : (n, n) ndarray 

1595 A possibly permuted diagonal matrix whose nonzero entries are 

1596 integer powers of 2 to avoid numerical truncation errors. 

1597 scale, perm : (n,) ndarray 

1598 If ``separate`` keyword is set to True then instead of the array 

1599 ``T`` above, the scaling and the permutation vectors are given 

1600 separately as a tuple without allocating the full array ``T``. 

1601 

1602 Notes 

1603 ----- 

1604 This algorithm is particularly useful for eigenvalue and matrix 

1605 decompositions and in many cases it is already called by various 

1606 LAPACK routines. 

1607 

1608 The algorithm is based on the well-known technique of [1]_ and has 

1609 been modified to account for special cases. See [2]_ for details 

1610 which have been implemented since LAPACK v3.5.0. Before this version 

1611 there are corner cases where balancing can actually worsen the 

1612 conditioning. See [3]_ for such examples. 

1613 

1614 The code is a wrapper around LAPACK's xGEBAL routine family for matrix 

1615 balancing. 

1616 

1617 .. versionadded:: 0.19.0 

1618 

1619 References 

1620 ---------- 

1621 .. [1] B.N. Parlett and C. Reinsch, "Balancing a Matrix for 

1622 Calculation of Eigenvalues and Eigenvectors", Numerische Mathematik, 

1623 Vol.13(4), 1969, :doi:`10.1007/BF02165404` 

1624 .. [2] R. James, J. Langou, B.R. Lowery, "On matrix balancing and 

1625 eigenvector computation", 2014, :arxiv:`1401.5766` 

1626 .. [3] D.S. Watkins. A case where balancing is harmful. 

1627 Electron. Trans. Numer. Anal, Vol.23, 2006. 

1628 

1629 Examples 

1630 -------- 

1631 >>> import numpy as np 

1632 >>> from scipy import linalg 

1633 >>> x = np.array([[1,2,0], [9,1,0.01], [1,2,10*np.pi]]) 

1634 

1635 >>> y, permscale = linalg.matrix_balance(x) 

1636 >>> np.abs(x).sum(axis=0) / np.abs(x).sum(axis=1) 

1637 array([ 3.66666667, 0.4995005 , 0.91312162]) 

1638 

1639 >>> np.abs(y).sum(axis=0) / np.abs(y).sum(axis=1) 

1640 array([ 1.2 , 1.27041742, 0.92658316]) # may vary 

1641 

1642 >>> permscale # only powers of 2 (0.5 == 2^(-1)) 

1643 array([[ 0.5, 0. , 0. ], # may vary 

1644 [ 0. , 1. , 0. ], 

1645 [ 0. , 0. , 1. ]]) 

1646 

1647 """ 

1648 

1649 A = np.atleast_2d(_asarray_validated(A, check_finite=True)) 

1650 

1651 if not np.equal(*A.shape): 

1652 raise ValueError('The data matrix for balancing should be square.') 

1653 

1654 gebal = get_lapack_funcs(('gebal'), (A,)) 

1655 B, lo, hi, ps, info = gebal(A, scale=scale, permute=permute, 

1656 overwrite_a=overwrite_a) 

1657 

1658 if info < 0: 

1659 raise ValueError('xGEBAL exited with the internal error ' 

1660 f'"illegal value in argument number {-info}.". See ' 

1661 'LAPACK documentation for the xGEBAL error codes.') 

1662 

1663 # Separate the permutations from the scalings and then convert to int 

1664 scaling = np.ones_like(ps, dtype=float) 

1665 scaling[lo:hi+1] = ps[lo:hi+1] 

1666 

1667 # gebal uses 1-indexing 

1668 ps = ps.astype(int, copy=False) - 1 

1669 n = A.shape[0] 

1670 perm = np.arange(n) 

1671 

1672 # LAPACK permutes with the ordering n --> hi, then 0--> lo 

1673 if hi < n: 

1674 for ind, x in enumerate(ps[hi+1:][::-1], 1): 

1675 if n-ind == x: 

1676 continue 

1677 perm[[x, n-ind]] = perm[[n-ind, x]] 

1678 

1679 if lo > 0: 

1680 for ind, x in enumerate(ps[:lo]): 

1681 if ind == x: 

1682 continue 

1683 perm[[x, ind]] = perm[[ind, x]] 

1684 

1685 if separate: 

1686 return B, (scaling, perm) 

1687 

1688 # get the inverse permutation 

1689 iperm = np.empty_like(perm) 

1690 iperm[perm] = np.arange(n) 

1691 

1692 return B, np.diag(scaling)[iperm, :] 

1693 

1694 

1695def _validate_args_for_toeplitz_ops(c_or_cr, b, check_finite, keep_b_shape, 

1696 enforce_square=True): 

1697 """Validate arguments and format inputs for toeplitz functions 

1698 

1699 Parameters 

1700 ---------- 

1701 c_or_cr : array_like or tuple of (array_like, array_like) 

1702 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the 

1703 actual shape of ``c``, it will be converted to a 1-D array. If not 

1704 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is 

1705 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row 

1706 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape 

1707 of ``r``, it will be converted to a 1-D array. 

1708 b : (M,) or (M, K) array_like 

1709 Right-hand side in ``T x = b``. 

1710 check_finite : bool 

1711 Whether to check that the input matrices contain only finite numbers. 

1712 Disabling may give a performance gain, but may result in problems 

1713 (result entirely NaNs) if the inputs do contain infinities or NaNs. 

1714 keep_b_shape : bool 

1715 Whether to convert a (M,) dimensional b into a (M, 1) dimensional 

1716 matrix. 

1717 enforce_square : bool, optional 

1718 If True (default), this verifies that the Toeplitz matrix is square. 

1719 

1720 Returns 

1721 ------- 

1722 r : array 

1723 1d array corresponding to the first row of the Toeplitz matrix. 

1724 c: array 

1725 1d array corresponding to the first column of the Toeplitz matrix. 

1726 b: array 

1727 (M,), (M, 1) or (M, K) dimensional array, post validation, 

1728 corresponding to ``b``. 

1729 dtype: numpy datatype 

1730 ``dtype`` stores the datatype of ``r``, ``c`` and ``b``. If any of 

1731 ``r``, ``c`` or ``b`` are complex, ``dtype`` is ``np.complex128``, 

1732 otherwise, it is ``np.float``. 

1733 b_shape: tuple 

1734 Shape of ``b`` after passing it through ``_asarray_validated``. 

1735 

1736 """ 

1737 

1738 if isinstance(c_or_cr, tuple): 

1739 c, r = c_or_cr 

1740 c = _asarray_validated(c, check_finite=check_finite).ravel() 

1741 r = _asarray_validated(r, check_finite=check_finite).ravel() 

1742 else: 

1743 c = _asarray_validated(c_or_cr, check_finite=check_finite).ravel() 

1744 r = c.conjugate() 

1745 

1746 if b is None: 

1747 raise ValueError('`b` must be an array, not None.') 

1748 

1749 b = _asarray_validated(b, check_finite=check_finite) 

1750 b_shape = b.shape 

1751 

1752 is_not_square = r.shape[0] != c.shape[0] 

1753 if (enforce_square and is_not_square) or b.shape[0] != r.shape[0]: 

1754 raise ValueError('Incompatible dimensions.') 

1755 

1756 is_cmplx = np.iscomplexobj(r) or np.iscomplexobj(c) or np.iscomplexobj(b) 

1757 dtype = np.complex128 if is_cmplx else np.float64 

1758 r, c, b = (np.asarray(i, dtype=dtype) for i in (r, c, b)) 

1759 

1760 if b.ndim == 1 and not keep_b_shape: 

1761 b = b.reshape(-1, 1) 

1762 elif b.ndim != 1: 

1763 b = b.reshape(b.shape[0], -1) 

1764 

1765 return r, c, b, dtype, b_shape 

1766 

1767 

1768def matmul_toeplitz(c_or_cr, x, check_finite=False, workers=None): 

1769 """Efficient Toeplitz Matrix-Matrix Multiplication using FFT 

1770 

1771 This function returns the matrix multiplication between a Toeplitz 

1772 matrix and a dense matrix. 

1773 

1774 The Toeplitz matrix has constant diagonals, with c as its first column 

1775 and r as its first row. If r is not given, ``r == conjugate(c)`` is 

1776 assumed. 

1777 

1778 Parameters 

1779 ---------- 

1780 c_or_cr : array_like or tuple of (array_like, array_like) 

1781 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the 

1782 actual shape of ``c``, it will be converted to a 1-D array. If not 

1783 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is 

1784 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row 

1785 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape 

1786 of ``r``, it will be converted to a 1-D array. 

1787 x : (M,) or (M, K) array_like 

1788 Matrix with which to multiply. 

1789 check_finite : bool, optional 

1790 Whether to check that the input matrices contain only finite numbers. 

1791 Disabling may give a performance gain, but may result in problems 

1792 (result entirely NaNs) if the inputs do contain infinities or NaNs. 

1793 workers : int, optional 

1794 To pass to scipy.fft.fft and ifft. Maximum number of workers to use 

1795 for parallel computation. If negative, the value wraps around from 

1796 ``os.cpu_count()``. See scipy.fft.fft for more details. 

1797 

1798 Returns 

1799 ------- 

1800 T @ x : (M,) or (M, K) ndarray 

1801 The result of the matrix multiplication ``T @ x``. Shape of return 

1802 matches shape of `x`. 

1803 

1804 See Also 

1805 -------- 

1806 toeplitz : Toeplitz matrix 

1807 solve_toeplitz : Solve a Toeplitz system using Levinson Recursion 

1808 

1809 Notes 

1810 ----- 

1811 The Toeplitz matrix is embedded in a circulant matrix and the FFT is used 

1812 to efficiently calculate the matrix-matrix product. 

1813 

1814 Because the computation is based on the FFT, integer inputs will 

1815 result in floating point outputs. This is unlike NumPy's `matmul`, 

1816 which preserves the data type of the input. 

1817 

1818 This is partly based on the implementation that can be found in [1]_, 

1819 licensed under the MIT license. More information about the method can be 

1820 found in reference [2]_. References [3]_ and [4]_ have more reference 

1821 implementations in Python. 

1822 

1823 .. versionadded:: 1.6.0 

1824 

1825 References 

1826 ---------- 

1827 .. [1] Jacob R Gardner, Geoff Pleiss, David Bindel, Kilian 

1828 Q Weinberger, Andrew Gordon Wilson, "GPyTorch: Blackbox Matrix-Matrix 

1829 Gaussian Process Inference with GPU Acceleration" with contributions 

1830 from Max Balandat and Ruihan Wu. Available online: 

1831 https://github.com/cornellius-gp/gpytorch 

1832 

1833 .. [2] J. Demmel, P. Koev, and X. Li, "A Brief Survey of Direct Linear 

1834 Solvers". In Z. Bai, J. Demmel, J. Dongarra, A. Ruhe, and H. van der 

1835 Vorst, editors. Templates for the Solution of Algebraic Eigenvalue 

1836 Problems: A Practical Guide. SIAM, Philadelphia, 2000. Available at: 

1837 http://www.netlib.org/utk/people/JackDongarra/etemplates/node384.html 

1838 

1839 .. [3] R. Scheibler, E. Bezzam, I. Dokmanic, Pyroomacoustics: A Python 

1840 package for audio room simulations and array processing algorithms, 

1841 Proc. IEEE ICASSP, Calgary, CA, 2018. 

1842 https://github.com/LCAV/pyroomacoustics/blob/pypi-release/ 

1843 pyroomacoustics/adaptive/util.py 

1844 

1845 .. [4] Marano S, Edwards B, Ferrari G and Fah D (2017), "Fitting 

1846 Earthquake Spectra: Colored Noise and Incomplete Data", Bulletin of 

1847 the Seismological Society of America., January, 2017. Vol. 107(1), 

1848 pp. 276-291. 

1849 

1850 Examples 

1851 -------- 

1852 Multiply the Toeplitz matrix T with matrix x:: 

1853 

1854 [ 1 -1 -2 -3] [1 10] 

1855 T = [ 3 1 -1 -2] x = [2 11] 

1856 [ 6 3 1 -1] [2 11] 

1857 [10 6 3 1] [5 19] 

1858 

1859 To specify the Toeplitz matrix, only the first column and the first 

1860 row are needed. 

1861 

1862 >>> import numpy as np 

1863 >>> c = np.array([1, 3, 6, 10]) # First column of T 

1864 >>> r = np.array([1, -1, -2, -3]) # First row of T 

1865 >>> x = np.array([[1, 10], [2, 11], [2, 11], [5, 19]]) 

1866 

1867 >>> from scipy.linalg import toeplitz, matmul_toeplitz 

1868 >>> matmul_toeplitz((c, r), x) 

1869 array([[-20., -80.], 

1870 [ -7., -8.], 

1871 [ 9., 85.], 

1872 [ 33., 218.]]) 

1873 

1874 Check the result by creating the full Toeplitz matrix and 

1875 multiplying it by ``x``. 

1876 

1877 >>> toeplitz(c, r) @ x 

1878 array([[-20, -80], 

1879 [ -7, -8], 

1880 [ 9, 85], 

1881 [ 33, 218]]) 

1882 

1883 The full matrix is never formed explicitly, so this routine 

1884 is suitable for very large Toeplitz matrices. 

1885 

1886 >>> n = 1000000 

1887 >>> matmul_toeplitz([1] + [0]*(n-1), np.ones(n)) 

1888 array([1., 1., 1., ..., 1., 1., 1.]) 

1889 

1890 """ 

1891 

1892 from ..fft import fft, ifft, rfft, irfft 

1893 

1894 r, c, x, dtype, x_shape = _validate_args_for_toeplitz_ops( 

1895 c_or_cr, x, check_finite, keep_b_shape=False, enforce_square=False) 

1896 n, m = x.shape 

1897 

1898 T_nrows = len(c) 

1899 T_ncols = len(r) 

1900 p = T_nrows + T_ncols - 1 # equivalent to len(embedded_col) 

1901 

1902 embedded_col = np.concatenate((c, r[-1:0:-1])) 

1903 

1904 if np.iscomplexobj(embedded_col) or np.iscomplexobj(x): 

1905 fft_mat = fft(embedded_col, axis=0, workers=workers).reshape(-1, 1) 

1906 fft_x = fft(x, n=p, axis=0, workers=workers) 

1907 

1908 mat_times_x = ifft(fft_mat*fft_x, axis=0, 

1909 workers=workers)[:T_nrows, :] 

1910 else: 

1911 # Real inputs; using rfft is faster 

1912 fft_mat = rfft(embedded_col, axis=0, workers=workers).reshape(-1, 1) 

1913 fft_x = rfft(x, n=p, axis=0, workers=workers) 

1914 

1915 mat_times_x = irfft(fft_mat*fft_x, axis=0, 

1916 workers=workers, n=p)[:T_nrows, :] 

1917 

1918 return_shape = (T_nrows,) if len(x_shape) == 1 else (T_nrows, m) 

1919 return mat_times_x.reshape(*return_shape)