matrices.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. #
  2. # A module consisting of deprecated matrix classes. New code should not be
  3. # added here.
  4. #
  5. from sympy.core.basic import Basic
  6. from sympy.core.symbol import Dummy
  7. from .common import MatrixCommon
  8. from .exceptions import NonSquareMatrixError
  9. from .utilities import _iszero, _is_zero_after_expand_mul, _simplify
  10. from .determinant import (
  11. _find_reasonable_pivot, _find_reasonable_pivot_naive,
  12. _adjugate, _charpoly, _cofactor, _cofactor_matrix, _per,
  13. _det, _det_bareiss, _det_berkowitz, _det_bird, _det_laplace, _det_LU,
  14. _minor, _minor_submatrix)
  15. from .reductions import _is_echelon, _echelon_form, _rank, _rref
  16. from .subspaces import _columnspace, _nullspace, _rowspace, _orthogonalize
  17. from .eigen import (
  18. _eigenvals, _eigenvects,
  19. _bidiagonalize, _bidiagonal_decomposition,
  20. _is_diagonalizable, _diagonalize,
  21. _is_positive_definite, _is_positive_semidefinite,
  22. _is_negative_definite, _is_negative_semidefinite, _is_indefinite,
  23. _jordan_form, _left_eigenvects, _singular_values)
  24. # This class was previously defined in this module, but was moved to
  25. # sympy.matrices.matrixbase. We import it here for backwards compatibility in
  26. # case someone was importing it from here.
  27. from .matrixbase import MatrixBase
  28. __doctest_requires__ = {
  29. ('MatrixEigen.is_indefinite',
  30. 'MatrixEigen.is_negative_definite',
  31. 'MatrixEigen.is_negative_semidefinite',
  32. 'MatrixEigen.is_positive_definite',
  33. 'MatrixEigen.is_positive_semidefinite'): ['matplotlib'],
  34. }
  35. class MatrixDeterminant(MatrixCommon):
  36. """Provides basic matrix determinant operations. Should not be instantiated
  37. directly. See ``determinant.py`` for their implementations."""
  38. def _eval_det_bareiss(self, iszerofunc=_is_zero_after_expand_mul):
  39. return _det_bareiss(self, iszerofunc=iszerofunc)
  40. def _eval_det_berkowitz(self):
  41. return _det_berkowitz(self)
  42. def _eval_det_lu(self, iszerofunc=_iszero, simpfunc=None):
  43. return _det_LU(self, iszerofunc=iszerofunc, simpfunc=simpfunc)
  44. def _eval_det_bird(self):
  45. return _det_bird(self)
  46. def _eval_det_laplace(self):
  47. return _det_laplace(self)
  48. def _eval_determinant(self): # for expressions.determinant.Determinant
  49. return _det(self)
  50. def adjugate(self, method="berkowitz"):
  51. return _adjugate(self, method=method)
  52. def charpoly(self, x='lambda', simplify=_simplify):
  53. return _charpoly(self, x=x, simplify=simplify)
  54. def cofactor(self, i, j, method="berkowitz"):
  55. return _cofactor(self, i, j, method=method)
  56. def cofactor_matrix(self, method="berkowitz"):
  57. return _cofactor_matrix(self, method=method)
  58. def det(self, method="bareiss", iszerofunc=None):
  59. return _det(self, method=method, iszerofunc=iszerofunc)
  60. def per(self):
  61. return _per(self)
  62. def minor(self, i, j, method="berkowitz"):
  63. return _minor(self, i, j, method=method)
  64. def minor_submatrix(self, i, j):
  65. return _minor_submatrix(self, i, j)
  66. _find_reasonable_pivot.__doc__ = _find_reasonable_pivot.__doc__
  67. _find_reasonable_pivot_naive.__doc__ = _find_reasonable_pivot_naive.__doc__
  68. _eval_det_bareiss.__doc__ = _det_bareiss.__doc__
  69. _eval_det_berkowitz.__doc__ = _det_berkowitz.__doc__
  70. _eval_det_bird.__doc__ = _det_bird.__doc__
  71. _eval_det_laplace.__doc__ = _det_laplace.__doc__
  72. _eval_det_lu.__doc__ = _det_LU.__doc__
  73. _eval_determinant.__doc__ = _det.__doc__
  74. adjugate.__doc__ = _adjugate.__doc__
  75. charpoly.__doc__ = _charpoly.__doc__
  76. cofactor.__doc__ = _cofactor.__doc__
  77. cofactor_matrix.__doc__ = _cofactor_matrix.__doc__
  78. det.__doc__ = _det.__doc__
  79. per.__doc__ = _per.__doc__
  80. minor.__doc__ = _minor.__doc__
  81. minor_submatrix.__doc__ = _minor_submatrix.__doc__
  82. class MatrixReductions(MatrixDeterminant):
  83. """Provides basic matrix row/column operations. Should not be instantiated
  84. directly. See ``reductions.py`` for some of their implementations."""
  85. def echelon_form(self, iszerofunc=_iszero, simplify=False, with_pivots=False):
  86. return _echelon_form(self, iszerofunc=iszerofunc, simplify=simplify,
  87. with_pivots=with_pivots)
  88. @property
  89. def is_echelon(self):
  90. return _is_echelon(self)
  91. def rank(self, iszerofunc=_iszero, simplify=False):
  92. return _rank(self, iszerofunc=iszerofunc, simplify=simplify)
  93. def rref_rhs(self, rhs):
  94. """Return reduced row-echelon form of matrix, matrix showing
  95. rhs after reduction steps. ``rhs`` must have the same number
  96. of rows as ``self``.
  97. Examples
  98. ========
  99. >>> from sympy import Matrix, symbols
  100. >>> r1, r2 = symbols('r1 r2')
  101. >>> Matrix([[1, 1], [2, 1]]).rref_rhs(Matrix([r1, r2]))
  102. (Matrix([
  103. [1, 0],
  104. [0, 1]]), Matrix([
  105. [ -r1 + r2],
  106. [2*r1 - r2]]))
  107. """
  108. r, _ = _rref(self.hstack(self, self.eye(self.rows), rhs))
  109. return r[:, :self.cols], r[:, -rhs.cols:]
  110. def rref(self, iszerofunc=_iszero, simplify=False, pivots=True,
  111. normalize_last=True):
  112. return _rref(self, iszerofunc=iszerofunc, simplify=simplify,
  113. pivots=pivots, normalize_last=normalize_last)
  114. echelon_form.__doc__ = _echelon_form.__doc__
  115. is_echelon.__doc__ = _is_echelon.__doc__
  116. rank.__doc__ = _rank.__doc__
  117. rref.__doc__ = _rref.__doc__
  118. def _normalize_op_args(self, op, col, k, col1, col2, error_str="col"):
  119. """Validate the arguments for a row/column operation. ``error_str``
  120. can be one of "row" or "col" depending on the arguments being parsed."""
  121. if op not in ["n->kn", "n<->m", "n->n+km"]:
  122. raise ValueError("Unknown {} operation '{}'. Valid col operations "
  123. "are 'n->kn', 'n<->m', 'n->n+km'".format(error_str, op))
  124. # define self_col according to error_str
  125. self_cols = self.cols if error_str == 'col' else self.rows
  126. # normalize and validate the arguments
  127. if op == "n->kn":
  128. col = col if col is not None else col1
  129. if col is None or k is None:
  130. raise ValueError("For a {0} operation 'n->kn' you must provide the "
  131. "kwargs `{0}` and `k`".format(error_str))
  132. if not 0 <= col < self_cols:
  133. raise ValueError("This matrix does not have a {} '{}'".format(error_str, col))
  134. elif op == "n<->m":
  135. # we need two cols to swap. It does not matter
  136. # how they were specified, so gather them together and
  137. # remove `None`
  138. cols = {col, k, col1, col2}.difference([None])
  139. if len(cols) > 2:
  140. # maybe the user left `k` by mistake?
  141. cols = {col, col1, col2}.difference([None])
  142. if len(cols) != 2:
  143. raise ValueError("For a {0} operation 'n<->m' you must provide the "
  144. "kwargs `{0}1` and `{0}2`".format(error_str))
  145. col1, col2 = cols
  146. if not 0 <= col1 < self_cols:
  147. raise ValueError("This matrix does not have a {} '{}'".format(error_str, col1))
  148. if not 0 <= col2 < self_cols:
  149. raise ValueError("This matrix does not have a {} '{}'".format(error_str, col2))
  150. elif op == "n->n+km":
  151. col = col1 if col is None else col
  152. col2 = col1 if col2 is None else col2
  153. if col is None or col2 is None or k is None:
  154. raise ValueError("For a {0} operation 'n->n+km' you must provide the "
  155. "kwargs `{0}`, `k`, and `{0}2`".format(error_str))
  156. if col == col2:
  157. raise ValueError("For a {0} operation 'n->n+km' `{0}` and `{0}2` must "
  158. "be different.".format(error_str))
  159. if not 0 <= col < self_cols:
  160. raise ValueError("This matrix does not have a {} '{}'".format(error_str, col))
  161. if not 0 <= col2 < self_cols:
  162. raise ValueError("This matrix does not have a {} '{}'".format(error_str, col2))
  163. else:
  164. raise ValueError('invalid operation %s' % repr(op))
  165. return op, col, k, col1, col2
  166. def _eval_col_op_multiply_col_by_const(self, col, k):
  167. def entry(i, j):
  168. if j == col:
  169. return k * self[i, j]
  170. return self[i, j]
  171. return self._new(self.rows, self.cols, entry)
  172. def _eval_col_op_swap(self, col1, col2):
  173. def entry(i, j):
  174. if j == col1:
  175. return self[i, col2]
  176. elif j == col2:
  177. return self[i, col1]
  178. return self[i, j]
  179. return self._new(self.rows, self.cols, entry)
  180. def _eval_col_op_add_multiple_to_other_col(self, col, k, col2):
  181. def entry(i, j):
  182. if j == col:
  183. return self[i, j] + k * self[i, col2]
  184. return self[i, j]
  185. return self._new(self.rows, self.cols, entry)
  186. def _eval_row_op_swap(self, row1, row2):
  187. def entry(i, j):
  188. if i == row1:
  189. return self[row2, j]
  190. elif i == row2:
  191. return self[row1, j]
  192. return self[i, j]
  193. return self._new(self.rows, self.cols, entry)
  194. def _eval_row_op_multiply_row_by_const(self, row, k):
  195. def entry(i, j):
  196. if i == row:
  197. return k * self[i, j]
  198. return self[i, j]
  199. return self._new(self.rows, self.cols, entry)
  200. def _eval_row_op_add_multiple_to_other_row(self, row, k, row2):
  201. def entry(i, j):
  202. if i == row:
  203. return self[i, j] + k * self[row2, j]
  204. return self[i, j]
  205. return self._new(self.rows, self.cols, entry)
  206. def elementary_col_op(self, op="n->kn", col=None, k=None, col1=None, col2=None):
  207. """Performs the elementary column operation `op`.
  208. `op` may be one of
  209. * ``"n->kn"`` (column n goes to k*n)
  210. * ``"n<->m"`` (swap column n and column m)
  211. * ``"n->n+km"`` (column n goes to column n + k*column m)
  212. Parameters
  213. ==========
  214. op : string; the elementary row operation
  215. col : the column to apply the column operation
  216. k : the multiple to apply in the column operation
  217. col1 : one column of a column swap
  218. col2 : second column of a column swap or column "m" in the column operation
  219. "n->n+km"
  220. """
  221. op, col, k, col1, col2 = self._normalize_op_args(op, col, k, col1, col2, "col")
  222. # now that we've validated, we're all good to dispatch
  223. if op == "n->kn":
  224. return self._eval_col_op_multiply_col_by_const(col, k)
  225. if op == "n<->m":
  226. return self._eval_col_op_swap(col1, col2)
  227. if op == "n->n+km":
  228. return self._eval_col_op_add_multiple_to_other_col(col, k, col2)
  229. def elementary_row_op(self, op="n->kn", row=None, k=None, row1=None, row2=None):
  230. """Performs the elementary row operation `op`.
  231. `op` may be one of
  232. * ``"n->kn"`` (row n goes to k*n)
  233. * ``"n<->m"`` (swap row n and row m)
  234. * ``"n->n+km"`` (row n goes to row n + k*row m)
  235. Parameters
  236. ==========
  237. op : string; the elementary row operation
  238. row : the row to apply the row operation
  239. k : the multiple to apply in the row operation
  240. row1 : one row of a row swap
  241. row2 : second row of a row swap or row "m" in the row operation
  242. "n->n+km"
  243. """
  244. op, row, k, row1, row2 = self._normalize_op_args(op, row, k, row1, row2, "row")
  245. # now that we've validated, we're all good to dispatch
  246. if op == "n->kn":
  247. return self._eval_row_op_multiply_row_by_const(row, k)
  248. if op == "n<->m":
  249. return self._eval_row_op_swap(row1, row2)
  250. if op == "n->n+km":
  251. return self._eval_row_op_add_multiple_to_other_row(row, k, row2)
  252. class MatrixSubspaces(MatrixReductions):
  253. """Provides methods relating to the fundamental subspaces of a matrix.
  254. Should not be instantiated directly. See ``subspaces.py`` for their
  255. implementations."""
  256. def columnspace(self, simplify=False):
  257. return _columnspace(self, simplify=simplify)
  258. def nullspace(self, simplify=False, iszerofunc=_iszero):
  259. return _nullspace(self, simplify=simplify, iszerofunc=iszerofunc)
  260. def rowspace(self, simplify=False):
  261. return _rowspace(self, simplify=simplify)
  262. # This is a classmethod but is converted to such later in order to allow
  263. # assignment of __doc__ since that does not work for already wrapped
  264. # classmethods in Python 3.6.
  265. def orthogonalize(cls, *vecs, **kwargs):
  266. return _orthogonalize(cls, *vecs, **kwargs)
  267. columnspace.__doc__ = _columnspace.__doc__
  268. nullspace.__doc__ = _nullspace.__doc__
  269. rowspace.__doc__ = _rowspace.__doc__
  270. orthogonalize.__doc__ = _orthogonalize.__doc__
  271. orthogonalize = classmethod(orthogonalize) # type:ignore
  272. class MatrixEigen(MatrixSubspaces):
  273. """Provides basic matrix eigenvalue/vector operations.
  274. Should not be instantiated directly. See ``eigen.py`` for their
  275. implementations."""
  276. def eigenvals(self, error_when_incomplete=True, **flags):
  277. return _eigenvals(self, error_when_incomplete=error_when_incomplete, **flags)
  278. def eigenvects(self, error_when_incomplete=True, iszerofunc=_iszero, **flags):
  279. return _eigenvects(self, error_when_incomplete=error_when_incomplete,
  280. iszerofunc=iszerofunc, **flags)
  281. def is_diagonalizable(self, reals_only=False, **kwargs):
  282. return _is_diagonalizable(self, reals_only=reals_only, **kwargs)
  283. def diagonalize(self, reals_only=False, sort=False, normalize=False):
  284. return _diagonalize(self, reals_only=reals_only, sort=sort,
  285. normalize=normalize)
  286. def bidiagonalize(self, upper=True):
  287. return _bidiagonalize(self, upper=upper)
  288. def bidiagonal_decomposition(self, upper=True):
  289. return _bidiagonal_decomposition(self, upper=upper)
  290. @property
  291. def is_positive_definite(self):
  292. return _is_positive_definite(self)
  293. @property
  294. def is_positive_semidefinite(self):
  295. return _is_positive_semidefinite(self)
  296. @property
  297. def is_negative_definite(self):
  298. return _is_negative_definite(self)
  299. @property
  300. def is_negative_semidefinite(self):
  301. return _is_negative_semidefinite(self)
  302. @property
  303. def is_indefinite(self):
  304. return _is_indefinite(self)
  305. def jordan_form(self, calc_transform=True, **kwargs):
  306. return _jordan_form(self, calc_transform=calc_transform, **kwargs)
  307. def left_eigenvects(self, **flags):
  308. return _left_eigenvects(self, **flags)
  309. def singular_values(self):
  310. return _singular_values(self)
  311. eigenvals.__doc__ = _eigenvals.__doc__
  312. eigenvects.__doc__ = _eigenvects.__doc__
  313. is_diagonalizable.__doc__ = _is_diagonalizable.__doc__
  314. diagonalize.__doc__ = _diagonalize.__doc__
  315. is_positive_definite.__doc__ = _is_positive_definite.__doc__
  316. is_positive_semidefinite.__doc__ = _is_positive_semidefinite.__doc__
  317. is_negative_definite.__doc__ = _is_negative_definite.__doc__
  318. is_negative_semidefinite.__doc__ = _is_negative_semidefinite.__doc__
  319. is_indefinite.__doc__ = _is_indefinite.__doc__
  320. jordan_form.__doc__ = _jordan_form.__doc__
  321. left_eigenvects.__doc__ = _left_eigenvects.__doc__
  322. singular_values.__doc__ = _singular_values.__doc__
  323. bidiagonalize.__doc__ = _bidiagonalize.__doc__
  324. bidiagonal_decomposition.__doc__ = _bidiagonal_decomposition.__doc__
  325. class MatrixCalculus(MatrixCommon):
  326. """Provides calculus-related matrix operations."""
  327. def diff(self, *args, evaluate=True, **kwargs):
  328. """Calculate the derivative of each element in the matrix.
  329. Examples
  330. ========
  331. >>> from sympy import Matrix
  332. >>> from sympy.abc import x, y
  333. >>> M = Matrix([[x, y], [1, 0]])
  334. >>> M.diff(x)
  335. Matrix([
  336. [1, 0],
  337. [0, 0]])
  338. See Also
  339. ========
  340. integrate
  341. limit
  342. """
  343. # XXX this should be handled here rather than in Derivative
  344. from sympy.tensor.array.array_derivatives import ArrayDerivative
  345. deriv = ArrayDerivative(self, *args, evaluate=evaluate)
  346. # XXX This can rather changed to always return immutable matrix
  347. if not isinstance(self, Basic) and evaluate:
  348. return deriv.as_mutable()
  349. return deriv
  350. def _eval_derivative(self, arg):
  351. return self.applyfunc(lambda x: x.diff(arg))
  352. def integrate(self, *args, **kwargs):
  353. """Integrate each element of the matrix. ``args`` will
  354. be passed to the ``integrate`` function.
  355. Examples
  356. ========
  357. >>> from sympy import Matrix
  358. >>> from sympy.abc import x, y
  359. >>> M = Matrix([[x, y], [1, 0]])
  360. >>> M.integrate((x, ))
  361. Matrix([
  362. [x**2/2, x*y],
  363. [ x, 0]])
  364. >>> M.integrate((x, 0, 2))
  365. Matrix([
  366. [2, 2*y],
  367. [2, 0]])
  368. See Also
  369. ========
  370. limit
  371. diff
  372. """
  373. return self.applyfunc(lambda x: x.integrate(*args, **kwargs))
  374. def jacobian(self, X):
  375. """Calculates the Jacobian matrix (derivative of a vector-valued function).
  376. Parameters
  377. ==========
  378. ``self`` : vector of expressions representing functions f_i(x_1, ..., x_n).
  379. X : set of x_i's in order, it can be a list or a Matrix
  380. Both ``self`` and X can be a row or a column matrix in any order
  381. (i.e., jacobian() should always work).
  382. Examples
  383. ========
  384. >>> from sympy import sin, cos, Matrix
  385. >>> from sympy.abc import rho, phi
  386. >>> X = Matrix([rho*cos(phi), rho*sin(phi), rho**2])
  387. >>> Y = Matrix([rho, phi])
  388. >>> X.jacobian(Y)
  389. Matrix([
  390. [cos(phi), -rho*sin(phi)],
  391. [sin(phi), rho*cos(phi)],
  392. [ 2*rho, 0]])
  393. >>> X = Matrix([rho*cos(phi), rho*sin(phi)])
  394. >>> X.jacobian(Y)
  395. Matrix([
  396. [cos(phi), -rho*sin(phi)],
  397. [sin(phi), rho*cos(phi)]])
  398. See Also
  399. ========
  400. hessian
  401. wronskian
  402. """
  403. if not isinstance(X, MatrixBase):
  404. X = self._new(X)
  405. # Both X and ``self`` can be a row or a column matrix, so we need to make
  406. # sure all valid combinations work, but everything else fails:
  407. if self.shape[0] == 1:
  408. m = self.shape[1]
  409. elif self.shape[1] == 1:
  410. m = self.shape[0]
  411. else:
  412. raise TypeError("``self`` must be a row or a column matrix")
  413. if X.shape[0] == 1:
  414. n = X.shape[1]
  415. elif X.shape[1] == 1:
  416. n = X.shape[0]
  417. else:
  418. raise TypeError("X must be a row or a column matrix")
  419. # m is the number of functions and n is the number of variables
  420. # computing the Jacobian is now easy:
  421. return self._new(m, n, lambda j, i: self[j].diff(X[i]))
  422. def limit(self, *args):
  423. """Calculate the limit of each element in the matrix.
  424. ``args`` will be passed to the ``limit`` function.
  425. Examples
  426. ========
  427. >>> from sympy import Matrix
  428. >>> from sympy.abc import x, y
  429. >>> M = Matrix([[x, y], [1, 0]])
  430. >>> M.limit(x, 2)
  431. Matrix([
  432. [2, y],
  433. [1, 0]])
  434. See Also
  435. ========
  436. integrate
  437. diff
  438. """
  439. return self.applyfunc(lambda x: x.limit(*args))
  440. # https://github.com/sympy/sympy/pull/12854
  441. class MatrixDeprecated(MatrixCommon):
  442. """A class to house deprecated matrix methods."""
  443. def berkowitz_charpoly(self, x=Dummy('lambda'), simplify=_simplify):
  444. return self.charpoly(x=x)
  445. def berkowitz_det(self):
  446. """Computes determinant using Berkowitz method.
  447. See Also
  448. ========
  449. det
  450. berkowitz
  451. """
  452. return self.det(method='berkowitz')
  453. def berkowitz_eigenvals(self, **flags):
  454. """Computes eigenvalues of a Matrix using Berkowitz method.
  455. See Also
  456. ========
  457. berkowitz
  458. """
  459. return self.eigenvals(**flags)
  460. def berkowitz_minors(self):
  461. """Computes principal minors using Berkowitz method.
  462. See Also
  463. ========
  464. berkowitz
  465. """
  466. sign, minors = self.one, []
  467. for poly in self.berkowitz():
  468. minors.append(sign * poly[-1])
  469. sign = -sign
  470. return tuple(minors)
  471. def berkowitz(self):
  472. from sympy.matrices import zeros
  473. berk = ((1,),)
  474. if not self:
  475. return berk
  476. if not self.is_square:
  477. raise NonSquareMatrixError()
  478. A, N = self, self.rows
  479. transforms = [0] * (N - 1)
  480. for n in range(N, 1, -1):
  481. T, k = zeros(n + 1, n), n - 1
  482. R, C = -A[k, :k], A[:k, k]
  483. A, a = A[:k, :k], -A[k, k]
  484. items = [C]
  485. for i in range(0, n - 2):
  486. items.append(A * items[i])
  487. for i, B in enumerate(items):
  488. items[i] = (R * B)[0, 0]
  489. items = [self.one, a] + items
  490. for i in range(n):
  491. T[i:, i] = items[:n - i + 1]
  492. transforms[k - 1] = T
  493. polys = [self._new([self.one, -A[0, 0]])]
  494. for i, T in enumerate(transforms):
  495. polys.append(T * polys[i])
  496. return berk + tuple(map(tuple, polys))
  497. def cofactorMatrix(self, method="berkowitz"):
  498. return self.cofactor_matrix(method=method)
  499. def det_bareis(self):
  500. return _det_bareiss(self)
  501. def det_LU_decomposition(self):
  502. """Compute matrix determinant using LU decomposition.
  503. Note that this method fails if the LU decomposition itself
  504. fails. In particular, if the matrix has no inverse this method
  505. will fail.
  506. TODO: Implement algorithm for sparse matrices (SFF),
  507. https://www.eecis.udel.edu/~saunders/papers/sffge/it5.ps
  508. See Also
  509. ========
  510. det
  511. det_bareiss
  512. berkowitz_det
  513. """
  514. return self.det(method='lu')
  515. def jordan_cell(self, eigenval, n):
  516. return self.jordan_block(size=n, eigenvalue=eigenval)
  517. def jordan_cells(self, calc_transformation=True):
  518. P, J = self.jordan_form()
  519. return P, J.get_diag_blocks()
  520. def minorEntry(self, i, j, method="berkowitz"):
  521. return self.minor(i, j, method=method)
  522. def minorMatrix(self, i, j):
  523. return self.minor_submatrix(i, j)
  524. def permuteBkwd(self, perm):
  525. """Permute the rows of the matrix with the given permutation in reverse."""
  526. return self.permute_rows(perm, direction='backward')
  527. def permuteFwd(self, perm):
  528. """Permute the rows of the matrix with the given permutation."""
  529. return self.permute_rows(perm, direction='forward')