Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scipy/linalg/_decomp.py: 6%

390 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-12 06:31 +0000

1# -*- coding: utf-8 -*- 

2# 

3# Author: Pearu Peterson, March 2002 

4# 

5# additions by Travis Oliphant, March 2002 

6# additions by Eric Jones, June 2002 

7# additions by Johannes Loehnert, June 2006 

8# additions by Bart Vandereycken, June 2006 

9# additions by Andrew D Straw, May 2007 

10# additions by Tiziano Zito, November 2008 

11# 

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

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

14# eigenstuff and for the Hessenberg form. 

15 

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

17 'eig_banded', 'eigvals_banded', 

18 'eigh_tridiagonal', 'eigvalsh_tridiagonal', 'hessenberg', 'cdf2rdf'] 

19 

20import warnings 

21 

22import numpy 

23from numpy import (array, isfinite, inexact, nonzero, iscomplexobj, cast, 

24 flatnonzero, conj, asarray, argsort, empty, 

25 iscomplex, zeros, einsum, eye, inf) 

26# Local imports 

27from scipy._lib._util import _asarray_validated 

28from ._misc import LinAlgError, _datacopied, norm 

29from .lapack import get_lapack_funcs, _compute_lwork 

30 

31 

32_I = cast['F'](1j) 

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 

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

271 overwrite_b=False, turbo=False, eigvals=None, type=1, 

272 check_finite=True, subset_by_index=None, subset_by_value=None, 

273 driver=None): 

274 """ 

275 Solve a standard or generalized eigenvalue problem for a complex 

276 Hermitian or real symmetric matrix. 

277 

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

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

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

281 ``v``) satisfies:: 

282 

283 a @ vi = λ * b @ vi 

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

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

286 

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

288 

289 Parameters 

290 ---------- 

291 a : (M, M) array_like 

292 A complex Hermitian or real symmetric matrix whose eigenvalues and 

293 eigenvectors will be computed. 

294 b : (M, M) array_like, optional 

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

296 If omitted, identity matrix is assumed. 

297 lower : bool, optional 

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

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

300 eigvals_only : bool, optional 

301 Whether to calculate only eigenvalues and no eigenvectors. 

302 (Default: both are calculated) 

303 subset_by_index : iterable, optional 

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

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

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

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

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

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

310 subset_by_value : iterable, optional 

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

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

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

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

315 driver : str, optional 

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

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

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

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

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

321 type : int, optional 

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

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

324 inputs):: 

325 

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

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

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

329 

330 This keyword is ignored for standard problems. 

331 overwrite_a : bool, optional 

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

333 is False. 

334 overwrite_b : bool, optional 

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

336 is False. 

337 check_finite : bool, optional 

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

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

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

341 turbo : bool, optional, deprecated 

342 .. deprecated:: 1.5.0 

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

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

345 1.12.0. 

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

347 .. deprecated:: 1.5.0 

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

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

350 1.12.0. 

351 

352 Returns 

353 ------- 

354 w : (N,) ndarray 

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

356 repeated according to its multiplicity. 

357 v : (M, N) ndarray 

358 (if ``eigvals_only == False``) 

359 

360 Raises 

361 ------ 

362 LinAlgError 

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

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

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

366 be wrong. 

367 

368 See Also 

369 -------- 

370 eigvalsh : eigenvalues of symmetric or Hermitian arrays 

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

372 eigh_tridiagonal : eigenvalues and right eiegenvectors for 

373 symmetric/Hermitian tridiagonal matrices 

374 

375 Notes 

376 ----- 

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

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

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

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

381 keyword. 

382 

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

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

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

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

387 etc. 

388 

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

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

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

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

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

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

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

396 

397 

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

399 type argument:: 

400 

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

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

403 

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

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

406 

407 

408 Examples 

409 -------- 

410 >>> import numpy as np 

411 >>> from scipy.linalg import eigh 

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

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

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

415 True 

416 

417 Request only the eigenvalues 

418 

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

420 

421 Request eigenvalues that are less than 10. 

422 

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

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

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

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

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

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

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

430 

431 Request the second smallest eigenvalue and its eigenvector 

432 

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

434 >>> w 

435 array([9.11938152]) 

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

437 (5, 1) 

438 

439 """ 

