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

393 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-23 06:43 +0000

1# 

2# Author: Pearu Peterson, March 2002 

3# 

4# additions by Travis Oliphant, March 2002 

5# additions by Eric Jones, June 2002 

6# additions by Johannes Loehnert, June 2006 

7# additions by Bart Vandereycken, June 2006 

8# additions by Andrew D Straw, May 2007 

9# additions by Tiziano Zito, November 2008 

10# 

11# April 2010: Functions for LU, QR, SVD, Schur, and Cholesky decompositions 

12# were moved to their own files. Still in this file are functions for 

13# eigenstuff and for the Hessenberg form. 

14 

15__all__ = ['eig', 'eigvals', 'eigh', 'eigvalsh', 

16 'eig_banded', 'eigvals_banded', 

17 'eigh_tridiagonal', 'eigvalsh_tridiagonal', 'hessenberg', 'cdf2rdf'] 

18 

19import warnings 

20 

21import numpy 

22from numpy import (array, isfinite, inexact, nonzero, iscomplexobj, 

23 flatnonzero, conj, asarray, argsort, empty, 

24 iscomplex, zeros, einsum, eye, inf) 

25# Local imports 

26from scipy._lib._util import _asarray_validated 

27from ._misc import LinAlgError, _datacopied, norm 

28from .lapack import get_lapack_funcs, _compute_lwork 

29from scipy._lib.deprecation import _NoValue, _deprecate_positional_args 

30 

31 

32_I = numpy.array(1j, dtype='F') 

33 

34 

35def _make_complex_eigvecs(w, vin, dtype): 

36 """ 

37 Produce complex-valued eigenvectors from LAPACK DGGEV real-valued output 

38 """ 

39 # - see LAPACK man page DGGEV at ALPHAI 

40 v = numpy.array(vin, dtype=dtype) 

41 m = (w.imag > 0) 

42 m[:-1] |= (w.imag[1:] < 0) # workaround for LAPACK bug, cf. ticket #709 

43 for i in flatnonzero(m): 

44 v.imag[:, i] = vin[:, i+1] 

45 conj(v[:, i], v[:, i+1]) 

46 return v 

47 

48 

49def _make_eigvals(alpha, beta, homogeneous_eigvals): 

50 if homogeneous_eigvals: 

51 if beta is None: 

52 return numpy.vstack((alpha, numpy.ones_like(alpha))) 

53 else: 

54 return numpy.vstack((alpha, beta)) 

55 else: 

56 if beta is None: 

57 return alpha 

58 else: 

59 w = numpy.empty_like(alpha) 

60 alpha_zero = (alpha == 0) 

61 beta_zero = (beta == 0) 

62 beta_nonzero = ~beta_zero 

63 w[beta_nonzero] = alpha[beta_nonzero]/beta[beta_nonzero] 

64 # Use numpy.inf for complex values too since 

65 # 1/numpy.inf = 0, i.e., it correctly behaves as projective 

66 # infinity. 

67 w[~alpha_zero & beta_zero] = numpy.inf 

68 if numpy.all(alpha.imag == 0): 

69 w[alpha_zero & beta_zero] = numpy.nan 

70 else: 

71 w[alpha_zero & beta_zero] = complex(numpy.nan, numpy.nan) 

72 return w 

73 

74 

75def _geneig(a1, b1, left, right, overwrite_a, overwrite_b, 

76 homogeneous_eigvals): 

77 ggev, = get_lapack_funcs(('ggev',), (a1, b1)) 

78 cvl, cvr = left, right 

79 res = ggev(a1, b1, lwork=-1) 

80 lwork = res[-2][0].real.astype(numpy.int_) 

81 if ggev.typecode in 'cz': 

82 alpha, beta, vl, vr, work, info = ggev(a1, b1, cvl, cvr, lwork, 

83 overwrite_a, overwrite_b) 

84 w = _make_eigvals(alpha, beta, homogeneous_eigvals) 

85 else: 

86 alphar, alphai, beta, vl, vr, work, info = ggev(a1, b1, cvl, cvr, 

87 lwork, overwrite_a, 

88 overwrite_b) 

89 alpha = alphar + _I * alphai 

90 w = _make_eigvals(alpha, beta, homogeneous_eigvals) 

91 _check_info(info, 'generalized eig algorithm (ggev)') 

92 

93 only_real = numpy.all(w.imag == 0.0) 

94 if not (ggev.typecode in 'cz' or only_real): 

95 t = w.dtype.char 

96 if left: 

97 vl = _make_complex_eigvecs(w, vl, t) 

98 if right: 

99 vr = _make_complex_eigvecs(w, vr, t) 

100 

101 # the eigenvectors returned by the lapack function are NOT normalized 

102 for i in range(vr.shape[0]): 

103 if right: 

104 vr[:, i] /= norm(vr[:, i]) 

105 if left: 

106 vl[:, i] /= norm(vl[:, i]) 

107 

108 if not (left or right): 

109 return w 

110 if left: 

111 if right: 

112 return w, vl, vr 

113 return w, vl 

114 return w, vr 

115 

116 

117def eig(a, b=None, left=False, right=True, overwrite_a=False, 

118 overwrite_b=False, check_finite=True, homogeneous_eigvals=False): 

119 """ 

120 Solve an ordinary or generalized eigenvalue problem of a square matrix. 

121 

122 Find eigenvalues w and right or left eigenvectors of a general matrix:: 

123 

124 a vr[:,i] = w[i] b vr[:,i] 

125 a.H vl[:,i] = w[i].conj() b.H vl[:,i] 

126 

127 where ``.H`` is the Hermitian conjugation. 

128 

129 Parameters 

130 ---------- 

131 a : (M, M) array_like 

132 A complex or real matrix whose eigenvalues and eigenvectors 

133 will be computed. 

134 b : (M, M) array_like, optional 

135 Right-hand side matrix in a generalized eigenvalue problem. 

136 Default is None, identity matrix is assumed. 

137 left : bool, optional 

138 Whether to calculate and return left eigenvectors. Default is False. 

139 right : bool, optional 

140 Whether to calculate and return right eigenvectors. Default is True. 

141 overwrite_a : bool, optional 

142 Whether to overwrite `a`; may improve performance. Default is False. 

143 overwrite_b : bool, optional 

144 Whether to overwrite `b`; may improve performance. Default is False. 

145 check_finite : bool, optional 

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

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

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

149 homogeneous_eigvals : bool, optional 

150 If True, return the eigenvalues in homogeneous coordinates. 

151 In this case ``w`` is a (2, M) array so that:: 

152 

153 w[1,i] a vr[:,i] = w[0,i] b vr[:,i] 

154 

155 Default is False. 

156 

157 Returns 

158 ------- 

159 w : (M,) or (2, M) double or complex ndarray 

160 The eigenvalues, each repeated according to its 

161 multiplicity. The shape is (M,) unless 

162 ``homogeneous_eigvals=True``. 

163 vl : (M, M) double or complex ndarray 

164 The normalized left eigenvector corresponding to the eigenvalue 

165 ``w[i]`` is the column ``vl[:,i]``. Only returned if ``left=True``. 

166 vr : (M, M) double or complex ndarray 

167 The normalized right eigenvector corresponding to the eigenvalue 

168 ``w[i]`` is the column ``vr[:,i]``. Only returned if ``right=True``. 

169 

170 Raises 

171 ------ 

172 LinAlgError 

173 If eigenvalue computation does not converge. 

174 

175 See Also 

176 -------- 

177 eigvals : eigenvalues of general arrays 

178 eigh : Eigenvalues and right eigenvectors for symmetric/Hermitian arrays. 

179 eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian 

180 band matrices 

181 eigh_tridiagonal : eigenvalues and right eiegenvectors for 

182 symmetric/Hermitian tridiagonal matrices 

183 

184 Examples 

185 -------- 

186 >>> import numpy as np 

187 >>> from scipy import linalg 

188 >>> a = np.array([[0., -1.], [1., 0.]]) 

189 >>> linalg.eigvals(a) 

190 array([0.+1.j, 0.-1.j]) 

191 

192 >>> b = np.array([[0., 1.], [1., 1.]]) 

193 >>> linalg.eigvals(a, b) 

194 array([ 1.+0.j, -1.+0.j]) 

195 

196 >>> a = np.array([[3., 0., 0.], [0., 8., 0.], [0., 0., 7.]]) 

197 >>> linalg.eigvals(a, homogeneous_eigvals=True) 

198 array([[3.+0.j, 8.+0.j, 7.+0.j], 

199 [1.+0.j, 1.+0.j, 1.+0.j]]) 

200 

201 >>> a = np.array([[0., -1.], [1., 0.]]) 

202 >>> linalg.eigvals(a) == linalg.eig(a)[0] 

203 array([ True, True]) 

204 >>> linalg.eig(a, left=True, right=False)[1] # normalized left eigenvector 

205 array([[-0.70710678+0.j , -0.70710678-0.j ], 

206 [-0. +0.70710678j, -0. -0.70710678j]]) 

207 >>> linalg.eig(a, left=False, right=True)[1] # normalized right eigenvector 

208 array([[0.70710678+0.j , 0.70710678-0.j ], 

209 [0. -0.70710678j, 0. +0.70710678j]]) 

210 

211 

212 

213 """ 

