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

428 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

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 

17 

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

19 'solve_toeplitz', 'solve_circulant', 'inv', 'det', 'lstsq', 

20 'pinv', 'pinvh', 'matrix_balance', 'matmul_toeplitz'] 

21 

22 

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

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

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

26 

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

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

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

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

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

32 

33 

34# Linear equations 

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

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

37 if info < 0: 

38 raise ValueError('LAPACK reported an illegal value in {}-th argument' 

39 '.'.format(-info)) 

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('Ill-conditioned matrix (rcond={:.6g}): ' 

48 'result may not be accurate.'.format(rcond), 

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('{} is not a recognized matrix structure' 

178 ''.format(assume_a)) 

179 

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

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

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

183 assume_a = 'sym' 

184 

185 # Get the correct lamch function. 

186 # The LAMCH functions only exists for S and D 

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

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

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

190 else: 

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

192 

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

194 # lansy, lanpo, lanhe. 

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

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

197 

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

199 # we can collect them all in this one call 

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

201 # the I-norm should be used 

202 if transposed: 

203 trans = 1 

204 norm = 'I' 

205 if np.iscomplexobj(a1): 

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

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

208 'for complex matrices.') 

209 else: 

210 trans = 0 

211 norm = '1' 

212 

213 anorm = lange(norm, a1) 

214 

215 # Generalized case 'gesv' 

216 if assume_a == 'gen': 

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

218 (a1, b1)) 

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

220 _solve_check(n, info) 

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

222 trans=trans, overwrite_b=overwrite_b) 

223 _solve_check(n, info) 

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

225 # Hermitian case 'hesv' 

226 elif assume_a == 'her': 

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

228 'hesv_lwork'), (a1, b1)) 

229 lwork = _compute_lwork(hesv_lw, n, lower) 

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

231 lower=lower, 

232 overwrite_a=overwrite_a, 

233 overwrite_b=overwrite_b) 

234 _solve_check(n, info) 

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

236 # Symmetric case 'sysv' 

237 elif assume_a == 'sym': 

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

239 'sysv_lwork'), (a1, b1)) 

240 lwork = _compute_lwork(sysv_lw, n, lower) 

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

242 lower=lower, 

243 overwrite_a=overwrite_a, 

244 overwrite_b=overwrite_b) 

245 _solve_check(n, info) 

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

247 # Positive definite case 'posv' 

248 else: 

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

250 (a1, b1)) 

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

252 overwrite_a=overwrite_a, 

253 overwrite_b=overwrite_b) 

254 _solve_check(n, info) 

255 rcond, info = pocon(lu, anorm) 

256 

257 _solve_check(n, info, lamch, rcond) 

258 

259 if b_is_1D: 

260 x = x.ravel() 

261 

262 return x 

263 

264 

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

266 overwrite_b=False, check_finite=True): 

267 """ 

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

269 

270 Parameters 

271 ---------- 

272 a : (M, M) array_like 

273 A triangular matrix 

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

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

276 lower : bool, optional 

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

278 Default is to use upper triangle. 

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

280 Type of system to solve: 

281 

282 ======== ========= 

283 trans system 

284 ======== ========= 

285 0 or 'N' a x = b 

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

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

288 ======== ========= 

289 unit_diagonal : bool, optional 

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

291 will not be referenced. 

292 overwrite_b : bool, optional 

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

294 check_finite : bool, optional 

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

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

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

298 

299 Returns 

300 ------- 

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

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

303 

304 Raises 

305 ------ 

306 LinAlgError 

307 If `a` is singular 

308 

309 Notes 

310 ----- 

311 .. versionadded:: 0.9.0 

312 

313 Examples 

314 -------- 

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

316 

317 [3 0 0 0] [4] 

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

319 [1 0 1 0] [4] 

320 [1 1 1 1] [2] 

321 

322 >>> import numpy as np 

323 >>> from scipy.linalg import solve_triangular 

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

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

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

327 >>> x 

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

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

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

331 

332 """ 

333 

334 a1 = _asarray_validated(a, check_finite=check_finite) 

335 b1 = _asarray_validated(b, check_finite=check_finite) 

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

337 raise ValueError('expected square matrix') 

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

339 raise ValueError('shapes of a {} and b {} are incompatible' 

340 .format(a1.shape, b1.shape)) 

