test_domainmatrix.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. from sympy.testing.pytest import raises
  2. from sympy.core.numbers import Integer, Rational
  3. from sympy.core.singleton import S
  4. from sympy.functions import sqrt
  5. from sympy.matrices.dense import Matrix
  6. from sympy.polys.domains import FF, ZZ, QQ, EXRAW
  7. from sympy.polys.matrices.domainmatrix import DomainMatrix, DomainScalar, DM
  8. from sympy.polys.matrices.exceptions import (
  9. DMBadInputError, DMDomainError, DMShapeError, DMFormatError, DMNotAField,
  10. DMNonSquareMatrixError, DMNonInvertibleMatrixError,
  11. )
  12. from sympy.polys.matrices.ddm import DDM
  13. from sympy.polys.matrices.sdm import SDM
  14. def test_DM():
  15. ddm = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  16. A = DM([[1, 2], [3, 4]], ZZ)
  17. assert A.rep == ddm
  18. assert A.shape == (2, 2)
  19. assert A.domain == ZZ
  20. def test_DomainMatrix_init():
  21. lol = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]]
  22. dod = {0: {0: ZZ(1), 1:ZZ(2)}, 1: {0:ZZ(3), 1:ZZ(4)}}
  23. ddm = DDM(lol, (2, 2), ZZ)
  24. sdm = SDM(dod, (2, 2), ZZ)
  25. A = DomainMatrix(lol, (2, 2), ZZ)
  26. assert A.rep == ddm
  27. assert A.shape == (2, 2)
  28. assert A.domain == ZZ
  29. A = DomainMatrix(dod, (2, 2), ZZ)
  30. assert A.rep == sdm
  31. assert A.shape == (2, 2)
  32. assert A.domain == ZZ
  33. raises(TypeError, lambda: DomainMatrix(ddm, (2, 2), ZZ))
  34. raises(TypeError, lambda: DomainMatrix(sdm, (2, 2), ZZ))
  35. raises(TypeError, lambda: DomainMatrix(Matrix([[1]]), (1, 1), ZZ))
  36. for fmt, rep in [('sparse', sdm), ('dense', ddm)]:
  37. A = DomainMatrix(lol, (2, 2), ZZ, fmt=fmt)
  38. assert A.rep == rep
  39. A = DomainMatrix(dod, (2, 2), ZZ, fmt=fmt)
  40. assert A.rep == rep
  41. raises(ValueError, lambda: DomainMatrix(lol, (2, 2), ZZ, fmt='invalid'))
  42. raises(DMBadInputError, lambda: DomainMatrix([[ZZ(1), ZZ(2)]], (2, 2), ZZ))
  43. def test_DomainMatrix_from_rep():
  44. ddm = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  45. A = DomainMatrix.from_rep(ddm)
  46. assert A.rep == ddm
  47. assert A.shape == (2, 2)
  48. assert A.domain == ZZ
  49. sdm = SDM({0: {0: ZZ(1), 1:ZZ(2)}, 1: {0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ)
  50. A = DomainMatrix.from_rep(sdm)
  51. assert A.rep == sdm
  52. assert A.shape == (2, 2)
  53. assert A.domain == ZZ
  54. A = DomainMatrix([[ZZ(1)]], (1, 1), ZZ)
  55. raises(TypeError, lambda: DomainMatrix.from_rep(A))
  56. def test_DomainMatrix_from_list():
  57. ddm = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  58. A = DomainMatrix.from_list([[1, 2], [3, 4]], ZZ)
  59. assert A.rep == ddm
  60. assert A.shape == (2, 2)
  61. assert A.domain == ZZ
  62. dom = FF(7)
  63. ddm = DDM([[dom(1), dom(2)], [dom(3), dom(4)]], (2, 2), dom)
  64. A = DomainMatrix.from_list([[1, 2], [3, 4]], dom)
  65. assert A.rep == ddm
  66. assert A.shape == (2, 2)
  67. assert A.domain == dom
  68. ddm = DDM([[QQ(1, 2), QQ(3, 1)], [QQ(1, 4), QQ(5, 1)]], (2, 2), QQ)
  69. A = DomainMatrix.from_list([[(1, 2), (3, 1)], [(1, 4), (5, 1)]], QQ)
  70. assert A.rep == ddm
  71. assert A.shape == (2, 2)
  72. assert A.domain == QQ
  73. def test_DomainMatrix_from_list_sympy():
  74. ddm = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  75. A = DomainMatrix.from_list_sympy(2, 2, [[1, 2], [3, 4]])
  76. assert A.rep == ddm
  77. assert A.shape == (2, 2)
  78. assert A.domain == ZZ
  79. K = QQ.algebraic_field(sqrt(2))
  80. ddm = DDM(
  81. [[K.convert(1 + sqrt(2)), K.convert(2 + sqrt(2))],
  82. [K.convert(3 + sqrt(2)), K.convert(4 + sqrt(2))]],
  83. (2, 2),
  84. K
  85. )
  86. A = DomainMatrix.from_list_sympy(
  87. 2, 2, [[1 + sqrt(2), 2 + sqrt(2)], [3 + sqrt(2), 4 + sqrt(2)]],
  88. extension=True)
  89. assert A.rep == ddm
  90. assert A.shape == (2, 2)
  91. assert A.domain == K
  92. def test_DomainMatrix_from_dict_sympy():
  93. sdm = SDM({0: {0: QQ(1, 2)}, 1: {1: QQ(2, 3)}}, (2, 2), QQ)
  94. sympy_dict = {0: {0: Rational(1, 2)}, 1: {1: Rational(2, 3)}}
  95. A = DomainMatrix.from_dict_sympy(2, 2, sympy_dict)
  96. assert A.rep == sdm
  97. assert A.shape == (2, 2)
  98. assert A.domain == QQ
  99. fds = DomainMatrix.from_dict_sympy
  100. raises(DMBadInputError, lambda: fds(2, 2, {3: {0: Rational(1, 2)}}))
  101. raises(DMBadInputError, lambda: fds(2, 2, {0: {3: Rational(1, 2)}}))
  102. def test_DomainMatrix_from_Matrix():
  103. sdm = SDM({0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}}, (2, 2), ZZ)
  104. A = DomainMatrix.from_Matrix(Matrix([[1, 2], [3, 4]]))
  105. assert A.rep == sdm
  106. assert A.shape == (2, 2)
  107. assert A.domain == ZZ
  108. K = QQ.algebraic_field(sqrt(2))
  109. sdm = SDM(
  110. {0: {0: K.convert(1 + sqrt(2)), 1: K.convert(2 + sqrt(2))},
  111. 1: {0: K.convert(3 + sqrt(2)), 1: K.convert(4 + sqrt(2))}},
  112. (2, 2),
  113. K
  114. )
  115. A = DomainMatrix.from_Matrix(
  116. Matrix([[1 + sqrt(2), 2 + sqrt(2)], [3 + sqrt(2), 4 + sqrt(2)]]),
  117. extension=True)
  118. assert A.rep == sdm
  119. assert A.shape == (2, 2)
  120. assert A.domain == K
  121. A = DomainMatrix.from_Matrix(Matrix([[QQ(1, 2), QQ(3, 4)], [QQ(0, 1), QQ(0, 1)]]), fmt='dense')
  122. ddm = DDM([[QQ(1, 2), QQ(3, 4)], [QQ(0, 1), QQ(0, 1)]], (2, 2), QQ)
  123. assert A.rep == ddm
  124. assert A.shape == (2, 2)
  125. assert A.domain == QQ
  126. def test_DomainMatrix_eq():
  127. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  128. assert A == A
  129. B = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(1)]], (2, 2), ZZ)
  130. assert A != B
  131. C = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]]
  132. assert A != C
  133. def test_DomainMatrix_unify_eq():
  134. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  135. B1 = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  136. B2 = DomainMatrix([[QQ(1), QQ(3)], [QQ(3), QQ(4)]], (2, 2), QQ)
  137. B3 = DomainMatrix([[ZZ(1)]], (1, 1), ZZ)
  138. assert A.unify_eq(B1) is True
  139. assert A.unify_eq(B2) is False
  140. assert A.unify_eq(B3) is False
  141. def test_DomainMatrix_get_domain():
  142. K, items = DomainMatrix.get_domain([1, 2, 3, 4])
  143. assert items == [ZZ(1), ZZ(2), ZZ(3), ZZ(4)]
  144. assert K == ZZ
  145. K, items = DomainMatrix.get_domain([1, 2, 3, Rational(1, 2)])
  146. assert items == [QQ(1), QQ(2), QQ(3), QQ(1, 2)]
  147. assert K == QQ
  148. def test_DomainMatrix_convert_to():
  149. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  150. Aq = A.convert_to(QQ)
  151. assert Aq == DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  152. Acopy = A.convert_to(None)
  153. assert Acopy == A and Acopy is not A
  154. def test_DomainMatrix_to_sympy():
  155. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  156. assert A.to_sympy() == A.convert_to(EXRAW)
  157. def test_DomainMatrix_to_field():
  158. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  159. Aq = A.to_field()
  160. assert Aq == DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  161. def test_DomainMatrix_to_sparse():
  162. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  163. A_sparse = A.to_sparse()
  164. assert A_sparse.rep == {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}
  165. def test_DomainMatrix_to_dense():
  166. A = DomainMatrix({0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}, (2, 2), ZZ)
  167. A_dense = A.to_dense()
  168. assert A_dense.rep == DDM([[1, 2], [3, 4]], (2, 2), ZZ)
  169. def test_DomainMatrix_unify():
  170. Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  171. Aq = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  172. assert Az.unify(Az) == (Az, Az)
  173. assert Az.unify(Aq) == (Aq, Aq)
  174. assert Aq.unify(Az) == (Aq, Aq)
  175. assert Aq.unify(Aq) == (Aq, Aq)
  176. As = DomainMatrix({0: {1: ZZ(1)}, 1:{0:ZZ(2)}}, (2, 2), ZZ)
  177. Ad = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  178. assert As.unify(As) == (As, As)
  179. assert Ad.unify(Ad) == (Ad, Ad)
  180. Bs, Bd = As.unify(Ad, fmt='dense')
  181. assert Bs.rep == DDM([[0, 1], [2, 0]], (2, 2), ZZ)
  182. assert Bd.rep == DDM([[1, 2],[3, 4]], (2, 2), ZZ)
  183. Bs, Bd = As.unify(Ad, fmt='sparse')
  184. assert Bs.rep == SDM({0: {1: 1}, 1: {0: 2}}, (2, 2), ZZ)
  185. assert Bd.rep == SDM({0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}, (2, 2), ZZ)
  186. raises(ValueError, lambda: As.unify(Ad, fmt='invalid'))
  187. def test_DomainMatrix_to_Matrix():
  188. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  189. assert A.to_Matrix() == Matrix([[1, 2], [3, 4]])
  190. def test_DomainMatrix_to_list():
  191. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  192. assert A.to_list() == [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]]
  193. def test_DomainMatrix_to_list_flat():
  194. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  195. assert A.to_list_flat() == [ZZ(1), ZZ(2), ZZ(3), ZZ(4)]
  196. def test_DomainMatrix_to_dok():
  197. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  198. assert A.to_dok() == {(0, 0):ZZ(1), (0, 1):ZZ(2), (1, 0):ZZ(3), (1, 1):ZZ(4)}
  199. def test_DomainMatrix_repr():
  200. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  201. assert repr(A) == 'DomainMatrix([[1, 2], [3, 4]], (2, 2), ZZ)'
  202. def test_DomainMatrix_transpose():
  203. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  204. AT = DomainMatrix([[ZZ(1), ZZ(3)], [ZZ(2), ZZ(4)]], (2, 2), ZZ)
  205. assert A.transpose() == AT
  206. def test_DomainMatrix_flat():
  207. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  208. assert A.flat() == [ZZ(1), ZZ(2), ZZ(3), ZZ(4)]
  209. def test_DomainMatrix_is_zero_matrix():
  210. A = DomainMatrix([[ZZ(1)]], (1, 1), ZZ)
  211. B = DomainMatrix([[ZZ(0)]], (1, 1), ZZ)
  212. assert A.is_zero_matrix is False
  213. assert B.is_zero_matrix is True
  214. def test_DomainMatrix_is_upper():
  215. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(0), ZZ(4)]], (2, 2), ZZ)
  216. B = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  217. assert A.is_upper is True
  218. assert B.is_upper is False
  219. def test_DomainMatrix_is_lower():
  220. A = DomainMatrix([[ZZ(1), ZZ(0)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  221. B = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  222. assert A.is_lower is True
  223. assert B.is_lower is False
  224. def test_DomainMatrix_is_square():
  225. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  226. B = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)], [ZZ(5), ZZ(6)]], (3, 2), ZZ)
  227. assert A.is_square is True
  228. assert B.is_square is False
  229. def test_DomainMatrix_rank():
  230. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(6), QQ(8)]], (3, 2), QQ)
  231. assert A.rank() == 2
  232. def test_DomainMatrix_add():
  233. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  234. B = DomainMatrix([[ZZ(2), ZZ(4)], [ZZ(6), ZZ(8)]], (2, 2), ZZ)
  235. assert A + A == A.add(A) == B
  236. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  237. L = [[2, 3], [3, 4]]
  238. raises(TypeError, lambda: A + L)
  239. raises(TypeError, lambda: L + A)
  240. A1 = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  241. A2 = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ)
  242. raises(DMShapeError, lambda: A1 + A2)
  243. raises(DMShapeError, lambda: A2 + A1)
  244. raises(DMShapeError, lambda: A1.add(A2))
  245. raises(DMShapeError, lambda: A2.add(A1))
  246. Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  247. Aq = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  248. Asum = DomainMatrix([[QQ(2), QQ(4)], [QQ(6), QQ(8)]], (2, 2), QQ)
  249. assert Az + Aq == Asum
  250. assert Aq + Az == Asum
  251. raises(DMDomainError, lambda: Az.add(Aq))
  252. raises(DMDomainError, lambda: Aq.add(Az))
  253. As = DomainMatrix({0: {1: ZZ(1)}, 1: {0: ZZ(2)}}, (2, 2), ZZ)
  254. Ad = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  255. Asd = As + Ad
  256. Ads = Ad + As
  257. assert Asd == DomainMatrix([[1, 3], [5, 4]], (2, 2), ZZ)
  258. assert Asd.rep == DDM([[1, 3], [5, 4]], (2, 2), ZZ)
  259. assert Ads == DomainMatrix([[1, 3], [5, 4]], (2, 2), ZZ)
  260. assert Ads.rep == DDM([[1, 3], [5, 4]], (2, 2), ZZ)
  261. raises(DMFormatError, lambda: As.add(Ad))
  262. def test_DomainMatrix_sub():
  263. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  264. B = DomainMatrix([[ZZ(0), ZZ(0)], [ZZ(0), ZZ(0)]], (2, 2), ZZ)
  265. assert A - A == A.sub(A) == B
  266. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  267. L = [[2, 3], [3, 4]]
  268. raises(TypeError, lambda: A - L)
  269. raises(TypeError, lambda: L - A)
  270. A1 = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  271. A2 = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ)
  272. raises(DMShapeError, lambda: A1 - A2)
  273. raises(DMShapeError, lambda: A2 - A1)
  274. raises(DMShapeError, lambda: A1.sub(A2))
  275. raises(DMShapeError, lambda: A2.sub(A1))
  276. Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  277. Aq = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  278. Adiff = DomainMatrix([[QQ(0), QQ(0)], [QQ(0), QQ(0)]], (2, 2), QQ)
  279. assert Az - Aq == Adiff
  280. assert Aq - Az == Adiff
  281. raises(DMDomainError, lambda: Az.sub(Aq))
  282. raises(DMDomainError, lambda: Aq.sub(Az))
  283. As = DomainMatrix({0: {1: ZZ(1)}, 1: {0: ZZ(2)}}, (2, 2), ZZ)
  284. Ad = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  285. Asd = As - Ad
  286. Ads = Ad - As
  287. assert Asd == DomainMatrix([[-1, -1], [-1, -4]], (2, 2), ZZ)
  288. assert Asd.rep == DDM([[-1, -1], [-1, -4]], (2, 2), ZZ)
  289. assert Asd == -Ads
  290. assert Asd.rep == -Ads.rep
  291. def test_DomainMatrix_neg():
  292. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  293. Aneg = DomainMatrix([[ZZ(-1), ZZ(-2)], [ZZ(-3), ZZ(-4)]], (2, 2), ZZ)
  294. assert -A == A.neg() == Aneg
  295. def test_DomainMatrix_mul():
  296. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  297. A2 = DomainMatrix([[ZZ(7), ZZ(10)], [ZZ(15), ZZ(22)]], (2, 2), ZZ)
  298. assert A*A == A.matmul(A) == A2
  299. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  300. L = [[1, 2], [3, 4]]
  301. raises(TypeError, lambda: A * L)
  302. raises(TypeError, lambda: L * A)
  303. Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  304. Aq = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  305. Aprod = DomainMatrix([[QQ(7), QQ(10)], [QQ(15), QQ(22)]], (2, 2), QQ)
  306. assert Az * Aq == Aprod
  307. assert Aq * Az == Aprod
  308. raises(DMDomainError, lambda: Az.matmul(Aq))
  309. raises(DMDomainError, lambda: Aq.matmul(Az))
  310. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  311. AA = DomainMatrix([[ZZ(2), ZZ(4)], [ZZ(6), ZZ(8)]], (2, 2), ZZ)
  312. x = ZZ(2)
  313. assert A * x == x * A == A.mul(x) == AA
  314. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  315. AA = DomainMatrix.zeros((2, 2), ZZ)
  316. x = ZZ(0)
  317. assert A * x == x * A == A.mul(x).to_sparse() == AA
  318. As = DomainMatrix({0: {1: ZZ(1)}, 1: {0: ZZ(2)}}, (2, 2), ZZ)
  319. Ad = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  320. Asd = As * Ad
  321. Ads = Ad * As
  322. assert Asd == DomainMatrix([[3, 4], [2, 4]], (2, 2), ZZ)
  323. assert Asd.rep == DDM([[3, 4], [2, 4]], (2, 2), ZZ)
  324. assert Ads == DomainMatrix([[4, 1], [8, 3]], (2, 2), ZZ)
  325. assert Ads.rep == DDM([[4, 1], [8, 3]], (2, 2), ZZ)
  326. def test_DomainMatrix_mul_elementwise():
  327. A = DomainMatrix([[ZZ(2), ZZ(2)], [ZZ(0), ZZ(0)]], (2, 2), ZZ)
  328. B = DomainMatrix([[ZZ(4), ZZ(0)], [ZZ(3), ZZ(0)]], (2, 2), ZZ)
  329. C = DomainMatrix([[ZZ(8), ZZ(0)], [ZZ(0), ZZ(0)]], (2, 2), ZZ)
  330. assert A.mul_elementwise(B) == C
  331. assert B.mul_elementwise(A) == C
  332. def test_DomainMatrix_pow():
  333. eye = DomainMatrix.eye(2, ZZ)
  334. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  335. A2 = DomainMatrix([[ZZ(7), ZZ(10)], [ZZ(15), ZZ(22)]], (2, 2), ZZ)
  336. A3 = DomainMatrix([[ZZ(37), ZZ(54)], [ZZ(81), ZZ(118)]], (2, 2), ZZ)
  337. assert A**0 == A.pow(0) == eye
  338. assert A**1 == A.pow(1) == A
  339. assert A**2 == A.pow(2) == A2
  340. assert A**3 == A.pow(3) == A3
  341. raises(TypeError, lambda: A ** Rational(1, 2))
  342. raises(NotImplementedError, lambda: A ** -1)
  343. raises(NotImplementedError, lambda: A.pow(-1))
  344. A = DomainMatrix.zeros((2, 1), ZZ)
  345. raises(DMNonSquareMatrixError, lambda: A ** 1)
  346. def test_DomainMatrix_scc():
  347. Ad = DomainMatrix([[ZZ(1), ZZ(2), ZZ(3)],
  348. [ZZ(0), ZZ(1), ZZ(0)],
  349. [ZZ(2), ZZ(0), ZZ(4)]], (3, 3), ZZ)
  350. As = Ad.to_sparse()
  351. Addm = Ad.rep
  352. Asdm = As.rep
  353. for A in [Ad, As, Addm, Asdm]:
  354. assert Ad.scc() == [[1], [0, 2]]
  355. def test_DomainMatrix_rref():
  356. A = DomainMatrix([], (0, 1), QQ)
  357. assert A.rref() == (A, ())
  358. A = DomainMatrix([[QQ(1)]], (1, 1), QQ)
  359. assert A.rref() == (A, (0,))
  360. A = DomainMatrix([[QQ(0)]], (1, 1), QQ)
  361. assert A.rref() == (A, ())
  362. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  363. Ar, pivots = A.rref()
  364. assert Ar == DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ)
  365. assert pivots == (0, 1)
  366. A = DomainMatrix([[QQ(0), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  367. Ar, pivots = A.rref()
  368. assert Ar == DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ)
  369. assert pivots == (0, 1)
  370. A = DomainMatrix([[QQ(0), QQ(2)], [QQ(0), QQ(4)]], (2, 2), QQ)
  371. Ar, pivots = A.rref()
  372. assert Ar == DomainMatrix([[QQ(0), QQ(1)], [QQ(0), QQ(0)]], (2, 2), QQ)
  373. assert pivots == (1,)
  374. Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  375. raises(DMNotAField, lambda: Az.rref())
  376. def test_DomainMatrix_columnspace():
  377. A = DomainMatrix([[QQ(1), QQ(-1), QQ(1)], [QQ(2), QQ(-2), QQ(3)]], (2, 3), QQ)
  378. Acol = DomainMatrix([[QQ(1), QQ(1)], [QQ(2), QQ(3)]], (2, 2), QQ)
  379. assert A.columnspace() == Acol
  380. Az = DomainMatrix([[ZZ(1), ZZ(-1), ZZ(1)], [ZZ(2), ZZ(-2), ZZ(3)]], (2, 3), ZZ)
  381. raises(DMNotAField, lambda: Az.columnspace())
  382. A = DomainMatrix([[QQ(1), QQ(-1), QQ(1)], [QQ(2), QQ(-2), QQ(3)]], (2, 3), QQ, fmt='sparse')
  383. Acol = DomainMatrix({0: {0: QQ(1), 1: QQ(1)}, 1: {0: QQ(2), 1: QQ(3)}}, (2, 2), QQ)
  384. assert A.columnspace() == Acol
  385. def test_DomainMatrix_rowspace():
  386. A = DomainMatrix([[QQ(1), QQ(-1), QQ(1)], [QQ(2), QQ(-2), QQ(3)]], (2, 3), QQ)
  387. assert A.rowspace() == A
  388. Az = DomainMatrix([[ZZ(1), ZZ(-1), ZZ(1)], [ZZ(2), ZZ(-2), ZZ(3)]], (2, 3), ZZ)
  389. raises(DMNotAField, lambda: Az.rowspace())
  390. A = DomainMatrix([[QQ(1), QQ(-1), QQ(1)], [QQ(2), QQ(-2), QQ(3)]], (2, 3), QQ, fmt='sparse')
  391. assert A.rowspace() == A
  392. def test_DomainMatrix_nullspace():
  393. A = DomainMatrix([[QQ(1), QQ(1)], [QQ(1), QQ(1)]], (2, 2), QQ)
  394. Anull = DomainMatrix([[QQ(-1), QQ(1)]], (1, 2), QQ)
  395. assert A.nullspace() == Anull
  396. Az = DomainMatrix([[ZZ(1), ZZ(1)], [ZZ(1), ZZ(1)]], (2, 2), ZZ)
  397. raises(DMNotAField, lambda: Az.nullspace())
  398. def test_DomainMatrix_solve():
  399. # XXX: Maybe the _solve method should be changed...
  400. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(2), QQ(4)]], (2, 2), QQ)
  401. b = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ)
  402. particular = DomainMatrix([[1, 0]], (1, 2), QQ)
  403. nullspace = DomainMatrix([[-2, 1]], (1, 2), QQ)
  404. assert A._solve(b) == (particular, nullspace)
  405. b3 = DomainMatrix([[QQ(1)], [QQ(1)], [QQ(1)]], (3, 1), QQ)
  406. raises(DMShapeError, lambda: A._solve(b3))
  407. bz = DomainMatrix([[ZZ(1)], [ZZ(1)]], (2, 1), ZZ)
  408. raises(DMNotAField, lambda: A._solve(bz))
  409. def test_DomainMatrix_inv():
  410. A = DomainMatrix([], (0, 0), QQ)
  411. assert A.inv() == A
  412. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  413. Ainv = DomainMatrix([[QQ(-2), QQ(1)], [QQ(3, 2), QQ(-1, 2)]], (2, 2), QQ)
  414. assert A.inv() == Ainv
  415. Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  416. raises(DMNotAField, lambda: Az.inv())
  417. Ans = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ)
  418. raises(DMNonSquareMatrixError, lambda: Ans.inv())
  419. Aninv = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(6)]], (2, 2), QQ)
  420. raises(DMNonInvertibleMatrixError, lambda: Aninv.inv())
  421. def test_DomainMatrix_det():
  422. A = DomainMatrix([], (0, 0), ZZ)
  423. assert A.det() == 1
  424. A = DomainMatrix([[1]], (1, 1), ZZ)
  425. assert A.det() == 1
  426. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  427. assert A.det() == ZZ(-2)
  428. A = DomainMatrix([[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(3), ZZ(5)]], (3, 3), ZZ)
  429. assert A.det() == ZZ(-1)
  430. A = DomainMatrix([[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(2), ZZ(5)]], (3, 3), ZZ)
  431. assert A.det() == ZZ(0)
  432. Ans = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ)
  433. raises(DMNonSquareMatrixError, lambda: Ans.det())
  434. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  435. assert A.det() == QQ(-2)
  436. def test_DomainMatrix_lu():
  437. A = DomainMatrix([], (0, 0), QQ)
  438. assert A.lu() == (A, A, [])
  439. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  440. L = DomainMatrix([[QQ(1), QQ(0)], [QQ(3), QQ(1)]], (2, 2), QQ)
  441. U = DomainMatrix([[QQ(1), QQ(2)], [QQ(0), QQ(-2)]], (2, 2), QQ)
  442. swaps = []
  443. assert A.lu() == (L, U, swaps)
  444. A = DomainMatrix([[QQ(0), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  445. L = DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ)
  446. U = DomainMatrix([[QQ(3), QQ(4)], [QQ(0), QQ(2)]], (2, 2), QQ)
  447. swaps = [(0, 1)]
  448. assert A.lu() == (L, U, swaps)
  449. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(2), QQ(4)]], (2, 2), QQ)
  450. L = DomainMatrix([[QQ(1), QQ(0)], [QQ(2), QQ(1)]], (2, 2), QQ)
  451. U = DomainMatrix([[QQ(1), QQ(2)], [QQ(0), QQ(0)]], (2, 2), QQ)
  452. swaps = []
  453. assert A.lu() == (L, U, swaps)
  454. A = DomainMatrix([[QQ(0), QQ(2)], [QQ(0), QQ(4)]], (2, 2), QQ)
  455. L = DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ)
  456. U = DomainMatrix([[QQ(0), QQ(2)], [QQ(0), QQ(4)]], (2, 2), QQ)
  457. swaps = []
  458. assert A.lu() == (L, U, swaps)
  459. A = DomainMatrix([[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)]], (2, 3), QQ)
  460. L = DomainMatrix([[QQ(1), QQ(0)], [QQ(4), QQ(1)]], (2, 2), QQ)
  461. U = DomainMatrix([[QQ(1), QQ(2), QQ(3)], [QQ(0), QQ(-3), QQ(-6)]], (2, 3), QQ)
  462. swaps = []
  463. assert A.lu() == (L, U, swaps)
  464. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ)
  465. L = DomainMatrix([
  466. [QQ(1), QQ(0), QQ(0)],
  467. [QQ(3), QQ(1), QQ(0)],
  468. [QQ(5), QQ(2), QQ(1)]], (3, 3), QQ)
  469. U = DomainMatrix([[QQ(1), QQ(2)], [QQ(0), QQ(-2)], [QQ(0), QQ(0)]], (3, 2), QQ)
  470. swaps = []
  471. assert A.lu() == (L, U, swaps)
  472. A = [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 2]]
  473. L = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 1]]
  474. U = [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]]
  475. to_dom = lambda rows, dom: [[dom(e) for e in row] for row in rows]
  476. A = DomainMatrix(to_dom(A, QQ), (4, 4), QQ)
  477. L = DomainMatrix(to_dom(L, QQ), (4, 4), QQ)
  478. U = DomainMatrix(to_dom(U, QQ), (4, 4), QQ)
  479. assert A.lu() == (L, U, [])
  480. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  481. raises(DMNotAField, lambda: A.lu())
  482. def test_DomainMatrix_lu_solve():
  483. # Base case
  484. A = b = x = DomainMatrix([], (0, 0), QQ)
  485. assert A.lu_solve(b) == x
  486. # Basic example
  487. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  488. b = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ)
  489. x = DomainMatrix([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ)
  490. assert A.lu_solve(b) == x
  491. # Example with swaps
  492. A = DomainMatrix([[QQ(0), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  493. b = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ)
  494. x = DomainMatrix([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ)
  495. assert A.lu_solve(b) == x
  496. # Non-invertible
  497. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(2), QQ(4)]], (2, 2), QQ)
  498. b = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ)
  499. raises(DMNonInvertibleMatrixError, lambda: A.lu_solve(b))
  500. # Overdetermined, consistent
  501. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ)
  502. b = DomainMatrix([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ)
  503. x = DomainMatrix([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ)
  504. assert A.lu_solve(b) == x
  505. # Overdetermined, inconsistent
  506. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ)
  507. b = DomainMatrix([[QQ(1)], [QQ(2)], [QQ(4)]], (3, 1), QQ)
  508. raises(DMNonInvertibleMatrixError, lambda: A.lu_solve(b))
  509. # Underdetermined
  510. A = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ)
  511. b = DomainMatrix([[QQ(1)]], (1, 1), QQ)
  512. raises(NotImplementedError, lambda: A.lu_solve(b))
  513. # Non-field
  514. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  515. b = DomainMatrix([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ)
  516. raises(DMNotAField, lambda: A.lu_solve(b))
  517. # Shape mismatch
  518. A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ)
  519. b = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ)
  520. raises(DMShapeError, lambda: A.lu_solve(b))
  521. def test_DomainMatrix_charpoly():
  522. A = DomainMatrix([], (0, 0), ZZ)
  523. assert A.charpoly() == [ZZ(1)]
  524. A = DomainMatrix([[1]], (1, 1), ZZ)
  525. assert A.charpoly() == [ZZ(1), ZZ(-1)]
  526. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  527. assert A.charpoly() == [ZZ(1), ZZ(-5), ZZ(-2)]
  528. A = DomainMatrix([[ZZ(1), ZZ(2), ZZ(3)], [ZZ(4), ZZ(5), ZZ(6)], [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ)
  529. assert A.charpoly() == [ZZ(1), ZZ(-15), ZZ(-18), ZZ(0)]
  530. Ans = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ)
  531. raises(DMNonSquareMatrixError, lambda: Ans.charpoly())
  532. def test_DomainMatrix_eye():
  533. A = DomainMatrix.eye(3, QQ)
  534. assert A.rep == SDM.eye((3, 3), QQ)
  535. assert A.shape == (3, 3)
  536. assert A.domain == QQ
  537. def test_DomainMatrix_zeros():
  538. A = DomainMatrix.zeros((1, 2), QQ)
  539. assert A.rep == SDM.zeros((1, 2), QQ)
  540. assert A.shape == (1, 2)
  541. assert A.domain == QQ
  542. def test_DomainMatrix_ones():
  543. A = DomainMatrix.ones((2, 3), QQ)
  544. assert A.rep == DDM.ones((2, 3), QQ)
  545. assert A.shape == (2, 3)
  546. assert A.domain == QQ
  547. def test_DomainMatrix_diag():
  548. A = DomainMatrix({0:{0:ZZ(2)}, 1:{1:ZZ(3)}}, (2, 2), ZZ)
  549. assert DomainMatrix.diag([ZZ(2), ZZ(3)], ZZ) == A
  550. A = DomainMatrix({0:{0:ZZ(2)}, 1:{1:ZZ(3)}}, (3, 4), ZZ)
  551. assert DomainMatrix.diag([ZZ(2), ZZ(3)], ZZ, (3, 4)) == A
  552. def test_DomainMatrix_hstack():
  553. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  554. B = DomainMatrix([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ)
  555. C = DomainMatrix([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
  556. AB = DomainMatrix([
  557. [ZZ(1), ZZ(2), ZZ(5), ZZ(6)],
  558. [ZZ(3), ZZ(4), ZZ(7), ZZ(8)]], (2, 4), ZZ)
  559. ABC = DomainMatrix([
  560. [ZZ(1), ZZ(2), ZZ(5), ZZ(6), ZZ(9), ZZ(10)],
  561. [ZZ(3), ZZ(4), ZZ(7), ZZ(8), ZZ(11), ZZ(12)]], (2, 6), ZZ)
  562. assert A.hstack(B) == AB
  563. assert A.hstack(B, C) == ABC
  564. def test_DomainMatrix_vstack():
  565. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  566. B = DomainMatrix([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ)
  567. C = DomainMatrix([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
  568. AB = DomainMatrix([
  569. [ZZ(1), ZZ(2)],
  570. [ZZ(3), ZZ(4)],
  571. [ZZ(5), ZZ(6)],
  572. [ZZ(7), ZZ(8)]], (4, 2), ZZ)
  573. ABC = DomainMatrix([
  574. [ZZ(1), ZZ(2)],
  575. [ZZ(3), ZZ(4)],
  576. [ZZ(5), ZZ(6)],
  577. [ZZ(7), ZZ(8)],
  578. [ZZ(9), ZZ(10)],
  579. [ZZ(11), ZZ(12)]], (6, 2), ZZ)
  580. assert A.vstack(B) == AB
  581. assert A.vstack(B, C) == ABC
  582. def test_DomainMatrix_applyfunc():
  583. A = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ)
  584. B = DomainMatrix([[ZZ(2), ZZ(4)]], (1, 2), ZZ)
  585. assert A.applyfunc(lambda x: 2*x) == B
  586. def test_DomainMatrix_scalarmul():
  587. A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  588. lamda = DomainScalar(QQ(3)/QQ(2), QQ)
  589. assert A * lamda == DomainMatrix([[QQ(3, 2), QQ(3)], [QQ(9, 2), QQ(6)]], (2, 2), QQ)
  590. assert A * 2 == DomainMatrix([[ZZ(2), ZZ(4)], [ZZ(6), ZZ(8)]], (2, 2), ZZ)
  591. assert 2 * A == DomainMatrix([[ZZ(2), ZZ(4)], [ZZ(6), ZZ(8)]], (2, 2), ZZ)
  592. assert A * DomainScalar(ZZ(0), ZZ) == DomainMatrix({}, (2, 2), ZZ)
  593. assert A * DomainScalar(ZZ(1), ZZ) == A
  594. raises(TypeError, lambda: A * 1.5)
  595. def test_DomainMatrix_truediv():
  596. A = DomainMatrix.from_Matrix(Matrix([[1, 2], [3, 4]]))
  597. lamda = DomainScalar(QQ(3)/QQ(2), QQ)
  598. assert A / lamda == DomainMatrix({0: {0: QQ(2, 3), 1: QQ(4, 3)}, 1: {0: QQ(2), 1: QQ(8, 3)}}, (2, 2), QQ)
  599. b = DomainScalar(ZZ(1), ZZ)
  600. assert A / b == DomainMatrix({0: {0: QQ(1), 1: QQ(2)}, 1: {0: QQ(3), 1: QQ(4)}}, (2, 2), QQ)
  601. assert A / 1 == DomainMatrix({0: {0: QQ(1), 1: QQ(2)}, 1: {0: QQ(3), 1: QQ(4)}}, (2, 2), QQ)
  602. assert A / 2 == DomainMatrix({0: {0: QQ(1, 2), 1: QQ(1)}, 1: {0: QQ(3, 2), 1: QQ(2)}}, (2, 2), QQ)
  603. raises(ZeroDivisionError, lambda: A / 0)
  604. raises(TypeError, lambda: A / 1.5)
  605. raises(ZeroDivisionError, lambda: A / DomainScalar(ZZ(0), ZZ))
  606. def test_DomainMatrix_getitem():
  607. dM = DomainMatrix([
  608. [ZZ(1), ZZ(2), ZZ(3)],
  609. [ZZ(4), ZZ(5), ZZ(6)],
  610. [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ)
  611. assert dM[1:,:-2] == DomainMatrix([[ZZ(4)], [ZZ(7)]], (2, 1), ZZ)
  612. assert dM[2,:-2] == DomainMatrix([[ZZ(7)]], (1, 1), ZZ)
  613. assert dM[:-2,:-2] == DomainMatrix([[ZZ(1)]], (1, 1), ZZ)
  614. assert dM[:-1,0:2] == DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(4), ZZ(5)]], (2, 2), ZZ)
  615. assert dM[:, -1] == DomainMatrix([[ZZ(3)], [ZZ(6)], [ZZ(9)]], (3, 1), ZZ)
  616. assert dM[-1, :] == DomainMatrix([[ZZ(7), ZZ(8), ZZ(9)]], (1, 3), ZZ)
  617. assert dM[::-1, :] == DomainMatrix([
  618. [ZZ(7), ZZ(8), ZZ(9)],
  619. [ZZ(4), ZZ(5), ZZ(6)],
  620. [ZZ(1), ZZ(2), ZZ(3)]], (3, 3), ZZ)
  621. raises(IndexError, lambda: dM[4, :-2])
  622. raises(IndexError, lambda: dM[:-2, 4])
  623. assert dM[1, 2] == DomainScalar(ZZ(6), ZZ)
  624. assert dM[-2, 2] == DomainScalar(ZZ(6), ZZ)
  625. assert dM[1, -2] == DomainScalar(ZZ(5), ZZ)
  626. assert dM[-1, -3] == DomainScalar(ZZ(7), ZZ)
  627. raises(IndexError, lambda: dM[3, 3])
  628. raises(IndexError, lambda: dM[1, 4])
  629. raises(IndexError, lambda: dM[-1, -4])
  630. dM = DomainMatrix({0: {0: ZZ(1)}}, (10, 10), ZZ)
  631. assert dM[5, 5] == DomainScalar(ZZ(0), ZZ)
  632. assert dM[0, 0] == DomainScalar(ZZ(1), ZZ)
  633. dM = DomainMatrix({1: {0: 1}}, (2,1), ZZ)
  634. assert dM[0:, 0] == DomainMatrix({1: {0: 1}}, (2, 1), ZZ)
  635. raises(IndexError, lambda: dM[3, 0])
  636. dM = DomainMatrix({2: {2: ZZ(1)}, 4: {4: ZZ(1)}}, (5, 5), ZZ)
  637. assert dM[:2,:2] == DomainMatrix({}, (2, 2), ZZ)
  638. assert dM[2:,2:] == DomainMatrix({0: {0: 1}, 2: {2: 1}}, (3, 3), ZZ)
  639. assert dM[3:,3:] == DomainMatrix({1: {1: 1}}, (2, 2), ZZ)
  640. assert dM[2:, 6:] == DomainMatrix({}, (3, 0), ZZ)
  641. def test_DomainMatrix_getitem_sympy():
  642. dM = DomainMatrix({2: {2: ZZ(2)}, 4: {4: ZZ(1)}}, (5, 5), ZZ)
  643. val1 = dM.getitem_sympy(0, 0)
  644. assert val1 is S.Zero
  645. val2 = dM.getitem_sympy(2, 2)
  646. assert val2 == 2 and isinstance(val2, Integer)
  647. def test_DomainMatrix_extract():
  648. dM1 = DomainMatrix([
  649. [ZZ(1), ZZ(2), ZZ(3)],
  650. [ZZ(4), ZZ(5), ZZ(6)],
  651. [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ)
  652. dM2 = DomainMatrix([
  653. [ZZ(1), ZZ(3)],
  654. [ZZ(7), ZZ(9)]], (2, 2), ZZ)
  655. assert dM1.extract([0, 2], [0, 2]) == dM2
  656. assert dM1.to_sparse().extract([0, 2], [0, 2]) == dM2.to_sparse()
  657. assert dM1.extract([0, -1], [0, -1]) == dM2
  658. assert dM1.to_sparse().extract([0, -1], [0, -1]) == dM2.to_sparse()
  659. dM3 = DomainMatrix([
  660. [ZZ(1), ZZ(2), ZZ(2)],
  661. [ZZ(4), ZZ(5), ZZ(5)],
  662. [ZZ(4), ZZ(5), ZZ(5)]], (3, 3), ZZ)
  663. assert dM1.extract([0, 1, 1], [0, 1, 1]) == dM3
  664. assert dM1.to_sparse().extract([0, 1, 1], [0, 1, 1]) == dM3.to_sparse()
  665. empty = [
  666. ([], [], (0, 0)),
  667. ([1], [], (1, 0)),
  668. ([], [1], (0, 1)),
  669. ]
  670. for rows, cols, size in empty:
  671. assert dM1.extract(rows, cols) == DomainMatrix.zeros(size, ZZ).to_dense()
  672. assert dM1.to_sparse().extract(rows, cols) == DomainMatrix.zeros(size, ZZ)
  673. dM = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  674. bad_indices = [([2], [0]), ([0], [2]), ([-3], [0]), ([0], [-3])]
  675. for rows, cols in bad_indices:
  676. raises(IndexError, lambda: dM.extract(rows, cols))
  677. raises(IndexError, lambda: dM.to_sparse().extract(rows, cols))
  678. def test_DomainMatrix_setitem():
  679. dM = DomainMatrix({2: {2: ZZ(1)}, 4: {4: ZZ(1)}}, (5, 5), ZZ)
  680. dM[2, 2] = ZZ(2)
  681. assert dM == DomainMatrix({2: {2: ZZ(2)}, 4: {4: ZZ(1)}}, (5, 5), ZZ)
  682. def setitem(i, j, val):
  683. dM[i, j] = val
  684. raises(TypeError, lambda: setitem(2, 2, QQ(1, 2)))
  685. raises(NotImplementedError, lambda: setitem(slice(1, 2), 2, ZZ(1)))
  686. def test_DomainMatrix_pickling():
  687. import pickle
  688. dM = DomainMatrix({2: {2: ZZ(1)}, 4: {4: ZZ(1)}}, (5, 5), ZZ)
  689. assert pickle.loads(pickle.dumps(dM)) == dM
  690. dM = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
  691. assert pickle.loads(pickle.dumps(dM)) == dM