decompositions.py 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629
  1. import copy
  2. from sympy.core import S
  3. from sympy.core.function import expand_mul
  4. from sympy.functions.elementary.miscellaneous import Min, sqrt
  5. from sympy.functions.elementary.complexes import sign
  6. from .common import NonSquareMatrixError, NonPositiveDefiniteMatrixError
  7. from .utilities import _get_intermediate_simp, _iszero
  8. from .determinant import _find_reasonable_pivot_naive
  9. def _rank_decomposition(M, iszerofunc=_iszero, simplify=False):
  10. r"""Returns a pair of matrices (`C`, `F`) with matching rank
  11. such that `A = C F`.
  12. Parameters
  13. ==========
  14. iszerofunc : Function, optional
  15. A function used for detecting whether an element can
  16. act as a pivot. ``lambda x: x.is_zero`` is used by default.
  17. simplify : Bool or Function, optional
  18. A function used to simplify elements when looking for a
  19. pivot. By default SymPy's ``simplify`` is used.
  20. Returns
  21. =======
  22. (C, F) : Matrices
  23. `C` and `F` are full-rank matrices with rank as same as `A`,
  24. whose product gives `A`.
  25. See Notes for additional mathematical details.
  26. Examples
  27. ========
  28. >>> from sympy import Matrix
  29. >>> A = Matrix([
  30. ... [1, 3, 1, 4],
  31. ... [2, 7, 3, 9],
  32. ... [1, 5, 3, 1],
  33. ... [1, 2, 0, 8]
  34. ... ])
  35. >>> C, F = A.rank_decomposition()
  36. >>> C
  37. Matrix([
  38. [1, 3, 4],
  39. [2, 7, 9],
  40. [1, 5, 1],
  41. [1, 2, 8]])
  42. >>> F
  43. Matrix([
  44. [1, 0, -2, 0],
  45. [0, 1, 1, 0],
  46. [0, 0, 0, 1]])
  47. >>> C * F == A
  48. True
  49. Notes
  50. =====
  51. Obtaining `F`, an RREF of `A`, is equivalent to creating a
  52. product
  53. .. math::
  54. E_n E_{n-1} ... E_1 A = F
  55. where `E_n, E_{n-1}, \dots, E_1` are the elimination matrices or
  56. permutation matrices equivalent to each row-reduction step.
  57. The inverse of the same product of elimination matrices gives
  58. `C`:
  59. .. math::
  60. C = \left(E_n E_{n-1} \dots E_1\right)^{-1}
  61. It is not necessary, however, to actually compute the inverse:
  62. the columns of `C` are those from the original matrix with the
  63. same column indices as the indices of the pivot columns of `F`.
  64. References
  65. ==========
  66. .. [1] https://en.wikipedia.org/wiki/Rank_factorization
  67. .. [2] Piziak, R.; Odell, P. L. (1 June 1999).
  68. "Full Rank Factorization of Matrices".
  69. Mathematics Magazine. 72 (3): 193. doi:10.2307/2690882
  70. See Also
  71. ========
  72. sympy.matrices.matrices.MatrixReductions.rref
  73. """
  74. F, pivot_cols = M.rref(simplify=simplify, iszerofunc=iszerofunc,
  75. pivots=True)
  76. rank = len(pivot_cols)
  77. C = M.extract(range(M.rows), pivot_cols)
  78. F = F[:rank, :]
  79. return C, F
  80. def _liupc(M):
  81. """Liu's algorithm, for pre-determination of the Elimination Tree of
  82. the given matrix, used in row-based symbolic Cholesky factorization.
  83. Examples
  84. ========
  85. >>> from sympy import SparseMatrix
  86. >>> S = SparseMatrix([
  87. ... [1, 0, 3, 2],
  88. ... [0, 0, 1, 0],
  89. ... [4, 0, 0, 5],
  90. ... [0, 6, 7, 0]])
  91. >>> S.liupc()
  92. ([[0], [], [0], [1, 2]], [4, 3, 4, 4])
  93. References
  94. ==========
  95. .. [1] Symbolic Sparse Cholesky Factorization using Elimination Trees,
  96. Jeroen Van Grondelle (1999)
  97. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.7582
  98. """
  99. # Algorithm 2.4, p 17 of reference
  100. # get the indices of the elements that are non-zero on or below diag
  101. R = [[] for r in range(M.rows)]
  102. for r, c, _ in M.row_list():
  103. if c <= r:
  104. R[r].append(c)
  105. inf = len(R) # nothing will be this large
  106. parent = [inf]*M.rows
  107. virtual = [inf]*M.rows
  108. for r in range(M.rows):
  109. for c in R[r][:-1]:
  110. while virtual[c] < r:
  111. t = virtual[c]
  112. virtual[c] = r
  113. c = t
  114. if virtual[c] == inf:
  115. parent[c] = virtual[c] = r
  116. return R, parent
  117. def _row_structure_symbolic_cholesky(M):
  118. """Symbolic cholesky factorization, for pre-determination of the
  119. non-zero structure of the Cholesky factororization.
  120. Examples
  121. ========
  122. >>> from sympy import SparseMatrix
  123. >>> S = SparseMatrix([
  124. ... [1, 0, 3, 2],
  125. ... [0, 0, 1, 0],
  126. ... [4, 0, 0, 5],
  127. ... [0, 6, 7, 0]])
  128. >>> S.row_structure_symbolic_cholesky()
  129. [[0], [], [0], [1, 2]]
  130. References
  131. ==========
  132. .. [1] Symbolic Sparse Cholesky Factorization using Elimination Trees,
  133. Jeroen Van Grondelle (1999)
  134. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.7582
  135. """
  136. R, parent = M.liupc()
  137. inf = len(R) # this acts as infinity
  138. Lrow = copy.deepcopy(R)
  139. for k in range(M.rows):
  140. for j in R[k]:
  141. while j != inf and j != k:
  142. Lrow[k].append(j)
  143. j = parent[j]
  144. Lrow[k] = list(sorted(set(Lrow[k])))
  145. return Lrow
  146. def _cholesky(M, hermitian=True):
  147. """Returns the Cholesky-type decomposition L of a matrix A
  148. such that L * L.H == A if hermitian flag is True,
  149. or L * L.T == A if hermitian is False.
  150. A must be a Hermitian positive-definite matrix if hermitian is True,
  151. or a symmetric matrix if it is False.
  152. Examples
  153. ========
  154. >>> from sympy import Matrix
  155. >>> A = Matrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11)))
  156. >>> A.cholesky()
  157. Matrix([
  158. [ 5, 0, 0],
  159. [ 3, 3, 0],
  160. [-1, 1, 3]])
  161. >>> A.cholesky() * A.cholesky().T
  162. Matrix([
  163. [25, 15, -5],
  164. [15, 18, 0],
  165. [-5, 0, 11]])
  166. The matrix can have complex entries:
  167. >>> from sympy import I
  168. >>> A = Matrix(((9, 3*I), (-3*I, 5)))
  169. >>> A.cholesky()
  170. Matrix([
  171. [ 3, 0],
  172. [-I, 2]])
  173. >>> A.cholesky() * A.cholesky().H
  174. Matrix([
  175. [ 9, 3*I],
  176. [-3*I, 5]])
  177. Non-hermitian Cholesky-type decomposition may be useful when the
  178. matrix is not positive-definite.
  179. >>> A = Matrix([[1, 2], [2, 1]])
  180. >>> L = A.cholesky(hermitian=False)
  181. >>> L
  182. Matrix([
  183. [1, 0],
  184. [2, sqrt(3)*I]])
  185. >>> L*L.T == A
  186. True
  187. See Also
  188. ========
  189. sympy.matrices.dense.DenseMatrix.LDLdecomposition
  190. sympy.matrices.matrices.MatrixBase.LUdecomposition
  191. QRdecomposition
  192. """
  193. from .dense import MutableDenseMatrix
  194. if not M.is_square:
  195. raise NonSquareMatrixError("Matrix must be square.")
  196. if hermitian and not M.is_hermitian:
  197. raise ValueError("Matrix must be Hermitian.")
  198. if not hermitian and not M.is_symmetric():
  199. raise ValueError("Matrix must be symmetric.")
  200. L = MutableDenseMatrix.zeros(M.rows, M.rows)
  201. if hermitian:
  202. for i in range(M.rows):
  203. for j in range(i):
  204. L[i, j] = ((1 / L[j, j])*(M[i, j] -
  205. sum(L[i, k]*L[j, k].conjugate() for k in range(j))))
  206. Lii2 = (M[i, i] -
  207. sum(L[i, k]*L[i, k].conjugate() for k in range(i)))
  208. if Lii2.is_positive is False:
  209. raise NonPositiveDefiniteMatrixError(
  210. "Matrix must be positive-definite")
  211. L[i, i] = sqrt(Lii2)
  212. else:
  213. for i in range(M.rows):
  214. for j in range(i):
  215. L[i, j] = ((1 / L[j, j])*(M[i, j] -
  216. sum(L[i, k]*L[j, k] for k in range(j))))
  217. L[i, i] = sqrt(M[i, i] -
  218. sum(L[i, k]**2 for k in range(i)))
  219. return M._new(L)
  220. def _cholesky_sparse(M, hermitian=True):
  221. """
  222. Returns the Cholesky decomposition L of a matrix A
  223. such that L * L.T = A
  224. A must be a square, symmetric, positive-definite
  225. and non-singular matrix
  226. Examples
  227. ========
  228. >>> from sympy import SparseMatrix
  229. >>> A = SparseMatrix(((25,15,-5),(15,18,0),(-5,0,11)))
  230. >>> A.cholesky()
  231. Matrix([
  232. [ 5, 0, 0],
  233. [ 3, 3, 0],
  234. [-1, 1, 3]])
  235. >>> A.cholesky() * A.cholesky().T == A
  236. True
  237. The matrix can have complex entries:
  238. >>> from sympy import I
  239. >>> A = SparseMatrix(((9, 3*I), (-3*I, 5)))
  240. >>> A.cholesky()
  241. Matrix([
  242. [ 3, 0],
  243. [-I, 2]])
  244. >>> A.cholesky() * A.cholesky().H
  245. Matrix([
  246. [ 9, 3*I],
  247. [-3*I, 5]])
  248. Non-hermitian Cholesky-type decomposition may be useful when the
  249. matrix is not positive-definite.
  250. >>> A = SparseMatrix([[1, 2], [2, 1]])
  251. >>> L = A.cholesky(hermitian=False)
  252. >>> L
  253. Matrix([
  254. [1, 0],
  255. [2, sqrt(3)*I]])
  256. >>> L*L.T == A
  257. True
  258. See Also
  259. ========
  260. sympy.matrices.sparse.SparseMatrix.LDLdecomposition
  261. sympy.matrices.matrices.MatrixBase.LUdecomposition
  262. QRdecomposition
  263. """
  264. from .dense import MutableDenseMatrix
  265. if not M.is_square:
  266. raise NonSquareMatrixError("Matrix must be square.")
  267. if hermitian and not M.is_hermitian:
  268. raise ValueError("Matrix must be Hermitian.")
  269. if not hermitian and not M.is_symmetric():
  270. raise ValueError("Matrix must be symmetric.")
  271. dps = _get_intermediate_simp(expand_mul, expand_mul)
  272. Crowstruc = M.row_structure_symbolic_cholesky()
  273. C = MutableDenseMatrix.zeros(M.rows)
  274. for i in range(len(Crowstruc)):
  275. for j in Crowstruc[i]:
  276. if i != j:
  277. C[i, j] = M[i, j]
  278. summ = 0
  279. for p1 in Crowstruc[i]:
  280. if p1 < j:
  281. for p2 in Crowstruc[j]:
  282. if p2 < j:
  283. if p1 == p2:
  284. if hermitian:
  285. summ += C[i, p1]*C[j, p1].conjugate()
  286. else:
  287. summ += C[i, p1]*C[j, p1]
  288. else:
  289. break
  290. else:
  291. break
  292. C[i, j] = dps((C[i, j] - summ) / C[j, j])
  293. else: # i == j
  294. C[j, j] = M[j, j]
  295. summ = 0
  296. for k in Crowstruc[j]:
  297. if k < j:
  298. if hermitian:
  299. summ += C[j, k]*C[j, k].conjugate()
  300. else:
  301. summ += C[j, k]**2
  302. else:
  303. break
  304. Cjj2 = dps(C[j, j] - summ)
  305. if hermitian and Cjj2.is_positive is False:
  306. raise NonPositiveDefiniteMatrixError(
  307. "Matrix must be positive-definite")
  308. C[j, j] = sqrt(Cjj2)
  309. return M._new(C)
  310. def _LDLdecomposition(M, hermitian=True):
  311. """Returns the LDL Decomposition (L, D) of matrix A,
  312. such that L * D * L.H == A if hermitian flag is True, or
  313. L * D * L.T == A if hermitian is False.
  314. This method eliminates the use of square root.
  315. Further this ensures that all the diagonal entries of L are 1.
  316. A must be a Hermitian positive-definite matrix if hermitian is True,
  317. or a symmetric matrix otherwise.
  318. Examples
  319. ========
  320. >>> from sympy import Matrix, eye
  321. >>> A = Matrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11)))
  322. >>> L, D = A.LDLdecomposition()
  323. >>> L
  324. Matrix([
  325. [ 1, 0, 0],
  326. [ 3/5, 1, 0],
  327. [-1/5, 1/3, 1]])
  328. >>> D
  329. Matrix([
  330. [25, 0, 0],
  331. [ 0, 9, 0],
  332. [ 0, 0, 9]])
  333. >>> L * D * L.T * A.inv() == eye(A.rows)
  334. True
  335. The matrix can have complex entries:
  336. >>> from sympy import I
  337. >>> A = Matrix(((9, 3*I), (-3*I, 5)))
  338. >>> L, D = A.LDLdecomposition()
  339. >>> L
  340. Matrix([
  341. [ 1, 0],
  342. [-I/3, 1]])
  343. >>> D
  344. Matrix([
  345. [9, 0],
  346. [0, 4]])
  347. >>> L*D*L.H == A
  348. True
  349. See Also
  350. ========
  351. sympy.matrices.dense.DenseMatrix.cholesky
  352. sympy.matrices.matrices.MatrixBase.LUdecomposition
  353. QRdecomposition
  354. """
  355. from .dense import MutableDenseMatrix
  356. if not M.is_square:
  357. raise NonSquareMatrixError("Matrix must be square.")
  358. if hermitian and not M.is_hermitian:
  359. raise ValueError("Matrix must be Hermitian.")
  360. if not hermitian and not M.is_symmetric():
  361. raise ValueError("Matrix must be symmetric.")
  362. D = MutableDenseMatrix.zeros(M.rows, M.rows)
  363. L = MutableDenseMatrix.eye(M.rows)
  364. if hermitian:
  365. for i in range(M.rows):
  366. for j in range(i):
  367. L[i, j] = (1 / D[j, j])*(M[i, j] - sum(
  368. L[i, k]*L[j, k].conjugate()*D[k, k] for k in range(j)))
  369. D[i, i] = (M[i, i] -
  370. sum(L[i, k]*L[i, k].conjugate()*D[k, k] for k in range(i)))
  371. if D[i, i].is_positive is False:
  372. raise NonPositiveDefiniteMatrixError(
  373. "Matrix must be positive-definite")
  374. else:
  375. for i in range(M.rows):
  376. for j in range(i):
  377. L[i, j] = (1 / D[j, j])*(M[i, j] - sum(
  378. L[i, k]*L[j, k]*D[k, k] for k in range(j)))
  379. D[i, i] = M[i, i] - sum(L[i, k]**2*D[k, k] for k in range(i))
  380. return M._new(L), M._new(D)
  381. def _LDLdecomposition_sparse(M, hermitian=True):
  382. """
  383. Returns the LDL Decomposition (matrices ``L`` and ``D``) of matrix
  384. ``A``, such that ``L * D * L.T == A``. ``A`` must be a square,
  385. symmetric, positive-definite and non-singular.
  386. This method eliminates the use of square root and ensures that all
  387. the diagonal entries of L are 1.
  388. Examples
  389. ========
  390. >>> from sympy import SparseMatrix
  391. >>> A = SparseMatrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11)))
  392. >>> L, D = A.LDLdecomposition()
  393. >>> L
  394. Matrix([
  395. [ 1, 0, 0],
  396. [ 3/5, 1, 0],
  397. [-1/5, 1/3, 1]])
  398. >>> D
  399. Matrix([
  400. [25, 0, 0],
  401. [ 0, 9, 0],
  402. [ 0, 0, 9]])
  403. >>> L * D * L.T == A
  404. True
  405. """
  406. from .dense import MutableDenseMatrix
  407. if not M.is_square:
  408. raise NonSquareMatrixError("Matrix must be square.")
  409. if hermitian and not M.is_hermitian:
  410. raise ValueError("Matrix must be Hermitian.")
  411. if not hermitian and not M.is_symmetric():
  412. raise ValueError("Matrix must be symmetric.")
  413. dps = _get_intermediate_simp(expand_mul, expand_mul)
  414. Lrowstruc = M.row_structure_symbolic_cholesky()
  415. L = MutableDenseMatrix.eye(M.rows)
  416. D = MutableDenseMatrix.zeros(M.rows, M.cols)
  417. for i in range(len(Lrowstruc)):
  418. for j in Lrowstruc[i]:
  419. if i != j:
  420. L[i, j] = M[i, j]
  421. summ = 0
  422. for p1 in Lrowstruc[i]:
  423. if p1 < j:
  424. for p2 in Lrowstruc[j]:
  425. if p2 < j:
  426. if p1 == p2:
  427. if hermitian:
  428. summ += L[i, p1]*L[j, p1].conjugate()*D[p1, p1]
  429. else:
  430. summ += L[i, p1]*L[j, p1]*D[p1, p1]
  431. else:
  432. break
  433. else:
  434. break
  435. L[i, j] = dps((L[i, j] - summ) / D[j, j])
  436. else: # i == j
  437. D[i, i] = M[i, i]
  438. summ = 0
  439. for k in Lrowstruc[i]:
  440. if k < i:
  441. if hermitian:
  442. summ += L[i, k]*L[i, k].conjugate()*D[k, k]
  443. else:
  444. summ += L[i, k]**2*D[k, k]
  445. else:
  446. break
  447. D[i, i] = dps(D[i, i] - summ)
  448. if hermitian and D[i, i].is_positive is False:
  449. raise NonPositiveDefiniteMatrixError(
  450. "Matrix must be positive-definite")
  451. return M._new(L), M._new(D)
  452. def _LUdecomposition(M, iszerofunc=_iszero, simpfunc=None, rankcheck=False):
  453. """Returns (L, U, perm) where L is a lower triangular matrix with unit
  454. diagonal, U is an upper triangular matrix, and perm is a list of row
  455. swap index pairs. If A is the original matrix, then
  456. ``A = (L*U).permuteBkwd(perm)``, and the row permutation matrix P such
  457. that $P A = L U$ can be computed by ``P = eye(A.rows).permuteFwd(perm)``.
  458. See documentation for LUCombined for details about the keyword argument
  459. rankcheck, iszerofunc, and simpfunc.
  460. Parameters
  461. ==========
  462. rankcheck : bool, optional
  463. Determines if this function should detect the rank
  464. deficiency of the matrixis and should raise a
  465. ``ValueError``.
  466. iszerofunc : function, optional
  467. A function which determines if a given expression is zero.
  468. The function should be a callable that takes a single
  469. SymPy expression and returns a 3-valued boolean value
  470. ``True``, ``False``, or ``None``.
  471. It is internally used by the pivot searching algorithm.
  472. See the notes section for a more information about the
  473. pivot searching algorithm.
  474. simpfunc : function or None, optional
  475. A function that simplifies the input.
  476. If this is specified as a function, this function should be
  477. a callable that takes a single SymPy expression and returns
  478. an another SymPy expression that is algebraically
  479. equivalent.
  480. If ``None``, it indicates that the pivot search algorithm
  481. should not attempt to simplify any candidate pivots.
  482. It is internally used by the pivot searching algorithm.
  483. See the notes section for a more information about the
  484. pivot searching algorithm.
  485. Examples
  486. ========
  487. >>> from sympy import Matrix
  488. >>> a = Matrix([[4, 3], [6, 3]])
  489. >>> L, U, _ = a.LUdecomposition()
  490. >>> L
  491. Matrix([
  492. [ 1, 0],
  493. [3/2, 1]])
  494. >>> U
  495. Matrix([
  496. [4, 3],
  497. [0, -3/2]])
  498. See Also
  499. ========
  500. sympy.matrices.dense.DenseMatrix.cholesky
  501. sympy.matrices.dense.DenseMatrix.LDLdecomposition
  502. QRdecomposition
  503. LUdecomposition_Simple
  504. LUdecompositionFF
  505. LUsolve
  506. """
  507. combined, p = M.LUdecomposition_Simple(iszerofunc=iszerofunc,
  508. simpfunc=simpfunc, rankcheck=rankcheck)
  509. # L is lower triangular ``M.rows x M.rows``
  510. # U is upper triangular ``M.rows x M.cols``
  511. # L has unit diagonal. For each column in combined, the subcolumn
  512. # below the diagonal of combined is shared by L.
  513. # If L has more columns than combined, then the remaining subcolumns
  514. # below the diagonal of L are zero.
  515. # The upper triangular portion of L and combined are equal.
  516. def entry_L(i, j):
  517. if i < j:
  518. # Super diagonal entry
  519. return M.zero
  520. elif i == j:
  521. return M.one
  522. elif j < combined.cols:
  523. return combined[i, j]
  524. # Subdiagonal entry of L with no corresponding
  525. # entry in combined
  526. return M.zero
  527. def entry_U(i, j):
  528. return M.zero if i > j else combined[i, j]
  529. L = M._new(combined.rows, combined.rows, entry_L)
  530. U = M._new(combined.rows, combined.cols, entry_U)
  531. return L, U, p
  532. def _LUdecomposition_Simple(M, iszerofunc=_iszero, simpfunc=None,
  533. rankcheck=False):
  534. r"""Compute the PLU decomposition of the matrix.
  535. Parameters
  536. ==========
  537. rankcheck : bool, optional
  538. Determines if this function should detect the rank
  539. deficiency of the matrixis and should raise a
  540. ``ValueError``.
  541. iszerofunc : function, optional
  542. A function which determines if a given expression is zero.
  543. The function should be a callable that takes a single
  544. SymPy expression and returns a 3-valued boolean value
  545. ``True``, ``False``, or ``None``.
  546. It is internally used by the pivot searching algorithm.
  547. See the notes section for a more information about the
  548. pivot searching algorithm.
  549. simpfunc : function or None, optional
  550. A function that simplifies the input.
  551. If this is specified as a function, this function should be
  552. a callable that takes a single SymPy expression and returns
  553. an another SymPy expression that is algebraically
  554. equivalent.
  555. If ``None``, it indicates that the pivot search algorithm
  556. should not attempt to simplify any candidate pivots.
  557. It is internally used by the pivot searching algorithm.
  558. See the notes section for a more information about the
  559. pivot searching algorithm.
  560. Returns
  561. =======
  562. (lu, row_swaps) : (Matrix, list)
  563. If the original matrix is a $m, n$ matrix:
  564. *lu* is a $m, n$ matrix, which contains result of the
  565. decomposition in a compresed form. See the notes section
  566. to see how the matrix is compressed.
  567. *row_swaps* is a $m$-element list where each element is a
  568. pair of row exchange indices.
  569. ``A = (L*U).permute_backward(perm)``, and the row
  570. permutation matrix $P$ from the formula $P A = L U$ can be
  571. computed by ``P=eye(A.row).permute_forward(perm)``.
  572. Raises
  573. ======
  574. ValueError
  575. Raised if ``rankcheck=True`` and the matrix is found to
  576. be rank deficient during the computation.
  577. Notes
  578. =====
  579. About the PLU decomposition:
  580. PLU decomposition is a generalization of a LU decomposition
  581. which can be extended for rank-deficient matrices.
  582. It can further be generalized for non-square matrices, and this
  583. is the notation that SymPy is using.
  584. PLU decomposition is a decomposition of a $m, n$ matrix $A$ in
  585. the form of $P A = L U$ where
  586. * $L$ is a $m, m$ lower triangular matrix with unit diagonal
  587. entries.
  588. * $U$ is a $m, n$ upper triangular matrix.
  589. * $P$ is a $m, m$ permutation matrix.
  590. So, for a square matrix, the decomposition would look like:
  591. .. math::
  592. L = \begin{bmatrix}
  593. 1 & 0 & 0 & \cdots & 0 \\
  594. L_{1, 0} & 1 & 0 & \cdots & 0 \\
  595. L_{2, 0} & L_{2, 1} & 1 & \cdots & 0 \\
  596. \vdots & \vdots & \vdots & \ddots & \vdots \\
  597. L_{n-1, 0} & L_{n-1, 1} & L_{n-1, 2} & \cdots & 1
  598. \end{bmatrix}
  599. .. math::
  600. U = \begin{bmatrix}
  601. U_{0, 0} & U_{0, 1} & U_{0, 2} & \cdots & U_{0, n-1} \\
  602. 0 & U_{1, 1} & U_{1, 2} & \cdots & U_{1, n-1} \\
  603. 0 & 0 & U_{2, 2} & \cdots & U_{2, n-1} \\
  604. \vdots & \vdots & \vdots & \ddots & \vdots \\
  605. 0 & 0 & 0 & \cdots & U_{n-1, n-1}
  606. \end{bmatrix}
  607. And for a matrix with more rows than the columns,
  608. the decomposition would look like:
  609. .. math::
  610. L = \begin{bmatrix}
  611. 1 & 0 & 0 & \cdots & 0 & 0 & \cdots & 0 \\
  612. L_{1, 0} & 1 & 0 & \cdots & 0 & 0 & \cdots & 0 \\
  613. L_{2, 0} & L_{2, 1} & 1 & \cdots & 0 & 0 & \cdots & 0 \\
  614. \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \ddots
  615. & \vdots \\
  616. L_{n-1, 0} & L_{n-1, 1} & L_{n-1, 2} & \cdots & 1 & 0
  617. & \cdots & 0 \\
  618. L_{n, 0} & L_{n, 1} & L_{n, 2} & \cdots & L_{n, n-1} & 1
  619. & \cdots & 0 \\
  620. \vdots & \vdots & \vdots & \ddots & \vdots & \vdots
  621. & \ddots & \vdots \\
  622. L_{m-1, 0} & L_{m-1, 1} & L_{m-1, 2} & \cdots & L_{m-1, n-1}
  623. & 0 & \cdots & 1 \\
  624. \end{bmatrix}
  625. .. math::
  626. U = \begin{bmatrix}
  627. U_{0, 0} & U_{0, 1} & U_{0, 2} & \cdots & U_{0, n-1} \\
  628. 0 & U_{1, 1} & U_{1, 2} & \cdots & U_{1, n-1} \\
  629. 0 & 0 & U_{2, 2} & \cdots & U_{2, n-1} \\
  630. \vdots & \vdots & \vdots & \ddots & \vdots \\
  631. 0 & 0 & 0 & \cdots & U_{n-1, n-1} \\
  632. 0 & 0 & 0 & \cdots & 0 \\
  633. \vdots & \vdots & \vdots & \ddots & \vdots \\
  634. 0 & 0 & 0 & \cdots & 0
  635. \end{bmatrix}
  636. Finally, for a matrix with more columns than the rows, the
  637. decomposition would look like:
  638. .. math::
  639. L = \begin{bmatrix}
  640. 1 & 0 & 0 & \cdots & 0 \\
  641. L_{1, 0} & 1 & 0 & \cdots & 0 \\
  642. L_{2, 0} & L_{2, 1} & 1 & \cdots & 0 \\
  643. \vdots & \vdots & \vdots & \ddots & \vdots \\
  644. L_{m-1, 0} & L_{m-1, 1} & L_{m-1, 2} & \cdots & 1
  645. \end{bmatrix}
  646. .. math::
  647. U = \begin{bmatrix}
  648. U_{0, 0} & U_{0, 1} & U_{0, 2} & \cdots & U_{0, m-1}
  649. & \cdots & U_{0, n-1} \\
  650. 0 & U_{1, 1} & U_{1, 2} & \cdots & U_{1, m-1}
  651. & \cdots & U_{1, n-1} \\
  652. 0 & 0 & U_{2, 2} & \cdots & U_{2, m-1}
  653. & \cdots & U_{2, n-1} \\
  654. \vdots & \vdots & \vdots & \ddots & \vdots
  655. & \cdots & \vdots \\
  656. 0 & 0 & 0 & \cdots & U_{m-1, m-1}
  657. & \cdots & U_{m-1, n-1} \\
  658. \end{bmatrix}
  659. About the compressed LU storage:
  660. The results of the decomposition are often stored in compressed
  661. forms rather than returning $L$ and $U$ matrices individually.
  662. It may be less intiuitive, but it is commonly used for a lot of
  663. numeric libraries because of the efficiency.
  664. The storage matrix is defined as following for this specific
  665. method:
  666. * The subdiagonal elements of $L$ are stored in the subdiagonal
  667. portion of $LU$, that is $LU_{i, j} = L_{i, j}$ whenever
  668. $i > j$.
  669. * The elements on the diagonal of $L$ are all 1, and are not
  670. explicitly stored.
  671. * $U$ is stored in the upper triangular portion of $LU$, that is
  672. $LU_{i, j} = U_{i, j}$ whenever $i <= j$.
  673. * For a case of $m > n$, the right side of the $L$ matrix is
  674. trivial to store.
  675. * For a case of $m < n$, the below side of the $U$ matrix is
  676. trivial to store.
  677. So, for a square matrix, the compressed output matrix would be:
  678. .. math::
  679. LU = \begin{bmatrix}
  680. U_{0, 0} & U_{0, 1} & U_{0, 2} & \cdots & U_{0, n-1} \\
  681. L_{1, 0} & U_{1, 1} & U_{1, 2} & \cdots & U_{1, n-1} \\
  682. L_{2, 0} & L_{2, 1} & U_{2, 2} & \cdots & U_{2, n-1} \\
  683. \vdots & \vdots & \vdots & \ddots & \vdots \\
  684. L_{n-1, 0} & L_{n-1, 1} & L_{n-1, 2} & \cdots & U_{n-1, n-1}
  685. \end{bmatrix}
  686. For a matrix with more rows than the columns, the compressed
  687. output matrix would be:
  688. .. math::
  689. LU = \begin{bmatrix}
  690. U_{0, 0} & U_{0, 1} & U_{0, 2} & \cdots & U_{0, n-1} \\
  691. L_{1, 0} & U_{1, 1} & U_{1, 2} & \cdots & U_{1, n-1} \\
  692. L_{2, 0} & L_{2, 1} & U_{2, 2} & \cdots & U_{2, n-1} \\
  693. \vdots & \vdots & \vdots & \ddots & \vdots \\
  694. L_{n-1, 0} & L_{n-1, 1} & L_{n-1, 2} & \cdots
  695. & U_{n-1, n-1} \\
  696. \vdots & \vdots & \vdots & \ddots & \vdots \\
  697. L_{m-1, 0} & L_{m-1, 1} & L_{m-1, 2} & \cdots
  698. & L_{m-1, n-1} \\
  699. \end{bmatrix}
  700. For a matrix with more columns than the rows, the compressed
  701. output matrix would be:
  702. .. math::
  703. LU = \begin{bmatrix}
  704. U_{0, 0} & U_{0, 1} & U_{0, 2} & \cdots & U_{0, m-1}
  705. & \cdots & U_{0, n-1} \\
  706. L_{1, 0} & U_{1, 1} & U_{1, 2} & \cdots & U_{1, m-1}
  707. & \cdots & U_{1, n-1} \\
  708. L_{2, 0} & L_{2, 1} & U_{2, 2} & \cdots & U_{2, m-1}
  709. & \cdots & U_{2, n-1} \\
  710. \vdots & \vdots & \vdots & \ddots & \vdots
  711. & \cdots & \vdots \\
  712. L_{m-1, 0} & L_{m-1, 1} & L_{m-1, 2} & \cdots & U_{m-1, m-1}
  713. & \cdots & U_{m-1, n-1} \\
  714. \end{bmatrix}
  715. About the pivot searching algorithm:
  716. When a matrix contains symbolic entries, the pivot search algorithm
  717. differs from the case where every entry can be categorized as zero or
  718. nonzero.
  719. The algorithm searches column by column through the submatrix whose
  720. top left entry coincides with the pivot position.
  721. If it exists, the pivot is the first entry in the current search
  722. column that iszerofunc guarantees is nonzero.
  723. If no such candidate exists, then each candidate pivot is simplified
  724. if simpfunc is not None.
  725. The search is repeated, with the difference that a candidate may be
  726. the pivot if ``iszerofunc()`` cannot guarantee that it is nonzero.
  727. In the second search the pivot is the first candidate that
  728. iszerofunc can guarantee is nonzero.
  729. If no such candidate exists, then the pivot is the first candidate
  730. for which iszerofunc returns None.
  731. If no such candidate exists, then the search is repeated in the next
  732. column to the right.
  733. The pivot search algorithm differs from the one in ``rref()``, which
  734. relies on ``_find_reasonable_pivot()``.
  735. Future versions of ``LUdecomposition_simple()`` may use
  736. ``_find_reasonable_pivot()``.
  737. See Also
  738. ========
  739. sympy.matrices.matrices.MatrixBase.LUdecomposition
  740. LUdecompositionFF
  741. LUsolve
  742. """
  743. if rankcheck:
  744. # https://github.com/sympy/sympy/issues/9796
  745. pass
  746. if S.Zero in M.shape:
  747. # Define LU decomposition of a matrix with no entries as a matrix
  748. # of the same dimensions with all zero entries.
  749. return M.zeros(M.rows, M.cols), []
  750. dps = _get_intermediate_simp()
  751. lu = M.as_mutable()
  752. row_swaps = []
  753. pivot_col = 0
  754. for pivot_row in range(0, lu.rows - 1):
  755. # Search for pivot. Prefer entry that iszeropivot determines
  756. # is nonzero, over entry that iszeropivot cannot guarantee
  757. # is zero.
  758. # XXX ``_find_reasonable_pivot`` uses slow zero testing. Blocked by bug #10279
  759. # Future versions of LUdecomposition_simple can pass iszerofunc and simpfunc
  760. # to _find_reasonable_pivot().
  761. # In pass 3 of _find_reasonable_pivot(), the predicate in ``if x.equals(S.Zero):``
  762. # calls sympy.simplify(), and not the simplification function passed in via
  763. # the keyword argument simpfunc.
  764. iszeropivot = True
  765. while pivot_col != M.cols and iszeropivot:
  766. sub_col = (lu[r, pivot_col] for r in range(pivot_row, M.rows))
  767. pivot_row_offset, pivot_value, is_assumed_non_zero, ind_simplified_pairs =\
  768. _find_reasonable_pivot_naive(sub_col, iszerofunc, simpfunc)
  769. iszeropivot = pivot_value is None
  770. if iszeropivot:
  771. # All candidate pivots in this column are zero.
  772. # Proceed to next column.
  773. pivot_col += 1
  774. if rankcheck and pivot_col != pivot_row:
  775. # All entries including and below the pivot position are
  776. # zero, which indicates that the rank of the matrix is
  777. # strictly less than min(num rows, num cols)
  778. # Mimic behavior of previous implementation, by throwing a
  779. # ValueError.
  780. raise ValueError("Rank of matrix is strictly less than"
  781. " number of rows or columns."
  782. " Pass keyword argument"
  783. " rankcheck=False to compute"
  784. " the LU decomposition of this matrix.")
  785. candidate_pivot_row = None if pivot_row_offset is None else pivot_row + pivot_row_offset
  786. if candidate_pivot_row is None and iszeropivot:
  787. # If candidate_pivot_row is None and iszeropivot is True
  788. # after pivot search has completed, then the submatrix
  789. # below and to the right of (pivot_row, pivot_col) is
  790. # all zeros, indicating that Gaussian elimination is
  791. # complete.
  792. return lu, row_swaps
  793. # Update entries simplified during pivot search.
  794. for offset, val in ind_simplified_pairs:
  795. lu[pivot_row + offset, pivot_col] = val
  796. if pivot_row != candidate_pivot_row:
  797. # Row swap book keeping:
  798. # Record which rows were swapped.
  799. # Update stored portion of L factor by multiplying L on the
  800. # left and right with the current permutation.
  801. # Swap rows of U.
  802. row_swaps.append([pivot_row, candidate_pivot_row])
  803. # Update L.
  804. lu[pivot_row, 0:pivot_row], lu[candidate_pivot_row, 0:pivot_row] = \
  805. lu[candidate_pivot_row, 0:pivot_row], lu[pivot_row, 0:pivot_row]
  806. # Swap pivot row of U with candidate pivot row.
  807. lu[pivot_row, pivot_col:lu.cols], lu[candidate_pivot_row, pivot_col:lu.cols] = \
  808. lu[candidate_pivot_row, pivot_col:lu.cols], lu[pivot_row, pivot_col:lu.cols]
  809. # Introduce zeros below the pivot by adding a multiple of the
  810. # pivot row to a row under it, and store the result in the
  811. # row under it.
  812. # Only entries in the target row whose index is greater than
  813. # start_col may be nonzero.
  814. start_col = pivot_col + 1
  815. for row in range(pivot_row + 1, lu.rows):
  816. # Store factors of L in the subcolumn below
  817. # (pivot_row, pivot_row).
  818. lu[row, pivot_row] = \
  819. dps(lu[row, pivot_col]/lu[pivot_row, pivot_col])
  820. # Form the linear combination of the pivot row and the current
  821. # row below the pivot row that zeros the entries below the pivot.
  822. # Employing slicing instead of a loop here raises
  823. # NotImplementedError: Cannot add Zero to MutableSparseMatrix
  824. # in sympy/matrices/tests/test_sparse.py.
  825. # c = pivot_row + 1 if pivot_row == pivot_col else pivot_col
  826. for c in range(start_col, lu.cols):
  827. lu[row, c] = dps(lu[row, c] - lu[row, pivot_row]*lu[pivot_row, c])
  828. if pivot_row != pivot_col:
  829. # matrix rank < min(num rows, num cols),
  830. # so factors of L are not stored directly below the pivot.
  831. # These entries are zero by construction, so don't bother
  832. # computing them.
  833. for row in range(pivot_row + 1, lu.rows):
  834. lu[row, pivot_col] = M.zero
  835. pivot_col += 1
  836. if pivot_col == lu.cols:
  837. # All candidate pivots are zero implies that Gaussian
  838. # elimination is complete.
  839. return lu, row_swaps
  840. if rankcheck:
  841. if iszerofunc(
  842. lu[Min(lu.rows, lu.cols) - 1, Min(lu.rows, lu.cols) - 1]):
  843. raise ValueError("Rank of matrix is strictly less than"
  844. " number of rows or columns."
  845. " Pass keyword argument"
  846. " rankcheck=False to compute"
  847. " the LU decomposition of this matrix.")
  848. return lu, row_swaps
  849. def _LUdecompositionFF(M):
  850. """Compute a fraction-free LU decomposition.
  851. Returns 4 matrices P, L, D, U such that PA = L D**-1 U.
  852. If the elements of the matrix belong to some integral domain I, then all
  853. elements of L, D and U are guaranteed to belong to I.
  854. See Also
  855. ========
  856. sympy.matrices.matrices.MatrixBase.LUdecomposition
  857. LUdecomposition_Simple
  858. LUsolve
  859. References
  860. ==========
  861. .. [1] W. Zhou & D.J. Jeffrey, "Fraction-free matrix factors: new forms
  862. for LU and QR factors". Frontiers in Computer Science in China,
  863. Vol 2, no. 1, pp. 67-80, 2008.
  864. """
  865. from sympy.matrices import SparseMatrix
  866. zeros = SparseMatrix.zeros
  867. eye = SparseMatrix.eye
  868. n, m = M.rows, M.cols
  869. U, L, P = M.as_mutable(), eye(n), eye(n)
  870. DD = zeros(n, n)
  871. oldpivot = 1
  872. for k in range(n - 1):
  873. if U[k, k] == 0:
  874. for kpivot in range(k + 1, n):
  875. if U[kpivot, k]:
  876. break
  877. else:
  878. raise ValueError("Matrix is not full rank")
  879. U[k, k:], U[kpivot, k:] = U[kpivot, k:], U[k, k:]
  880. L[k, :k], L[kpivot, :k] = L[kpivot, :k], L[k, :k]
  881. P[k, :], P[kpivot, :] = P[kpivot, :], P[k, :]
  882. L [k, k] = Ukk = U[k, k]
  883. DD[k, k] = oldpivot * Ukk
  884. for i in range(k + 1, n):
  885. L[i, k] = Uik = U[i, k]
  886. for j in range(k + 1, m):
  887. U[i, j] = (Ukk * U[i, j] - U[k, j] * Uik) / oldpivot
  888. U[i, k] = 0
  889. oldpivot = Ukk
  890. DD[n - 1, n - 1] = oldpivot
  891. return P, L, DD, U
  892. def _singular_value_decomposition(A):
  893. r"""Returns a Condensed Singular Value decomposition.
  894. Explanation
  895. ===========
  896. A Singular Value decomposition is a decomposition in the form $A = U \Sigma V$
  897. where
  898. - $U, V$ are column orthogonal matrix.
  899. - $\Sigma$ is a diagonal matrix, where the main diagonal contains singular
  900. values of matrix A.
  901. A column orthogonal matrix satisfies
  902. $\mathbb{I} = U^H U$ while a full orthogonal matrix satisfies
  903. relation $\mathbb{I} = U U^H = U^H U$ where $\mathbb{I}$ is an identity
  904. matrix with matching dimensions.
  905. For matrices which are not square or are rank-deficient, it is
  906. sufficient to return a column orthogonal matrix because augmenting
  907. them may introduce redundant computations.
  908. In condensed Singular Value Decomposition we only return column orthognal
  909. matrices because of this reason
  910. If you want to augment the results to return a full orthogonal
  911. decomposition, you should use the following procedures.
  912. - Augment the $U, V$ matrices with columns that are orthogonal to every
  913. other columns and make it square.
  914. - Augument the $\Sigma$ matrix with zero rows to make it have the same
  915. shape as the original matrix.
  916. The procedure will be illustrated in the examples section.
  917. Examples
  918. ========
  919. we take a full rank matrix first:
  920. >>> from sympy import Matrix
  921. >>> A = Matrix([[1, 2],[2,1]])
  922. >>> U, S, V = A.singular_value_decomposition()
  923. >>> U
  924. Matrix([
  925. [ sqrt(2)/2, sqrt(2)/2],
  926. [-sqrt(2)/2, sqrt(2)/2]])
  927. >>> S
  928. Matrix([
  929. [1, 0],
  930. [0, 3]])
  931. >>> V
  932. Matrix([
  933. [-sqrt(2)/2, sqrt(2)/2],
  934. [ sqrt(2)/2, sqrt(2)/2]])
  935. If a matrix if square and full rank both U, V
  936. are orthogonal in both directions
  937. >>> U * U.H
  938. Matrix([
  939. [1, 0],
  940. [0, 1]])
  941. >>> U.H * U
  942. Matrix([
  943. [1, 0],
  944. [0, 1]])
  945. >>> V * V.H
  946. Matrix([
  947. [1, 0],
  948. [0, 1]])
  949. >>> V.H * V
  950. Matrix([
  951. [1, 0],
  952. [0, 1]])
  953. >>> A == U * S * V.H
  954. True
  955. >>> C = Matrix([
  956. ... [1, 0, 0, 0, 2],
  957. ... [0, 0, 3, 0, 0],
  958. ... [0, 0, 0, 0, 0],
  959. ... [0, 2, 0, 0, 0],
  960. ... ])
  961. >>> U, S, V = C.singular_value_decomposition()
  962. >>> V.H * V
  963. Matrix([
  964. [1, 0, 0],
  965. [0, 1, 0],
  966. [0, 0, 1]])
  967. >>> V * V.H
  968. Matrix([
  969. [1/5, 0, 0, 0, 2/5],
  970. [ 0, 1, 0, 0, 0],
  971. [ 0, 0, 1, 0, 0],
  972. [ 0, 0, 0, 0, 0],
  973. [2/5, 0, 0, 0, 4/5]])
  974. If you want to augment the results to be a full orthogonal
  975. decomposition, you should augment $V$ with an another orthogonal
  976. column.
  977. You are able to append an arbitrary standard basis that are linearly
  978. independent to every other columns and you can run the Gram-Schmidt
  979. process to make them augmented as orthogonal basis.
  980. >>> V_aug = V.row_join(Matrix([[0,0,0,0,1],
  981. ... [0,0,0,1,0]]).H)
  982. >>> V_aug = V_aug.QRdecomposition()[0]
  983. >>> V_aug
  984. Matrix([
  985. [0, sqrt(5)/5, 0, -2*sqrt(5)/5, 0],
  986. [1, 0, 0, 0, 0],
  987. [0, 0, 1, 0, 0],
  988. [0, 0, 0, 0, 1],
  989. [0, 2*sqrt(5)/5, 0, sqrt(5)/5, 0]])
  990. >>> V_aug.H * V_aug
  991. Matrix([
  992. [1, 0, 0, 0, 0],
  993. [0, 1, 0, 0, 0],
  994. [0, 0, 1, 0, 0],
  995. [0, 0, 0, 1, 0],
  996. [0, 0, 0, 0, 1]])
  997. >>> V_aug * V_aug.H
  998. Matrix([
  999. [1, 0, 0, 0, 0],
  1000. [0, 1, 0, 0, 0],
  1001. [0, 0, 1, 0, 0],
  1002. [0, 0, 0, 1, 0],
  1003. [0, 0, 0, 0, 1]])
  1004. Similarly we augment U
  1005. >>> U_aug = U.row_join(Matrix([0,0,1,0]))
  1006. >>> U_aug = U_aug.QRdecomposition()[0]
  1007. >>> U_aug
  1008. Matrix([
  1009. [0, 1, 0, 0],
  1010. [0, 0, 1, 0],
  1011. [0, 0, 0, 1],
  1012. [1, 0, 0, 0]])
  1013. >>> U_aug.H * U_aug
  1014. Matrix([
  1015. [1, 0, 0, 0],
  1016. [0, 1, 0, 0],
  1017. [0, 0, 1, 0],
  1018. [0, 0, 0, 1]])
  1019. >>> U_aug * U_aug.H
  1020. Matrix([
  1021. [1, 0, 0, 0],
  1022. [0, 1, 0, 0],
  1023. [0, 0, 1, 0],
  1024. [0, 0, 0, 1]])
  1025. We add 2 zero columns and one row to S
  1026. >>> S_aug = S.col_join(Matrix([[0,0,0]]))
  1027. >>> S_aug = S_aug.row_join(Matrix([[0,0,0,0],
  1028. ... [0,0,0,0]]).H)
  1029. >>> S_aug
  1030. Matrix([
  1031. [2, 0, 0, 0, 0],
  1032. [0, sqrt(5), 0, 0, 0],
  1033. [0, 0, 3, 0, 0],
  1034. [0, 0, 0, 0, 0]])
  1035. >>> U_aug * S_aug * V_aug.H == C
  1036. True
  1037. """
  1038. AH = A.H
  1039. m, n = A.shape
  1040. if m >= n:
  1041. V, S = (AH * A).diagonalize()
  1042. ranked = []
  1043. for i, x in enumerate(S.diagonal()):
  1044. if not x.is_zero:
  1045. ranked.append(i)
  1046. V = V[:, ranked]
  1047. Singular_vals = [sqrt(S[i, i]) for i in range(S.rows) if i in ranked]
  1048. S = S.zeros(len(Singular_vals))
  1049. for i in range(len(Singular_vals)):
  1050. S[i, i] = Singular_vals[i]
  1051. V, _ = V.QRdecomposition()
  1052. U = A * V * S.inv()
  1053. else:
  1054. U, S = (A * AH).diagonalize()
  1055. ranked = []
  1056. for i, x in enumerate(S.diagonal()):
  1057. if not x.is_zero:
  1058. ranked.append(i)
  1059. U = U[:, ranked]
  1060. Singular_vals = [sqrt(S[i, i]) for i in range(S.rows) if i in ranked]
  1061. S = S.zeros(len(Singular_vals))
  1062. for i in range(len(Singular_vals)):
  1063. S[i, i] = Singular_vals[i]
  1064. U, _ = U.QRdecomposition()
  1065. V = AH * U * S.inv()
  1066. return U, S, V
  1067. def _QRdecomposition_optional(M, normalize=True):
  1068. def dot(u, v):
  1069. return u.dot(v, hermitian=True)
  1070. dps = _get_intermediate_simp(expand_mul, expand_mul)
  1071. A = M.as_mutable()
  1072. ranked = list()
  1073. Q = A
  1074. R = A.zeros(A.cols)
  1075. for j in range(A.cols):
  1076. for i in range(j):
  1077. if Q[:, i].is_zero_matrix:
  1078. continue
  1079. R[i, j] = dot(Q[:, i], Q[:, j]) / dot(Q[:, i], Q[:, i])
  1080. R[i, j] = dps(R[i, j])
  1081. Q[:, j] -= Q[:, i] * R[i, j]
  1082. Q[:, j] = dps(Q[:, j])
  1083. if Q[:, j].is_zero_matrix is False:
  1084. ranked.append(j)
  1085. R[j, j] = M.one
  1086. Q = Q.extract(range(Q.rows), ranked)
  1087. R = R.extract(ranked, range(R.cols))
  1088. if normalize:
  1089. # Normalization
  1090. for i in range(Q.cols):
  1091. norm = Q[:, i].norm()
  1092. Q[:, i] /= norm
  1093. R[i, :] *= norm
  1094. return M.__class__(Q), M.__class__(R)
  1095. def _QRdecomposition(M):
  1096. r"""Returns a QR decomposition.
  1097. Explanation
  1098. ===========
  1099. A QR decomposition is a decomposition in the form $A = Q R$
  1100. where
  1101. - $Q$ is a column orthogonal matrix.
  1102. - $R$ is a upper triangular (trapezoidal) matrix.
  1103. A column orthogonal matrix satisfies
  1104. $\mathbb{I} = Q^H Q$ while a full orthogonal matrix satisfies
  1105. relation $\mathbb{I} = Q Q^H = Q^H Q$ where $I$ is an identity
  1106. matrix with matching dimensions.
  1107. For matrices which are not square or are rank-deficient, it is
  1108. sufficient to return a column orthogonal matrix because augmenting
  1109. them may introduce redundant computations.
  1110. And an another advantage of this is that you can easily inspect the
  1111. matrix rank by counting the number of columns of $Q$.
  1112. If you want to augment the results to return a full orthogonal
  1113. decomposition, you should use the following procedures.
  1114. - Augment the $Q$ matrix with columns that are orthogonal to every
  1115. other columns and make it square.
  1116. - Augument the $R$ matrix with zero rows to make it have the same
  1117. shape as the original matrix.
  1118. The procedure will be illustrated in the examples section.
  1119. Examples
  1120. ========
  1121. A full rank matrix example:
  1122. >>> from sympy import Matrix
  1123. >>> A = Matrix([[12, -51, 4], [6, 167, -68], [-4, 24, -41]])
  1124. >>> Q, R = A.QRdecomposition()
  1125. >>> Q
  1126. Matrix([
  1127. [ 6/7, -69/175, -58/175],
  1128. [ 3/7, 158/175, 6/175],
  1129. [-2/7, 6/35, -33/35]])
  1130. >>> R
  1131. Matrix([
  1132. [14, 21, -14],
  1133. [ 0, 175, -70],
  1134. [ 0, 0, 35]])
  1135. If the matrix is square and full rank, the $Q$ matrix becomes
  1136. orthogonal in both directions, and needs no augmentation.
  1137. >>> Q * Q.H
  1138. Matrix([
  1139. [1, 0, 0],
  1140. [0, 1, 0],
  1141. [0, 0, 1]])
  1142. >>> Q.H * Q
  1143. Matrix([
  1144. [1, 0, 0],
  1145. [0, 1, 0],
  1146. [0, 0, 1]])
  1147. >>> A == Q*R
  1148. True
  1149. A rank deficient matrix example:
  1150. >>> A = Matrix([[12, -51, 0], [6, 167, 0], [-4, 24, 0]])
  1151. >>> Q, R = A.QRdecomposition()
  1152. >>> Q
  1153. Matrix([
  1154. [ 6/7, -69/175],
  1155. [ 3/7, 158/175],
  1156. [-2/7, 6/35]])
  1157. >>> R
  1158. Matrix([
  1159. [14, 21, 0],
  1160. [ 0, 175, 0]])
  1161. QRdecomposition might return a matrix Q that is rectangular.
  1162. In this case the orthogonality condition might be satisfied as
  1163. $\mathbb{I} = Q.H*Q$ but not in the reversed product
  1164. $\mathbb{I} = Q * Q.H$.
  1165. >>> Q.H * Q
  1166. Matrix([
  1167. [1, 0],
  1168. [0, 1]])
  1169. >>> Q * Q.H
  1170. Matrix([
  1171. [27261/30625, 348/30625, -1914/6125],
  1172. [ 348/30625, 30589/30625, 198/6125],
  1173. [ -1914/6125, 198/6125, 136/1225]])
  1174. If you want to augment the results to be a full orthogonal
  1175. decomposition, you should augment $Q$ with an another orthogonal
  1176. column.
  1177. You are able to append an arbitrary standard basis that are linearly
  1178. independent to every other columns and you can run the Gram-Schmidt
  1179. process to make them augmented as orthogonal basis.
  1180. >>> Q_aug = Q.row_join(Matrix([0, 0, 1]))
  1181. >>> Q_aug = Q_aug.QRdecomposition()[0]
  1182. >>> Q_aug
  1183. Matrix([
  1184. [ 6/7, -69/175, 58/175],
  1185. [ 3/7, 158/175, -6/175],
  1186. [-2/7, 6/35, 33/35]])
  1187. >>> Q_aug.H * Q_aug
  1188. Matrix([
  1189. [1, 0, 0],
  1190. [0, 1, 0],
  1191. [0, 0, 1]])
  1192. >>> Q_aug * Q_aug.H
  1193. Matrix([
  1194. [1, 0, 0],
  1195. [0, 1, 0],
  1196. [0, 0, 1]])
  1197. Augmenting the $R$ matrix with zero row is straightforward.
  1198. >>> R_aug = R.col_join(Matrix([[0, 0, 0]]))
  1199. >>> R_aug
  1200. Matrix([
  1201. [14, 21, 0],
  1202. [ 0, 175, 0],
  1203. [ 0, 0, 0]])
  1204. >>> Q_aug * R_aug == A
  1205. True
  1206. A zero matrix example:
  1207. >>> from sympy import Matrix
  1208. >>> A = Matrix.zeros(3, 4)
  1209. >>> Q, R = A.QRdecomposition()
  1210. They may return matrices with zero rows and columns.
  1211. >>> Q
  1212. Matrix(3, 0, [])
  1213. >>> R
  1214. Matrix(0, 4, [])
  1215. >>> Q*R
  1216. Matrix([
  1217. [0, 0, 0, 0],
  1218. [0, 0, 0, 0],
  1219. [0, 0, 0, 0]])
  1220. As the same augmentation rule described above, $Q$ can be augmented
  1221. with columns of an identity matrix and $R$ can be augmented with
  1222. rows of a zero matrix.
  1223. >>> Q_aug = Q.row_join(Matrix.eye(3))
  1224. >>> R_aug = R.col_join(Matrix.zeros(3, 4))
  1225. >>> Q_aug * Q_aug.T
  1226. Matrix([
  1227. [1, 0, 0],
  1228. [0, 1, 0],
  1229. [0, 0, 1]])
  1230. >>> R_aug
  1231. Matrix([
  1232. [0, 0, 0, 0],
  1233. [0, 0, 0, 0],
  1234. [0, 0, 0, 0]])
  1235. >>> Q_aug * R_aug == A
  1236. True
  1237. See Also
  1238. ========
  1239. sympy.matrices.dense.DenseMatrix.cholesky
  1240. sympy.matrices.dense.DenseMatrix.LDLdecomposition
  1241. sympy.matrices.matrices.MatrixBase.LUdecomposition
  1242. QRsolve
  1243. """
  1244. return _QRdecomposition_optional(M, normalize=True)
  1245. def _upper_hessenberg_decomposition(A):
  1246. """Converts a matrix into Hessenberg matrix H
  1247. Returns 2 matrices H, P s.t.
  1248. $P H P^{T} = A$, where H is an upper hessenberg matrix
  1249. and P is an orthogonal matrix
  1250. Examples
  1251. ========
  1252. >>> from sympy import Matrix
  1253. >>> A = Matrix([
  1254. ... [1,2,3],
  1255. ... [-3,5,6],
  1256. ... [4,-8,9],
  1257. ... ])
  1258. >>> H, P = A.upper_hessenberg_decomposition()
  1259. >>> H
  1260. Matrix([
  1261. [1, 6/5, 17/5],
  1262. [5, 213/25, -134/25],
  1263. [0, 216/25, 137/25]])
  1264. >>> P
  1265. Matrix([
  1266. [1, 0, 0],
  1267. [0, -3/5, 4/5],
  1268. [0, 4/5, 3/5]])
  1269. >>> P * H * P.H == A
  1270. True
  1271. References
  1272. ==========
  1273. .. [#] https://mathworld.wolfram.com/HessenbergDecomposition.html
  1274. """
  1275. M = A.as_mutable()
  1276. if not M.is_square:
  1277. raise NonSquareMatrixError("Matrix must be square.")
  1278. n = M.cols
  1279. P = M.eye(n)
  1280. H = M
  1281. for j in range(n - 2):
  1282. u = H[j + 1:, j]
  1283. if u[1:, :].is_zero_matrix:
  1284. continue
  1285. if sign(u[0]) != 0:
  1286. u[0] = u[0] + sign(u[0]) * u.norm()
  1287. else:
  1288. u[0] = u[0] + u.norm()
  1289. v = u / u.norm()
  1290. H[j + 1:, :] = H[j + 1:, :] - 2 * v * (v.H * H[j + 1:, :])
  1291. H[:, j + 1:] = H[:, j + 1:] - (H[:, j + 1:] * (2 * v)) * v.H
  1292. P[:, j + 1:] = P[:, j + 1:] - (P[:, j + 1:] * (2 * v)) * v.H
  1293. return H, P