341 overwrite_b = overwrite_b or _datacopied(b1, b) 

342 

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

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

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

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

347 trans=trans, unitdiag=unit_diagonal) 

348 else: 

349 # transposed system is solved since trtrs expects Fortran ordering 

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

351 trans=not trans, unitdiag=unit_diagonal) 

352 

353 if info == 0: 

354 return x 

355 if info > 0: 

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

357 (info-1)) 

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

359 (-info)) 

360 

361 

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

363 check_finite=True): 

364 """ 

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

366 

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

368 

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

370 

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

372 

373 * a01 a12 a23 a34 a45 

374 a00 a11 a22 a33 a44 a55 

375 a10 a21 a32 a43 a54 * 

376 a20 a31 a42 a53 * * 

377 

378 Parameters 

379 ---------- 

380 (l, u) : (integer, integer) 

381 Number of non-zero lower and upper diagonals 

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

383 Banded matrix 

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

385 Right-hand side 

386 overwrite_ab : bool, optional 

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

388 overwrite_b : bool, optional 

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

390 check_finite : bool, optional 

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

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

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

394 

395 Returns 

396 ------- 

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

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

399 shape of `b`. 

400 

401 Examples 

402 -------- 

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

404 

405 [5 2 -1 0 0] [0] 

406 [1 4 2 -1 0] [1] 

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

408 [0 0 1 2 2] [2] 

409 [0 0 0 1 1] [3] 

410 

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

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

413 

414 [* * -1 -1 -1] 

415 ab = [* 2 2 2 2] 

416 [5 4 3 2 1] 

417 [1 1 1 1 *] 

418 

419 >>> import numpy as np 

420 >>> from scipy.linalg import solve_banded 

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

422 ... [0, 2, 2, 2, 2], 

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

424 ... [1, 1, 1, 1, 0]]) 

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

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

427 >>> x 

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

429 

430 """ 

431 

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

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

434 # Validate shapes. 

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

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

437 (nlower, nupper) = l_and_u 

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

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

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

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

442 

443 overwrite_b = overwrite_b or _datacopied(b1, b) 

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

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

446 b2 /= a1[1, 0] 

447 return b2 

448 if nlower == nupper == 1: 

449 overwrite_ab = overwrite_ab or _datacopied(a1, ab) 

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

451 du = a1[0, 1:] 

452 d = a1[1, :] 

453 dl = a1[2, :-1] 

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

455 overwrite_ab, overwrite_b) 

456 else: 

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

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

459 a2[nlower:, :] = a1 

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

461 overwrite_b=overwrite_b) 

462 if info == 0: 

463 return x 

464 if info > 0: 

465 raise LinAlgError("singular matrix") 

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

467 'gbsv/gtsv' % -info) 

468 

469 

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

471 check_finite=True): 

472 """ 

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

474 

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

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

477 matrices. 

478 

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

480 diagonal ordered form: 

481 

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

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

484 

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

486 ``u`` =2):: 

487 

488 upper form: 

489 * * a02 a13 a24 a35 

490 * a01 a12 a23 a34 a45 

491 a00 a11 a22 a33 a44 a55 

492 

493 lower form: 

494 a00 a11 a22 a33 a44 a55 

495 a10 a21 a32 a43 a54 * 

496 a20 a31 a42 a53 * * 

497 

498 Cells marked with * are not used. 

499 

500 Parameters 

501 ---------- 

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

503 Banded matrix 

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

505 Right-hand side 

506 overwrite_ab : bool, optional 

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

508 overwrite_b : bool, optional 

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

510 lower : bool, optional 

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

512 check_finite : bool, optional 

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

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

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

516 

517 Returns 

518 ------- 

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

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

521 of `b`. 

522 

523 Notes 

524 ----- 

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

526 `solve_banded` may be used. 

527 

528 Examples 

529 -------- 

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

531 

532 [ 4 2 -1 0 0 0] [1] 

533 [ 2 5 2 -1 0 0] [2] 

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

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

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

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

538 

539 >>> import numpy as np 

540 >>> from scipy.linalg import solveh_banded 

541 

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

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

544 

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

546 ... [ 2, 2, 2, 2, 2, 0], 

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

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

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

550 >>> x 

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

552 0.34733894]) 

553 

554 

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

556 

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

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

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

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

561 

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

563 

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

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

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

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

568 >>> x 

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

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

571 

572 """ 