440 if turbo: 

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

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

443 "SciPy 1.12.0.", 

444 DeprecationWarning, stacklevel=2) 

445 if eigvals: 

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

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

448 "in SciPy 1.12.0.", 

449 DeprecationWarning, stacklevel=2) 

450 

451 # set lower 

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

453 # Set job for Fortran routines 

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

455 

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

457 if driver not in drv_str: 

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

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

460 

461 a1 = _asarray_validated(a, check_finite=check_finite) 

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

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

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

465 cplx = True if iscomplexobj(a1) else False 

466 n = a1.shape[0] 

467 drv_args = {'overwrite_a': overwrite_a} 

468 

469 if b is not None: 

470 b1 = _asarray_validated(b, check_finite=check_finite) 

471 overwrite_b = overwrite_b or _datacopied(b1, b) 

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

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

474 

475 if b1.shape != a1.shape: 

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

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

478 

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

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

481 

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

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

484 

485 # backwards-compatibility handling 

486 subset_by_index = subset_by_index if (eigvals is None) else eigvals 

487 

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

489 

490 # Both subsets can't be given 

491 if subset_by_index and subset_by_value: 

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

493 

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

495 if turbo and b is not None: 

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

497 

498 # Check indices if given 

499 if subset_by_index: 

500 lo, hi = [int(x) for x in subset_by_index] 

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

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

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

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

505 # fortran is 1-indexed 

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

507 

508 if subset_by_value: 

509 lo, hi = subset_by_value 

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

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

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

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

514 

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

516 

517 # fix prefix for lapack routines 

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

519 

520 # decide on the driver if not given 

521 # first early exit on incompatible choice 

522 if driver: 

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

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

525 'for generalized eigenvalue problems.' 

526 ''.format(driver)) 

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

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

529 'for standard eigenvalue problems.' 

530 ''.format(driver)) 

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

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

533 ''.format(driver)) 

534 

535 # Default driver is evr and gvd 

536 else: 

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

538 

539 lwork_spec = { 

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

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

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

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

544 } 

545 

546 if b is None: # Standard problem 

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

548 [a1]) 

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

550 if driver == 'evd': 

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

552 

553 lw = _compute_lwork(drvlw, **clw_args) 

554 # Multiple lwork vars 

555 if isinstance(lw, tuple): 

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

557 else: 

558 lwork_args = {'lwork': lw} 

559 

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

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

562 

563 else: # Generalized problem 

564 # 'gvd' doesn't have lwork query 

565 if driver == "gvd": 

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

567 lwork_args = {} 

568 else: 

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

570 [a1, b1]) 

571 # generalized drivers use uplo instead of lower 

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

573 lwork_args = {'lwork': lw} 

574 

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

576 

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

578 

579 # m is always the first extra argument 

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

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

582 

583 # Check if we had a successful exit 

584 if info == 0: 

585 if eigvals_only: 

586 return w 

587 else: 

588 return w, v 

589 else: 

590 if info < -1: 

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

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

593 elif info > n: 

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

595 'positive definite. The factorization of B ' 

596 'could not be completed and no eigenvalues ' 

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

598 else: 

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

600 'off-diagonal elements of an intermediate ' 

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

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

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

604 'while working on the submatrix lying in rows ' 

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

606 'evr': 'Internal Error.' 

607 } 

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

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

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

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

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

613 if eigvals_only: 

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

615 else: 

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

617 else: 

618 msg = drv_err['evr'] 

619 

620 raise LinAlgError(msg) 

621 

622 

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

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

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

626 

627 

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

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

630 if isinstance(select, str): 

631 select = select.lower() 

632 try: 

633 select = _conv_dict[select] 

634 except KeyError as e: 

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

636 vl, vu = 0., 1. 

637 il = iu = 1 

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

639 sr = asarray(select_range) 

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

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

642 'in nondecreasing order') 

643 if select == 1: # (value) 

644 vl, vu = sr 

645 if max_ev == 0: 