214 a1 = _asarray_validated(a, check_finite=check_finite) 

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

216 raise ValueError('expected square matrix') 

217 overwrite_a = overwrite_a or (_datacopied(a1, a)) 

218 if b is not None: 

219 b1 = _asarray_validated(b, check_finite=check_finite) 

220 overwrite_b = overwrite_b or _datacopied(b1, b) 

221 if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]: 

222 raise ValueError('expected square matrix') 

223 if b1.shape != a1.shape: 

224 raise ValueError('a and b must have the same shape') 

225 return _geneig(a1, b1, left, right, overwrite_a, overwrite_b, 

226 homogeneous_eigvals) 

227 

228 geev, geev_lwork = get_lapack_funcs(('geev', 'geev_lwork'), (a1,)) 

229 compute_vl, compute_vr = left, right 

230 

231 lwork = _compute_lwork(geev_lwork, a1.shape[0], 

232 compute_vl=compute_vl, 

233 compute_vr=compute_vr) 

234 

235 if geev.typecode in 'cz': 

236 w, vl, vr, info = geev(a1, lwork=lwork, 

237 compute_vl=compute_vl, 

238 compute_vr=compute_vr, 

239 overwrite_a=overwrite_a) 

240 w = _make_eigvals(w, None, homogeneous_eigvals) 

241 else: 

242 wr, wi, vl, vr, info = geev(a1, lwork=lwork, 

243 compute_vl=compute_vl, 

244 compute_vr=compute_vr, 

245 overwrite_a=overwrite_a) 

246 t = {'f': 'F', 'd': 'D'}[wr.dtype.char] 

247 w = wr + _I * wi 

248 w = _make_eigvals(w, None, homogeneous_eigvals) 

249 

250 _check_info(info, 'eig algorithm (geev)', 

251 positive='did not converge (only eigenvalues ' 

252 'with order >= %d have converged)') 

253 

254 only_real = numpy.all(w.imag == 0.0) 

255 if not (geev.typecode in 'cz' or only_real): 

256 t = w.dtype.char 

257 if left: 

258 vl = _make_complex_eigvecs(w, vl, t) 

259 if right: 

260 vr = _make_complex_eigvecs(w, vr, t) 

261 if not (left or right): 

262 return w 

263 if left: 

264 if right: 

265 return w, vl, vr 

266 return w, vl 

267 return w, vr 

268 

269 

270@_deprecate_positional_args(version="1.14.0") 

271def eigh(a, b=None, *, lower=True, eigvals_only=False, overwrite_a=False, 

272 overwrite_b=False, turbo=_NoValue, eigvals=_NoValue, type=1, 

273 check_finite=True, subset_by_index=None, subset_by_value=None, 

274 driver=None): 

275 """ 

276 Solve a standard or generalized eigenvalue problem for a complex 

277 Hermitian or real symmetric matrix. 

278 

279 Find eigenvalues array ``w`` and optionally eigenvectors array ``v`` of 

280 array ``a``, where ``b`` is positive definite such that for every 

281 eigenvalue λ (i-th entry of w) and its eigenvector ``vi`` (i-th column of 

282 ``v``) satisfies:: 

283 

284 a @ vi = λ * b @ vi 

285 vi.conj().T @ a @ vi = λ 

286 vi.conj().T @ b @ vi = 1 

287 

288 In the standard problem, ``b`` is assumed to be the identity matrix. 

289 

290 Parameters 

291 ---------- 

292 a : (M, M) array_like 

293 A complex Hermitian or real symmetric matrix whose eigenvalues and 

294 eigenvectors will be computed. 

295 b : (M, M) array_like, optional 

296 A complex Hermitian or real symmetric definite positive matrix in. 

297 If omitted, identity matrix is assumed. 

298 lower : bool, optional 

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

300 triangle of ``a`` and, if applicable, ``b``. (Default: lower) 

301 eigvals_only : bool, optional 

302 Whether to calculate only eigenvalues and no eigenvectors. 

303 (Default: both are calculated) 

304 subset_by_index : iterable, optional 

305 If provided, this two-element iterable defines the start and the end 

306 indices of the desired eigenvalues (ascending order and 0-indexed). 

307 To return only the second smallest to fifth smallest eigenvalues, 

308 ``[1, 4]`` is used. ``[n-3, n-1]`` returns the largest three. Only 

309 available with "evr", "evx", and "gvx" drivers. The entries are 

310 directly converted to integers via ``int()``. 

311 subset_by_value : iterable, optional 

312 If provided, this two-element iterable defines the half-open interval 

313 ``(a, b]`` that, if any, only the eigenvalues between these values 

314 are returned. Only available with "evr", "evx", and "gvx" drivers. Use 

315 ``np.inf`` for the unconstrained ends. 

316 driver : str, optional 

317 Defines which LAPACK driver should be used. Valid options are "ev", 

318 "evd", "evr", "evx" for standard problems and "gv", "gvd", "gvx" for 

319 generalized (where b is not None) problems. See the Notes section. 

320 The default for standard problems is "evr". For generalized problems, 

321 "gvd" is used for full set, and "gvx" for subset requested cases. 

322 type : int, optional 

323 For the generalized problems, this keyword specifies the problem type 

324 to be solved for ``w`` and ``v`` (only takes 1, 2, 3 as possible 

325 inputs):: 

326 

327 1 => a @ v = w @ b @ v 

328 2 => a @ b @ v = w @ v 

329 3 => b @ a @ v = w @ v 

330 

331 This keyword is ignored for standard problems. 

332 overwrite_a : bool, optional 

333 Whether to overwrite data in ``a`` (may improve performance). Default 

334 is False. 

335 overwrite_b : bool, optional 

336 Whether to overwrite data in ``b`` (may improve performance). Default 

337 is False. 

338 check_finite : bool, optional 

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

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

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

342 turbo : bool, optional, deprecated 

343 .. deprecated:: 1.5.0 

344 `eigh` keyword argument `turbo` is deprecated in favour of 

345 ``driver=gvd`` keyword instead and will be removed in SciPy 

346 1.14.0. 

347 eigvals : tuple (lo, hi), optional, deprecated 

348 .. deprecated:: 1.5.0 

349 `eigh` keyword argument `eigvals` is deprecated in favour of 

350 `subset_by_index` keyword instead and will be removed in SciPy 

351 1.14.0. 

352 

353 Returns 

354 ------- 

355 w : (N,) ndarray 

356 The N (N<=M) selected eigenvalues, in ascending order, each 

357 repeated according to its multiplicity. 

358 v : (M, N) ndarray 

359 The normalized eigenvector corresponding to the eigenvalue ``w[i]`` is 

360 the column ``v[:,i]``. Only returned if ``eigvals_only=False``. 

361 

362 Raises 

363 ------ 

364 LinAlgError 

365 If eigenvalue computation does not converge, an error occurred, or 

366 b matrix is not definite positive. Note that if input matrices are 

367 not symmetric or Hermitian, no error will be reported but results will 

368 be wrong. 

369 

370 See Also 

371 -------- 

372 eigvalsh : eigenvalues of symmetric or Hermitian arrays 

373 eig : eigenvalues and right eigenvectors for non-symmetric arrays 

374 eigh_tridiagonal : eigenvalues and right eiegenvectors for 

375 symmetric/Hermitian tridiagonal matrices 

376 

377 Notes 

378 ----- 

379 This function does not check the input array for being Hermitian/symmetric 

380 in order to allow for representing arrays with only their upper/lower 

381 triangular parts. Also, note that even though not taken into account, 

382 finiteness check applies to the whole array and unaffected by "lower" 

383 keyword. 

384 

385 This function uses LAPACK drivers for computations in all possible keyword 

386 combinations, prefixed with ``sy`` if arrays are real and ``he`` if 

387 complex, e.g., a float array with "evr" driver is solved via 

388 "syevr", complex arrays with "gvx" driver problem is solved via "hegvx" 

389 etc. 

390 

391 As a brief summary, the slowest and the most robust driver is the 

392 classical ``<sy/he>ev`` which uses symmetric QR. ``<sy/he>evr`` is seen as 

393 the optimal choice for the most general cases. However, there are certain 

394 occasions that ``<sy/he>evd`` computes faster at the expense of more 

395 memory usage. ``<sy/he>evx``, while still being faster than ``<sy/he>ev``, 

396 often performs worse than the rest except when very few eigenvalues are 

397 requested for large arrays though there is still no performance guarantee. 

398 

399 

400 For the generalized problem, normalization with respect to the given 

401 type argument:: 

402 

403 type 1 and 3 : v.conj().T @ a @ v = w 

404 type 2 : inv(v).conj().T @ a @ inv(v) = w 

405 

406 type 1 or 2 : v.conj().T @ b @ v = I 

407 type 3 : v.conj().T @ inv(b) @ v = I 

408 

409 

410 Examples 

411 -------- 

412 >>> import numpy as np 

413 >>> from scipy.linalg import eigh 

414 >>> A = np.array([[6, 3, 1, 5], [3, 0, 5, 1], [1, 5, 6, 2], [5, 1, 2, 2]]) 

415 >>> w, v = eigh(A) 

416 >>> np.allclose(A @ v - v @ np.diag(w), np.zeros((4, 4))) 

417 True 

418 

419 Request only the eigenvalues 

420 

421 >>> w = eigh(A, eigvals_only=True) 

422 

423 Request eigenvalues that are less than 10. 

424 

425 >>> A = np.array([[34, -4, -10, -7, 2], 

426 ... [-4, 7, 2, 12, 0], 

427 ... [-10, 2, 44, 2, -19], 

428 ... [-7, 12, 2, 79, -34], 

429 ... [2, 0, -19, -34, 29]]) 

430 >>> eigh(A, eigvals_only=True, subset_by_value=[-np.inf, 10]) 

431 array([6.69199443e-07, 9.11938152e+00]) 

432 

433 Request the second smallest eigenvalue and its eigenvector 

434 

435 >>> w, v = eigh(A, subset_by_index=[1, 1]) 

436 >>> w 

437 array([9.11938152]) 

438 >>> v.shape # only a single column is returned 

439 (5, 1) 

440 

441 """ 