573 a1 = _asarray_validated(ab, check_finite=check_finite) 

574 b1 = _asarray_validated(b, check_finite=check_finite) 

575 # Validate shapes. 

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

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

578 

579 overwrite_b = overwrite_b or _datacopied(b1, b) 

580 overwrite_ab = overwrite_ab or _datacopied(a1, ab) 

581 

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

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

584 if lower: 

585 d = a1[0, :].real 

586 e = a1[1, :-1] 

587 else: 

588 d = a1[1, :].real 

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

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

591 overwrite_b) 

592 else: 

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

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

595 overwrite_b=overwrite_b) 

596 if info > 0: 

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

598 if info < 0: 

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

600 'pbsv' % -info) 

601 return x 

602 

603 

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

605 """Solve a Toeplitz system using Levinson Recursion 

606 

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

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

609 assumed. 

610 

611 Parameters 

612 ---------- 

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

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

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

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

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

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

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

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

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

622 check_finite : bool, optional 

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

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

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

626 

627 Returns 

628 ------- 

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

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

631 of `b`. 

632 

633 See Also 

634 -------- 

635 toeplitz : Toeplitz matrix 

636 

637 Notes 

638 ----- 

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

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

641 

642 Examples 

643 -------- 

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

645 

646 [ 1 -1 -2 -3] [1] 

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

648 [ 6 3 1 -1] [2] 

649 [10 6 3 1] [5] 

650 

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

652 row are needed. 

653 

654 >>> import numpy as np 

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

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

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

658 

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

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

661 >>> x 

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

663 

664 Check the result by creating the full Toeplitz matrix and 

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

666 

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

668 >>> T.dot(x) 

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

670 

671 """ 

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

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

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

675 

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

677 c_or_cr, b, check_finite, keep_b_shape=True) 

678 

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

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

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

682 if b is None: 

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

684 

685 if b.ndim == 1: 

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

687 else: 

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

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

690 x = x.reshape(*b_shape) 

691 

692 return x 

693 

694 

695def _get_axis_len(aname, a, axis): 

696 ax = axis 

697 if ax < 0: 

698 ax += a.ndim 

699 if 0 <= ax < a.ndim: 

700 return a.shape[ax] 

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

702 

703 

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

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

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

707 

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

709 

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

711 calculation is:: 

712 

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

714 

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

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

717 solving the system with the full circulant matrix. 

718 

719 Parameters 

720 ---------- 

721 c : array_like 

722 The coefficients of the circulant matrix. 

723 b : array_like 

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

725 singular : str, optional 

726 This argument controls how a near singular circulant matrix is 

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

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

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

730 tol : float, optional 

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

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

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

734 

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

736 

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

738 of the circulant matrix. 

739 caxis : int 

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

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

742 holds the vectors of circulant coefficients. 

743 baxis : int 

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

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

746 right-hand side vectors. 

747 outaxis : int 

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

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

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

751 

752 Returns 

753 ------- 

754 x : ndarray 

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

756 

757 Raises 

758 ------ 

759 LinAlgError 

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

761 

762 See Also 

763 -------- 

764 circulant : circulant matrix 

765 

766 Notes 

767 ----- 

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

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

770 

771 solve_circulant(c, b) 

772 

773 returns the same result as 

774 

775 solve(circulant(c), b) 

776 

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

778 

779 .. versionadded:: 0.16.0 

780 

781 Examples 

782 -------- 

783 >>> import numpy as np 

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

785 

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

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

788 >>> solve_circulant(c, b) 

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

790 

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

792 

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

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

795 

796 A singular example: 

797 

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

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

800 

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

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

803 

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

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

806 

807 Compare to `scipy.linalg.lstsq`: 

808 

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

810 >>> x 

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

812 

813 A broadcasting example: 

814 

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

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

817 (3, 5). For example, 

818 

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

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

821 

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

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

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

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

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

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

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

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

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

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

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

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

834 

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

836 >>> x.shape 

837 (2, 3, 5) 

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

839 >>> x 

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

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

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

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

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

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

846 

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

848 

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

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

851 