646 max_ev = max_len 

647 else: # 2 (index) 

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

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

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

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

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

653 il, iu = sr + 1 

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

655 raise ValueError('select_range out of bounds') 

656 max_ev = iu - il + 1 

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

658 

659 

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

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

662 """ 

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

664 

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

666 

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

668 v.H v = identity 

669 

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

671 diagonal ordered form: 

672 

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

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

675 

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

677 

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

679 

680 upper form: 

681 * * a02 a13 a24 a35 

682 * a01 a12 a23 a34 a45 

683 a00 a11 a22 a33 a44 a55 

684 

685 lower form: 

686 a00 a11 a22 a33 a44 a55 

687 a10 a21 a32 a43 a54 * 

688 a20 a31 a42 a53 * * 

689 

690 Cells marked with * are not used. 

691 

692 Parameters 

693 ---------- 

694 a_band : (u+1, M) array_like 

695 The bands of the M by M matrix a. 

696 lower : bool, optional 

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

698 eigvals_only : bool, optional 

699 Compute only the eigenvalues and no eigenvectors. 

700 (Default: calculate also eigenvectors) 

701 overwrite_a_band : bool, optional 

702 Discard data in a_band (may enhance performance) 

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

704 Which eigenvalues to calculate 

705 

706 ====== ======================================== 

707 select calculated 

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

709 'a' All eigenvalues 

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

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

712 ====== ======================================== 

713 select_range : (min, max), optional 

714 Range of selected eigenvalues 

715 max_ev : int, optional 

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

717 For other values of select, has no meaning. 

718 

719 In doubt, leave this parameter untouched. 

720 

721 check_finite : bool, optional 

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

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

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

725 

726 Returns 

727 ------- 

728 w : (M,) ndarray 

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

730 multiplicity. 

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

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

733 the column v[:,i]. 

734 

735 Raises 

736 ------ 

737 LinAlgError 

738 If eigenvalue computation does not converge. 

739 

740 See Also 

741 -------- 

742 eigvals_banded : eigenvalues for symmetric/Hermitian band matrices 

743 eig : eigenvalues and right eigenvectors of general arrays. 

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

745 eigh_tridiagonal : eigenvalues and right eigenvectors for 

746 symmetric/Hermitian tridiagonal matrices 

747 

748 Examples 

749 -------- 

750 >>> import numpy as np 

751 >>> from scipy.linalg import eig_banded 

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

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

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

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

756 True 

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

758 >>> w 

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

760 

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

762 

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

764 >>> w 

765 array([-2.22987175, 3.95222349]) 

766 

767 """ 

768 if eigvals_only or overwrite_a_band: 

769 a1 = _asarray_validated(a_band, check_finite=check_finite) 

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

771 else: 

772 a1 = array(a_band) 

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

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

775 overwrite_a_band = 1 

776 

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

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

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

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

781 del select_range 

782 if select == 0: 

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

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

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

786 # or by using calc_lwork.f ??? 

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

788 internal_name = 'hbevd' 

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

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

791 # see above 

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

793 internal_name = 'sbevd' 

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

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

796 lower=lower, overwrite_ab=overwrite_a_band) 

797 else: # select in [1, 2] 

798 if eigvals_only: 

799 max_ev = 1 

800 # calculate optimal abstol for dsbevx (see manpage) 

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

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

803 else: 

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

805 abstol = 2 * lamch('s') 

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

807 internal_name = 'hbevx' 

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

809 internal_name = 'sbevx' 

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

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

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

813 range=select, lower=lower, overwrite_ab=overwrite_a_band, 

814 abstol=abstol) 

815 # crop off w and v 

816 w = w[:m] 

817 if not eigvals_only: 

818 v = v[:, :m] 

819 _check_info(info, internal_name) 

820 

821 if eigvals_only: 

822 return w 

823 return w, v 

824 

825 

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

827 homogeneous_eigvals=False): 