442 if turbo is not _NoValue: 

443 warnings.warn("Keyword argument 'turbo' is deprecated in favour of '" 

444 "driver=gvd' keyword instead and will be removed in " 

445 "SciPy 1.14.0.", 

446 DeprecationWarning, stacklevel=2) 

447 if eigvals is not _NoValue: 

448 warnings.warn("Keyword argument 'eigvals' is deprecated in favour of " 

449 "'subset_by_index' keyword instead and will be removed " 

450 "in SciPy 1.14.0.", 

451 DeprecationWarning, stacklevel=2) 

452 

453 # set lower 

454 uplo = 'L' if lower else 'U' 

455 # Set job for Fortran routines 

456 _job = 'N' if eigvals_only else 'V' 

457 

458 drv_str = [None, "ev", "evd", "evr", "evx", "gv", "gvd", "gvx"] 

459 if driver not in drv_str: 

460 raise ValueError('"{}" is unknown. Possible values are "None", "{}".' 

461 ''.format(driver, '", "'.join(drv_str[1:]))) 

462 

463 a1 = _asarray_validated(a, check_finite=check_finite) 

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

465 raise ValueError('expected square "a" matrix') 

466 overwrite_a = overwrite_a or (_datacopied(a1, a)) 

467 cplx = True if iscomplexobj(a1) else False 

468 n = a1.shape[0] 

469 drv_args = {'overwrite_a': overwrite_a} 

470 

471 if b is not None: 

472 b1 = _asarray_validated(b, check_finite=check_finite) 

473 overwrite_b = overwrite_b or _datacopied(b1, b) 

474 if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]: 

475 raise ValueError('expected square "b" matrix') 

476 

477 if b1.shape != a1.shape: 

478 raise ValueError("wrong b dimensions {}, should " 

479 "be {}".format(b1.shape, a1.shape)) 

480 

481 if type not in [1, 2, 3]: 

482 raise ValueError('"type" keyword only accepts 1, 2, and 3.') 

483 

484 cplx = True if iscomplexobj(b1) else (cplx or False) 

485 drv_args.update({'overwrite_b': overwrite_b, 'itype': type}) 

486 

487 # backwards-compatibility handling 

488 subset_by_index = subset_by_index if (eigvals in (None, _NoValue)) else eigvals 

489 

490 subset = (subset_by_index is not None) or (subset_by_value is not None) 

491 

492 # Both subsets can't be given 

493 if subset_by_index and subset_by_value: 

494 raise ValueError('Either index or value subset can be requested.') 

495 

496 # Take turbo into account if all conditions are met otherwise ignore 

497 if turbo not in (None, _NoValue) and b is not None: 

498 driver = 'gvx' if subset else 'gvd' 

499 

500 # Check indices if given 

501 if subset_by_index: 

502 lo, hi = (int(x) for x in subset_by_index) 

503 if not (0 <= lo <= hi < n): 

504 raise ValueError('Requested eigenvalue indices are not valid. ' 

505 'Valid range is [0, {}] and start <= end, but ' 

506 'start={}, end={} is given'.format(n-1, lo, hi)) 

507 # fortran is 1-indexed 

508 drv_args.update({'range': 'I', 'il': lo + 1, 'iu': hi + 1}) 

509 

510 if subset_by_value: 

511 lo, hi = subset_by_value 

512 if not (-inf <= lo < hi <= inf): 

513 raise ValueError('Requested eigenvalue bounds are not valid. ' 

514 'Valid range is (-inf, inf) and low < high, but ' 

515 'low={}, high={} is given'.format(lo, hi)) 

516 

517 drv_args.update({'range': 'V', 'vl': lo, 'vu': hi}) 

518 

519 # fix prefix for lapack routines 

520 pfx = 'he' if cplx else 'sy' 

521 

522 # decide on the driver if not given 

523 # first early exit on incompatible choice 

524 if driver: 

525 if b is None and (driver in ["gv", "gvd", "gvx"]): 

526 raise ValueError('{} requires input b array to be supplied ' 

527 'for generalized eigenvalue problems.' 

528 ''.format(driver)) 

529 if (b is not None) and (driver in ['ev', 'evd', 'evr', 'evx']): 

530 raise ValueError('"{}" does not accept input b array ' 

531 'for standard eigenvalue problems.' 

532 ''.format(driver)) 

533 if subset and (driver in ["ev", "evd", "gv", "gvd"]): 

534 raise ValueError('"{}" cannot compute subsets of eigenvalues' 

535 ''.format(driver)) 

536 

537 # Default driver is evr and gvd 

538 else: 

539 driver = "evr" if b is None else ("gvx" if subset else "gvd") 

540 

541 lwork_spec = { 

542 'syevd': ['lwork', 'liwork'], 

543 'syevr': ['lwork', 'liwork'], 

544 'heevd': ['lwork', 'liwork', 'lrwork'], 

545 'heevr': ['lwork', 'lrwork', 'liwork'], 

546 } 

547 

548 if b is None: # Standard problem 

549 drv, drvlw = get_lapack_funcs((pfx + driver, pfx+driver+'_lwork'), 

550 [a1]) 

551 clw_args = {'n': n, 'lower': lower} 

552 if driver == 'evd': 

553 clw_args.update({'compute_v': 0 if _job == "N" else 1}) 

554 

555 lw = _compute_lwork(drvlw, **clw_args) 

556 # Multiple lwork vars 

557 if isinstance(lw, tuple): 

558 lwork_args = dict(zip(lwork_spec[pfx+driver], lw)) 

559 else: 

560 lwork_args = {'lwork': lw} 

561 

562 drv_args.update({'lower': lower, 'compute_v': 0 if _job == "N" else 1}) 

563 w, v, *other_args, info = drv(a=a1, **drv_args, **lwork_args) 

564 

565 else: # Generalized problem 

566 # 'gvd' doesn't have lwork query 

567 if driver == "gvd": 

568 drv = get_lapack_funcs(pfx + "gvd", [a1, b1]) 

569 lwork_args = {} 

570 else: 

571 drv, drvlw = get_lapack_funcs((pfx + driver, pfx+driver+'_lwork'), 

572 [a1, b1]) 

573 # generalized drivers use uplo instead of lower 

574 lw = _compute_lwork(drvlw, n, uplo=uplo) 

575 lwork_args = {'lwork': lw} 

576 

577 drv_args.update({'uplo': uplo, 'jobz': _job}) 

578 

579 w, v, *other_args, info = drv(a=a1, b=b1, **drv_args, **lwork_args) 

580 

581 # m is always the first extra argument 

582 w = w[:other_args[0]] if subset else w 

583 v = v[:, :other_args[0]] if (subset and not eigvals_only) else v 

584 

585 # Check if we had a successful exit 

586 if info == 0: 

587 if eigvals_only: 

588 return w 

589 else: 

590 return w, v 