852 """ 

853 c = np.atleast_1d(c) 

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

855 b = np.atleast_1d(b) 

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

857 if nc != nb: 

858 raise ValueError('Shapes of c {} and b {} are incompatible' 

859 .format(c.shape, b.shape)) 

860 

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

862 abs_fc = np.abs(fc) 

863 if tol is None: 

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

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

866 if tol.shape != (): 

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

868 else: 

869 tol = np.atleast_1d(tol) 

870 

871 near_zeros = abs_fc <= tol 

872 is_near_singular = np.any(near_zeros) 

873 if is_near_singular: 

874 if singular == 'raise': 

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

876 else: 

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

878 # division fb/fc below. 

879 fc[near_zeros] = 1 

880 

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

882 

883 q = fb / fc 

884 

885 if is_near_singular: 

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

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

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

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

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

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

892 q[mask] = 0 

893 

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

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

896 x = x.real 

897 if outaxis != -1: 

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

899 return x 

900 

901 

902# matrix inversion 

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

904 """ 

905 Compute the inverse of a matrix. 

906 

907 Parameters 

908 ---------- 

909 a : array_like 

910 Square matrix to be inverted. 

911 overwrite_a : bool, optional 

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

913 check_finite : bool, optional 

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

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

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

917 

918 Returns 

919 ------- 

920 ainv : ndarray 

921 Inverse of the matrix `a`. 

922 

923 Raises 

924 ------ 

925 LinAlgError 

926 If `a` is singular. 

927 ValueError 

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

929 

930 Examples 

931 -------- 

932 >>> import numpy as np 

933 >>> from scipy import linalg 

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

935 >>> linalg.inv(a) 

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

937 [ 1.5, -0.5]]) 

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

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

940 [ 0., 1.]]) 

941 

942 """ 

943 a1 = _asarray_validated(a, check_finite=check_finite) 

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

945 raise ValueError('expected square matrix') 

946 overwrite_a = overwrite_a or _datacopied(a1, a) 

947 # XXX: I found no advantage or disadvantage of using finv. 

948# finv, = get_flinalg_funcs(('inv',),(a1,)) 

949# if finv is not None: 

950# a_inv,info = finv(a1,overwrite_a=overwrite_a) 

951# if info==0: 

952# return a_inv 

953# if info>0: raise LinAlgError, "singular matrix" 

954# if info<0: raise ValueError('illegal value in %d-th argument of ' 

955# 'internal inv.getrf|getri'%(-info)) 

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

957 'getri_lwork'), 

958 (a1,)) 

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

960 if info == 0: 

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

962 

963 # XXX: the following line fixes curious SEGFAULT when 

964 # benchmarking 500x500 matrix inverse. This seems to 

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

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

967 # all tests pass. Further investigation is required if 

968 # more such SEGFAULTs occur. 

969 lwork = int(1.01 * lwork) 

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

971 if info > 0: 

972 raise LinAlgError("singular matrix") 

973 if info < 0: 

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

975 'getrf|getri' % -info) 

976 return inv_a 

977 

978 

979# Determinant 

980 

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

982 """ 

983 Compute the determinant of a matrix 

984 

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

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

987 

988 Parameters 

989 ---------- 

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

991 Input array to compute determinants for. 

992 overwrite_a : bool, optional 

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

994 check_finite : bool, optional 

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

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

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

998 

999 Returns 

1000 ------- 

1001 det : (...) float or complex 

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

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

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

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

1006 

1007 Notes 

1008 ----- 

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

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

1011 diagonal entries of the U factor. 

1012 

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

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

1015 overflows. 

1016 

1017 Examples 

1018 -------- 

1019 >>> import numpy as np 

1020 >>> from scipy import linalg 

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

1022 >>> linalg.det(a) 

1023 0.0 

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

1025 >>> linalg.det(b) 

1026 3.0 

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

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

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

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

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

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

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

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

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

1036 [-2., -2.], 

1037 [-2., -2.]]) 

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

1039 -2.0 

