eigen.py 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. from types import FunctionType
  2. from collections import Counter
  3. from mpmath import mp, workprec
  4. from mpmath.libmp.libmpf import prec_to_dps
  5. from sympy.core.sorting import default_sort_key
  6. from sympy.core.evalf import DEFAULT_MAXPREC, PrecisionExhausted
  7. from sympy.core.logic import fuzzy_and, fuzzy_or
  8. from sympy.core.numbers import Float
  9. from sympy.core.sympify import _sympify
  10. from sympy.functions.elementary.miscellaneous import sqrt
  11. from sympy.polys import roots, CRootOf, ZZ, QQ, EX
  12. from sympy.polys.matrices import DomainMatrix
  13. from sympy.polys.matrices.eigen import dom_eigenvects, dom_eigenvects_to_sympy
  14. from sympy.polys.polytools import gcd
  15. from .exceptions import MatrixError, NonSquareMatrixError
  16. from .determinant import _find_reasonable_pivot
  17. from .utilities import _iszero, _simplify
  18. __doctest_requires__ = {
  19. ('_is_indefinite',
  20. '_is_negative_definite',
  21. '_is_negative_semidefinite',
  22. '_is_positive_definite',
  23. '_is_positive_semidefinite'): ['matplotlib'],
  24. }
  25. def _eigenvals_eigenvects_mpmath(M):
  26. norm2 = lambda v: mp.sqrt(sum(i**2 for i in v))
  27. v1 = None
  28. prec = max(x._prec for x in M.atoms(Float))
  29. eps = 2**-prec
  30. while prec < DEFAULT_MAXPREC:
  31. with workprec(prec):
  32. A = mp.matrix(M.evalf(n=prec_to_dps(prec)))
  33. E, ER = mp.eig(A)
  34. v2 = norm2([i for e in E for i in (mp.re(e), mp.im(e))])
  35. if v1 is not None and mp.fabs(v1 - v2) < eps:
  36. return E, ER
  37. v1 = v2
  38. prec *= 2
  39. # we get here because the next step would have taken us
  40. # past MAXPREC or because we never took a step; in case
  41. # of the latter, we refuse to send back a solution since
  42. # it would not have been verified; we also resist taking
  43. # a small step to arrive exactly at MAXPREC since then
  44. # the two calculations might be artificially close.
  45. raise PrecisionExhausted
  46. def _eigenvals_mpmath(M, multiple=False):
  47. """Compute eigenvalues using mpmath"""
  48. E, _ = _eigenvals_eigenvects_mpmath(M)
  49. result = [_sympify(x) for x in E]
  50. if multiple:
  51. return result
  52. return dict(Counter(result))
  53. def _eigenvects_mpmath(M):
  54. E, ER = _eigenvals_eigenvects_mpmath(M)
  55. result = []
  56. for i in range(M.rows):
  57. eigenval = _sympify(E[i])
  58. eigenvect = _sympify(ER[:, i])
  59. result.append((eigenval, 1, [eigenvect]))
  60. return result
  61. # This function is a candidate for caching if it gets implemented for matrices.
  62. def _eigenvals(
  63. M, error_when_incomplete=True, *, simplify=False, multiple=False,
  64. rational=False, **flags):
  65. r"""Compute eigenvalues of the matrix.
  66. Parameters
  67. ==========
  68. error_when_incomplete : bool, optional
  69. If it is set to ``True``, it will raise an error if not all
  70. eigenvalues are computed. This is caused by ``roots`` not returning
  71. a full list of eigenvalues.
  72. simplify : bool or function, optional
  73. If it is set to ``True``, it attempts to return the most
  74. simplified form of expressions returned by applying default
  75. simplification method in every routine.
  76. If it is set to ``False``, it will skip simplification in this
  77. particular routine to save computation resources.
  78. If a function is passed to, it will attempt to apply
  79. the particular function as simplification method.
  80. rational : bool, optional
  81. If it is set to ``True``, every floating point numbers would be
  82. replaced with rationals before computation. It can solve some
  83. issues of ``roots`` routine not working well with floats.
  84. multiple : bool, optional
  85. If it is set to ``True``, the result will be in the form of a
  86. list.
  87. If it is set to ``False``, the result will be in the form of a
  88. dictionary.
  89. Returns
  90. =======
  91. eigs : list or dict
  92. Eigenvalues of a matrix. The return format would be specified by
  93. the key ``multiple``.
  94. Raises
  95. ======
  96. MatrixError
  97. If not enough roots had got computed.
  98. NonSquareMatrixError
  99. If attempted to compute eigenvalues from a non-square matrix.
  100. Examples
  101. ========
  102. >>> from sympy import Matrix
  103. >>> M = Matrix(3, 3, [0, 1, 1, 1, 0, 0, 1, 1, 1])
  104. >>> M.eigenvals()
  105. {-1: 1, 0: 1, 2: 1}
  106. See Also
  107. ========
  108. MatrixBase.charpoly
  109. eigenvects
  110. Notes
  111. =====
  112. Eigenvalues of a matrix $A$ can be computed by solving a matrix
  113. equation $\det(A - \lambda I) = 0$
  114. It's not always possible to return radical solutions for
  115. eigenvalues for matrices larger than $4, 4$ shape due to
  116. Abel-Ruffini theorem.
  117. If there is no radical solution is found for the eigenvalue,
  118. it may return eigenvalues in the form of
  119. :class:`sympy.polys.rootoftools.ComplexRootOf`.
  120. """
  121. if not M:
  122. if multiple:
  123. return []
  124. return {}
  125. if not M.is_square:
  126. raise NonSquareMatrixError("{} must be a square matrix.".format(M))
  127. if M._rep.domain not in (ZZ, QQ):
  128. # Skip this check for ZZ/QQ because it can be slow
  129. if all(x.is_number for x in M) and M.has(Float):
  130. return _eigenvals_mpmath(M, multiple=multiple)
  131. if rational:
  132. from sympy.simplify import nsimplify
  133. M = M.applyfunc(
  134. lambda x: nsimplify(x, rational=True) if x.has(Float) else x)
  135. if multiple:
  136. return _eigenvals_list(
  137. M, error_when_incomplete=error_when_incomplete, simplify=simplify,
  138. **flags)
  139. return _eigenvals_dict(
  140. M, error_when_incomplete=error_when_incomplete, simplify=simplify,
  141. **flags)
  142. eigenvals_error_message = \
  143. "It is not always possible to express the eigenvalues of a matrix " + \
  144. "of size 5x5 or higher in radicals. " + \
  145. "We have CRootOf, but domains other than the rationals are not " + \
  146. "currently supported. " + \
  147. "If there are no symbols in the matrix, " + \
  148. "it should still be possible to compute numeric approximations " + \
  149. "of the eigenvalues using " + \
  150. "M.evalf().eigenvals() or M.charpoly().nroots()."
  151. def _eigenvals_list(
  152. M, error_when_incomplete=True, simplify=False, **flags):
  153. iblocks = M.strongly_connected_components()
  154. all_eigs = []
  155. is_dom = M._rep.domain in (ZZ, QQ)
  156. for b in iblocks:
  157. # Fast path for a 1x1 block:
  158. if is_dom and len(b) == 1:
  159. index = b[0]
  160. val = M[index, index]
  161. all_eigs.append(val)
  162. continue
  163. block = M[b, b]
  164. if isinstance(simplify, FunctionType):
  165. charpoly = block.charpoly(simplify=simplify)
  166. else:
  167. charpoly = block.charpoly()
  168. eigs = roots(charpoly, multiple=True, **flags)
  169. if len(eigs) != block.rows:
  170. try:
  171. eigs = charpoly.all_roots(multiple=True)
  172. except NotImplementedError:
  173. if error_when_incomplete:
  174. raise MatrixError(eigenvals_error_message)
  175. else:
  176. eigs = []
  177. all_eigs += eigs
  178. if not simplify:
  179. return all_eigs
  180. if not isinstance(simplify, FunctionType):
  181. simplify = _simplify
  182. return [simplify(value) for value in all_eigs]
  183. def _eigenvals_dict(
  184. M, error_when_incomplete=True, simplify=False, **flags):
  185. iblocks = M.strongly_connected_components()
  186. all_eigs = {}
  187. is_dom = M._rep.domain in (ZZ, QQ)
  188. for b in iblocks:
  189. # Fast path for a 1x1 block:
  190. if is_dom and len(b) == 1:
  191. index = b[0]
  192. val = M[index, index]
  193. all_eigs[val] = all_eigs.get(val, 0) + 1
  194. continue
  195. block = M[b, b]
  196. if isinstance(simplify, FunctionType):
  197. charpoly = block.charpoly(simplify=simplify)
  198. else:
  199. charpoly = block.charpoly()
  200. eigs = roots(charpoly, multiple=False, **flags)
  201. if sum(eigs.values()) != block.rows:
  202. try:
  203. eigs = dict(charpoly.all_roots(multiple=False))
  204. except NotImplementedError:
  205. if error_when_incomplete:
  206. raise MatrixError(eigenvals_error_message)
  207. else:
  208. eigs = {}
  209. for k, v in eigs.items():
  210. if k in all_eigs:
  211. all_eigs[k] += v
  212. else:
  213. all_eigs[k] = v
  214. if not simplify:
  215. return all_eigs
  216. if not isinstance(simplify, FunctionType):
  217. simplify = _simplify
  218. return {simplify(key): value for key, value in all_eigs.items()}
  219. def _eigenspace(M, eigenval, iszerofunc=_iszero, simplify=False):
  220. """Get a basis for the eigenspace for a particular eigenvalue"""
  221. m = M - M.eye(M.rows) * eigenval
  222. ret = m.nullspace(iszerofunc=iszerofunc)
  223. # The nullspace for a real eigenvalue should be non-trivial.
  224. # If we didn't find an eigenvector, try once more a little harder
  225. if len(ret) == 0 and simplify:
  226. ret = m.nullspace(iszerofunc=iszerofunc, simplify=True)
  227. if len(ret) == 0:
  228. raise NotImplementedError(
  229. "Can't evaluate eigenvector for eigenvalue {}".format(eigenval))
  230. return ret
  231. def _eigenvects_DOM(M, **kwargs):
  232. DOM = DomainMatrix.from_Matrix(M, field=True, extension=True)
  233. DOM = DOM.to_dense()
  234. if DOM.domain != EX:
  235. rational, algebraic = dom_eigenvects(DOM)
  236. eigenvects = dom_eigenvects_to_sympy(
  237. rational, algebraic, M.__class__, **kwargs)
  238. eigenvects = sorted(eigenvects, key=lambda x: default_sort_key(x[0]))
  239. return eigenvects
  240. return None
  241. def _eigenvects_sympy(M, iszerofunc, simplify=True, **flags):
  242. eigenvals = M.eigenvals(rational=False, **flags)
  243. # Make sure that we have all roots in radical form
  244. for x in eigenvals:
  245. if x.has(CRootOf):
  246. raise MatrixError(
  247. "Eigenvector computation is not implemented if the matrix have "
  248. "eigenvalues in CRootOf form")
  249. eigenvals = sorted(eigenvals.items(), key=default_sort_key)
  250. ret = []
  251. for val, mult in eigenvals:
  252. vects = _eigenspace(M, val, iszerofunc=iszerofunc, simplify=simplify)
  253. ret.append((val, mult, vects))
  254. return ret
  255. # This functions is a candidate for caching if it gets implemented for matrices.
  256. def _eigenvects(M, error_when_incomplete=True, iszerofunc=_iszero, *, chop=False, **flags):
  257. """Compute eigenvectors of the matrix.
  258. Parameters
  259. ==========
  260. error_when_incomplete : bool, optional
  261. Raise an error when not all eigenvalues are computed. This is
  262. caused by ``roots`` not returning a full list of eigenvalues.
  263. iszerofunc : function, optional
  264. Specifies a zero testing function to be used in ``rref``.
  265. Default value is ``_iszero``, which uses SymPy's naive and fast
  266. default assumption handler.
  267. It can also accept any user-specified zero testing function, if it
  268. is formatted as a function which accepts a single symbolic argument
  269. and returns ``True`` if it is tested as zero and ``False`` if it
  270. is tested as non-zero, and ``None`` if it is undecidable.
  271. simplify : bool or function, optional
  272. If ``True``, ``as_content_primitive()`` will be used to tidy up
  273. normalization artifacts.
  274. It will also be used by the ``nullspace`` routine.
  275. chop : bool or positive number, optional
  276. If the matrix contains any Floats, they will be changed to Rationals
  277. for computation purposes, but the answers will be returned after
  278. being evaluated with evalf. The ``chop`` flag is passed to ``evalf``.
  279. When ``chop=True`` a default precision will be used; a number will
  280. be interpreted as the desired level of precision.
  281. Returns
  282. =======
  283. ret : [(eigenval, multiplicity, eigenspace), ...]
  284. A ragged list containing tuples of data obtained by ``eigenvals``
  285. and ``nullspace``.
  286. ``eigenspace`` is a list containing the ``eigenvector`` for each
  287. eigenvalue.
  288. ``eigenvector`` is a vector in the form of a ``Matrix``. e.g.
  289. a vector of length 3 is returned as ``Matrix([a_1, a_2, a_3])``.
  290. Raises
  291. ======
  292. NotImplementedError
  293. If failed to compute nullspace.
  294. Examples
  295. ========
  296. >>> from sympy import Matrix
  297. >>> M = Matrix(3, 3, [0, 1, 1, 1, 0, 0, 1, 1, 1])
  298. >>> M.eigenvects()
  299. [(-1, 1, [Matrix([
  300. [-1],
  301. [ 1],
  302. [ 0]])]), (0, 1, [Matrix([
  303. [ 0],
  304. [-1],
  305. [ 1]])]), (2, 1, [Matrix([
  306. [2/3],
  307. [1/3],
  308. [ 1]])])]
  309. See Also
  310. ========
  311. eigenvals
  312. MatrixBase.nullspace
  313. """
  314. simplify = flags.get('simplify', True)
  315. primitive = flags.get('simplify', False)
  316. flags.pop('simplify', None) # remove this if it's there
  317. flags.pop('multiple', None) # remove this if it's there
  318. if not isinstance(simplify, FunctionType):
  319. simpfunc = _simplify if simplify else lambda x: x
  320. has_floats = M.has(Float)
  321. if has_floats:
  322. if all(x.is_number for x in M):
  323. return _eigenvects_mpmath(M)
  324. from sympy.simplify import nsimplify
  325. M = M.applyfunc(lambda x: nsimplify(x, rational=True))
  326. ret = _eigenvects_DOM(M)
  327. if ret is None:
  328. ret = _eigenvects_sympy(M, iszerofunc, simplify=simplify, **flags)
  329. if primitive:
  330. # if the primitive flag is set, get rid of any common
  331. # integer denominators
  332. def denom_clean(l):
  333. return [(v / gcd(list(v))).applyfunc(simpfunc) for v in l]
  334. ret = [(val, mult, denom_clean(es)) for val, mult, es in ret]
  335. if has_floats:
  336. # if we had floats to start with, turn the eigenvectors to floats
  337. ret = [(val.evalf(chop=chop), mult, [v.evalf(chop=chop) for v in es])
  338. for val, mult, es in ret]
  339. return ret
  340. def _is_diagonalizable_with_eigen(M, reals_only=False):
  341. """See _is_diagonalizable. This function returns the bool along with the
  342. eigenvectors to avoid calculating them again in functions like
  343. ``diagonalize``."""
  344. if not M.is_square:
  345. return False, []
  346. eigenvecs = M.eigenvects(simplify=True)
  347. for val, mult, basis in eigenvecs:
  348. if reals_only and not val.is_real: # if we have a complex eigenvalue
  349. return False, eigenvecs
  350. if mult != len(basis): # if the geometric multiplicity doesn't equal the algebraic
  351. return False, eigenvecs
  352. return True, eigenvecs
  353. def _is_diagonalizable(M, reals_only=False, **kwargs):
  354. """Returns ``True`` if a matrix is diagonalizable.
  355. Parameters
  356. ==========
  357. reals_only : bool, optional
  358. If ``True``, it tests whether the matrix can be diagonalized
  359. to contain only real numbers on the diagonal.
  360. If ``False``, it tests whether the matrix can be diagonalized
  361. at all, even with numbers that may not be real.
  362. Examples
  363. ========
  364. Example of a diagonalizable matrix:
  365. >>> from sympy import Matrix
  366. >>> M = Matrix([[1, 2, 0], [0, 3, 0], [2, -4, 2]])
  367. >>> M.is_diagonalizable()
  368. True
  369. Example of a non-diagonalizable matrix:
  370. >>> M = Matrix([[0, 1], [0, 0]])
  371. >>> M.is_diagonalizable()
  372. False
  373. Example of a matrix that is diagonalized in terms of non-real entries:
  374. >>> M = Matrix([[0, 1], [-1, 0]])
  375. >>> M.is_diagonalizable(reals_only=False)
  376. True
  377. >>> M.is_diagonalizable(reals_only=True)
  378. False
  379. See Also
  380. ========
  381. sympy.matrices.matrixbase.MatrixBase.is_diagonal
  382. diagonalize
  383. """
  384. if not M.is_square:
  385. return False
  386. if all(e.is_real for e in M) and M.is_symmetric():
  387. return True
  388. if all(e.is_complex for e in M) and M.is_hermitian:
  389. return True
  390. return _is_diagonalizable_with_eigen(M, reals_only=reals_only)[0]
  391. #G&VL, Matrix Computations, Algo 5.4.2
  392. def _householder_vector(x):
  393. if not x.cols == 1:
  394. raise ValueError("Input must be a column matrix")
  395. v = x.copy()
  396. v_plus = x.copy()
  397. v_minus = x.copy()
  398. q = x[0, 0] / abs(x[0, 0])
  399. norm_x = x.norm()
  400. v_plus[0, 0] = x[0, 0] + q * norm_x
  401. v_minus[0, 0] = x[0, 0] - q * norm_x
  402. if x[1:, 0].norm() == 0:
  403. bet = 0
  404. v[0, 0] = 1
  405. else:
  406. if v_plus.norm() <= v_minus.norm():
  407. v = v_plus
  408. else:
  409. v = v_minus
  410. v = v / v[0]
  411. bet = 2 / (v.norm() ** 2)
  412. return v, bet
  413. def _bidiagonal_decmp_hholder(M):
  414. m = M.rows
  415. n = M.cols
  416. A = M.as_mutable()
  417. U, V = A.eye(m), A.eye(n)
  418. for i in range(min(m, n)):
  419. v, bet = _householder_vector(A[i:, i])
  420. hh_mat = A.eye(m - i) - bet * v * v.H
  421. A[i:, i:] = hh_mat * A[i:, i:]
  422. temp = A.eye(m)
  423. temp[i:, i:] = hh_mat
  424. U = U * temp
  425. if i + 1 <= n - 2:
  426. v, bet = _householder_vector(A[i, i+1:].T)
  427. hh_mat = A.eye(n - i - 1) - bet * v * v.H
  428. A[i:, i+1:] = A[i:, i+1:] * hh_mat
  429. temp = A.eye(n)
  430. temp[i+1:, i+1:] = hh_mat
  431. V = temp * V
  432. return U, A, V
  433. def _eval_bidiag_hholder(M):
  434. m = M.rows
  435. n = M.cols
  436. A = M.as_mutable()
  437. for i in range(min(m, n)):
  438. v, bet = _householder_vector(A[i:, i])
  439. hh_mat = A.eye(m-i) - bet * v * v.H
  440. A[i:, i:] = hh_mat * A[i:, i:]
  441. if i + 1 <= n - 2:
  442. v, bet = _householder_vector(A[i, i+1:].T)
  443. hh_mat = A.eye(n - i - 1) - bet * v * v.H
  444. A[i:, i+1:] = A[i:, i+1:] * hh_mat
  445. return A
  446. def _bidiagonal_decomposition(M, upper=True):
  447. """
  448. Returns $(U,B,V.H)$ for
  449. $$A = UBV^{H}$$
  450. where $A$ is the input matrix, and $B$ is its Bidiagonalized form
  451. Note: Bidiagonal Computation can hang for symbolic matrices.
  452. Parameters
  453. ==========
  454. upper : bool. Whether to do upper bidiagnalization or lower.
  455. True for upper and False for lower.
  456. References
  457. ==========
  458. .. [1] Algorithm 5.4.2, Matrix computations by Golub and Van Loan, 4th edition
  459. .. [2] Complex Matrix Bidiagonalization, https://github.com/vslobody/Householder-Bidiagonalization
  460. """
  461. if not isinstance(upper, bool):
  462. raise ValueError("upper must be a boolean")
  463. if upper:
  464. return _bidiagonal_decmp_hholder(M)
  465. X = _bidiagonal_decmp_hholder(M.H)
  466. return X[2].H, X[1].H, X[0].H
  467. def _bidiagonalize(M, upper=True):
  468. """
  469. Returns $B$, the Bidiagonalized form of the input matrix.
  470. Note: Bidiagonal Computation can hang for symbolic matrices.
  471. Parameters
  472. ==========
  473. upper : bool. Whether to do upper bidiagnalization or lower.
  474. True for upper and False for lower.
  475. References
  476. ==========
  477. .. [1] Algorithm 5.4.2, Matrix computations by Golub and Van Loan, 4th edition
  478. .. [2] Complex Matrix Bidiagonalization : https://github.com/vslobody/Householder-Bidiagonalization
  479. """
  480. if not isinstance(upper, bool):
  481. raise ValueError("upper must be a boolean")
  482. if upper:
  483. return _eval_bidiag_hholder(M)
  484. return _eval_bidiag_hholder(M.H).H
  485. def _diagonalize(M, reals_only=False, sort=False, normalize=False):
  486. """
  487. Return (P, D), where D is diagonal and
  488. D = P^-1 * M * P
  489. where M is current matrix.
  490. Parameters
  491. ==========
  492. reals_only : bool. Whether to throw an error if complex numbers are need
  493. to diagonalize. (Default: False)
  494. sort : bool. Sort the eigenvalues along the diagonal. (Default: False)
  495. normalize : bool. If True, normalize the columns of P. (Default: False)
  496. Examples
  497. ========
  498. >>> from sympy import Matrix
  499. >>> M = Matrix(3, 3, [1, 2, 0, 0, 3, 0, 2, -4, 2])
  500. >>> M
  501. Matrix([
  502. [1, 2, 0],
  503. [0, 3, 0],
  504. [2, -4, 2]])
  505. >>> (P, D) = M.diagonalize()
  506. >>> D
  507. Matrix([
  508. [1, 0, 0],
  509. [0, 2, 0],
  510. [0, 0, 3]])
  511. >>> P
  512. Matrix([
  513. [-1, 0, -1],
  514. [ 0, 0, -1],
  515. [ 2, 1, 2]])
  516. >>> P.inv() * M * P
  517. Matrix([
  518. [1, 0, 0],
  519. [0, 2, 0],
  520. [0, 0, 3]])
  521. See Also
  522. ========
  523. sympy.matrices.matrixbase.MatrixBase.is_diagonal
  524. is_diagonalizable
  525. """
  526. if not M.is_square:
  527. raise NonSquareMatrixError()
  528. is_diagonalizable, eigenvecs = _is_diagonalizable_with_eigen(M,
  529. reals_only=reals_only)
  530. if not is_diagonalizable:
  531. raise MatrixError("Matrix is not diagonalizable")
  532. if sort:
  533. eigenvecs = sorted(eigenvecs, key=default_sort_key)
  534. p_cols, diag = [], []
  535. for val, mult, basis in eigenvecs:
  536. diag += [val] * mult
  537. p_cols += basis
  538. if normalize:
  539. p_cols = [v / v.norm() for v in p_cols]
  540. return M.hstack(*p_cols), M.diag(*diag)
  541. def _fuzzy_positive_definite(M):
  542. positive_diagonals = M._has_positive_diagonals()
  543. if positive_diagonals is False:
  544. return False
  545. if positive_diagonals and M.is_strongly_diagonally_dominant:
  546. return True
  547. return None
  548. def _fuzzy_positive_semidefinite(M):
  549. nonnegative_diagonals = M._has_nonnegative_diagonals()
  550. if nonnegative_diagonals is False:
  551. return False
  552. if nonnegative_diagonals and M.is_weakly_diagonally_dominant:
  553. return True
  554. return None
  555. def _is_positive_definite(M):
  556. if not M.is_hermitian:
  557. if not M.is_square:
  558. return False
  559. M = M + M.H
  560. fuzzy = _fuzzy_positive_definite(M)
  561. if fuzzy is not None:
  562. return fuzzy
  563. return _is_positive_definite_GE(M)
  564. def _is_positive_semidefinite(M):
  565. if not M.is_hermitian:
  566. if not M.is_square:
  567. return False
  568. M = M + M.H
  569. fuzzy = _fuzzy_positive_semidefinite(M)
  570. if fuzzy is not None:
  571. return fuzzy
  572. return _is_positive_semidefinite_cholesky(M)
  573. def _is_negative_definite(M):
  574. return _is_positive_definite(-M)
  575. def _is_negative_semidefinite(M):
  576. return _is_positive_semidefinite(-M)
  577. def _is_indefinite(M):
  578. if M.is_hermitian:
  579. eigen = M.eigenvals()
  580. args1 = [x.is_positive for x in eigen.keys()]
  581. any_positive = fuzzy_or(args1)
  582. args2 = [x.is_negative for x in eigen.keys()]
  583. any_negative = fuzzy_or(args2)
  584. return fuzzy_and([any_positive, any_negative])
  585. elif M.is_square:
  586. return (M + M.H).is_indefinite
  587. return False
  588. def _is_positive_definite_GE(M):
  589. """A division-free gaussian elimination method for testing
  590. positive-definiteness."""
  591. M = M.as_mutable()
  592. size = M.rows
  593. for i in range(size):
  594. is_positive = M[i, i].is_positive
  595. if is_positive is not True:
  596. return is_positive
  597. for j in range(i+1, size):
  598. M[j, i+1:] = M[i, i] * M[j, i+1:] - M[j, i] * M[i, i+1:]
  599. return True
  600. def _is_positive_semidefinite_cholesky(M):
  601. """Uses Cholesky factorization with complete pivoting
  602. References
  603. ==========
  604. .. [1] http://eprints.ma.man.ac.uk/1199/1/covered/MIMS_ep2008_116.pdf
  605. .. [2] https://www.value-at-risk.net/cholesky-factorization/
  606. """
  607. M = M.as_mutable()
  608. for k in range(M.rows):
  609. diags = [M[i, i] for i in range(k, M.rows)]
  610. pivot, pivot_val, nonzero, _ = _find_reasonable_pivot(diags)
  611. if nonzero:
  612. return None
  613. if pivot is None:
  614. for i in range(k+1, M.rows):
  615. for j in range(k, M.cols):
  616. iszero = M[i, j].is_zero
  617. if iszero is None:
  618. return None
  619. elif iszero is False:
  620. return False
  621. return True
  622. if M[k, k].is_negative or pivot_val.is_negative:
  623. return False
  624. elif not (M[k, k].is_nonnegative and pivot_val.is_nonnegative):
  625. return None
  626. if pivot > 0:
  627. M.col_swap(k, k+pivot)
  628. M.row_swap(k, k+pivot)
  629. M[k, k] = sqrt(M[k, k])
  630. M[k, k+1:] /= M[k, k]
  631. M[k+1:, k+1:] -= M[k, k+1:].H * M[k, k+1:]
  632. return M[-1, -1].is_nonnegative
  633. _doc_positive_definite = \
  634. r"""Finds out the definiteness of a matrix.
  635. Explanation
  636. ===========
  637. A square real matrix $A$ is:
  638. - A positive definite matrix if $x^T A x > 0$
  639. for all non-zero real vectors $x$.
  640. - A positive semidefinite matrix if $x^T A x \geq 0$
  641. for all non-zero real vectors $x$.
  642. - A negative definite matrix if $x^T A x < 0$
  643. for all non-zero real vectors $x$.
  644. - A negative semidefinite matrix if $x^T A x \leq 0$
  645. for all non-zero real vectors $x$.
  646. - An indefinite matrix if there exists non-zero real vectors
  647. $x, y$ with $x^T A x > 0 > y^T A y$.
  648. A square complex matrix $A$ is:
  649. - A positive definite matrix if $\text{re}(x^H A x) > 0$
  650. for all non-zero complex vectors $x$.
  651. - A positive semidefinite matrix if $\text{re}(x^H A x) \geq 0$
  652. for all non-zero complex vectors $x$.
  653. - A negative definite matrix if $\text{re}(x^H A x) < 0$
  654. for all non-zero complex vectors $x$.
  655. - A negative semidefinite matrix if $\text{re}(x^H A x) \leq 0$
  656. for all non-zero complex vectors $x$.
  657. - An indefinite matrix if there exists non-zero complex vectors
  658. $x, y$ with $\text{re}(x^H A x) > 0 > \text{re}(y^H A y)$.
  659. A matrix need not be symmetric or hermitian to be positive definite.
  660. - A real non-symmetric matrix is positive definite if and only if
  661. $\frac{A + A^T}{2}$ is positive definite.
  662. - A complex non-hermitian matrix is positive definite if and only if
  663. $\frac{A + A^H}{2}$ is positive definite.
  664. And this extension can apply for all the definitions above.
  665. However, for complex cases, you can restrict the definition of
  666. $\text{re}(x^H A x) > 0$ to $x^H A x > 0$ and require the matrix
  667. to be hermitian.
  668. But we do not present this restriction for computation because you
  669. can check ``M.is_hermitian`` independently with this and use
  670. the same procedure.
  671. Examples
  672. ========
  673. An example of symmetric positive definite matrix:
  674. .. plot::
  675. :context: reset
  676. :format: doctest
  677. :include-source: True
  678. >>> from sympy import Matrix, symbols
  679. >>> from sympy.plotting import plot3d
  680. >>> a, b = symbols('a b')
  681. >>> x = Matrix([a, b])
  682. >>> A = Matrix([[1, 0], [0, 1]])
  683. >>> A.is_positive_definite
  684. True
  685. >>> A.is_positive_semidefinite
  686. True
  687. >>> p = plot3d((x.T*A*x)[0, 0], (a, -1, 1), (b, -1, 1))
  688. An example of symmetric positive semidefinite matrix:
  689. .. plot::
  690. :context: close-figs
  691. :format: doctest
  692. :include-source: True
  693. >>> A = Matrix([[1, -1], [-1, 1]])
  694. >>> A.is_positive_definite
  695. False
  696. >>> A.is_positive_semidefinite
  697. True
  698. >>> p = plot3d((x.T*A*x)[0, 0], (a, -1, 1), (b, -1, 1))
  699. An example of symmetric negative definite matrix:
  700. .. plot::
  701. :context: close-figs
  702. :format: doctest
  703. :include-source: True
  704. >>> A = Matrix([[-1, 0], [0, -1]])
  705. >>> A.is_negative_definite
  706. True
  707. >>> A.is_negative_semidefinite
  708. True
  709. >>> A.is_indefinite
  710. False
  711. >>> p = plot3d((x.T*A*x)[0, 0], (a, -1, 1), (b, -1, 1))
  712. An example of symmetric indefinite matrix:
  713. .. plot::
  714. :context: close-figs
  715. :format: doctest
  716. :include-source: True
  717. >>> A = Matrix([[1, 2], [2, -1]])
  718. >>> A.is_indefinite
  719. True
  720. >>> p = plot3d((x.T*A*x)[0, 0], (a, -1, 1), (b, -1, 1))
  721. An example of non-symmetric positive definite matrix.
  722. .. plot::
  723. :context: close-figs
  724. :format: doctest
  725. :include-source: True
  726. >>> A = Matrix([[1, 2], [-2, 1]])
  727. >>> A.is_positive_definite
  728. True
  729. >>> A.is_positive_semidefinite
  730. True
  731. >>> p = plot3d((x.T*A*x)[0, 0], (a, -1, 1), (b, -1, 1))
  732. Notes
  733. =====
  734. Although some people trivialize the definition of positive definite
  735. matrices only for symmetric or hermitian matrices, this restriction
  736. is not correct because it does not classify all instances of
  737. positive definite matrices from the definition $x^T A x > 0$ or
  738. $\text{re}(x^H A x) > 0$.
  739. For instance, ``Matrix([[1, 2], [-2, 1]])`` presented in
  740. the example above is an example of real positive definite matrix
  741. that is not symmetric.
  742. However, since the following formula holds true;
  743. .. math::
  744. \text{re}(x^H A x) > 0 \iff
  745. \text{re}(x^H \frac{A + A^H}{2} x) > 0
  746. We can classify all positive definite matrices that may or may not
  747. be symmetric or hermitian by transforming the matrix to
  748. $\frac{A + A^T}{2}$ or $\frac{A + A^H}{2}$
  749. (which is guaranteed to be always real symmetric or complex
  750. hermitian) and we can defer most of the studies to symmetric or
  751. hermitian positive definite matrices.
  752. But it is a different problem for the existence of Cholesky
  753. decomposition. Because even though a non symmetric or a non
  754. hermitian matrix can be positive definite, Cholesky or LDL
  755. decomposition does not exist because the decompositions require the
  756. matrix to be symmetric or hermitian.
  757. References
  758. ==========
  759. .. [1] https://en.wikipedia.org/wiki/Definiteness_of_a_matrix#Eigenvalues
  760. .. [2] https://mathworld.wolfram.com/PositiveDefiniteMatrix.html
  761. .. [3] Johnson, C. R. "Positive Definite Matrices." Amer.
  762. Math. Monthly 77, 259-264 1970.
  763. """
  764. _is_positive_definite.__doc__ = _doc_positive_definite
  765. _is_positive_semidefinite.__doc__ = _doc_positive_definite
  766. _is_negative_definite.__doc__ = _doc_positive_definite
  767. _is_negative_semidefinite.__doc__ = _doc_positive_definite
  768. _is_indefinite.__doc__ = _doc_positive_definite
  769. def _jordan_form(M, calc_transform=True, *, chop=False):
  770. """Return $(P, J)$ where $J$ is a Jordan block
  771. matrix and $P$ is a matrix such that $M = P J P^{-1}$
  772. Parameters
  773. ==========
  774. calc_transform : bool
  775. If ``False``, then only $J$ is returned.
  776. chop : bool
  777. All matrices are converted to exact types when computing
  778. eigenvalues and eigenvectors. As a result, there may be
  779. approximation errors. If ``chop==True``, these errors
  780. will be truncated.
  781. Examples
  782. ========
  783. >>> from sympy import Matrix
  784. >>> M = Matrix([[ 6, 5, -2, -3], [-3, -1, 3, 3], [ 2, 1, -2, -3], [-1, 1, 5, 5]])
  785. >>> P, J = M.jordan_form()
  786. >>> J
  787. Matrix([
  788. [2, 1, 0, 0],
  789. [0, 2, 0, 0],
  790. [0, 0, 2, 1],
  791. [0, 0, 0, 2]])
  792. See Also
  793. ========
  794. jordan_block
  795. """
  796. if not M.is_square:
  797. raise NonSquareMatrixError("Only square matrices have Jordan forms")
  798. mat = M
  799. has_floats = M.has(Float)
  800. if has_floats:
  801. try:
  802. max_prec = max(term._prec for term in M.values() if isinstance(term, Float))
  803. except ValueError:
  804. # if no term in the matrix is explicitly a Float calling max()
  805. # will throw a error so setting max_prec to default value of 53
  806. max_prec = 53
  807. # setting minimum max_dps to 15 to prevent loss of precision in
  808. # matrix containing non evaluated expressions
  809. max_dps = max(prec_to_dps(max_prec), 15)
  810. def restore_floats(*args):
  811. """If ``has_floats`` is `True`, cast all ``args`` as
  812. matrices of floats."""
  813. if has_floats:
  814. args = [m.evalf(n=max_dps, chop=chop) for m in args]
  815. if len(args) == 1:
  816. return args[0]
  817. return args
  818. # cache calculations for some speedup
  819. mat_cache = {}
  820. def eig_mat(val, pow):
  821. """Cache computations of ``(M - val*I)**pow`` for quick
  822. retrieval"""
  823. if (val, pow) in mat_cache:
  824. return mat_cache[(val, pow)]
  825. if (val, pow - 1) in mat_cache:
  826. mat_cache[(val, pow)] = mat_cache[(val, pow - 1)].multiply(
  827. mat_cache[(val, 1)], dotprodsimp=None)
  828. else:
  829. mat_cache[(val, pow)] = (mat - val*M.eye(M.rows)).pow(pow)
  830. return mat_cache[(val, pow)]
  831. # helper functions
  832. def nullity_chain(val, algebraic_multiplicity):
  833. """Calculate the sequence [0, nullity(E), nullity(E**2), ...]
  834. until it is constant where ``E = M - val*I``"""
  835. # mat.rank() is faster than computing the null space,
  836. # so use the rank-nullity theorem
  837. cols = M.cols
  838. ret = [0]
  839. nullity = cols - eig_mat(val, 1).rank()
  840. i = 2
  841. while nullity != ret[-1]:
  842. ret.append(nullity)
  843. if nullity == algebraic_multiplicity:
  844. break
  845. nullity = cols - eig_mat(val, i).rank()
  846. i += 1
  847. # Due to issues like #7146 and #15872, SymPy sometimes
  848. # gives the wrong rank. In this case, raise an error
  849. # instead of returning an incorrect matrix
  850. if nullity < ret[-1] or nullity > algebraic_multiplicity:
  851. raise MatrixError(
  852. "SymPy had encountered an inconsistent "
  853. "result while computing Jordan block: "
  854. "{}".format(M))
  855. return ret
  856. def blocks_from_nullity_chain(d):
  857. """Return a list of the size of each Jordan block.
  858. If d_n is the nullity of E**n, then the number
  859. of Jordan blocks of size n is
  860. 2*d_n - d_(n-1) - d_(n+1)"""
  861. # d[0] is always the number of columns, so skip past it
  862. mid = [2*d[n] - d[n - 1] - d[n + 1] for n in range(1, len(d) - 1)]
  863. # d is assumed to plateau with "d[ len(d) ] == d[-1]", so
  864. # 2*d_n - d_(n-1) - d_(n+1) == d_n - d_(n-1)
  865. end = [d[-1] - d[-2]] if len(d) > 1 else [d[0]]
  866. return mid + end
  867. def pick_vec(small_basis, big_basis):
  868. """Picks a vector from big_basis that isn't in
  869. the subspace spanned by small_basis"""
  870. if len(small_basis) == 0:
  871. return big_basis[0]
  872. for v in big_basis:
  873. _, pivots = M.hstack(*(small_basis + [v])).echelon_form(
  874. with_pivots=True)
  875. if pivots[-1] == len(small_basis):
  876. return v
  877. # roots doesn't like Floats, so replace them with Rationals
  878. if has_floats:
  879. from sympy.simplify import nsimplify
  880. mat = mat.applyfunc(lambda x: nsimplify(x, rational=True))
  881. # first calculate the jordan block structure
  882. eigs = mat.eigenvals()
  883. # Make sure that we have all roots in radical form
  884. for x in eigs:
  885. if x.has(CRootOf):
  886. raise MatrixError(
  887. "Jordan normal form is not implemented if the matrix have "
  888. "eigenvalues in CRootOf form")
  889. # most matrices have distinct eigenvalues
  890. # and so are diagonalizable. In this case, don't
  891. # do extra work!
  892. if len(eigs.keys()) == mat.cols:
  893. blocks = sorted(eigs.keys(), key=default_sort_key)
  894. jordan_mat = mat.diag(*blocks)
  895. if not calc_transform:
  896. return restore_floats(jordan_mat)
  897. jordan_basis = [eig_mat(eig, 1).nullspace()[0]
  898. for eig in blocks]
  899. basis_mat = mat.hstack(*jordan_basis)
  900. return restore_floats(basis_mat, jordan_mat)
  901. block_structure = []
  902. for eig in sorted(eigs.keys(), key=default_sort_key):
  903. algebraic_multiplicity = eigs[eig]
  904. chain = nullity_chain(eig, algebraic_multiplicity)
  905. block_sizes = blocks_from_nullity_chain(chain)
  906. # if block_sizes = = [a, b, c, ...], then the number of
  907. # Jordan blocks of size 1 is a, of size 2 is b, etc.
  908. # create an array that has (eig, block_size) with one
  909. # entry for each block
  910. size_nums = [(i+1, num) for i, num in enumerate(block_sizes)]
  911. # we expect larger Jordan blocks to come earlier
  912. size_nums.reverse()
  913. block_structure.extend(
  914. [(eig, size) for size, num in size_nums for _ in range(num)])
  915. jordan_form_size = sum(size for eig, size in block_structure)
  916. if jordan_form_size != M.rows:
  917. raise MatrixError(
  918. "SymPy had encountered an inconsistent result while "
  919. "computing Jordan block. : {}".format(M))
  920. blocks = (mat.jordan_block(size=size, eigenvalue=eig) for eig, size in block_structure)
  921. jordan_mat = mat.diag(*blocks)
  922. if not calc_transform:
  923. return restore_floats(jordan_mat)
  924. # For each generalized eigenspace, calculate a basis.
  925. # We start by looking for a vector in null( (A - eig*I)**n )
  926. # which isn't in null( (A - eig*I)**(n-1) ) where n is
  927. # the size of the Jordan block
  928. #
  929. # Ideally we'd just loop through block_structure and
  930. # compute each generalized eigenspace. However, this
  931. # causes a lot of unneeded computation. Instead, we
  932. # go through the eigenvalues separately, since we know
  933. # their generalized eigenspaces must have bases that
  934. # are linearly independent.
  935. jordan_basis = []
  936. for eig in sorted(eigs.keys(), key=default_sort_key):
  937. eig_basis = []
  938. for block_eig, size in block_structure:
  939. if block_eig != eig:
  940. continue
  941. null_big = (eig_mat(eig, size)).nullspace()
  942. null_small = (eig_mat(eig, size - 1)).nullspace()
  943. # we want to pick something that is in the big basis
  944. # and not the small, but also something that is independent
  945. # of any other generalized eigenvectors from a different
  946. # generalized eigenspace sharing the same eigenvalue.
  947. vec = pick_vec(null_small + eig_basis, null_big)
  948. new_vecs = [eig_mat(eig, i).multiply(vec, dotprodsimp=None)
  949. for i in range(size)]
  950. eig_basis.extend(new_vecs)
  951. jordan_basis.extend(reversed(new_vecs))
  952. basis_mat = mat.hstack(*jordan_basis)
  953. return restore_floats(basis_mat, jordan_mat)
  954. def _left_eigenvects(M, **flags):
  955. """Returns left eigenvectors and eigenvalues.
  956. This function returns the list of triples (eigenval, multiplicity,
  957. basis) for the left eigenvectors. Options are the same as for
  958. eigenvects(), i.e. the ``**flags`` arguments gets passed directly to
  959. eigenvects().
  960. Examples
  961. ========
  962. >>> from sympy import Matrix
  963. >>> M = Matrix([[0, 1, 1], [1, 0, 0], [1, 1, 1]])
  964. >>> M.eigenvects()
  965. [(-1, 1, [Matrix([
  966. [-1],
  967. [ 1],
  968. [ 0]])]), (0, 1, [Matrix([
  969. [ 0],
  970. [-1],
  971. [ 1]])]), (2, 1, [Matrix([
  972. [2/3],
  973. [1/3],
  974. [ 1]])])]
  975. >>> M.left_eigenvects()
  976. [(-1, 1, [Matrix([[-2, 1, 1]])]), (0, 1, [Matrix([[-1, -1, 1]])]), (2,
  977. 1, [Matrix([[1, 1, 1]])])]
  978. """
  979. eigs = M.transpose().eigenvects(**flags)
  980. return [(val, mult, [l.transpose() for l in basis]) for val, mult, basis in eigs]
  981. def _singular_values(M):
  982. """Compute the singular values of a Matrix
  983. Examples
  984. ========
  985. >>> from sympy import Matrix, Symbol
  986. >>> x = Symbol('x', real=True)
  987. >>> M = Matrix([[0, 1, 0], [0, x, 0], [-1, 0, 0]])
  988. >>> M.singular_values()
  989. [sqrt(x**2 + 1), 1, 0]
  990. See Also
  991. ========
  992. condition_number
  993. """
  994. if M.rows >= M.cols:
  995. valmultpairs = M.H.multiply(M).eigenvals()
  996. else:
  997. valmultpairs = M.multiply(M.H).eigenvals()
  998. # Expands result from eigenvals into a simple list
  999. vals = []
  1000. for k, v in valmultpairs.items():
  1001. vals += [sqrt(k)] * v # dangerous! same k in several spots!
  1002. # Pad with zeros if singular values are computed in reverse way,
  1003. # to give consistent format.
  1004. if len(vals) < M.cols:
  1005. vals += [M.zero] * (M.cols - len(vals))
  1006. # sort them in descending order
  1007. vals.sort(reverse=True, key=default_sort_key)
  1008. return vals