591 else: 

592 if info < -1: 

593 raise LinAlgError('Illegal value in argument {} of internal {}' 

594 ''.format(-info, drv.typecode + pfx + driver)) 

595 elif info > n: 

596 raise LinAlgError('The leading minor of order {} of B is not ' 

597 'positive definite. The factorization of B ' 

598 'could not be completed and no eigenvalues ' 

599 'or eigenvectors were computed.'.format(info-n)) 

600 else: 

601 drv_err = {'ev': 'The algorithm failed to converge; {} ' 

602 'off-diagonal elements of an intermediate ' 

603 'tridiagonal form did not converge to zero.', 

604 'evx': '{} eigenvectors failed to converge.', 

605 'evd': 'The algorithm failed to compute an eigenvalue ' 

606 'while working on the submatrix lying in rows ' 

607 'and columns {0}/{1} through mod({0},{1}).', 

608 'evr': 'Internal Error.' 

609 } 

610 if driver in ['ev', 'gv']: 

611 msg = drv_err['ev'].format(info) 

612 elif driver in ['evx', 'gvx']: 

613 msg = drv_err['evx'].format(info) 

614 elif driver in ['evd', 'gvd']: 

615 if eigvals_only: 

616 msg = drv_err['ev'].format(info) 

617 else: 

618 msg = drv_err['evd'].format(info, n+1) 

619 else: 

620 msg = drv_err['evr'] 

621 

622 raise LinAlgError(msg) 

623 

624 

625_conv_dict = {0: 0, 1: 1, 2: 2, 

626 'all': 0, 'value': 1, 'index': 2, 

627 'a': 0, 'v': 1, 'i': 2} 

628 

629 

630def _check_select(select, select_range, max_ev, max_len): 

631 """Check that select is valid, convert to Fortran style.""" 

632 if isinstance(select, str): 

633 select = select.lower() 

634 try: 

635 select = _conv_dict[select] 

636 except KeyError as e: 

637 raise ValueError('invalid argument for select') from e 

638 vl, vu = 0., 1. 

639 il = iu = 1 

640 if select != 0: # (non-all) 

641 sr = asarray(select_range) 

642 if sr.ndim != 1 or sr.size != 2 or sr[1] < sr[0]: 

643 raise ValueError('select_range must be a 2-element array-like ' 

644 'in nondecreasing order') 

645 if select == 1: # (value) 

646 vl, vu = sr 

647 if max_ev == 0: 

648 max_ev = max_len 

649 else: # 2 (index) 

650 if sr.dtype.char.lower() not in 'hilqp': 

651 raise ValueError('when using select="i", select_range must ' 

652 'contain integers, got dtype %s (%s)' 

653 % (sr.dtype, sr.dtype.char)) 

654 # translate Python (0 ... N-1) into Fortran (1 ... N) with + 1 

655 il, iu = sr + 1 

656 if min(il, iu) < 1 or max(il, iu) > max_len: 

657 raise ValueError('select_range out of bounds') 

658 max_ev = iu - il + 1 

659 return select, vl, vu, il, iu, max_ev 

660 

661 

662def eig_banded(a_band, lower=False, eigvals_only=False, overwrite_a_band=False, 

663 select='a', select_range=None, max_ev=0, check_finite=True): 

664 """ 

665 Solve real symmetric or complex Hermitian band matrix eigenvalue problem. 

666 

667 Find eigenvalues w and optionally right eigenvectors v of a:: 

668 

669 a v[:,i] = w[i] v[:,i] 

670 v.H v = identity 

671 

672 The matrix a is stored in a_band either in lower diagonal or upper 

673 diagonal ordered form: 

674 

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

676 a_band[ i - j, j] == a[i,j] (if lower form; i >= j) 

677 

678 where u is the number of bands above the diagonal. 

679 

680 Example of a_band (shape of a is (6,6), u=2):: 

681 

682 upper form: 

683 * * a02 a13 a24 a35 

684 * a01 a12 a23 a34 a45 

685 a00 a11 a22 a33 a44 a55 

686 

687 lower form: 

688 a00 a11 a22 a33 a44 a55 

689 a10 a21 a32 a43 a54 * 

690 a20 a31 a42 a53 * * 

691 

692 Cells marked with * are not used. 

693 

694 Parameters 

695 ---------- 

696 a_band : (u+1, M) array_like 

697 The bands of the M by M matrix a. 

698 lower : bool, optional 

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

700 eigvals_only : bool, optional 

701 Compute only the eigenvalues and no eigenvectors. 

702 (Default: calculate also eigenvectors) 

703 overwrite_a_band : bool, optional 

704 Discard data in a_band (may enhance performance) 

705 select : {'a', 'v', 'i'}, optional 

706 Which eigenvalues to calculate 

707 

708 ====== ======================================== 

709 select calculated 

710 ====== ======================================== 

711 'a' All eigenvalues 

712 'v' Eigenvalues in the interval (min, max] 

713 'i' Eigenvalues with indices min <= i <= max 

714 ====== ======================================== 

715 select_range : (min, max), optional 

716 Range of selected eigenvalues 

717 max_ev : int, optional 

718 For select=='v', maximum number of eigenvalues expected. 

719 For other values of select, has no meaning. 

720 

721 In doubt, leave this parameter untouched. 

722 

723 check_finite : bool, optional 

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

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

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

727 

728 Returns 

729 ------- 

730 w : (M,) ndarray 

731 The eigenvalues, in ascending order, each repeated according to its 

732 multiplicity. 

733 v : (M, M) float or complex ndarray 

734 The normalized eigenvector corresponding to the eigenvalue w[i] is 

735 the column v[:,i]. Only returned if ``eigvals_only=False``. 

736 

737 Raises 

738 ------ 

739 LinAlgError 

740 If eigenvalue computation does not converge. 

741 

742 See Also 

743 -------- 

744 eigvals_banded : eigenvalues for symmetric/Hermitian band matrices 

745 eig : eigenvalues and right eigenvectors of general arrays. 

746 eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays 

747 eigh_tridiagonal : eigenvalues and right eigenvectors for 

748 symmetric/Hermitian tridiagonal matrices 

749 

750 Examples 

751 -------- 

752 >>> import numpy as np 

753 >>> from scipy.linalg import eig_banded 

754 >>> A = np.array([[1, 5, 2, 0], [5, 2, 5, 2], [2, 5, 3, 5], [0, 2, 5, 4]]) 

755 >>> Ab = np.array([[1, 2, 3, 4], [5, 5, 5, 0], [2, 2, 0, 0]]) 

756 >>> w, v = eig_banded(Ab, lower=True) 

757 >>> np.allclose(A @ v - v @ np.diag(w), np.zeros((4, 4))) 

758 True 

759 >>> w = eig_banded(Ab, lower=True, eigvals_only=True) 

760 >>> w 

761 array([-4.26200532, -2.22987175, 3.95222349, 12.53965359]) 

762 

763 Request only the eigenvalues between ``[-3, 4]`` 

764 

765 >>> w, v = eig_banded(Ab, lower=True, select='v', select_range=[-3, 4]) 

766 >>> w 

767 array([-2.22987175, 3.95222349]) 

768 

769 """ 

770 if eigvals_only or overwrite_a_band: 

771 a1 = _asarray_validated(a_band, check_finite=check_finite) 

772 overwrite_a_band = overwrite_a_band or (_datacopied(a1, a_band)) 

773 else: 

774 a1 = array(a_band) 

775 if issubclass(a1.dtype.type, inexact) and not isfinite(a1).all(): 

776 raise ValueError("array must not contain infs or NaNs") 

777 overwrite_a_band = 1 

778 

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

780 raise ValueError('expected a 2-D array') 

781 select, vl, vu, il, iu, max_ev = _check_select( 

782 select, select_range, max_ev, a1.shape[1]) 

783 del select_range 

784 if select == 0: 

785 if a1.dtype.char in 'GFD': 

786 # FIXME: implement this somewhen, for now go with builtin values 

787 # FIXME: calc optimal lwork by calling ?hbevd(lwork=-1) 

788 # or by using calc_lwork.f ??? 

789 # lwork = calc_lwork.hbevd(bevd.typecode, a1.shape[0], lower) 

790 internal_name = 'hbevd' 

791 else: # a1.dtype.char in 'fd': 

792 # FIXME: implement this somewhen, for now go with builtin values 

793 # see above 

794 # lwork = calc_lwork.sbevd(bevd.typecode, a1.shape[0], lower) 

795 internal_name = 'sbevd' 

796 bevd, = get_lapack_funcs((internal_name,), (a1,)) 

797 w, v, info = bevd(a1, compute_v=not eigvals_only, 

798 lower=lower, overwrite_ab=overwrite_a_band) 

799 else: # select in [1, 2] 