1040 """ 

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

1042 

1043 # First we check and make arrays. 

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

1045 if a1.ndim < 2: 

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

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

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

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

1050 

1051 # Also check if dtype is LAPACK compatible 

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

1053 dtype_char = lapack_cast_dict[a1.dtype.char] 

1054 if not dtype_char: # No casting possible 

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

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

1057 

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

1059 overwrite_a = True 

1060 

1061 # Empty array has determinant 1 because math. 

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

1063 if a1.ndim == 2: 

1064 return np.float64(1.) 

1065 else: 

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

1067 

1068 # Scalar case 

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

1070 # Either ndarray with spurious singletons or a single element 

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

1072 temp = np.squeeze(a1) 

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

1074 return temp 

1075 else: 

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

1077 temp.astype('D')) 

1078 else: 

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

1080 np.complex128(a1.item())) 

1081 

1082 # Then check overwrite permission 

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

1084 if not overwrite_a: 

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

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

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

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

1089 

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

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

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

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

1094 

1095 if a1.ndim == 2: 

1096 det = find_det_from_lu(a1) 

1097 # Convert float, complex to to NumPy scalars 

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

1099 

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

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

1102 dtype_char = a1.dtype.char 

1103 if dtype_char in 'fF': 

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

1105 

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

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

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

1109 return det 

1110 

1111 

1112# Linear Least Squares 

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

1114 check_finite=True, lapack_driver=None): 

1115 """ 

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

1117 

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

1119 

1120 Parameters 

1121 ---------- 

1122 a : (M, N) array_like 

1123 Left-hand side array 

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

1125 Right hand side array 

1126 cond : float, optional 

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

1128 rank of a. Singular values smaller than 

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

1130 overwrite_a : bool, optional 

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

1132 overwrite_b : bool, optional 

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

1134 check_finite : bool, optional 

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

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

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

1138 lapack_driver : str, optional 

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

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

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

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

1143 generally slow but uses less memory. 

1144 

1145 .. versionadded:: 0.17.0 

1146 

1147 Returns 

1148 ------- 

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

1150 Least-squares solution. 

1151 residues : (K,) ndarray or float 

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

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

1154 (0,)-shaped array is returned. 

1155 rank : int 

1156 Effective rank of `a`. 

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

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

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

1160 

1161 Raises 

1162 ------ 

1163 LinAlgError 

1164 If computation does not converge. 

1165 

1166 ValueError 

1167 When parameters are not compatible. 

1168 

1169 See Also 

1170 -------- 

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

1172 

1173 Notes 

1174 ----- 

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

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

1177 

1178 Examples 

1179 -------- 

1180 >>> import numpy as np 

1181 >>> from scipy.linalg import lstsq 

1182 >>> import matplotlib.pyplot as plt 

1183 

1184 Suppose we have the following data: 

1185 

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

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

1188 

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

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

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

1192 

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

1194 >>> M 

1195 array([[ 1. , 1. ], 

1196 [ 1. , 6.25], 

1197 [ 1. , 12.25], 

1198 [ 1. , 16. ], 

1199 [ 1. , 25. ], 

1200 [ 1. , 49. ], 

1201 [ 1. , 72.25]]) 

1202 

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

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

1205 ``a`` and ``b``. 

1206 

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

1208 >>> p 

1209 array([ 0.20925829, 0.12013861]) 

1210 

1211 Plot the data and the fitted curve. 

1212 

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

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

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

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

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

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

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

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

1221 >>> plt.show() 

1222 

1223 """ 

1224 a1 = _asarray_validated(a, check_finite=check_finite) 

1225 b1 = _asarray_validated(b, check_finite=check_finite) 

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

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

1228 m, n = a1.shape 

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

1230 nrhs = b1.shape[1] 

1231 else: 

1232 nrhs = 1 

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

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

1235 ' of rows ({} != {}).'.format(m, b1.shape[0])) 

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

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

1238 if n == 0: 

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

1240 else: 

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

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

1243 

1244 driver = lapack_driver 

1245 if driver is None: 

1246 driver = lstsq.default_lapack_driver 

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

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

1249 

1250 lapack_func, lapack_lwork = get_lapack_funcs((driver, 

1251 '%s_lwork' % driver), 

1252 (a1, b1)) 

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

1254 

1255 if m < n: 

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

1257 # a larger solution matrix 

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

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

1260 b2[:m, :] = b1 

1261 else: 

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

1263 b2[:m] = b1 

1264 b1 = b2 

1265 

1266 overwrite_a = overwrite_a or _datacopied(a1, a) 

1267 overwrite_b = overwrite_b or _datacopied(b1, b) 

1268 

1269 if cond is None: 

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

1271 

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

1273 if driver == 'gelss': 

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

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

1276 overwrite_a=overwrite_a, 

1277 overwrite_b=overwrite_b) 

1278 

1279 elif driver == 'gelsd': 

1280 if real_data: 

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

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

1283 iwork, cond, False, False) 

1284 else: # complex data 

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

1286 nrhs, cond) 

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

1288 cond, False, False) 

1289 if info > 0: 

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

1291 if info < 0: 

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

1293 % (-info, lapack_driver)) 

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

1295 if m > n: 

1296 x1 = x[:n] 

1297 if rank == n: 

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

1299 x = x1 

1300 return x, resids, rank, s 

1301 

1302 elif driver == 'gelsy': 

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

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

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

1306 lwork, False, False) 

1307 if info < 0: 

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

1309 "gelsy" % -info) 

1310 if m > n: 

1311 x1 = x[:n] 

1312 x = x1 

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

1314 

1315 

1316lstsq.default_lapack_driver = 'gelsd' 

1317 

1318 

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

1320 cond=None, rcond=None): 

1321 """ 

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