828 """ 

829 Compute eigenvalues from an ordinary or generalized eigenvalue problem. 

830 

831 Find eigenvalues of a general matrix:: 

832 

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

834 

835 Parameters 

836 ---------- 

837 a : (M, M) array_like 

838 A complex or real matrix whose eigenvalues and eigenvectors 

839 will be computed. 

840 b : (M, M) array_like, optional 

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

842 If omitted, identity matrix is assumed. 

843 overwrite_a : bool, optional 

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

845 check_finite : bool, optional 

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

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

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

849 or NaNs. 

850 homogeneous_eigvals : bool, optional 

851 If True, return the eigenvalues in homogeneous coordinates. 

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

853 

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

855 

856 Default is False. 

857 

858 Returns 

859 ------- 

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

861 The eigenvalues, each repeated according to its multiplicity 

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

863 ``homogeneous_eigvals=True``. 

864 

865 Raises 

866 ------ 

867 LinAlgError 

868 If eigenvalue computation does not converge 

869 

870 See Also 

871 -------- 

872 eig : eigenvalues and right eigenvectors of general arrays. 

873 eigvalsh : eigenvalues of symmetric or Hermitian arrays 

874 eigvals_banded : eigenvalues for symmetric/Hermitian band matrices 

875 eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal 

876 matrices 

877 

878 Examples 

879 -------- 

880 >>> import numpy as np 

881 >>> from scipy import linalg 

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

883 >>> linalg.eigvals(a) 

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

885 

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

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

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

889 

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

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

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

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

894 

895 """ 

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

897 check_finite=check_finite, 

898 homogeneous_eigvals=homogeneous_eigvals) 

899 

900 

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

902 overwrite_b=False, turbo=False, eigvals=None, type=1, 

903 check_finite=True, subset_by_index=None, subset_by_value=None, 

904 driver=None): 

905 """ 

906 Solves a standard or generalized eigenvalue problem for a complex 

907 Hermitian or real symmetric matrix. 

908 

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

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

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

912 

913 a @ vi = λ * b @ vi 

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

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

916 

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

918 

919 Parameters 

920 ---------- 

921 a : (M, M) array_like 

922 A complex Hermitian or real symmetric matrix whose eigenvalues will 

923 be computed. 

924 b : (M, M) array_like, optional 

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

926 If omitted, identity matrix is assumed. 

927 lower : bool, optional 

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

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

930 overwrite_a : bool, optional 

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

932 is False. 

933 overwrite_b : bool, optional 

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

935 is False. 

936 type : int, optional 

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

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

939 inputs):: 

940 

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

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

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

944 

945 This keyword is ignored for standard problems. 

946 check_finite : bool, optional 

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

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

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

950 subset_by_index : iterable, optional 

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

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

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

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

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

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

957 subset_by_value : iterable, optional 

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

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

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

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

962 driver : str, optional 

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

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

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

966 `scipy.linalg.eigh`. 

967 turbo : bool, optional, deprecated 

968 .. deprecated:: 1.5.0 

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

970 ``driver=gvd`` option and will be removed in SciPy 1.12.0. 

971 

972 eigvals : tuple (lo, hi), optional 

973 .. deprecated:: 1.5.0 

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

975 `subset_by_index` option and will be removed in SciPy 1.12.0. 

976 

977 Returns 

978 ------- 

979 w : (N,) ndarray 

980 The ``N`` (``1<=N<=M``) selected eigenvalues, in ascending order, each 

981 repeated according to its multiplicity. 

982 

983 Raises 

984 ------ 

985 LinAlgError 

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

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

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

989 be wrong. 

990 

991 See Also 

992 -------- 

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

994 eigvals : eigenvalues of general arrays 

995 eigvals_banded : eigenvalues for symmetric/Hermitian band matrices 

996 eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal 

997 matrices 

998 

999 Notes 

1000 ----- 

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

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

1003 triangular parts. 

1004 

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

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

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

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

1009 more pythonic. 

1010 

1011 Examples 

1012 -------- 

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

1014 

1015 >>> import numpy as np 

1016 >>> from scipy.linalg import eigvalsh 

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

1018 >>> w = eigvalsh(A) 

1019 >>> w 

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

1021 

1022 """ 

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

1024 overwrite_a=overwrite_a, overwrite_b=overwrite_b, 

