dense.py 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  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.utilities.decorator import doctest_depends_on
  8. from sympy.utilities.exceptions import sympy_deprecation_warning
  9. from sympy.utilities.iterables import is_sequence
  10. from .common import ShapeError
  11. from .decompositions import _cholesky, _LDLdecomposition
  12. from .matrices import MatrixBase
  13. from .repmatrix import MutableRepMatrix, RepMatrix
  14. from .solvers import _lower_triangular_solve, _upper_triangular_solve
  15. def _iszero(x):
  16. """Returns True if x is zero."""
  17. return x.is_zero
  18. class DenseMatrix(RepMatrix):
  19. """Matrix implementation based on DomainMatrix as the internal representation"""
  20. #
  21. # DenseMatrix is a superclass for both MutableDenseMatrix and
  22. # ImmutableDenseMatrix. Methods shared by both classes but not for the
  23. # Sparse classes should be implemented here.
  24. #
  25. is_MatrixExpr = False # type: bool
  26. _op_priority = 10.01
  27. _class_priority = 4
  28. @property
  29. def _mat(self):
  30. sympy_deprecation_warning(
  31. """
  32. The private _mat attribute of Matrix is deprecated. Use the
  33. .flat() method instead.
  34. """,
  35. deprecated_since_version="1.9",
  36. active_deprecations_target="deprecated-private-matrix-attributes"
  37. )
  38. return self.flat()
  39. def _eval_inverse(self, **kwargs):
  40. return self.inv(method=kwargs.get('method', 'GE'),
  41. iszerofunc=kwargs.get('iszerofunc', _iszero),
  42. try_block_diag=kwargs.get('try_block_diag', False))
  43. def as_immutable(self):
  44. """Returns an Immutable version of this Matrix
  45. """
  46. from .immutable import ImmutableDenseMatrix as cls
  47. return cls._fromrep(self._rep.copy())
  48. def as_mutable(self):
  49. """Returns a mutable version of this matrix
  50. Examples
  51. ========
  52. >>> from sympy import ImmutableMatrix
  53. >>> X = ImmutableMatrix([[1, 2], [3, 4]])
  54. >>> Y = X.as_mutable()
  55. >>> Y[1, 1] = 5 # Can set values in Y
  56. >>> Y
  57. Matrix([
  58. [1, 2],
  59. [3, 5]])
  60. """
  61. return Matrix(self)
  62. def cholesky(self, hermitian=True):
  63. return _cholesky(self, hermitian=hermitian)
  64. def LDLdecomposition(self, hermitian=True):
  65. return _LDLdecomposition(self, hermitian=hermitian)
  66. def lower_triangular_solve(self, rhs):
  67. return _lower_triangular_solve(self, rhs)
  68. def upper_triangular_solve(self, rhs):
  69. return _upper_triangular_solve(self, rhs)
  70. cholesky.__doc__ = _cholesky.__doc__
  71. LDLdecomposition.__doc__ = _LDLdecomposition.__doc__
  72. lower_triangular_solve.__doc__ = _lower_triangular_solve.__doc__
  73. upper_triangular_solve.__doc__ = _upper_triangular_solve.__doc__
  74. def _force_mutable(x):
  75. """Return a matrix as a Matrix, otherwise return x."""
  76. if getattr(x, 'is_Matrix', False):
  77. return x.as_mutable()
  78. elif isinstance(x, Basic):
  79. return x
  80. elif hasattr(x, '__array__'):
  81. a = x.__array__()
  82. if len(a.shape) == 0:
  83. return sympify(a)
  84. return Matrix(x)
  85. return x
  86. class MutableDenseMatrix(DenseMatrix, MutableRepMatrix):
  87. def simplify(self, **kwargs):
  88. """Applies simplify to the elements of a matrix in place.
  89. This is a shortcut for M.applyfunc(lambda x: simplify(x, ratio, measure))
  90. See Also
  91. ========
  92. sympy.simplify.simplify.simplify
  93. """
  94. from sympy.simplify.simplify import simplify as _simplify
  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
  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. ###########
  126. # Rotation matrices:
  127. # rot_givens, rot_axis[123], rot_ccw_axis[123]
  128. ###########
  129. def rot_givens(i, j, theta, dim=3):
  130. r"""Returns a a Givens rotation matrix, a a rotation in the
  131. plane spanned by two coordinates axes.
  132. Explanation
  133. ===========
  134. The Givens rotation corresponds to a generalization of rotation
  135. matrices to any number of dimensions, given by:
  136. .. math::
  137. G(i, j, \theta) =
  138. \begin{bmatrix}
  139. 1 & \cdots & 0 & \cdots & 0 & \cdots & 0 \\
  140. \vdots & \ddots & \vdots & & \vdots & & \vdots \\
  141. 0 & \cdots & c & \cdots & -s & \cdots & 0 \\
  142. \vdots & & \vdots & \ddots & \vdots & & \vdots \\
  143. 0 & \cdots & s & \cdots & c & \cdots & 0 \\
  144. \vdots & & \vdots & & \vdots & \ddots & \vdots \\
  145. 0 & \cdots & 0 & \cdots & 0 & \cdots & 1
  146. \end{bmatrix}
  147. Where $c = \cos(\theta)$ and $s = \sin(\theta)$ appear at the intersections
  148. ``i``\th and ``j``\th rows and columns.
  149. For fixed ``i > j``\, the non-zero elements of a Givens matrix are
  150. given by:
  151. - $g_{kk} = 1$ for $k \ne i,\,j$
  152. - $g_{kk} = c$ for $k = i,\,j$
  153. - $g_{ji} = -g_{ij} = -s$
  154. Parameters
  155. ==========
  156. i : int between ``0`` and ``dim - 1``
  157. Represents first axis
  158. j : int between ``0`` and ``dim - 1``
  159. Represents second axis
  160. dim : int bigger than 1
  161. Number of dimentions. Defaults to 3.
  162. Examples
  163. ========
  164. >>> from sympy import pi, rot_givens
  165. A counterclockwise rotation of pi/3 (60 degrees) around
  166. the third axis (z-axis):
  167. >>> rot_givens(1, 0, pi/3)
  168. Matrix([
  169. [ 1/2, -sqrt(3)/2, 0],
  170. [sqrt(3)/2, 1/2, 0],
  171. [ 0, 0, 1]])
  172. If we rotate by pi/2 (90 degrees):
  173. >>> rot_givens(1, 0, pi/2)
  174. Matrix([
  175. [0, -1, 0],
  176. [1, 0, 0],
  177. [0, 0, 1]])
  178. This can be generalized to any number
  179. of dimensions:
  180. >>> rot_givens(1, 0, pi/2, dim=4)
  181. Matrix([
  182. [0, -1, 0, 0],
  183. [1, 0, 0, 0],
  184. [0, 0, 1, 0],
  185. [0, 0, 0, 1]])
  186. References
  187. ==========
  188. .. [1] https://en.wikipedia.org/wiki/Givens_rotation
  189. See Also
  190. ========
  191. rot_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  192. about the 1-axis (clockwise around the x axis)
  193. rot_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  194. about the 2-axis (clockwise around the y axis)
  195. rot_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  196. about the 3-axis (clockwise around the z axis)
  197. rot_ccw_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  198. about the 1-axis (counterclockwise around the x axis)
  199. rot_ccw_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  200. about the 2-axis (counterclockwise around the y axis)
  201. rot_ccw_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  202. about the 3-axis (counterclockwise around the z axis)
  203. """
  204. if not isinstance(dim, int) or dim < 2:
  205. raise ValueError('dim must be an integer biggen than one, '
  206. 'got {}.'.format(dim))
  207. if i == j:
  208. raise ValueError('i and j must be different, '
  209. 'got ({}, {})'.format(i, j))
  210. for ij in [i, j]:
  211. if not isinstance(ij, int) or ij < 0 or ij > dim - 1:
  212. raise ValueError('i and j must be integers between 0 and '
  213. '{}, got i={} and j={}.'.format(dim-1, i, j))
  214. theta = sympify(theta)
  215. c = cos(theta)
  216. s = sin(theta)
  217. M = eye(dim)
  218. M[i, i] = c
  219. M[j, j] = c
  220. M[i, j] = s
  221. M[j, i] = -s
  222. return M
  223. def rot_axis3(theta):
  224. r"""Returns a rotation matrix for a rotation of theta (in radians)
  225. about the 3-axis.
  226. Explanation
  227. ===========
  228. For a right-handed coordinate system, this corresponds to a
  229. clockwise rotation around the `z`-axis, given by:
  230. .. math::
  231. R = \begin{bmatrix}
  232. \cos(\theta) & \sin(\theta) & 0 \\
  233. -\sin(\theta) & \cos(\theta) & 0 \\
  234. 0 & 0 & 1
  235. \end{bmatrix}
  236. Examples
  237. ========
  238. >>> from sympy import pi, rot_axis3
  239. A rotation of pi/3 (60 degrees):
  240. >>> theta = pi/3
  241. >>> rot_axis3(theta)
  242. Matrix([
  243. [ 1/2, sqrt(3)/2, 0],
  244. [-sqrt(3)/2, 1/2, 0],
  245. [ 0, 0, 1]])
  246. If we rotate by pi/2 (90 degrees):
  247. >>> rot_axis3(pi/2)
  248. Matrix([
  249. [ 0, 1, 0],
  250. [-1, 0, 0],
  251. [ 0, 0, 1]])
  252. See Also
  253. ========
  254. rot_givens: Returns a Givens rotation matrix (generalized rotation for
  255. any number of dimensions)
  256. rot_ccw_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  257. about the 3-axis (counterclockwise around the z axis)
  258. rot_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  259. about the 1-axis (clockwise around the x axis)
  260. rot_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  261. about the 2-axis (clockwise around the y axis)
  262. """
  263. return rot_givens(0, 1, theta, dim=3)
  264. def rot_axis2(theta):
  265. r"""Returns a rotation matrix for a rotation of theta (in radians)
  266. about the 2-axis.
  267. Explanation
  268. ===========
  269. For a right-handed coordinate system, this corresponds to a
  270. clockwise rotation around the `y`-axis, given by:
  271. .. math::
  272. R = \begin{bmatrix}
  273. \cos(\theta) & 0 & -\sin(\theta) \\
  274. 0 & 1 & 0 \\
  275. \sin(\theta) & 0 & \cos(\theta)
  276. \end{bmatrix}
  277. Examples
  278. ========
  279. >>> from sympy import pi, rot_axis2
  280. A rotation of pi/3 (60 degrees):
  281. >>> theta = pi/3
  282. >>> rot_axis2(theta)
  283. Matrix([
  284. [ 1/2, 0, -sqrt(3)/2],
  285. [ 0, 1, 0],
  286. [sqrt(3)/2, 0, 1/2]])
  287. If we rotate by pi/2 (90 degrees):
  288. >>> rot_axis2(pi/2)
  289. Matrix([
  290. [0, 0, -1],
  291. [0, 1, 0],
  292. [1, 0, 0]])
  293. See Also
  294. ========
  295. rot_givens: Returns a Givens rotation matrix (generalized rotation for
  296. any number of dimensions)
  297. rot_ccw_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  298. about the 2-axis (clockwise around the y axis)
  299. rot_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  300. about the 1-axis (counterclockwise around the x axis)
  301. rot_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  302. about the 3-axis (counterclockwise around the z axis)
  303. """
  304. return rot_givens(2, 0, theta, dim=3)
  305. def rot_axis1(theta):
  306. r"""Returns a rotation matrix for a rotation of theta (in radians)
  307. about the 1-axis.
  308. Explanation
  309. ===========
  310. For a right-handed coordinate system, this corresponds to a
  311. clockwise rotation around the `x`-axis, given by:
  312. .. math::
  313. R = \begin{bmatrix}
  314. 1 & 0 & 0 \\
  315. 0 & \cos(\theta) & \sin(\theta) \\
  316. 0 & -\sin(\theta) & \cos(\theta)
  317. \end{bmatrix}
  318. Examples
  319. ========
  320. >>> from sympy import pi, rot_axis1
  321. A rotation of pi/3 (60 degrees):
  322. >>> theta = pi/3
  323. >>> rot_axis1(theta)
  324. Matrix([
  325. [1, 0, 0],
  326. [0, 1/2, sqrt(3)/2],
  327. [0, -sqrt(3)/2, 1/2]])
  328. If we rotate by pi/2 (90 degrees):
  329. >>> rot_axis1(pi/2)
  330. Matrix([
  331. [1, 0, 0],
  332. [0, 0, 1],
  333. [0, -1, 0]])
  334. See Also
  335. ========
  336. rot_givens: Returns a Givens rotation matrix (generalized rotation for
  337. any number of dimensions)
  338. rot_ccw_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  339. about the 1-axis (counterclockwise around the x axis)
  340. rot_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  341. about the 2-axis (clockwise around the y axis)
  342. rot_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  343. about the 3-axis (clockwise around the z axis)
  344. """
  345. return rot_givens(1, 2, theta, dim=3)
  346. def rot_ccw_axis3(theta):
  347. r"""Returns a rotation matrix for a rotation of theta (in radians)
  348. about the 3-axis.
  349. Explanation
  350. ===========
  351. For a right-handed coordinate system, this corresponds to a
  352. counterclockwise rotation around the `z`-axis, given by:
  353. .. math::
  354. R = \begin{bmatrix}
  355. \cos(\theta) & -\sin(\theta) & 0 \\
  356. \sin(\theta) & \cos(\theta) & 0 \\
  357. 0 & 0 & 1
  358. \end{bmatrix}
  359. Examples
  360. ========
  361. >>> from sympy import pi, rot_ccw_axis3
  362. A rotation of pi/3 (60 degrees):
  363. >>> theta = pi/3
  364. >>> rot_ccw_axis3(theta)
  365. Matrix([
  366. [ 1/2, -sqrt(3)/2, 0],
  367. [sqrt(3)/2, 1/2, 0],
  368. [ 0, 0, 1]])
  369. If we rotate by pi/2 (90 degrees):
  370. >>> rot_ccw_axis3(pi/2)
  371. Matrix([
  372. [0, -1, 0],
  373. [1, 0, 0],
  374. [0, 0, 1]])
  375. See Also
  376. ========
  377. rot_givens: Returns a Givens rotation matrix (generalized rotation for
  378. any number of dimensions)
  379. rot_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  380. about the 3-axis (clockwise around the z axis)
  381. rot_ccw_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  382. about the 1-axis (counterclockwise around the x axis)
  383. rot_ccw_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  384. about the 2-axis (counterclockwise around the y axis)
  385. """
  386. return rot_givens(1, 0, theta, dim=3)
  387. def rot_ccw_axis2(theta):
  388. r"""Returns a rotation matrix for a rotation of theta (in radians)
  389. about the 2-axis.
  390. Explanation
  391. ===========
  392. For a right-handed coordinate system, this corresponds to a
  393. counterclockwise rotation around the `y`-axis, given by:
  394. .. math::
  395. R = \begin{bmatrix}
  396. \cos(\theta) & 0 & \sin(\theta) \\
  397. 0 & 1 & 0 \\
  398. -\sin(\theta) & 0 & \cos(\theta)
  399. \end{bmatrix}
  400. Examples
  401. ========
  402. >>> from sympy import pi, rot_ccw_axis2
  403. A rotation of pi/3 (60 degrees):
  404. >>> theta = pi/3
  405. >>> rot_ccw_axis2(theta)
  406. Matrix([
  407. [ 1/2, 0, sqrt(3)/2],
  408. [ 0, 1, 0],
  409. [-sqrt(3)/2, 0, 1/2]])
  410. If we rotate by pi/2 (90 degrees):
  411. >>> rot_ccw_axis2(pi/2)
  412. Matrix([
  413. [ 0, 0, 1],
  414. [ 0, 1, 0],
  415. [-1, 0, 0]])
  416. See Also
  417. ========
  418. rot_givens: Returns a Givens rotation matrix (generalized rotation for
  419. any number of dimensions)
  420. rot_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  421. about the 2-axis (clockwise around the y axis)
  422. rot_ccw_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  423. about the 1-axis (counterclockwise around the x axis)
  424. rot_ccw_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  425. about the 3-axis (counterclockwise around the z axis)
  426. """
  427. return rot_givens(0, 2, theta, dim=3)
  428. def rot_ccw_axis1(theta):
  429. r"""Returns a rotation matrix for a rotation of theta (in radians)
  430. about the 1-axis.
  431. Explanation
  432. ===========
  433. For a right-handed coordinate system, this corresponds to a
  434. counterclockwise rotation around the `x`-axis, given by:
  435. .. math::
  436. R = \begin{bmatrix}
  437. 1 & 0 & 0 \\
  438. 0 & \cos(\theta) & -\sin(\theta) \\
  439. 0 & \sin(\theta) & \cos(\theta)
  440. \end{bmatrix}
  441. Examples
  442. ========
  443. >>> from sympy import pi, rot_ccw_axis1
  444. A rotation of pi/3 (60 degrees):
  445. >>> theta = pi/3
  446. >>> rot_ccw_axis1(theta)
  447. Matrix([
  448. [1, 0, 0],
  449. [0, 1/2, -sqrt(3)/2],
  450. [0, sqrt(3)/2, 1/2]])
  451. If we rotate by pi/2 (90 degrees):
  452. >>> rot_ccw_axis1(pi/2)
  453. Matrix([
  454. [1, 0, 0],
  455. [0, 0, -1],
  456. [0, 1, 0]])
  457. See Also
  458. ========
  459. rot_givens: Returns a Givens rotation matrix (generalized rotation for
  460. any number of dimensions)
  461. rot_axis1: Returns a rotation matrix for a rotation of theta (in radians)
  462. about the 1-axis (clockwise around the x axis)
  463. rot_ccw_axis2: Returns a rotation matrix for a rotation of theta (in radians)
  464. about the 2-axis (counterclockwise around the y axis)
  465. rot_ccw_axis3: Returns a rotation matrix for a rotation of theta (in radians)
  466. about the 3-axis (counterclockwise around the z axis)
  467. """
  468. return rot_givens(2, 1, theta, dim=3)
  469. @doctest_depends_on(modules=('numpy',))
  470. def symarray(prefix, shape, **kwargs): # pragma: no cover
  471. r"""Create a numpy ndarray of symbols (as an object array).
  472. The created symbols are named ``prefix_i1_i2_``... You should thus provide a
  473. non-empty prefix if you want your symbols to be unique for different output
  474. arrays, as SymPy symbols with identical names are the same object.
  475. Parameters
  476. ----------
  477. prefix : string
  478. A prefix prepended to the name of every symbol.
  479. shape : int or tuple
  480. Shape of the created array. If an int, the array is one-dimensional; for
  481. more than one dimension the shape must be a tuple.
  482. \*\*kwargs : dict
  483. keyword arguments passed on to Symbol
  484. Examples
  485. ========
  486. These doctests require numpy.
  487. >>> from sympy import symarray
  488. >>> symarray('', 3)
  489. [_0 _1 _2]
  490. If you want multiple symarrays to contain distinct symbols, you *must*
  491. provide unique prefixes:
  492. >>> a = symarray('', 3)
  493. >>> b = symarray('', 3)
  494. >>> a[0] == b[0]
  495. True
  496. >>> a = symarray('a', 3)
  497. >>> b = symarray('b', 3)
  498. >>> a[0] == b[0]
  499. False
  500. Creating symarrays with a prefix:
  501. >>> symarray('a', 3)
  502. [a_0 a_1 a_2]
  503. For more than one dimension, the shape must be given as a tuple:
  504. >>> symarray('a', (2, 3))
  505. [[a_0_0 a_0_1 a_0_2]
  506. [a_1_0 a_1_1 a_1_2]]
  507. >>> symarray('a', (2, 3, 2))
  508. [[[a_0_0_0 a_0_0_1]
  509. [a_0_1_0 a_0_1_1]
  510. [a_0_2_0 a_0_2_1]]
  511. <BLANKLINE>
  512. [[a_1_0_0 a_1_0_1]
  513. [a_1_1_0 a_1_1_1]
  514. [a_1_2_0 a_1_2_1]]]
  515. For setting assumptions of the underlying Symbols:
  516. >>> [s.is_real for s in symarray('a', 2, real=True)]
  517. [True, True]
  518. """
  519. from numpy import empty, ndindex
  520. arr = empty(shape, dtype=object)
  521. for index in ndindex(shape):
  522. arr[index] = Symbol('%s_%s' % (prefix, '_'.join(map(str, index))),
  523. **kwargs)
  524. return arr
  525. ###############
  526. # Functions
  527. ###############
  528. def casoratian(seqs, n, zero=True):
  529. """Given linear difference operator L of order 'k' and homogeneous
  530. equation Ly = 0 we want to compute kernel of L, which is a set
  531. of 'k' sequences: a(n), b(n), ... z(n).
  532. Solutions of L are linearly independent iff their Casoratian,
  533. denoted as C(a, b, ..., z), do not vanish for n = 0.
  534. Casoratian is defined by k x k determinant::
  535. + a(n) b(n) . . . z(n) +
  536. | a(n+1) b(n+1) . . . z(n+1) |
  537. | . . . . |
  538. | . . . . |
  539. | . . . . |
  540. + a(n+k-1) b(n+k-1) . . . z(n+k-1) +
  541. It proves very useful in rsolve_hyper() where it is applied
  542. to a generating set of a recurrence to factor out linearly
  543. dependent solutions and return a basis:
  544. >>> from sympy import Symbol, casoratian, factorial
  545. >>> n = Symbol('n', integer=True)
  546. Exponential and factorial are linearly independent:
  547. >>> casoratian([2**n, factorial(n)], n) != 0
  548. True
  549. """
  550. seqs = list(map(sympify, seqs))
  551. if not zero:
  552. f = lambda i, j: seqs[j].subs(n, n + i)
  553. else:
  554. f = lambda i, j: seqs[j].subs(n, i)
  555. k = len(seqs)
  556. return Matrix(k, k, f).det()
  557. def eye(*args, **kwargs):
  558. """Create square identity matrix n x n
  559. See Also
  560. ========
  561. diag
  562. zeros
  563. ones
  564. """
  565. return Matrix.eye(*args, **kwargs)
  566. def diag(*values, strict=True, unpack=False, **kwargs):
  567. """Returns a matrix with the provided values placed on the
  568. diagonal. If non-square matrices are included, they will
  569. produce a block-diagonal matrix.
  570. Examples
  571. ========
  572. This version of diag is a thin wrapper to Matrix.diag that differs
  573. in that it treats all lists like matrices -- even when a single list
  574. is given. If this is not desired, either put a `*` before the list or
  575. set `unpack=True`.
  576. >>> from sympy import diag
  577. >>> diag([1, 2, 3], unpack=True) # = diag(1,2,3) or diag(*[1,2,3])
  578. Matrix([
  579. [1, 0, 0],
  580. [0, 2, 0],
  581. [0, 0, 3]])
  582. >>> diag([1, 2, 3]) # a column vector
  583. Matrix([
  584. [1],
  585. [2],
  586. [3]])
  587. See Also
  588. ========
  589. .common.MatrixCommon.eye
  590. .common.MatrixCommon.diagonal
  591. .common.MatrixCommon.diag
  592. .expressions.blockmatrix.BlockMatrix
  593. """
  594. return Matrix.diag(*values, strict=strict, unpack=unpack, **kwargs)
  595. def GramSchmidt(vlist, orthonormal=False):
  596. """Apply the Gram-Schmidt process to a set of vectors.
  597. Parameters
  598. ==========
  599. vlist : List of Matrix
  600. Vectors to be orthogonalized for.
  601. orthonormal : Bool, optional
  602. If true, return an orthonormal basis.
  603. Returns
  604. =======
  605. vlist : List of Matrix
  606. Orthogonalized vectors
  607. Notes
  608. =====
  609. This routine is mostly duplicate from ``Matrix.orthogonalize``,
  610. except for some difference that this always raises error when
  611. linearly dependent vectors are found, and the keyword ``normalize``
  612. has been named as ``orthonormal`` in this function.
  613. See Also
  614. ========
  615. .matrices.MatrixSubspaces.orthogonalize
  616. References
  617. ==========
  618. .. [1] https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process
  619. """
  620. return MutableDenseMatrix.orthogonalize(
  621. *vlist, normalize=orthonormal, rankcheck=True
  622. )
  623. def hessian(f, varlist, constraints=()):
  624. """Compute Hessian matrix for a function f wrt parameters in varlist
  625. which may be given as a sequence or a row/column vector. A list of
  626. constraints may optionally be given.
  627. Examples
  628. ========
  629. >>> from sympy import Function, hessian, pprint
  630. >>> from sympy.abc import x, y
  631. >>> f = Function('f')(x, y)
  632. >>> g1 = Function('g')(x, y)
  633. >>> g2 = x**2 + 3*y
  634. >>> pprint(hessian(f, (x, y), [g1, g2]))
  635. [ d d ]
  636. [ 0 0 --(g(x, y)) --(g(x, y)) ]
  637. [ dx dy ]
  638. [ ]
  639. [ 0 0 2*x 3 ]
  640. [ ]
  641. [ 2 2 ]
  642. [d d d ]
  643. [--(g(x, y)) 2*x ---(f(x, y)) -----(f(x, y))]
  644. [dx 2 dy dx ]
  645. [ dx ]
  646. [ ]
  647. [ 2 2 ]
  648. [d d d ]
  649. [--(g(x, y)) 3 -----(f(x, y)) ---(f(x, y)) ]
  650. [dy dy dx 2 ]
  651. [ dy ]
  652. References
  653. ==========
  654. .. [1] https://en.wikipedia.org/wiki/Hessian_matrix
  655. See Also
  656. ========
  657. sympy.matrices.matrices.MatrixCalculus.jacobian
  658. wronskian
  659. """
  660. # f is the expression representing a function f, return regular matrix
  661. if isinstance(varlist, MatrixBase):
  662. if 1 not in varlist.shape:
  663. raise ShapeError("`varlist` must be a column or row vector.")
  664. if varlist.cols == 1:
  665. varlist = varlist.T
  666. varlist = varlist.tolist()[0]
  667. if is_sequence(varlist):
  668. n = len(varlist)
  669. if not n:
  670. raise ShapeError("`len(varlist)` must not be zero.")
  671. else:
  672. raise ValueError("Improper variable list in hessian function")
  673. if not getattr(f, 'diff'):
  674. # check differentiability
  675. raise ValueError("Function `f` (%s) is not differentiable" % f)
  676. m = len(constraints)
  677. N = m + n
  678. out = zeros(N)
  679. for k, g in enumerate(constraints):
  680. if not getattr(g, 'diff'):
  681. # check differentiability
  682. raise ValueError("Function `f` (%s) is not differentiable" % f)
  683. for i in range(n):
  684. out[k, i + m] = g.diff(varlist[i])
  685. for i in range(n):
  686. for j in range(i, n):
  687. out[i + m, j + m] = f.diff(varlist[i]).diff(varlist[j])
  688. for i in range(N):
  689. for j in range(i + 1, N):
  690. out[j, i] = out[i, j]
  691. return out
  692. def jordan_cell(eigenval, n):
  693. """
  694. Create a Jordan block:
  695. Examples
  696. ========
  697. >>> from sympy import jordan_cell
  698. >>> from sympy.abc import x
  699. >>> jordan_cell(x, 4)
  700. Matrix([
  701. [x, 1, 0, 0],
  702. [0, x, 1, 0],
  703. [0, 0, x, 1],
  704. [0, 0, 0, x]])
  705. """
  706. return Matrix.jordan_block(size=n, eigenvalue=eigenval)
  707. def matrix_multiply_elementwise(A, B):
  708. """Return the Hadamard product (elementwise product) of A and B
  709. >>> from sympy import Matrix, matrix_multiply_elementwise
  710. >>> A = Matrix([[0, 1, 2], [3, 4, 5]])
  711. >>> B = Matrix([[1, 10, 100], [100, 10, 1]])
  712. >>> matrix_multiply_elementwise(A, B)
  713. Matrix([
  714. [ 0, 10, 200],
  715. [300, 40, 5]])
  716. See Also
  717. ========
  718. sympy.matrices.common.MatrixCommon.__mul__
  719. """
  720. return A.multiply_elementwise(B)
  721. def ones(*args, **kwargs):
  722. """Returns a matrix of ones with ``rows`` rows and ``cols`` columns;
  723. if ``cols`` is omitted a square matrix will be returned.
  724. See Also
  725. ========
  726. zeros
  727. eye
  728. diag
  729. """
  730. if 'c' in kwargs:
  731. kwargs['cols'] = kwargs.pop('c')
  732. return Matrix.ones(*args, **kwargs)
  733. def randMatrix(r, c=None, min=0, max=99, seed=None, symmetric=False,
  734. percent=100, prng=None):
  735. """Create random matrix with dimensions ``r`` x ``c``. If ``c`` is omitted
  736. the matrix will be square. If ``symmetric`` is True the matrix must be
  737. square. If ``percent`` is less than 100 then only approximately the given
  738. percentage of elements will be non-zero.
  739. The pseudo-random number generator used to generate matrix is chosen in the
  740. following way.
  741. * If ``prng`` is supplied, it will be used as random number generator.
  742. It should be an instance of ``random.Random``, or at least have
  743. ``randint`` and ``shuffle`` methods with same signatures.
  744. * if ``prng`` is not supplied but ``seed`` is supplied, then new
  745. ``random.Random`` with given ``seed`` will be created;
  746. * otherwise, a new ``random.Random`` with default seed will be used.
  747. Examples
  748. ========
  749. >>> from sympy import randMatrix
  750. >>> randMatrix(3) # doctest:+SKIP
  751. [25, 45, 27]
  752. [44, 54, 9]
  753. [23, 96, 46]
  754. >>> randMatrix(3, 2) # doctest:+SKIP
  755. [87, 29]
  756. [23, 37]
  757. [90, 26]
  758. >>> randMatrix(3, 3, 0, 2) # doctest:+SKIP
  759. [0, 2, 0]
  760. [2, 0, 1]
  761. [0, 0, 1]
  762. >>> randMatrix(3, symmetric=True) # doctest:+SKIP
  763. [85, 26, 29]
  764. [26, 71, 43]
  765. [29, 43, 57]
  766. >>> A = randMatrix(3, seed=1)
  767. >>> B = randMatrix(3, seed=2)
  768. >>> A == B
  769. False
  770. >>> A == randMatrix(3, seed=1)
  771. True
  772. >>> randMatrix(3, symmetric=True, percent=50) # doctest:+SKIP
  773. [77, 70, 0],
  774. [70, 0, 0],
  775. [ 0, 0, 88]
  776. """
  777. # Note that ``Random()`` is equivalent to ``Random(None)``
  778. prng = prng or random.Random(seed)
  779. if c is None:
  780. c = r
  781. if symmetric and r != c:
  782. raise ValueError('For symmetric matrices, r must equal c, but %i != %i' % (r, c))
  783. ij = range(r * c)
  784. if percent != 100:
  785. ij = prng.sample(ij, int(len(ij)*percent // 100))
  786. m = zeros(r, c)
  787. if not symmetric:
  788. for ijk in ij:
  789. i, j = divmod(ijk, c)
  790. m[i, j] = prng.randint(min, max)
  791. else:
  792. for ijk in ij:
  793. i, j = divmod(ijk, c)
  794. if i <= j:
  795. m[i, j] = m[j, i] = prng.randint(min, max)
  796. return m
  797. def wronskian(functions, var, method='bareiss'):
  798. """
  799. Compute Wronskian for [] of functions
  800. ::
  801. | f1 f2 ... fn |
  802. | f1' f2' ... fn' |
  803. | . . . . |
  804. W(f1, ..., fn) = | . . . . |
  805. | . . . . |
  806. | (n) (n) (n) |
  807. | D (f1) D (f2) ... D (fn) |
  808. see: https://en.wikipedia.org/wiki/Wronskian
  809. See Also
  810. ========
  811. sympy.matrices.matrices.MatrixCalculus.jacobian
  812. hessian
  813. """
  814. functions = [sympify(f) for f in functions]
  815. n = len(functions)
  816. if n == 0:
  817. return S.One
  818. W = Matrix(n, n, lambda i, j: functions[i].diff(var, j))
  819. return W.det(method)
  820. def zeros(*args, **kwargs):
  821. """Returns a matrix of zeros with ``rows`` rows and ``cols`` columns;
  822. if ``cols`` is omitted a square matrix will be returned.
  823. See Also
  824. ========
  825. ones
  826. eye
  827. diag
  828. """
  829. if 'c' in kwargs:
  830. kwargs['cols'] = kwargs.pop('c')
  831. return Matrix.zeros(*args, **kwargs)