1323 

1324 Calculate a generalized inverse of a matrix using its 

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

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

1327 values. 

1328 

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

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

1331 singular value below this value is assumed insignificant. 

1332 

1333 Parameters 

1334 ---------- 

1335 a : (M, N) array_like 

1336 Matrix to be pseudo-inverted. 

1337 atol : float, optional 

1338 Absolute threshold term, default value is 0. 

1339 

1340 .. versionadded:: 1.7.0 

1341 

1342 rtol : float, optional 

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

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

1345 

1346 .. versionadded:: 1.7.0 

1347 

1348 return_rank : bool, optional 

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

1350 check_finite : bool, optional 

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

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

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

1354 cond, rcond : float, optional 

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

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

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

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

1359 atol, rtol takes precedence over these keywords. 

1360 

1361 .. versionchanged:: 1.7.0 

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

1363 will be removed in future versions of SciPy. 

1364 

1365 .. versionchanged:: 1.3.0 

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

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

1368 

1369 Returns 

1370 ------- 

1371 B : (N, M) ndarray 

1372 The pseudo-inverse of matrix `a`. 

1373 rank : int 

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

1375 

1376 Raises 

1377 ------ 

1378 LinAlgError 

1379 If SVD computation does not converge. 

1380 

1381 See Also 

1382 -------- 

1383 pinvh : Moore-Penrose pseudoinverse of a hermititan matrix. 

1384 

1385 Notes 

1386 ----- 

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

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

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

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

1391 

1392 References 

1393 ---------- 

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

1395 equations. Mathematical Proceedings of the Cambridge Philosophical 

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

1397 

1398 Examples 

1399 -------- 

1400 

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

1402 Moore-Penrose conditions are: 

1403 

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

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

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

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

1408 

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

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

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

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

1413 independant columns/rows. 

1414 

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

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

1417 

1418 >>> import numpy as np 

1419 >>> from scipy import linalg 

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

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

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

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

1424 True 

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

1426 True 

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

1428 True 

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

1430 True 

1431 

1432 """ 

1433 a = _asarray_validated(a, check_finite=check_finite) 

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

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

1436 maxS = np.max(s) 

1437 

1438 if rcond or cond: 

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

1440 'will be removed in future versions of SciPy. Use "atol" and ' 

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

1442 

1443 # backwards compatible only atol and rtol are both missing 

1444 if (rcond or cond) and (atol is None) and (rtol is None): 

1445 atol = rcond or cond 

1446 rtol = 0. 

1447 

1448 atol = 0. if atol is None else atol 

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

1450 

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

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

1453 

1454 val = atol + maxS * rtol 

1455 rank = np.sum(s > val) 

1456 

1457 u = u[:, :rank] 

1458 u /= s[:rank] 

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

1460 

1461 if return_rank: 

1462 return B, rank 

1463 else: 

1464 return B 

1465 

1466 

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

1468 check_finite=True): 

1469 """ 

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

1471 

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

1473 matrix using its eigenvalue decomposition and including all eigenvalues 

1474 with 'large' absolute value. 

1475 

1476 Parameters 

1477 ---------- 

1478 a : (N, N) array_like 

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

1480 

1481 atol : float, optional 

1482 Absolute threshold term, default value is 0. 

1483 

1484 .. versionadded:: 1.7.0 