1025 turbo=turbo, eigvals=eigvals, type=type, 

1026 check_finite=check_finite, subset_by_index=subset_by_index, 

1027 subset_by_value=subset_by_value, driver=driver) 

1028 

1029 

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

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

1032 """ 

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

1034 

1035 Find eigenvalues w of a:: 

1036 

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

1038 v.H v = identity 

1039 

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

1041 diagonal ordered form: 

1042 

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

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

1045 

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

1047 

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

1049 

1050 upper form: 

1051 * * a02 a13 a24 a35 

1052 * a01 a12 a23 a34 a45 

1053 a00 a11 a22 a33 a44 a55 

1054 

1055 lower form: 

1056 a00 a11 a22 a33 a44 a55 

1057 a10 a21 a32 a43 a54 * 

1058 a20 a31 a42 a53 * * 

1059 

1060 Cells marked with * are not used. 

1061 

1062 Parameters 

1063 ---------- 

1064 a_band : (u+1, M) array_like 

1065 The bands of the M by M matrix a. 

1066 lower : bool, optional 

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

1068 overwrite_a_band : bool, optional 

1069 Discard data in a_band (may enhance performance) 

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

1071 Which eigenvalues to calculate 

1072 

1073 ====== ======================================== 

1074 select calculated 

1075 ====== ======================================== 

1076 'a' All eigenvalues 

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

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

1079 ====== ======================================== 

1080 select_range : (min, max), optional 

1081 Range of selected eigenvalues 

1082 check_finite : bool, optional 

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

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

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

1086 

1087 Returns 

1088 ------- 

1089 w : (M,) ndarray 

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

1091 multiplicity. 

1092 

1093 Raises 

1094 ------ 

1095 LinAlgError 

1096 If eigenvalue computation does not converge. 

1097 

1098 See Also 

1099 -------- 

1100 eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian 

1101 band matrices 

1102 eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal 

1103 matrices 

1104 eigvals : eigenvalues of general arrays 

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

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

1107 

1108 Examples 

1109 -------- 

1110 >>> import numpy as np 

1111 >>> from scipy.linalg import eigvals_banded 

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

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

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

1115 >>> w 

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

1117 """ 

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

1119 overwrite_a_band=overwrite_a_band, select=select, 

1120 select_range=select_range, check_finite=check_finite) 

1121 

1122 

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

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

1125 """ 

1126 Solve eigenvalue problem for a real symmetric tridiagonal matrix. 

1127 

1128 Find eigenvalues `w` of ``a``:: 

1129 

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

1131 v.H v = identity 

1132 

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

1134 off-diagonal elements `e`. 

1135 

1136 Parameters 

1137 ---------- 

1138 d : ndarray, shape (ndim,) 

1139 The diagonal elements of the array. 

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

1141 The off-diagonal elements of the array. 

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

1143 Which eigenvalues to calculate 

1144 

1145 ====== ======================================== 

1146 select calculated 

1147 ====== ======================================== 

1148 'a' All eigenvalues 

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

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

1151 ====== ======================================== 

1152 select_range : (min, max), optional 

1153 Range of selected eigenvalues 

1154 check_finite : bool, optional 

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

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

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

1158 tol : float 

1159 The absolute tolerance to which each eigenvalue is required 

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

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

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

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

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

1165 lapack_driver : str 

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

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

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

1169 ``select='a'``. 

1170 

1171 Returns 

1172 ------- 

1173 w : (M,) ndarray 

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

1175 multiplicity. 

1176 

1177 Raises 

1178 ------ 

1179 LinAlgError 

1180 If eigenvalue computation does not converge. 

1181 

1182 See Also 

1183 -------- 

1184 eigh_tridiagonal : eigenvalues and right eiegenvectors for 

1185 symmetric/Hermitian tridiagonal matrices 

1186 

1187 Examples 

1188 -------- 

1189 >>> import numpy as np 

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

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

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

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

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

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

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

1197 True 

1198 """ 

1199 return eigh_tridiagonal( 

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

1201 check_finite=check_finite, tol=tol, lapack_driver=lapack_driver) 