800 if eigvals_only: 

801 max_ev = 1 

802 # calculate optimal abstol for dsbevx (see manpage) 

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

804 lamch, = get_lapack_funcs(('lamch',), (array(0, dtype='f'),)) 

805 else: 

806 lamch, = get_lapack_funcs(('lamch',), (array(0, dtype='d'),)) 

807 abstol = 2 * lamch('s') 

808 if a1.dtype.char in 'GFD': 

809 internal_name = 'hbevx' 

810 else: # a1.dtype.char in 'gfd' 

811 internal_name = 'sbevx' 

812 bevx, = get_lapack_funcs((internal_name,), (a1,)) 

813 w, v, m, ifail, info = bevx( 

814 a1, vl, vu, il, iu, compute_v=not eigvals_only, mmax=max_ev, 

815 range=select, lower=lower, overwrite_ab=overwrite_a_band, 

816 abstol=abstol) 

817 # crop off w and v 

818 w = w[:m] 

819 if not eigvals_only: 

820 v = v[:, :m] 

821 _check_info(info, internal_name) 

822 

823 if eigvals_only: 

824 return w 

825 return w, v 

826 

827 

828def eigvals(a, b=None, overwrite_a=False, check_finite=True, 

829 homogeneous_eigvals=False): 

830 """ 

831 Compute eigenvalues from an ordinary or generalized eigenvalue problem. 

832 

833 Find eigenvalues of a general matrix:: 

834 

835 a vr[:,i] = w[i] b vr[:,i] 

836 

837 Parameters 

838 ---------- 

839 a : (M, M) array_like 

840 A complex or real matrix whose eigenvalues and eigenvectors 

841 will be computed. 

842 b : (M, M) array_like, optional 

843 Right-hand side matrix in a generalized eigenvalue problem. 

844 If omitted, identity matrix is assumed. 

845 overwrite_a : bool, optional 

846 Whether to overwrite data in a (may improve performance) 

847 check_finite : bool, optional 

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

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

850 (crashes, non-termination) if the inputs do contain infinities 

851 or NaNs. 

852 homogeneous_eigvals : bool, optional 

853 If True, return the eigenvalues in homogeneous coordinates. 

854 In this case ``w`` is a (2, M) array so that:: 

855 

856 w[1,i] a vr[:,i] = w[0,i] b vr[:,i] 

857 

858 Default is False. 

859 

860 Returns 

861 ------- 

862 w : (M,) or (2, M) double or complex ndarray 

863 The eigenvalues, each repeated according to its multiplicity 

864 but not in any specific order. The shape is (M,) unless 

865 ``homogeneous_eigvals=True``. 

866 

867 Raises 

868 ------ 

869 LinAlgError 

870 If eigenvalue computation does not converge 

871 

872 See Also 

873 -------- 

874 eig : eigenvalues and right eigenvectors of general arrays. 

875 eigvalsh : eigenvalues of symmetric or Hermitian arrays 

876 eigvals_banded : eigenvalues for symmetric/Hermitian band matrices 

877 eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal 

878 matrices 

879 

880 Examples 

881 -------- 

882 >>> import numpy as np 

883 >>> from scipy import linalg 

884 >>> a = np.array([[0., -1.], [1., 0.]]) 

885 >>> linalg.eigvals(a) 

886 array([0.+1.j, 0.-1.j]) 

887 

888 >>> b = np.array([[0., 1.], [1., 1.]]) 

889 >>> linalg.eigvals(a, b) 

890 array([ 1.+0.j, -1.+0.j]) 

891 

892 >>> a = np.array([[3., 0., 0.], [0., 8., 0.], [0., 0., 7.]]) 

893 >>> linalg.eigvals(a, homogeneous_eigvals=True) 

894 array([[3.+0.j, 8.+0.j, 7.+0.j], 

895 [1.+0.j, 1.+0.j, 1.+0.j]]) 

896 

897 """ 

898 return eig(a, b=b, left=0, right=0, overwrite_a=overwrite_a, 

899 check_finite=check_finite, 

900 homogeneous_eigvals=homogeneous_eigvals) 

901 

902 

903@_deprecate_positional_args(version="1.14.0") 

904def eigvalsh(a, b=None, *, lower=True, overwrite_a=False, 

905 overwrite_b=False, turbo=_NoValue, eigvals=_NoValue, type=1, 

906 check_finite=True, subset_by_index=None, subset_by_value=None, 

907 driver=None): 

908 """ 

909 Solves a standard or generalized eigenvalue problem for a complex 

910 Hermitian or real symmetric matrix. 

911 

912 Find eigenvalues array ``w`` of array ``a``, where ``b`` is positive 

913 definite such that for every eigenvalue λ (i-th entry of w) and its 

914 eigenvector vi (i-th column of v) satisfies:: 

915 

916 a @ vi = λ * b @ vi 

917 vi.conj().T @ a @ vi = λ 

918 vi.conj().T @ b @ vi = 1 

919 

920 In the standard problem, b is assumed to be the identity matrix. 

921 

922 Parameters 

923 ---------- 

924 a : (M, M) array_like 

925 A complex Hermitian or real symmetric matrix whose eigenvalues will 

926 be computed. 

927 b : (M, M) array_like, optional 

928 A complex Hermitian or real symmetric definite positive matrix in. 

929 If omitted, identity matrix is assumed. 

930 lower : bool, optional 

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

932 triangle of ``a`` and, if applicable, ``b``. (Default: lower) 

933 overwrite_a : bool, optional 

934 Whether to overwrite data in ``a`` (may improve performance). Default 

935 is False. 

936 overwrite_b : bool, optional 

937 Whether to overwrite data in ``b`` (may improve performance). Default 

938 is False. 

939 type : int, optional 

940 For the generalized problems, this keyword specifies the problem type 

941 to be solved for ``w`` and ``v`` (only takes 1, 2, 3 as possible 

942 inputs):: 

943 

944 1 => a @ v = w @ b @ v 

945 2 => a @ b @ v = w @ v 

946 3 => b @ a @ v = w @ v 

947 

948 This keyword is ignored for standard problems. 

949 check_finite : bool, optional 

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

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

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

953 subset_by_index : iterable, optional 

954 If provided, this two-element iterable defines the start and the end 

955 indices of the desired eigenvalues (ascending order and 0-indexed). 

956 To return only the second smallest to fifth smallest eigenvalues, 

957 ``[1, 4]`` is used. ``[n-3, n-1]`` returns the largest three. Only 

958 available with "evr", "evx", and "gvx" drivers. The entries are 

959 directly converted to integers via ``int()``. 

960 subset_by_value : iterable, optional 

961 If provided, this two-element iterable defines the half-open interval 

962 ``(a, b]`` that, if any, only the eigenvalues between these values 

963 are returned. Only available with "evr", "evx", and "gvx" drivers. Use 

964 ``np.inf`` for the unconstrained ends. 

965 driver : str, optional 

966 Defines which LAPACK driver should be used. Valid options are "ev", 

967 "evd", "evr", "evx" for standard problems and "gv", "gvd", "gvx" for 

968 generalized (where b is not None) problems. See the Notes section of 

969 `scipy.linalg.eigh`. 

970 turbo : bool, optional, deprecated 

971 .. deprecated:: 1.5.0 

972 'eigvalsh' keyword argument `turbo` is deprecated in favor of 

973 ``driver=gvd`` option and will be removed in SciPy 1.14.0. 

974 

975 eigvals : tuple (lo, hi), optional 

976 .. deprecated:: 1.5.0 

977 'eigvalsh' keyword argument `eigvals` is deprecated in favor of 

978 `subset_by_index` option and will be removed in SciPy 1.14.0. 

979 

980 Returns 

981 ------- 

982 w : (N,) ndarray 

983 The N (N<=M) selected eigenvalues, in ascending order, each 

984 repeated according to its multiplicity. 

985 

986 Raises 

987 ------ 

988 LinAlgError 

989 If eigenvalue computation does not converge, an error occurred, or 

990 b matrix is not definite positive. Note that if input matrices are 

991 not symmetric or Hermitian, no error will be reported but results will 

992 be wrong. 

993 

994 See Also 

995 -------- 

996 eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays 

997 eigvals : eigenvalues of general arrays 

998 eigvals_banded : eigenvalues for symmetric/Hermitian band matrices 

999 eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal 

1000 matrices 

1001 

1002 Notes 

1003 ----- 

1004 This function does not check the input array for being Hermitian/symmetric 

1005 in order to allow for representing arrays with only their upper/lower 

1006 triangular parts. 

1007 

1008 This function serves as a one-liner shorthand for `scipy.linalg.eigh` with 

1009 the option ``eigvals_only=True`` to get the eigenvalues and not the 

1010 eigenvectors. Here it is kept as a legacy convenience. It might be 

1011 beneficial to use the main function to have full control and to be a bit 

1012 more pythonic. 

1013 

1014 Examples 

1015 -------- 

1016 For more examples see `scipy.linalg.eigh`. 

1017 

1018 >>> import numpy as np 

1019 >>> from scipy.linalg import eigvalsh 

1020 >>> A = np.array([[6, 3, 1, 5], [3, 0, 5, 1], [1, 5, 6, 2], [5, 1, 2, 2]]) 

1021 >>> w = eigvalsh(A) 

1022 >>> w 

1023 array([-3.74637491, -0.76263923, 6.08502336, 12.42399079]) 

1024 

1025 """ 

