dense.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. import random
  2. from sympy.core.basic import Basic
  3. from sympy.core.singleton import S
  4. from sympy.core.symbol import Symbol
  5. from sympy.core.sympify import sympify
  6. from sympy.functions.elementary.trigonometric import cos, sin
  7. from sympy.simplify.simplify import simplify as _simplify
  8. from sympy.utilities.decorator import doctest_depends_on
  9. from sympy.utilities.exceptions import sympy_deprecation_warning
  10. from sympy.utilities.iterables import is_sequence
  11. from .common import ShapeError
  12. from .decompositions import _cholesky, _LDLdecomposition
  13. from .matrices import MatrixBase
  14. from .repmatrix import MutableRepMatrix, RepMatrix
  15. from .solvers import _lower_triangular_solve, _upper_triangular_solve
  16. def _iszero(x):
  17. """Returns True if x is zero."""
  18. return x.is_zero
  19. class DenseMatrix(RepMatrix):
  20. """Matrix implementation based on DomainMatrix as the internal representation"""
  21. #
  22. # DenseMatrix is a superclass for both MutableDenseMatrix and
  23. # ImmutableDenseMatrix. Methods shared by both classes but not for the
  24. # Sparse classes should be implemented here.
  25. #
  26. is_MatrixExpr = False # type: bool
  27. _op_priority = 10.01
  28. _class_priority = 4
  29. @property
  30. def _mat(self):
  31. sympy_deprecation_warning(
  32. """
  33. The private _mat attribute of Matrix is deprecated. Use the
  34. .flat() method instead.
  35. """,
  36. deprecated_since_version="1.9",
  37. active_deprecations_target="deprecated-private-matrix-attributes"
  38. )
  39. return self.flat()
  40. def _eval_inverse(self, **kwargs):
  41. return self.inv(method=kwargs.get('method', 'GE'),
  42. iszerofunc=kwargs.get('iszerofunc', _iszero),
  43. try_block_diag=kwargs.get('try_block_diag', False))
  44. def as_immutable(self):
  45. """Returns an Immutable version of this Matrix
  46. """
  47. from .immutable import ImmutableDenseMatrix as cls
  48. return cls._fromrep(self._rep.copy())
  49. def as_mutable(self):
  50. """Returns a mutable version of this matrix
  51. Examples
  52. ========
  53. >>> from sympy import ImmutableMatrix
  54. >>> X = ImmutableMatrix([[1, 2], [3, 4]])
  55. >>> Y = X.as_mutable()
  56. >>> Y[1, 1] = 5 # Can set values in Y
  57. >>> Y
  58. Matrix([
  59. [1, 2],
  60. [3, 5]])
  61. """
  62. return Matrix(self)
  63. def cholesky(self, hermitian=True):
  64. return _cholesky(self, hermitian=hermitian)
  65. def LDLdecomposition(self, hermitian=True):
  66. return _LDLdecomposition(self, hermitian=hermitian)
  67. def lower_triangular_solve(self, rhs):
  68. return _lower_triangular_solve(self, rhs)
  69. def upper_triangular_solve(self, rhs):
  70. return _upper_triangular_solve(self, rhs)
  71. cholesky.__doc__ = _cholesky.__doc__
  72. LDLdecomposition.__doc__ = _LDLdecomposition.__doc__
  73. lower_triangular_solve.__doc__ = _lower_triangular_solve.__doc__
  74. upper_triangular_solve.__doc__ = _upper_triangular_solve.__doc__
  75. def _force_mutable(x):
  76. """Return a matrix as a Matrix, otherwise return x."""
  77. if getattr(x, 'is_Matrix', False):
  78. return x.as_mutable()
  79. elif isinstance(x, Basic):
  80. return x
  81. elif hasattr(x, '__array__'):
  82. a = x.__array__()
  83. if len(a.shape) == 0:
  84. return sympify(a)
  85. return Matrix(x)
  86. return x
  87. class MutableDenseMatrix(DenseMatrix, MutableRepMatrix):
  88. def simplify(self, **kwargs):
  89. """Applies simplify to the elements of a matrix in place.
  90. This is a shortcut for M.applyfunc(lambda x: simplify(x, ratio, measure))
  91. See Also
  92. ========
  93. sympy.simplify.simplify.simplify
  94. """
  95. for (i, j), element in self.todok().items():
  96. self[i, j] = _simplify(element, **kwargs)
  97. MutableMatrix = Matrix = MutableDenseMatrix
  98. ###########
  99. # Numpy Utility Functions:
  100. # list2numpy, matrix2numpy, symmarray, rot_axis[123]
  101. ###########
  102. def list2numpy(l, dtype=object): # pragma: no cover
  103. """Converts Python list of SymPy expressions to a NumPy array.
  104. See Also
  105. ========
  106. matrix2numpy
  107. """
  108. from numpy import empty
  109. a = empty(len(l), dtype)
  110. for i, s in enumerate(l):
  111. a[i] = s
  112. return a
  113. def matrix2numpy(m, dtype=object): # pragma: no cover
  114. """Converts SymPy's matrix to a NumPy array.
  115. See Also
  116. ========
  117. list2numpy
  118. """
  119. from numpy import empty
  120. a = empty(m.shape, dtype)
  121. for i in range(m.rows):
  122. for j in range(m.cols):
  123. a[i, j] = m[i, j]
  124. return a
  125. def rot_axis3(theta):
  126. """Returns a rotation matrix for a rotation of theta (in radians) about
  127. the 3-axis.
  128. Examples
  129. ========
  130. >>> from sympy import pi, rot_axis3
  131. A rotation of pi/3 (60 degrees):
  132. >>> theta = pi/3
  133. >>> rot_axis3(theta)
  134. Matrix([
  135. [ 1/2, sqrt(3)/2, 0],
  136. [-sqrt(3)/2, 1/2, 0],
  137. [ 0, 0, 1]])
  138. If we rotate by pi/2 (90 degrees):
  139. >>> rot_axis3(pi/2)
  140. Matrix([
  141. [ 0, 1, 0],
  142. [-1, 0, 0],
  143. [ 0, 0, 1]])
  144. See Also
  145. ========
  146. rot_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  147. about the 1-axis
  148. rot_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  149. about the 2-axis
  150. """
  151. ct = cos(theta)
  152. st = sin(theta)
  153. lil = ((ct, st, 0),
  154. (-st, ct, 0),
  155. (0, 0, 1))
  156. return Matrix(lil)
  157. def rot_axis2(theta):
  158. """Returns a rotation matrix for a rotation of theta (in radians) about
  159. the 2-axis.
  160. Examples
  161. ========
  162. >>> from sympy import pi, rot_axis2
  163. A rotation of pi/3 (60 degrees):
  164. >>> theta = pi/3
  165. >>> rot_axis2(theta)
  166. Matrix([
  167. [ 1/2, 0, -sqrt(3)/2],
  168. [ 0, 1, 0],
  169. [sqrt(3)/2, 0, 1/2]])
  170. If we rotate by pi/2 (90 degrees):
  171. >>> rot_axis2(pi/2)
  172. Matrix([
  173. [0, 0, -1],
  174. [0, 1, 0],
  175. [1, 0, 0]])
  176. See Also
  177. ========
  178. rot_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  179. about the 1-axis
  180. rot_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  181. about the 3-axis
  182. """
  183. ct = cos(theta)
  184. st = sin(theta)
  185. lil = ((ct, 0, -st),
  186. (0, 1, 0),
  187. (st, 0, ct))
  188. return Matrix(lil)
  189. def rot_axis1(theta):
  190. """Returns a rotation matrix for a rotation of theta (in radians) about
  191. the 1-axis.
  192. Examples
  193. ========
  194. >>> from sympy import pi, rot_axis1
  195. A rotation of pi/3 (60 degrees):
  196. >>> theta = pi/3
  197. >>> rot_axis1(theta)
  198. Matrix([
  199. [1, 0, 0],
  200. [0, 1/2, sqrt(3)/2],
  201. [0, -sqrt(3)/2, 1/2]])
  202. If we rotate by pi/2 (90 degrees):
  203. >>> rot_axis1(pi/2)
  204. Matrix([
  205. [1, 0, 0],
  206. [0, 0, 1],
  207. [0, -1, 0]])
  208. See Also
  209. ========
  210. rot_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  211. about the 2-axis
  212. rot_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  213. about the 3-axis
  214. """
  215. ct = cos(theta)
  216. st = sin(theta)
  217. lil = ((1, 0, 0),
  218. (0, ct, st),
  219. (0, -st, ct))
  220. return Matrix(lil)
  221. @doctest_depends_on(modules=('numpy',))
  222. def symarray(prefix, shape, **kwargs): # pragma: no cover
  223. r"""Create a numpy ndarray of symbols (as an object array).
  224. The created symbols are named ``prefix_i1_i2_``... You should thus provide a
  225. non-empty prefix if you want your symbols to be unique for different output
  226. arrays, as SymPy symbols with identical names are the same object.
  227. Parameters
  228. ----------
  229. prefix : string
  230. A prefix prepended to the name of every symbol.
  231. shape : int or tuple
  232. Shape of the created array. If an int, the array is one-dimensional; for
  233. more than one dimension the shape must be a tuple.
  234. \*\*kwargs : dict
  235. keyword arguments passed on to Symbol
  236. Examples
  237. ========
  238. These doctests require numpy.
  239. >>> from sympy import symarray
  240. >>> symarray('', 3)
  241. [_0 _1 _2]
  242. If you want multiple symarrays to contain distinct symbols, you *must*
  243. provide unique prefixes:
  244. >>> a = symarray('', 3)
  245. >>> b = symarray('', 3)
  246. >>> a[0] == b[0]
  247. True
  248. >>> a = symarray('a', 3)
  249. >>> b = symarray('b', 3)
  250. >>> a[0] == b[0]
  251. False
  252. Creating symarrays with a prefix:
  253. >>> symarray('a', 3)
  254. [a_0 a_1 a_2]
  255. For more than one dimension, the shape must be given as a tuple:
  256. >>> symarray('a', (2, 3))
  257. [[a_0_0 a_0_1 a_0_2]
  258. [a_1_0 a_1_1 a_1_2]]
  259. >>> symarray('a', (2, 3, 2))
  260. [[[a_0_0_0 a_0_0_1]
  261. [a_0_1_0 a_0_1_1]
  262. [a_0_2_0 a_0_2_1]]
  263. <BLANKLINE>
  264. [[a_1_0_0 a_1_0_1]
  265. [a_1_1_0 a_1_1_1]
  266. [a_1_2_0 a_1_2_1]]]
  267. For setting assumptions of the underlying Symbols:
  268. >>> [s.is_real for s in symarray('a', 2, real=True)]
  269. [True, True]
  270. """
  271. from numpy import empty, ndindex
  272. arr = empty(shape, dtype=object)
  273. for index in ndindex(shape):
  274. arr[index] = Symbol('%s_%s' % (prefix, '_'.join(map(str, index))),
  275. **kwargs)
  276. return arr
  277. ###############
  278. # Functions
  279. ###############
  280. def casoratian(seqs, n, zero=True):
  281. """Given linear difference operator L of order 'k' and homogeneous
  282. equation Ly = 0 we want to compute kernel of L, which is a set
  283. of 'k' sequences: a(n), b(n), ... z(n).
  284. Solutions of L are linearly independent iff their Casoratian,
  285. denoted as C(a, b, ..., z), do not vanish for n = 0.
  286. Casoratian is defined by k x k determinant::
  287. + a(n) b(n) . . . z(n) +
  288. | a(n+1) b(n+1) . . . z(n+1) |
  289. | . . . . |
  290. | . . . . |
  291. | . . . . |
  292. + a(n+k-1) b(n+k-1) . . . z(n+k-1) +
  293. It proves very useful in rsolve_hyper() where it is applied
  294. to a generating set of a recurrence to factor out linearly
  295. dependent solutions and return a basis:
  296. >>> from sympy import Symbol, casoratian, factorial
  297. >>> n = Symbol('n', integer=True)
  298. Exponential and factorial are linearly independent:
  299. >>> casoratian([2**n, factorial(n)], n) != 0
  300. True
  301. """
  302. seqs = list(map(sympify, seqs))
  303. if not zero:
  304. f = lambda i, j: seqs[j].subs(n, n + i)
  305. else:
  306. f = lambda i, j: seqs[j].subs(n, i)
  307. k = len(seqs)
  308. return Matrix(k, k, f).det()
  309. def eye(*args, **kwargs):
  310. """Create square identity matrix n x n
  311. See Also
  312. ========
  313. diag
  314. zeros
  315. ones
  316. """
  317. return Matrix.eye(*args, **kwargs)
  318. def diag(*values, strict=True, unpack=False, **kwargs):
  319. """Returns a matrix with the provided values placed on the
  320. diagonal. If non-square matrices are included, they will
  321. produce a block-diagonal matrix.
  322. Examples
  323. ========
  324. This version of diag is a thin wrapper to Matrix.diag that differs
  325. in that it treats all lists like matrices -- even when a single list
  326. is given. If this is not desired, either put a `*` before the list or
  327. set `unpack=True`.
  328. >>> from sympy import diag
  329. >>> diag([1, 2, 3], unpack=True) # = diag(1,2,3) or diag(*[1,2,3])
  330. Matrix([
  331. [1, 0, 0],
  332. [0, 2, 0],
  333. [0, 0, 3]])
  334. >>> diag([1, 2, 3]) # a column vector
  335. Matrix([
  336. [1],
  337. [2],
  338. [3]])
  339. See Also
  340. ========
  341. .common.MatrixCommon.eye
  342. .common.MatrixCommon.diagonal - to extract a diagonal
  343. .common.MatrixCommon.diag
  344. .expressions.blockmatrix.BlockMatrix
  345. """
  346. return Matrix.diag(*values, strict=strict, unpack=unpack, **kwargs)
  347. def GramSchmidt(vlist, orthonormal=False):
  348. """Apply the Gram-Schmidt process to a set of vectors.
  349. Parameters
  350. ==========
  351. vlist : List of Matrix
  352. Vectors to be orthogonalized for.
  353. orthonormal : Bool, optional
  354. If true, return an orthonormal basis.
  355. Returns
  356. =======
  357. vlist : List of Matrix
  358. Orthogonalized vectors
  359. Notes
  360. =====
  361. This routine is mostly duplicate from ``Matrix.orthogonalize``,
  362. except for some difference that this always raises error when
  363. linearly dependent vectors are found, and the keyword ``normalize``
  364. has been named as ``orthonormal`` in this function.
  365. See Also
  366. ========
  367. .matrices.MatrixSubspaces.orthogonalize
  368. References
  369. ==========
  370. .. [1] https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process
  371. """
  372. return MutableDenseMatrix.orthogonalize(
  373. *vlist, normalize=orthonormal, rankcheck=True
  374. )
  375. def hessian(f, varlist, constraints=()):
  376. """Compute Hessian matrix for a function f wrt parameters in varlist
  377. which may be given as a sequence or a row/column vector. A list of
  378. constraints may optionally be given.
  379. Examples
  380. ========
  381. >>> from sympy import Function, hessian, pprint
  382. >>> from sympy.abc import x, y
  383. >>> f = Function('f')(x, y)
  384. >>> g1 = Function('g')(x, y)
  385. >>> g2 = x**2 + 3*y
  386. >>> pprint(hessian(f, (x, y), [g1, g2]))
  387. [ d d ]
  388. [ 0 0 --(g(x, y)) --(g(x, y)) ]
  389. [ dx dy ]
  390. [ ]
  391. [ 0 0 2*x 3 ]
  392. [ ]
  393. [ 2 2 ]
  394. [d d d ]
  395. [--(g(x, y)) 2*x ---(f(x, y)) -----(f(x, y))]
  396. [dx 2 dy dx ]
  397. [ dx ]
  398. [ ]
  399. [ 2 2 ]
  400. [d d d ]
  401. [--(g(x, y)) 3 -----(f(x, y)) ---(f(x, y)) ]
  402. [dy dy dx 2 ]
  403. [ dy ]
  404. References
  405. ==========
  406. .. [1] https://en.wikipedia.org/wiki/Hessian_matrix
  407. See Also
  408. ========
  409. sympy.matrices.matrices.MatrixCalculus.jacobian
  410. wronskian
  411. """
  412. # f is the expression representing a function f, return regular matrix
  413. if isinstance(varlist, MatrixBase):
  414. if 1 not in varlist.shape:
  415. raise ShapeError("`varlist` must be a column or row vector.")
  416. if varlist.cols == 1:
  417. varlist = varlist.T
  418. varlist = varlist.tolist()[0]
  419. if is_sequence(varlist):
  420. n = len(varlist)
  421. if not n:
  422. raise ShapeError("`len(varlist)` must not be zero.")
  423. else:
  424. raise ValueError("Improper variable list in hessian function")
  425. if not getattr(f, 'diff'):
  426. # check differentiability
  427. raise ValueError("Function `f` (%s) is not differentiable" % f)
  428. m = len(constraints)
  429. N = m + n
  430. out = zeros(N)
  431. for k, g in enumerate(constraints):
  432. if not getattr(g, 'diff'):
  433. # check differentiability
  434. raise ValueError("Function `f` (%s) is not differentiable" % f)
  435. for i in range(n):
  436. out[k, i + m] = g.diff(varlist[i])
  437. for i in range(n):
  438. for j in range(i, n):
  439. out[i + m, j + m] = f.diff(varlist[i]).diff(varlist[j])
  440. for i in range(N):
  441. for j in range(i + 1, N):
  442. out[j, i] = out[i, j]
  443. return out
  444. def jordan_cell(eigenval, n):
  445. """
  446. Create a Jordan block:
  447. Examples
  448. ========
  449. >>> from sympy import jordan_cell
  450. >>> from sympy.abc import x
  451. >>> jordan_cell(x, 4)
  452. Matrix([
  453. [x, 1, 0, 0],
  454. [0, x, 1, 0],
  455. [0, 0, x, 1],
  456. [0, 0, 0, x]])
  457. """
  458. return Matrix.jordan_block(size=n, eigenvalue=eigenval)
  459. def matrix_multiply_elementwise(A, B):
  460. """Return the Hadamard product (elementwise product) of A and B
  461. >>> from sympy import Matrix, matrix_multiply_elementwise
  462. >>> A = Matrix([[0, 1, 2], [3, 4, 5]])
  463. >>> B = Matrix([[1, 10, 100], [100, 10, 1]])
  464. >>> matrix_multiply_elementwise(A, B)
  465. Matrix([
  466. [ 0, 10, 200],
  467. [300, 40, 5]])
  468. See Also
  469. ========
  470. sympy.matrices.common.MatrixCommon.__mul__
  471. """
  472. return A.multiply_elementwise(B)
  473. def ones(*args, **kwargs):
  474. """Returns a matrix of ones with ``rows`` rows and ``cols`` columns;
  475. if ``cols`` is omitted a square matrix will be returned.
  476. See Also
  477. ========
  478. zeros
  479. eye
  480. diag
  481. """
  482. if 'c' in kwargs:
  483. kwargs['cols'] = kwargs.pop('c')
  484. return Matrix.ones(*args, **kwargs)
  485. def randMatrix(r, c=None, min=0, max=99, seed=None, symmetric=False,
  486. percent=100, prng=None):
  487. """Create random matrix with dimensions ``r`` x ``c``. If ``c`` is omitted
  488. the matrix will be square. If ``symmetric`` is True the matrix must be
  489. square. If ``percent`` is less than 100 then only approximately the given
  490. percentage of elements will be non-zero.
  491. The pseudo-random number generator used to generate matrix is chosen in the
  492. following way.
  493. * If ``prng`` is supplied, it will be used as random number generator.
  494. It should be an instance of ``random.Random``, or at least have
  495. ``randint`` and ``shuffle`` methods with same signatures.
  496. * if ``prng`` is not supplied but ``seed`` is supplied, then new
  497. ``random.Random`` with given ``seed`` will be created;
  498. * otherwise, a new ``random.Random`` with default seed will be used.
  499. Examples
  500. ========
  501. >>> from sympy import randMatrix
  502. >>> randMatrix(3) # doctest:+SKIP
  503. [25, 45, 27]
  504. [44, 54, 9]
  505. [23, 96, 46]
  506. >>> randMatrix(3, 2) # doctest:+SKIP
  507. [87, 29]
  508. [23, 37]
  509. [90, 26]
  510. >>> randMatrix(3, 3, 0, 2) # doctest:+SKIP
  511. [0, 2, 0]
  512. [2, 0, 1]
  513. [0, 0, 1]
  514. >>> randMatrix(3, symmetric=True) # doctest:+SKIP
  515. [85, 26, 29]
  516. [26, 71, 43]
  517. [29, 43, 57]
  518. >>> A = randMatrix(3, seed=1)
  519. >>> B = randMatrix(3, seed=2)
  520. >>> A == B
  521. False
  522. >>> A == randMatrix(3, seed=1)
  523. True
  524. >>> randMatrix(3, symmetric=True, percent=50) # doctest:+SKIP
  525. [77, 70, 0],
  526. [70, 0, 0],
  527. [ 0, 0, 88]
  528. """
  529. # Note that ``Random()`` is equivalent to ``Random(None)``
  530. prng = prng or random.Random(seed)
  531. if c is None:
  532. c = r
  533. if symmetric and r != c:
  534. raise ValueError('For symmetric matrices, r must equal c, but %i != %i' % (r, c))
  535. ij = range(r * c)
  536. if percent != 100:
  537. ij = prng.sample(ij, int(len(ij)*percent // 100))
  538. m = zeros(r, c)
  539. if not symmetric:
  540. for ijk in ij:
  541. i, j = divmod(ijk, c)
  542. m[i, j] = prng.randint(min, max)
  543. else:
  544. for ijk in ij:
  545. i, j = divmod(ijk, c)
  546. if i <= j:
  547. m[i, j] = m[j, i] = prng.randint(min, max)
  548. return m
  549. def wronskian(functions, var, method='bareiss'):
  550. """
  551. Compute Wronskian for [] of functions
  552. ::
  553. | f1 f2 ... fn |
  554. | f1' f2' ... fn' |
  555. | . . . . |
  556. W(f1, ..., fn) = | . . . . |
  557. | . . . . |
  558. | (n) (n) (n) |
  559. | D (f1) D (f2) ... D (fn) |
  560. see: https://en.wikipedia.org/wiki/Wronskian
  561. See Also
  562. ========
  563. sympy.matrices.matrices.MatrixCalculus.jacobian
  564. hessian
  565. """
  566. for index in range(0, len(functions)):
  567. functions[index] = sympify(functions[index])
  568. n = len(functions)
  569. if n == 0:
  570. return S.One
  571. W = Matrix(n, n, lambda i, j: functions[i].diff(var, j))
  572. return W.det(method)
  573. def zeros(*args, **kwargs):
  574. """Returns a matrix of zeros with ``rows`` rows and ``cols`` columns;
  575. if ``cols`` is omitted a square matrix will be returned.
  576. See Also
  577. ========
  578. ones
  579. eye
  580. diag
  581. """
  582. if 'c' in kwargs:
  583. kwargs['cols'] = kwargs.pop('c')
  584. return Matrix.zeros(*args, **kwargs)