1202 

1203 

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

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

1206 """ 

1207 Solve eigenvalue problem for a real symmetric tridiagonal matrix. 

1208 

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

1210 

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

1212 v.H v = identity 

1213 

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

1215 off-diagonal elements `e`. 

1216 

1217 Parameters 

1218 ---------- 

1219 d : ndarray, shape (ndim,) 

1220 The diagonal elements of the array. 

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

1222 The off-diagonal elements of the array. 

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

1224 Which eigenvalues to calculate 

1225 

1226 ====== ======================================== 

1227 select calculated 

1228 ====== ======================================== 

1229 'a' All eigenvalues 

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

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

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

1233 select_range : (min, max), optional 

1234 Range of selected eigenvalues 

1235 check_finite : bool, optional 

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

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

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

1239 tol : float 

1240 The absolute tolerance to which each eigenvalue is required 

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

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

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

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

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

1246 lapack_driver : str 

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

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

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

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

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

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

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

1254 

1255 Returns 

1256 ------- 

1257 w : (M,) ndarray 

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

1259 multiplicity. 

1260 v : (M, M) ndarray 

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

1262 the column ``v[:,i]``. 

1263 

1264 Raises 

1265 ------ 

1266 LinAlgError 

1267 If eigenvalue computation does not converge. 

1268 

1269 See Also 

1270 -------- 

1271 eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal 

1272 matrices 

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

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

1275 eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian 

1276 band matrices 

1277 

1278 Notes 

1279 ----- 

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

1281 

1282 Examples 

1283 -------- 

1284 >>> import numpy as np 

1285 >>> from scipy.linalg import eigh_tridiagonal 

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

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

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

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

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

1291 True 

1292 """ 

1293 d = _asarray_validated(d, check_finite=check_finite) 

1294 e = _asarray_validated(e, check_finite=check_finite) 

1295 for check in (d, e): 

1296 if check.ndim != 1: 

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

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

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

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

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

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

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

1304 select, select_range, 0, d.size) 

1305 if not isinstance(lapack_driver, str): 

1306 raise TypeError('lapack_driver must be str') 

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

1308 if lapack_driver not in drivers: 

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

1310 % (drivers, lapack_driver)) 

1311 if lapack_driver == 'auto': 

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

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

1314 compute_v = not eigvals_only 

1315 if lapack_driver == 'sterf': 

1316 if select != 0: 

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

1318 if not eigvals_only: 

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

1320 'True') 

1321 w, info = func(d, e) 

1322 m = len(w) 

1323 elif lapack_driver == 'stev': 

1324 if select != 0: 

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

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

1327 m = len(w) 

1328 elif lapack_driver == 'stebz': 

1329 tol = float(tol) 

1330 internal_name = 'stebz' 

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

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

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

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

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

1336 order) 

1337 else: # 'stemr' 

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

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

1340 e_[:-1] = e 

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

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

1343 compute_v=compute_v) 

1344 _check_info(info, 'stemr_lwork') 

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

1346 compute_v=compute_v, lwork=lwork, liwork=liwork) 

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

1348 w = w[:m] 

1349 if eigvals_only: 

1350 return w 

1351 else: 

1352 # Do we still need to compute the eigenvalues? 

1353 if lapack_driver == 'stebz': 

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

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

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

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

1358 # Convert block-order to matrix-order 

1359 order = argsort(w) 

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

1361 else: 

1362 v = v[:, :m] 

1363 return w, v 

1364 

1365 

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

1367 """Check info return value.""" 

1368 if info < 0: 

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

1370 % (-info, driver)) 

1371 if info > 0 and positive: 

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

1373 

1374 

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