1026 return eigh(a, b=b, lower=lower, eigvals_only=True, 

1027 overwrite_a=overwrite_a, overwrite_b=overwrite_b, 

1028 turbo=turbo, eigvals=eigvals, type=type, 

1029 check_finite=check_finite, subset_by_index=subset_by_index, 

1030 subset_by_value=subset_by_value, driver=driver) 

1031 

1032 

1033def eigvals_banded(a_band, lower=False, overwrite_a_band=False, 

1034 select='a', select_range=None, check_finite=True): 

1035 """ 

1036 Solve real symmetric or complex Hermitian band matrix eigenvalue problem. 

1037 

1038 Find eigenvalues w of a:: 

1039 

1040 a v[:,i] = w[i] v[:,i] 

1041 v.H v = identity 

1042 

1043 The matrix a is stored in a_band either in lower diagonal or upper 

1044 diagonal ordered form: 

1045 

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

1047 a_band[ i - j, j] == a[i,j] (if lower form; i >= j) 

1048 

1049 where u is the number of bands above the diagonal. 

1050 

1051 Example of a_band (shape of a is (6,6), u=2):: 

1052 

1053 upper form: 

1054 * * a02 a13 a24 a35 

1055 * a01 a12 a23 a34 a45 

1056 a00 a11 a22 a33 a44 a55 

1057 

1058 lower form: 

1059 a00 a11 a22 a33 a44 a55 

1060 a10 a21 a32 a43 a54 * 

1061 a20 a31 a42 a53 * * 

1062 

1063 Cells marked with * are not used. 

1064 

1065 Parameters 

1066 ---------- 

1067 a_band : (u+1, M) array_like 

1068 The bands of the M by M matrix a. 

1069 lower : bool, optional 

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

1071 overwrite_a_band : bool, optional 

1072 Discard data in a_band (may enhance performance) 

1073 select : {'a', 'v', 'i'}, optional 

1074 Which eigenvalues to calculate 

1075 

1076 ====== ======================================== 

1077 select calculated 

1078 ====== ======================================== 

1079 'a' All eigenvalues 

1080 'v' Eigenvalues in the interval (min, max] 

1081 'i' Eigenvalues with indices min <= i <= max 

1082 ====== ======================================== 

1083 select_range : (min, max), optional 

1084 Range of selected eigenvalues 

1085 check_finite : bool, optional 

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

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

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

1089 

1090 Returns 

1091 ------- 

1092 w : (M,) ndarray 

1093 The eigenvalues, in ascending order, each repeated according to its 

1094 multiplicity. 

1095 

1096 Raises 

1097 ------ 

1098 LinAlgError 

1099 If eigenvalue computation does not converge. 

1100 

1101 See Also 

1102 -------- 

1103 eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian 

1104 band matrices 

1105 eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal 

1106 matrices 

1107 eigvals : eigenvalues of general arrays 

1108 eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays 

1109 eig : eigenvalues and right eigenvectors for non-symmetric arrays 

1110 

1111 Examples 

1112 -------- 

1113 >>> import numpy as np 

1114 >>> from scipy.linalg import eigvals_banded 

1115 >>> A = np.array([[1, 5, 2, 0], [5, 2, 5, 2], [2, 5, 3, 5], [0, 2, 5, 4]]) 

1116 >>> Ab = np.array([[1, 2, 3, 4], [5, 5, 5, 0], [2, 2, 0, 0]]) 

1117 >>> w = eigvals_banded(Ab, lower=True) 

1118 >>> w 

1119 array([-4.26200532, -2.22987175, 3.95222349, 12.53965359]) 

1120 """ 

1121 return eig_banded(a_band, lower=lower, eigvals_only=1, 

1122 overwrite_a_band=overwrite_a_band, select=select, 

1123 select_range=select_range, check_finite=check_finite) 

1124 

1125 

1126def eigvalsh_tridiagonal(d, e, select='a', select_range=None, 

1127 check_finite=True, tol=0., lapack_driver='auto'): 

1128 """ 

1129 Solve eigenvalue problem for a real symmetric tridiagonal matrix. 

1130 

1131 Find eigenvalues `w` of ``a``:: 

1132 

1133 a v[:,i] = w[i] v[:,i] 

1134 v.H v = identity 

1135 

1136 For a real symmetric matrix ``a`` with diagonal elements `d` and 

1137 off-diagonal elements `e`. 

1138 

1139 Parameters 

1140 ---------- 

1141 d : ndarray, shape (ndim,) 

1142 The diagonal elements of the array. 

1143 e : ndarray, shape (ndim-1,) 

1144 The off-diagonal elements of the array. 

1145 select : {'a', 'v', 'i'}, optional 

1146 Which eigenvalues to calculate 

1147 

1148 ====== ======================================== 

1149 select calculated 

1150 ====== ======================================== 

1151 'a' All eigenvalues 

1152 'v' Eigenvalues in the interval (min, max] 

1153 'i' Eigenvalues with indices min <= i <= max 

1154 ====== ======================================== 

1155 select_range : (min, max), optional 

1156 Range of selected eigenvalues 

1157 check_finite : bool, optional 

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

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

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

1161 tol : float 

1162 The absolute tolerance to which each eigenvalue is required 

1163 (only used when ``lapack_driver='stebz'``). 

1164 An eigenvalue (or cluster) is considered to have converged if it 

1165 lies in an interval of this width. If <= 0. (default), 

1166 the value ``eps*|a|`` is used where eps is the machine precision, 

1167 and ``|a|`` is the 1-norm of the matrix ``a``. 

1168 lapack_driver : str 

1169 LAPACK function to use, can be 'auto', 'stemr', 'stebz', 'sterf', 

1170 or 'stev'. When 'auto' (default), it will use 'stemr' if ``select='a'`` 

1171 and 'stebz' otherwise. 'sterf' and 'stev' can only be used when 

1172 ``select='a'``. 

1173 

1174 Returns 

1175 ------- 

1176 w : (M,) ndarray 

1177 The eigenvalues, in ascending order, each repeated according to its 

1178 multiplicity. 

1179 

1180 Raises 

1181 ------ 

1182 LinAlgError 

1183 If eigenvalue computation does not converge. 

1184 

1185 See Also 

1186 -------- 

1187 eigh_tridiagonal : eigenvalues and right eiegenvectors for 

1188 symmetric/Hermitian tridiagonal matrices 

1189 

1190 Examples 

1191 -------- 

1192 >>> import numpy as np 

1193 >>> from scipy.linalg import eigvalsh_tridiagonal, eigvalsh 

1194 >>> d = 3*np.ones(4) 

1195 >>> e = -1*np.ones(3) 

1196 >>> w = eigvalsh_tridiagonal(d, e) 

1197 >>> A = np.diag(d) + np.diag(e, k=1) + np.diag(e, k=-1) 

1198 >>> w2 = eigvalsh(A) # Verify with other eigenvalue routines 

1199 >>> np.allclose(w - w2, np.zeros(4)) 

1200 True 

1201 """ 

1202 return eigh_tridiagonal( 

1203 d, e, eigvals_only=True, select=select, select_range=select_range, 

1204 check_finite=check_finite, tol=tol, lapack_driver=lapack_driver) 

1205 

1206 

1207def eigh_tridiagonal(d, e, eigvals_only=False, select='a', select_range=None, 

1208 check_finite=True, tol=0., lapack_driver='auto'): 