1485 

1486 rtol : float, optional 

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

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

1489 

1490 .. versionadded:: 1.7.0 

1491 

1492 lower : bool, optional 

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

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

1495 return_rank : bool, optional 

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

1497 check_finite : bool, optional 

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

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

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

1501 

1502 Returns 

1503 ------- 

1504 B : (N, N) ndarray 

1505 The pseudo-inverse of matrix `a`. 

1506 rank : int 

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

1508 

1509 Raises 

1510 ------ 

1511 LinAlgError 

1512 If eigenvalue algorithm does not converge. 

1513 

1514 See Also 

1515 -------- 

1516 pinv : Moore-Penrose pseudoinverse of a matrix. 

1517 

1518 Examples 

1519 -------- 

1520 

1521 For a more detailed example see `pinv`. 

1522 

1523 >>> import numpy as np 

1524 >>> from scipy.linalg import pinvh 

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

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

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

1528 >>> B = pinvh(a) 

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

1530 True 

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

1532 True 

1533 

1534 """ 

1535 a = _asarray_validated(a, check_finite=check_finite) 

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

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

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

1539 

1540 atol = 0. if atol is None else atol 

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

1542 

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

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

1545 

1546 val = atol + maxS * rtol 

1547 above_cutoff = (abs(s) > val) 

1548 

1549 psigma_diag = 1.0 / s[above_cutoff] 

1550 u = u[:, above_cutoff] 

1551 

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

1553 

1554 if return_rank: 

1555 return B, len(psigma_diag) 

1556 else: 

1557 return B 

1558 

1559 

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

1561 overwrite_a=False): 

1562 """ 

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

1564 

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

1566 a similarity transformation such that the magnitude variation of the 

1567 matrix entries is reflected to the scaling matrices. 

1568 

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

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

1571 only the remaining subblocks are subjected to scaling. 

1572 

1573 The balanced matrix satisfies the following equality 

1574 

1575 .. math:: 

1576 

1577 B = T^{-1} A T 

1578 

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

1580 to avoid round-off errors. 

1581 

1582 Parameters 

1583 ---------- 

1584 A : (n, n) array_like 

1585 Square data matrix for the balancing. 

1586 permute : bool, optional 

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

1588 prior to scaling. 

1589 scale : bool, optional 

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

1591 will not be scaled. 

1592 separate : bool, optional 

1593 This switches from returning a full matrix of the transformation 

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

1595 overwrite_a : bool, optional 

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

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

1598 for details. This is False by default. 

1599 

1600 Returns 

1601 ------- 

1602 B : (n, n) ndarray 

1603 Balanced matrix 

1604 T : (n, n) ndarray 

1605 A possibly permuted diagonal matrix whose nonzero entries are 

1606 integer powers of 2 to avoid numerical truncation errors. 

1607 scale, perm : (n,) ndarray 

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

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

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

1611 

1612 Notes 

1613 ----- 

1614 This algorithm is particularly useful for eigenvalue and matrix 

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

1616 LAPACK routines. 

1617 

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

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

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

1621 there are corner cases where balancing can actually worsen the 

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

1623 

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

1625 balancing. 

1626 

1627 .. versionadded:: 0.19.0 

1628 

1629 References 

1630 ---------- 

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

1632 Calculation of Eigenvalues and Eigenvectors", Numerische Mathematik, 

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

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

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

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

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

1638 

1639 Examples 

1640 -------- 

1641 >>> import numpy as np 

1642 >>> from scipy import linalg 

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

1644 

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

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

1647 array([ 3.66666667, 0.4995005 , 0.91312162]) 

1648 

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

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

1651 

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

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

1654 [ 0. , 1. , 0. ], 

1655 [ 0. , 0. , 1. ]]) 

1656 