1376 """ 

1377 Compute Hessenberg form of a matrix. 

1378 

1379 The Hessenberg decomposition is:: 

1380 

1381 A = Q H Q^H 

1382 

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

1384 the first sub-diagonal. 

1385 

1386 Parameters 

1387 ---------- 

1388 a : (M, M) array_like 

1389 Matrix to bring into Hessenberg form. 

1390 calc_q : bool, optional 

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

1392 overwrite_a : bool, optional 

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

1394 Default is False. 

1395 check_finite : bool, optional 

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

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

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

1399 

1400 Returns 

1401 ------- 

1402 H : (M, M) ndarray 

1403 Hessenberg form of `a`. 

1404 Q : (M, M) ndarray 

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

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

1407 

1408 Examples 

1409 -------- 

1410 >>> import numpy as np 

1411 >>> from scipy.linalg import hessenberg 

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

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

1414 >>> H 

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

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

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

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

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

1420 True 

1421 """ 

1422 a1 = _asarray_validated(a, check_finite=check_finite) 

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

1424 raise ValueError('expected square matrix') 

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

1426 

1427 # if 2x2 or smaller: already in Hessenberg 

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

1429 if calc_q: 

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

1431 return a1 

1432 

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

1434 'gehrd_lwork'), (a1,)) 

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

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

1437 n = len(a1) 

1438 

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

1440 

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

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

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

1444 if not calc_q: 

1445 return h 

1446 

1447 # use orghr/unghr to compute q 

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

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

1450 

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

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

1453 return h, q 

1454 

1455 

1456def cdf2rdf(w, v): 

1457 """ 

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

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

1460 eigenvectors ``vr``, such that:: 

1461 

1462 vr @ wr = X @ vr 

1463 

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

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

1466 

1467 .. versionadded:: 1.1.0 

1468 

1469 Parameters 

1470 ---------- 

1471 w : (..., M) array_like 

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

1473 

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

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

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

1477 

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

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

1480 

1481 Returns 

1482 ------- 

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

1484 Real diagonal block form of eigenvalues 

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

1486 Real eigenvectors associated with ``wr`` 

1487 

1488 See Also 

1489 -------- 

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

1491 rsf2csf : Convert real Schur form to complex Schur form 

1492 

1493 Notes 

1494 ----- 

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

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

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

1498 stacked arrays. 

1499 

1500 .. versionadded:: 1.1.0 

1501 

1502 Examples 

1503 -------- 

1504 >>> import numpy as np 

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

1506 >>> X 

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

1508 [ 0, 4, 5], 

1509 [ 0, -5, 4]]) 

1510 

1511 >>> from scipy import linalg 

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

1513 >>> w 

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

1515 >>> v 

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

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

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

1519 

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

1521 >>> wr 

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

1523 [ 0., 4., 5.], 

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

1525 >>> vr 

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

1527 [ 0. , 0.64788, 0. ], 

1528 [ 0. , 0. , 0.64788]]) 

1529 

1530 >>> vr @ wr 

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

1532 [ 0. , 2.59153, 3.23942], 

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

1534 >>> X @ vr 

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

1536 [ 0. , 2.59153, 3.23942], 

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

1538 """ 

1539 w, v = _asarray_validated(w), _asarray_validated(v) 

1540 

1541 # check dimensions 

1542 if w.ndim < 1: 

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

1544 if v.ndim < 2: 

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

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

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

1548 'dimension more than eigenvalues array') 

1549 

1550 # check shapes 

1551 n = w.shape[-1] 

1552 M = w.shape[:-1] 

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

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

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

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

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

1558 'eigenvectors') 

1559 

1560 # get indices for each first pair of complex eigenvalues 

1561 complex_mask = iscomplex(w) 

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

1563 

1564 # check if all complex eigenvalues have conjugate pairs 

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

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

1567 

1568 # find complex indices 

1569 idx = nonzero(complex_mask) 

1570 idx_stack = idx[:-1] 

1571 idx_elem = idx[-1] 

1572 

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

1574 j = idx_elem[0::2] 

1575 k = idx_elem[1::2] 

1576 stack_ind = () 

1577 for i in idx_stack: 

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

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

1580 "Conjugate pair spanned different arrays!" 

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

1582 

1583 # all eigenvalues to diagonal form 

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

1585 di = range(n) 

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

1587 

1588 # complex eigenvalues to real block diagonal form 

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

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

1591 

1592 # compute real eigenvectors associated with real block diagonal eigenvalues 

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

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

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

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

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

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

1599 

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

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

1602 

1603 return wr, vr