1209 """ 

1210 Solve eigenvalue problem for a real symmetric tridiagonal matrix. 

1211 

1212 Find eigenvalues `w` and optionally right eigenvectors `v` of ``a``:: 

1213 

1214 a v[:,i] = w[i] v[:,i] 

1215 v.H v = identity 

1216 

1217 For a real symmetric matrix ``a`` with diagonal elements `d` and 

1218 off-diagonal elements `e`. 

1219 

1220 Parameters 

1221 ---------- 

1222 d : ndarray, shape (ndim,) 

1223 The diagonal elements of the array. 

1224 e : ndarray, shape (ndim-1,) 

1225 The off-diagonal elements of the array. 

1226 eigvals_only : bool, optional 

1227 Compute only the eigenvalues and no eigenvectors. 

1228 (Default: calculate also eigenvectors) 

1229 select : {'a', 'v', 'i'}, optional 

1230 Which eigenvalues to calculate 

1231 

1232 ====== ======================================== 

1233 select calculated 

1234 ====== ======================================== 

1235 'a' All eigenvalues 

1236 'v' Eigenvalues in the interval (min, max] 

1237 'i' Eigenvalues with indices min <= i <= max 

1238 ====== ======================================== 

1239 select_range : (min, max), optional 

1240 Range of selected eigenvalues 

1241 check_finite : bool, optional 

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

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

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

1245 tol : float 

1246 The absolute tolerance to which each eigenvalue is required 

1247 (only used when 'stebz' is the `lapack_driver`). 

1248 An eigenvalue (or cluster) is considered to have converged if it 

1249 lies in an interval of this width. If <= 0. (default), 

1250 the value ``eps*|a|`` is used where eps is the machine precision, 

1251 and ``|a|`` is the 1-norm of the matrix ``a``. 

1252 lapack_driver : str 

1253 LAPACK function to use, can be 'auto', 'stemr', 'stebz', 'sterf', 

1254 or 'stev'. When 'auto' (default), it will use 'stemr' if ``select='a'`` 

1255 and 'stebz' otherwise. When 'stebz' is used to find the eigenvalues and 

1256 ``eigvals_only=False``, then a second LAPACK call (to ``?STEIN``) is 

1257 used to find the corresponding eigenvectors. 'sterf' can only be 

1258 used when ``eigvals_only=True`` and ``select='a'``. 'stev' can only 

1259 be used when ``select='a'``. 

1260 

1261 Returns 

1262 ------- 

1263 w : (M,) ndarray 

1264 The eigenvalues, in ascending order, each repeated according to its 

1265 multiplicity. 

1266 v : (M, M) ndarray 

1267 The normalized eigenvector corresponding to the eigenvalue ``w[i]`` is 

1268 the column ``v[:,i]``. Only returned if ``eigvals_only=False``. 

1269 

1270 Raises 

1271 ------ 

1272 LinAlgError 

1273 If eigenvalue computation does not converge. 

1274 

1275 See Also 

1276 -------- 

1277 eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal 

1278 matrices 

1279 eig : eigenvalues and right eigenvectors for non-symmetric arrays 

1280 eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays 

1281 eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian 

1282 band matrices 

1283 

1284 Notes 

1285 ----- 

1286 This function makes use of LAPACK ``S/DSTEMR`` routines. 

1287 

1288 Examples 

1289 -------- 

1290 >>> import numpy as np 

1291 >>> from scipy.linalg import eigh_tridiagonal 

1292 >>> d = 3*np.ones(4) 

1293 >>> e = -1*np.ones(3) 

1294 >>> w, v = eigh_tridiagonal(d, e) 

1295 >>> A = np.diag(d) + np.diag(e, k=1) + np.diag(e, k=-1) 

1296 >>> np.allclose(A @ v - v @ np.diag(w), np.zeros((4, 4))) 

1297 True 

1298 """ 

1299 d = _asarray_validated(d, check_finite=check_finite) 

1300 e = _asarray_validated(e, check_finite=check_finite) 

1301 for check in (d, e): 

1302 if check.ndim != 1: 

1303 raise ValueError('expected a 1-D array') 

1304 if check.dtype.char in 'GFD': # complex 

1305 raise TypeError('Only real arrays currently supported') 

1306 if d.size != e.size + 1: 

1307 raise ValueError('d (%s) must have one more element than e (%s)' 

1308 % (d.size, e.size)) 

1309 select, vl, vu, il, iu, _ = _check_select( 

1310 select, select_range, 0, d.size) 

1311 if not isinstance(lapack_driver, str): 

1312 raise TypeError('lapack_driver must be str') 

1313 drivers = ('auto', 'stemr', 'sterf', 'stebz', 'stev') 

1314 if lapack_driver not in drivers: 

1315 raise ValueError('lapack_driver must be one of %s, got %s' 

1316 % (drivers, lapack_driver)) 

1317 if lapack_driver == 'auto': 

1318 lapack_driver = 'stemr' if select == 0 else 'stebz' 

1319 func, = get_lapack_funcs((lapack_driver,), (d, e)) 

1320 compute_v = not eigvals_only 

1321 if lapack_driver == 'sterf': 

1322 if select != 0: 

1323 raise ValueError('sterf can only be used when select == "a"') 

1324 if not eigvals_only: 

1325 raise ValueError('sterf can only be used when eigvals_only is ' 

1326 'True') 

1327 w, info = func(d, e) 

1328 m = len(w) 

1329 elif lapack_driver == 'stev': 

1330 if select != 0: 

1331 raise ValueError('stev can only be used when select == "a"') 

1332 w, v, info = func(d, e, compute_v=compute_v) 

1333 m = len(w) 

1334 elif lapack_driver == 'stebz': 

1335 tol = float(tol) 

1336 internal_name = 'stebz' 

1337 stebz, = get_lapack_funcs((internal_name,), (d, e)) 

1338 # If getting eigenvectors, needs to be block-ordered (B) instead of 

1339 # matrix-ordered (E), and we will reorder later 

1340 order = 'E' if eigvals_only else 'B' 

1341 m, w, iblock, isplit, info = stebz(d, e, select, vl, vu, il, iu, tol, 

1342 order) 

1343 else: # 'stemr' 

1344 # ?STEMR annoyingly requires size N instead of N-1 

1345 e_ = empty(e.size+1, e.dtype) 

1346 e_[:-1] = e 

1347 stemr_lwork, = get_lapack_funcs(('stemr_lwork',), (d, e)) 

1348 lwork, liwork, info = stemr_lwork(d, e_, select, vl, vu, il, iu, 

1349 compute_v=compute_v) 

1350 _check_info(info, 'stemr_lwork') 

1351 m, w, v, info = func(d, e_, select, vl, vu, il, iu, 

1352 compute_v=compute_v, lwork=lwork, liwork=liwork) 

1353 _check_info(info, lapack_driver + ' (eigh_tridiagonal)') 

1354 w = w[:m] 

1355 if eigvals_only: 

1356 return w 

1357 else: 

1358 # Do we still need to compute the eigenvalues? 

1359 if lapack_driver == 'stebz': 

1360 func, = get_lapack_funcs(('stein',), (d, e)) 

1361 v, info = func(d, e, w, iblock, isplit) 

1362 _check_info(info, 'stein (eigh_tridiagonal)', 

1363 positive='%d eigenvectors failed to converge') 

1364 # Convert block-order to matrix-order 

1365 order = argsort(w) 

1366 w, v = w[order], v[:, order] 

1367 else: 

1368 v = v[:, :m] 

1369 return w, v 

1370 

1371 

1372def _check_info(info, driver, positive='did not converge (LAPACK info=%d)'): 

1373 """Check info return value.""" 

1374 if info < 0: 

1375 raise ValueError('illegal value in argument %d of internal %s' 

1376 % (-info, driver)) 

1377 if info > 0 and positive: 

1378 raise LinAlgError(("%s " + positive) % (driver, info,)) 

1379 

1380 

1381def hessenberg(a, calc_q=False, overwrite_a=False, check_finite=True): 

1382 """ 

1383 Compute Hessenberg form of a matrix. 

1384 

1385 The Hessenberg decomposition is:: 

1386 

1387 A = Q H Q^H 

1388 

1389 where `Q` is unitary/orthogonal and `H` has only zero elements below 

1390 the first sub-diagonal. 

1391 

1392 Parameters 

1393 ---------- 

1394 a : (M, M) array_like 

1395 Matrix to bring into Hessenberg form. 

1396 calc_q : bool, optional 

1397 Whether to compute the transformation matrix. Default is False. 

1398 overwrite_a : bool, optional 

1399 Whether to overwrite `a`; may improve performance. 

1400 Default is False. 

1401 check_finite : bool, optional 

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

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

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

1405 

1406 Returns 

1407 ------- 

1408 H : (M, M) ndarray 

1409 Hessenberg form of `a`. 

1410 Q : (M, M) ndarray 

1411 Unitary/orthogonal similarity transformation matrix ``A = Q H Q^H``. 

1412 Only returned if ``calc_q=True``. 

1413 

1414 Examples 

1415 -------- 

1416 >>> import numpy as np 

1417 >>> from scipy.linalg import hessenberg 

1418 >>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]]) 

1419 >>> H, Q = hessenberg(A, calc_q=True) 

1420 >>> H 

1421 array([[ 2. , -11.65843866, 1.42005301, 0.25349066], 

1422 [ -9.94987437, 14.53535354, -5.31022304, 2.43081618], 

1423 [ 0. , -1.83299243, 0.38969961, -0.51527034], 

1424 [ 0. , 0. , -3.83189513, 1.07494686]]) 

1425 >>> np.allclose(Q @ H @ Q.conj().T - A, np.zeros((4, 4))) 

1426 True 

1427 """ 