1657 """ 

1658 

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

1660 

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

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

1663 

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

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

1666 overwrite_a=overwrite_a) 

1667 

1668 if info < 0: 

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

1670 '"illegal value in argument number {}.". See ' 

1671 'LAPACK documentation for the xGEBAL error codes.' 

1672 ''.format(-info)) 

1673 

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

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

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

1677 

1678 # gebal uses 1-indexing 

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

1680 n = A.shape[0] 

1681 perm = np.arange(n) 

1682 

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

1684 if hi < n: 

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

1686 if n-ind == x: 

1687 continue 

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

1689 

1690 if lo > 0: 

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

1692 if ind == x: 

1693 continue 

1694 perm[[x, ind]] = perm[[ind, x]] 

1695 

1696 if separate: 

1697 return B, (scaling, perm) 

1698 

1699 # get the inverse permutation 

1700 iperm = np.empty_like(perm) 

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

1702 

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

1704 

1705 

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

1707 enforce_square=True): 

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

1709 

1710 Parameters 

1711 ---------- 

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

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

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

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

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

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

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

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

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

1721 check_finite : bool 

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

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

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

1725 keep_b_shape : bool 

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

1727 matrix. 

1728 enforce_square : bool, optional 

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

1730 

1731 Returns 

1732 ------- 

1733 r : array 

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

1735 c: array 

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

1737 b: array 

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

1739 corresponding to ``b``. 

1740 dtype: numpy datatype 

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

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

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

1744 b_shape: tuple 

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

1746 

1747 """ 

1748 

1749 if isinstance(c_or_cr, tuple): 

1750 c, r = c_or_cr 

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

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

1753 else: 

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

1755 r = c.conjugate() 

1756 

1757 if b is None: 

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

1759 

1760 b = _asarray_validated(b, check_finite=check_finite) 

1761 b_shape = b.shape 

1762 

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

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

1765 raise ValueError('Incompatible dimensions.') 

1766 

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

1768 dtype = np.complex128 if is_cmplx else np.double 

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

1770 

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

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

1773 elif b.ndim != 1: 

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

1775 

1776 return r, c, b, dtype, b_shape 

1777 

1778 

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

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

1781 

1782 This function returns the matrix multiplication between a Toeplitz 

1783 matrix and a dense matrix. 

1784 

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

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

1787 assumed. 

1788 

1789 Parameters 

1790 ---------- 

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

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

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

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

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

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

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

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

1799 Matrix with which to multiply. 

1800 check_finite : bool, optional 

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

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

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

1804 workers : int, optional 

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

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

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

1808 

1809 Returns 

1810 ------- 

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

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

1813 matches shape of `x`. 

1814 

1815 See Also 

1816 -------- 

1817 toeplitz : Toeplitz matrix 

1818 solve_toeplitz : Solve a Toeplitz system using Levinson Recursion 

1819 

1820 Notes 

1821 ----- 

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

1823 to efficiently calculate the matrix-matrix product. 

1824 

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

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

1827 which preserves the data type of the input. 

1828 

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

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

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

1832 implementations in Python. 

1833 

1834 .. versionadded:: 1.6.0 

1835 

1836 References 

1837 ---------- 

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

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

1840 Gaussian Process Inference with GPU Acceleration" with contributions 

1841 from Max Balandat and Ruihan Wu. Available online: 

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

1843 

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

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

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

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

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

1849 

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

1851 package for audio room simulations and array processing algorithms, 

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

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

1854 pyroomacoustics/adaptive/util.py 

1855 

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

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

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

1859 pp. 276-291. 

1860 

1861 Examples 

1862 -------- 

1863 Multiply the Toeplitz matrix T with matrix x:: 

1864 

1865 [ 1 -1 -2 -3] [1 10] 

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

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

1868 [10 6 3 1] [5 19] 

1869 

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

1871 row are needed. 

1872 

1873 >>> import numpy as np 

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

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

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

1877 

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

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

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

1881 [ -7., -8.], 

1882 [ 9., 85.], 

1883 [ 33., 218.]]) 

1884 

1885 Check the result by creating the full Toeplitz matrix and 

1886 multiplying it by ``x``. 

1887 

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

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

1890 [ -7, -8], 

1891 [ 9, 85], 

1892 [ 33, 218]]) 

1893 

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

1895 is suitable for very large Toeplitz matrices. 

1896 

1897 >>> n = 1000000 

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

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

1900 

1901 """ 

1902 

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

1904 

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

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

1907 n, m = x.shape 

1908 

1909 T_nrows = len(c) 

1910 T_ncols = len(r) 

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

1912 

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

1914 

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

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

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

1918 

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

1920 workers=workers)[:T_nrows, :] 

1921 else: 

1922 # Real inputs; using rfft is faster 

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

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

1925 

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

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

1928 

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

1930 return mat_times_x.reshape(*return_shape)