1428 a1 = _asarray_validated(a, check_finite=check_finite) 

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

1430 raise ValueError('expected square matrix') 

1431 overwrite_a = overwrite_a or (_datacopied(a1, a)) 

1432 

1433 # if 2x2 or smaller: already in Hessenberg 

1434 if a1.shape[0] <= 2: 

1435 if calc_q: 

1436 return a1, eye(a1.shape[0]) 

1437 return a1 

1438 

1439 gehrd, gebal, gehrd_lwork = get_lapack_funcs(('gehrd', 'gebal', 

1440 'gehrd_lwork'), (a1,)) 

1441 ba, lo, hi, pivscale, info = gebal(a1, permute=0, overwrite_a=overwrite_a) 

1442 _check_info(info, 'gebal (hessenberg)', positive=False) 

1443 n = len(a1) 

1444 

1445 lwork = _compute_lwork(gehrd_lwork, ba.shape[0], lo=lo, hi=hi) 

1446 

1447 hq, tau, info = gehrd(ba, lo=lo, hi=hi, lwork=lwork, overwrite_a=1) 

1448 _check_info(info, 'gehrd (hessenberg)', positive=False) 

1449 h = numpy.triu(hq, -1) 

1450 if not calc_q: 

1451 return h 

1452 

1453 # use orghr/unghr to compute q 

1454 orghr, orghr_lwork = get_lapack_funcs(('orghr', 'orghr_lwork'), (a1,)) 

1455 lwork = _compute_lwork(orghr_lwork, n, lo=lo, hi=hi) 

1456 

1457 q, info = orghr(a=hq, tau=tau, lo=lo, hi=hi, lwork=lwork, overwrite_a=1) 

1458 _check_info(info, 'orghr (hessenberg)', positive=False) 

1459 return h, q 

1460 

1461 

1462def cdf2rdf(w, v): 

1463 """ 

1464 Converts complex eigenvalues ``w`` and eigenvectors ``v`` to real 

1465 eigenvalues in a block diagonal form ``wr`` and the associated real 

1466 eigenvectors ``vr``, such that:: 

1467 

1468 vr @ wr = X @ vr 

1469 

1470 continues to hold, where ``X`` is the original array for which ``w`` and 

1471 ``v`` are the eigenvalues and eigenvectors. 

1472 

1473 .. versionadded:: 1.1.0 

1474 

1475 Parameters 

1476 ---------- 

1477 w : (..., M) array_like 

1478 Complex or real eigenvalues, an array or stack of arrays 

1479 

1480 Conjugate pairs must not be interleaved, else the wrong result 

1481 will be produced. So ``[1+1j, 1, 1-1j]`` will give a correct result, 

1482 but ``[1+1j, 2+1j, 1-1j, 2-1j]`` will not. 

1483 

1484 v : (..., M, M) array_like 

1485 Complex or real eigenvectors, a square array or stack of square arrays. 

1486 

1487 Returns 

1488 ------- 

1489 wr : (..., M, M) ndarray 

1490 Real diagonal block form of eigenvalues 

1491 vr : (..., M, M) ndarray 

1492 Real eigenvectors associated with ``wr`` 

1493 

1494 See Also 

1495 -------- 

1496 eig : Eigenvalues and right eigenvectors for non-symmetric arrays 

1497 rsf2csf : Convert real Schur form to complex Schur form 

1498 

1499 Notes 

1500 ----- 

1501 ``w``, ``v`` must be the eigenstructure for some *real* matrix ``X``. 

1502 For example, obtained by ``w, v = scipy.linalg.eig(X)`` or 

1503 ``w, v = numpy.linalg.eig(X)`` in which case ``X`` can also represent 

1504 stacked arrays. 

1505 

1506 .. versionadded:: 1.1.0 

1507 

1508 Examples 

1509 -------- 

1510 >>> import numpy as np 

1511 >>> X = np.array([[1, 2, 3], [0, 4, 5], [0, -5, 4]]) 

1512 >>> X 

1513 array([[ 1, 2, 3], 

1514 [ 0, 4, 5], 

1515 [ 0, -5, 4]]) 

1516 

1517 >>> from scipy import linalg 

1518 >>> w, v = linalg.eig(X) 

1519 >>> w 

1520 array([ 1.+0.j, 4.+5.j, 4.-5.j]) 

1521 >>> v 

1522 array([[ 1.00000+0.j , -0.01906-0.40016j, -0.01906+0.40016j], 

1523 [ 0.00000+0.j , 0.00000-0.64788j, 0.00000+0.64788j], 

1524 [ 0.00000+0.j , 0.64788+0.j , 0.64788-0.j ]]) 

1525 

1526 >>> wr, vr = linalg.cdf2rdf(w, v) 

1527 >>> wr 

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

1529 [ 0., 4., 5.], 

1530 [ 0., -5., 4.]]) 

1531 >>> vr 

1532 array([[ 1. , 0.40016, -0.01906], 

1533 [ 0. , 0.64788, 0. ], 

1534 [ 0. , 0. , 0.64788]]) 

1535 

1536 >>> vr @ wr 

1537 array([[ 1. , 1.69593, 1.9246 ], 

1538 [ 0. , 2.59153, 3.23942], 

1539 [ 0. , -3.23942, 2.59153]]) 

1540 >>> X @ vr 

1541 array([[ 1. , 1.69593, 1.9246 ], 

1542 [ 0. , 2.59153, 3.23942], 

1543 [ 0. , -3.23942, 2.59153]]) 

1544 """ 

1545 w, v = _asarray_validated(w), _asarray_validated(v) 

1546 

1547 # check dimensions 

1548 if w.ndim < 1: 

1549 raise ValueError('expected w to be at least 1D') 

1550 if v.ndim < 2: 

1551 raise ValueError('expected v to be at least 2D') 

1552 if v.ndim != w.ndim + 1: 

1553 raise ValueError('expected eigenvectors array to have exactly one ' 

1554 'dimension more than eigenvalues array') 

1555 

1556 # check shapes 

1557 n = w.shape[-1] 

1558 M = w.shape[:-1] 

1559 if v.shape[-2] != v.shape[-1]: 

1560 raise ValueError('expected v to be a square matrix or stacked square ' 

1561 'matrices: v.shape[-2] = v.shape[-1]') 

1562 if v.shape[-1] != n: 

1563 raise ValueError('expected the same number of eigenvalues as ' 

1564 'eigenvectors') 

1565 

1566 # get indices for each first pair of complex eigenvalues 

1567 complex_mask = iscomplex(w) 

1568 n_complex = complex_mask.sum(axis=-1) 

1569 

1570 # check if all complex eigenvalues have conjugate pairs 

1571 if not (n_complex % 2 == 0).all(): 

1572 raise ValueError('expected complex-conjugate pairs of eigenvalues') 

1573 

1574 # find complex indices 

1575 idx = nonzero(complex_mask) 

1576 idx_stack = idx[:-1] 

1577 idx_elem = idx[-1] 

1578 

1579 # filter them to conjugate indices, assuming pairs are not interleaved 

1580 j = idx_elem[0::2] 

1581 k = idx_elem[1::2] 

1582 stack_ind = () 

1583 for i in idx_stack: 

1584 # should never happen, assuming nonzero orders by the last axis 

1585 assert (i[0::2] == i[1::2]).all(),\ 

1586 "Conjugate pair spanned different arrays!" 

1587 stack_ind += (i[0::2],) 

1588 

1589 # all eigenvalues to diagonal form 

1590 wr = zeros(M + (n, n), dtype=w.real.dtype) 

1591 di = range(n) 

1592 wr[..., di, di] = w.real 

1593 

1594 # complex eigenvalues to real block diagonal form 

1595 wr[stack_ind + (j, k)] = w[stack_ind + (j,)].imag 

1596 wr[stack_ind + (k, j)] = w[stack_ind + (k,)].imag 

1597 

1598 # compute real eigenvectors associated with real block diagonal eigenvalues 

1599 u = zeros(M + (n, n), dtype=numpy.cdouble) 

1600 u[..., di, di] = 1.0 

1601 u[stack_ind + (j, j)] = 0.5j 

1602 u[stack_ind + (j, k)] = 0.5 

1603 u[stack_ind + (k, j)] = -0.5j 

1604 u[stack_ind + (k, k)] = 0.5 

1605 

1606 # multipy matrices v and u (equivalent to v @ u) 

1607 vr = einsum('...ij,...jk->...ik', v, u).real 

1608 

1609 return wr, vr