test_rref.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. from sympy import ZZ, QQ, ZZ_I, EX, Matrix, eye, zeros, symbols
  2. from sympy.polys.matrices import DM, DomainMatrix
  3. from sympy.polys.matrices.dense import ddm_irref_den, ddm_irref
  4. from sympy.polys.matrices.ddm import DDM
  5. from sympy.polys.matrices.sdm import SDM, sdm_irref, sdm_rref_den
  6. import pytest
  7. #
  8. # The dense and sparse implementations of rref_den are ddm_irref_den and
  9. # sdm_irref_den. These can give results that differ by some factor and also
  10. # give different results if the order of the rows is changed. The tests below
  11. # show all results on lowest terms as should be returned by cancel_denom.
  12. #
  13. # The EX domain is also a case where the dense and sparse implementations
  14. # can give results in different forms: the results should be equivalent but
  15. # are not canonical because EX does not have a canonical form.
  16. #
  17. a, b, c, d = symbols('a, b, c, d')
  18. qq_large_1 = DM([
  19. [ (1,2), (1,3), (1,5), (1,7), (1,11), (1,13), (1,17), (1,19), (1,23), (1,29), (1,31)],
  20. [ (1,37), (1,41), (1,43), (1,47), (1,53), (1,59), (1,61), (1,67), (1,71), (1,73), (1,79)],
  21. [ (1,83), (1,89), (1,97),(1,101),(1,103),(1,107),(1,109),(1,113),(1,127),(1,131),(1,137)],
  22. [(1,139),(1,149),(1,151),(1,157),(1,163),(1,167),(1,173),(1,179),(1,181),(1,191),(1,193)],
  23. [(1,197),(1,199),(1,211),(1,223),(1,227),(1,229),(1,233),(1,239),(1,241),(1,251),(1,257)],
  24. [(1,263),(1,269),(1,271),(1,277),(1,281),(1,283),(1,293),(1,307),(1,311),(1,313),(1,317)],
  25. [(1,331),(1,337),(1,347),(1,349),(1,353),(1,359),(1,367),(1,373),(1,379),(1,383),(1,389)],
  26. [(1,397),(1,401),(1,409),(1,419),(1,421),(1,431),(1,433),(1,439),(1,443),(1,449),(1,457)],
  27. [(1,461),(1,463),(1,467),(1,479),(1,487),(1,491),(1,499),(1,503),(1,509),(1,521),(1,523)],
  28. [(1,541),(1,547),(1,557),(1,563),(1,569),(1,571),(1,577),(1,587),(1,593),(1,599),(1,601)],
  29. [(1,607),(1,613),(1,617),(1,619),(1,631),(1,641),(1,643),(1,647),(1,653),(1,659),(1,661)]],
  30. QQ)
  31. qq_large_2 = qq_large_1 + 10**100 * DomainMatrix.eye(11, QQ)
  32. RREF_EXAMPLES = [
  33. (
  34. 'zz_1',
  35. DM([[1, 2, 3]], ZZ),
  36. DM([[1, 2, 3]], ZZ),
  37. ZZ(1),
  38. ),
  39. (
  40. 'zz_2',
  41. DomainMatrix([], (0, 0), ZZ),
  42. DomainMatrix([], (0, 0), ZZ),
  43. ZZ(1),
  44. ),
  45. (
  46. 'zz_3',
  47. DM([[1, 2],
  48. [3, 4]], ZZ),
  49. DM([[1, 0],
  50. [0, 1]], ZZ),
  51. ZZ(1),
  52. ),
  53. (
  54. 'zz_4',
  55. DM([[1, 0],
  56. [3, 4]], ZZ),
  57. DM([[1, 0],
  58. [0, 1]], ZZ),
  59. ZZ(1),
  60. ),
  61. (
  62. 'zz_5',
  63. DM([[0, 2],
  64. [3, 4]], ZZ),
  65. DM([[1, 0],
  66. [0, 1]], ZZ),
  67. ZZ(1),
  68. ),
  69. (
  70. 'zz_6',
  71. DM([[1, 2, 3],
  72. [4, 5, 6],
  73. [7, 8, 9]], ZZ),
  74. DM([[1, 0, -1],
  75. [0, 1, 2],
  76. [0, 0, 0]], ZZ),
  77. ZZ(1),
  78. ),
  79. (
  80. 'zz_7',
  81. DM([[0, 0, 0],
  82. [0, 0, 0],
  83. [1, 0, 0]], ZZ),
  84. DM([[1, 0, 0],
  85. [0, 0, 0],
  86. [0, 0, 0]], ZZ),
  87. ZZ(1),
  88. ),
  89. (
  90. 'zz_8',
  91. DM([[0, 0, 0],
  92. [0, 0, 0],
  93. [0, 0, 0]], ZZ),
  94. DM([[0, 0, 0],
  95. [0, 0, 0],
  96. [0, 0, 0]], ZZ),
  97. ZZ(1),
  98. ),
  99. (
  100. 'zz_9',
  101. DM([[1, 1, 0],
  102. [0, 0, 2],
  103. [0, 0, 0]], ZZ),
  104. DM([[1, 1, 0],
  105. [0, 0, 1],
  106. [0, 0, 0]], ZZ),
  107. ZZ(1),
  108. ),
  109. (
  110. 'zz_10',
  111. DM([[2, 2, 0],
  112. [0, 0, 2],
  113. [0, 0, 0]], ZZ),
  114. DM([[1, 1, 0],
  115. [0, 0, 1],
  116. [0, 0, 0]], ZZ),
  117. ZZ(1),
  118. ),
  119. (
  120. 'zz_11',
  121. DM([[2, 2, 0],
  122. [0, 2, 2],
  123. [0, 0, 2]], ZZ),
  124. DM([[1, 0, 0],
  125. [0, 1, 0],
  126. [0, 0, 1]], ZZ),
  127. ZZ(1),
  128. ),
  129. (
  130. 'zz_12',
  131. DM([[ 1, 2, 3],
  132. [ 4, 5, 6],
  133. [ 7, 8, 9],
  134. [10, 11, 12]], ZZ),
  135. DM([[1, 0, -1],
  136. [0, 1, 2],
  137. [0, 0, 0],
  138. [0, 0, 0]], ZZ),
  139. ZZ(1),
  140. ),
  141. (
  142. 'zz_13',
  143. DM([[ 1, 2, 3],
  144. [ 4, 5, 6],
  145. [ 7, 8, 9],
  146. [10, 11, 13]], ZZ),
  147. DM([[ 1, 0, 0],
  148. [ 0, 1, 0],
  149. [ 0, 0, 1],
  150. [ 0, 0, 0]], ZZ),
  151. ZZ(1),
  152. ),
  153. (
  154. 'zz_14',
  155. DM([[1, 2, 4, 3],
  156. [4, 5, 10, 6],
  157. [7, 8, 16, 9]], ZZ),
  158. DM([[1, 0, 0, -1],
  159. [0, 1, 2, 2],
  160. [0, 0, 0, 0]], ZZ),
  161. ZZ(1),
  162. ),
  163. (
  164. 'zz_15',
  165. DM([[1, 2, 4, 3],
  166. [4, 5, 10, 6],
  167. [7, 8, 17, 9]], ZZ),
  168. DM([[1, 0, 0, -1],
  169. [0, 1, 0, 2],
  170. [0, 0, 1, 0]], ZZ),
  171. ZZ(1),
  172. ),
  173. (
  174. 'zz_16',
  175. DM([[1, 2, 0, 1],
  176. [1, 1, 9, 0]], ZZ),
  177. DM([[1, 0, 18, -1],
  178. [0, 1, -9, 1]], ZZ),
  179. ZZ(1),
  180. ),
  181. (
  182. 'zz_17',
  183. DM([[1, 1, 1],
  184. [1, 2, 2]], ZZ),
  185. DM([[1, 0, 0],
  186. [0, 1, 1]], ZZ),
  187. ZZ(1),
  188. ),
  189. (
  190. # Here the sparse implementation and dense implementation give very
  191. # different denominators: 4061232 and -1765176.
  192. 'zz_18',
  193. DM([[94, 24, 0, 27, 0],
  194. [79, 0, 0, 0, 0],
  195. [85, 16, 71, 81, 0],
  196. [ 0, 0, 72, 77, 0],
  197. [21, 0, 34, 0, 0]], ZZ),
  198. DM([[ 1, 0, 0, 0, 0],
  199. [ 0, 1, 0, 0, 0],
  200. [ 0, 0, 1, 0, 0],
  201. [ 0, 0, 0, 1, 0],
  202. [ 0, 0, 0, 0, 0]], ZZ),
  203. ZZ(1),
  204. ),
  205. (
  206. # Let's have a denominator that cannot be cancelled.
  207. 'zz_19',
  208. DM([[1, 2, 4],
  209. [4, 5, 6]], ZZ),
  210. DM([[3, 0, -8],
  211. [0, 3, 10]], ZZ),
  212. ZZ(3),
  213. ),
  214. (
  215. 'zz_20',
  216. DM([[0, 0, 0, 0, 0],
  217. [0, 0, 0, 0, 0],
  218. [0, 0, 0, 0, 4]], ZZ),
  219. DM([[0, 0, 0, 0, 1],
  220. [0, 0, 0, 0, 0],
  221. [0, 0, 0, 0, 0]], ZZ),
  222. ZZ(1),
  223. ),
  224. (
  225. 'zz_21',
  226. DM([[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
  227. [1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
  228. [0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
  229. [0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
  230. [0, 0, 0, 0, 1, 0, 0, 0, 0, 1]], ZZ),
  231. DM([[1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
  232. [0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
  233. [0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
  234. [0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
  235. [0, 0, 0, 0, 0, 1, 0, 0, 0, 0]], ZZ),
  236. ZZ(1),
  237. ),
  238. (
  239. 'zz_22',
  240. DM([[1, 1, 1, 0, 1],
  241. [1, 1, 0, 1, 0],
  242. [1, 0, 1, 0, 1],
  243. [1, 1, 0, 1, 0],
  244. [1, 0, 0, 0, 0]], ZZ),
  245. DM([[1, 0, 0, 0, 0],
  246. [0, 1, 0, 0, 0],
  247. [0, 0, 1, 0, 1],
  248. [0, 0, 0, 1, 0],
  249. [0, 0, 0, 0, 0]], ZZ),
  250. ZZ(1),
  251. ),
  252. (
  253. 'zz_large_1',
  254. DM([
  255. [ 0, 0, 0, 81, 0, 0, 75, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0],
  256. [ 0, 0, 0, 0, 0, 86, 0, 92, 79, 54, 0, 7, 0, 0, 0, 0, 79, 0, 0, 0],
  257. [89, 54, 81, 0, 0, 20, 0, 0, 0, 0, 0, 0, 51, 0, 94, 0, 0, 77, 0, 0],
  258. [ 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 48, 29, 0, 0, 5, 0, 32, 0],
  259. [ 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 11],
  260. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 43, 0, 0],
  261. [ 0, 0, 0, 0, 0, 38, 91, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 26, 0, 0],
  262. [69, 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55],
  263. [ 0, 13, 18, 49, 49, 88, 0, 0, 35, 54, 0, 0, 51, 0, 0, 0, 0, 0, 0, 87],
  264. [ 0, 0, 0, 0, 31, 0, 40, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 88, 0],
  265. [ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 15, 53, 0, 92, 0, 0, 0, 0],
  266. [ 0, 0, 0, 95, 0, 0, 0, 36, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 73, 19],
  267. [ 0, 65, 14, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 34, 0, 0],
  268. [ 0, 0, 0, 16, 39, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0],
  269. [ 0, 17, 0, 0, 0, 99, 84, 13, 50, 84, 0, 0, 0, 0, 95, 0, 43, 33, 20, 0],
  270. [79, 0, 17, 52, 99, 12, 69, 0, 98, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  271. [ 0, 0, 0, 82, 0, 44, 0, 0, 0, 97, 0, 0, 0, 0, 0, 10, 0, 0, 31, 0],
  272. [ 0, 0, 21, 0, 67, 0, 0, 0, 0, 0, 4, 0, 50, 0, 0, 0, 33, 0, 0, 0],
  273. [ 0, 0, 0, 0, 9, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8],
  274. [ 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 34, 93, 0, 0, 0, 0, 47, 0, 0, 0]],
  275. ZZ),
  276. DM([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  277. [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  278. [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  279. [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  280. [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  281. [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  282. [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  283. [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  284. [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  285. [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  286. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  287. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
  288. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
  289. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
  290. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
  291. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
  292. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
  293. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
  294. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
  295. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]], ZZ),
  296. ZZ(1),
  297. ),
  298. (
  299. 'zz_large_2',
  300. DM([
  301. [ 0, 0, 0, 0, 50, 0, 6, 81, 0, 1, 86, 0, 0, 98, 82, 94, 4, 0, 0, 29],
  302. [ 0, 44, 43, 0, 62, 0, 0, 0, 60, 0, 0, 0, 0, 71, 9, 0, 57, 41, 0, 93],
  303. [ 0, 0, 28, 0, 74, 89, 42, 0, 28, 0, 6, 0, 0, 0, 44, 0, 0, 0, 77, 19],
  304. [ 0, 21, 82, 0, 30, 88, 0, 89, 68, 0, 0, 0, 79, 41, 0, 0, 99, 0, 0, 0],
  305. [31, 0, 0, 0, 19, 64, 0, 0, 79, 0, 5, 0, 72, 10, 60, 32, 64, 59, 0, 24],
  306. [ 0, 0, 0, 0, 0, 57, 0, 94, 0, 83, 20, 0, 0, 9, 31, 0, 49, 26, 58, 0],
  307. [ 0, 65, 56, 31, 64, 0, 0, 0, 0, 0, 0, 52, 85, 0, 0, 0, 0, 51, 0, 0],
  308. [ 0, 35, 0, 0, 0, 69, 0, 0, 64, 0, 0, 0, 0, 70, 0, 0, 90, 0, 75, 76],
  309. [69, 7, 0, 90, 0, 0, 84, 0, 47, 69, 19, 20, 42, 0, 0, 32, 71, 35, 0, 0],
  310. [39, 0, 90, 0, 0, 4, 85, 0, 0, 55, 0, 0, 0, 35, 67, 40, 0, 40, 0, 77],
  311. [98, 63, 0, 71, 0, 50, 0, 2, 61, 0, 38, 0, 0, 0, 0, 75, 0, 40, 33, 56],
  312. [ 0, 73, 0, 64, 0, 38, 0, 35, 61, 0, 0, 52, 0, 7, 0, 51, 0, 0, 0, 34],
  313. [ 0, 0, 28, 0, 34, 5, 63, 45, 14, 42, 60, 16, 76, 54, 99, 0, 28, 30, 0, 0],
  314. [58, 37, 14, 0, 0, 0, 94, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 8, 90, 53],
  315. [86, 74, 94, 0, 49, 10, 60, 0, 40, 18, 0, 0, 0, 31, 60, 24, 0, 1, 0, 29],
  316. [53, 0, 0, 97, 0, 0, 58, 0, 0, 39, 44, 47, 0, 0, 0, 12, 50, 0, 0, 11],
  317. [ 4, 0, 92, 10, 28, 0, 0, 89, 0, 0, 18, 54, 23, 39, 0, 2, 0, 48, 0, 92],
  318. [ 0, 0, 90, 77, 95, 33, 0, 0, 49, 22, 39, 0, 0, 0, 0, 0, 0, 40, 0, 0],
  319. [96, 0, 0, 0, 0, 38, 86, 0, 22, 76, 0, 0, 0, 0, 83, 88, 95, 65, 72, 0],
  320. [81, 65, 0, 4, 60, 0, 19, 0, 0, 68, 0, 0, 89, 0, 67, 22, 0, 0, 55, 33]],
  321. ZZ),
  322. DM([
  323. [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  324. [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  325. [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  326. [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  327. [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  328. [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  329. [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  330. [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  331. [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  332. [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  333. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  334. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
  335. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
  336. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
  337. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
  338. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
  339. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
  340. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
  341. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
  342. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]],
  343. ZZ),
  344. ZZ(1),
  345. ),
  346. (
  347. 'zz_large_3',
  348. DM([
  349. [62,35,89,58,22,47,30,28,52,72,17,56,80,26,64,21,10,35,24,42,96,32,23,50,92,37,76,94,63,66],
  350. [20,47,96,34,10,98,19,6,29,2,19,92,61,94,38,41,32,9,5,94,31,58,27,41,72,85,61,62,40,46],
  351. [69,26,35,68,25,52,94,13,38,65,81,10,29,15,5,4,13,99,85,0,80,51,60,60,26,77,85,2,87,25],
  352. [99,58,69,15,52,12,18,7,27,56,12,54,21,92,38,95,33,83,28,1,44,8,29,84,92,12,2,25,46,46],
  353. [93,13,55,48,35,87,24,40,23,35,25,32,0,19,0,85,4,79,26,11,46,75,7,96,76,11,7,57,99,75],
  354. [128,85,26,51,161,173,77,78,85,103,123,58,91,147,38,91,161,36,123,81,102,25,75,59,17,150,112,65,77,143],
  355. [15,59,61,82,12,83,34,8,94,71,66,7,91,21,48,69,26,12,64,38,97,87,38,15,51,33,93,43,66,89],
  356. [74,74,53,39,69,90,41,80,32,66,40,83,87,87,61,38,12,80,24,49,37,90,19,33,56,0,46,57,56,60],
  357. [82,11,0,25,56,58,39,49,92,93,80,38,19,62,33,85,19,61,14,30,45,91,97,34,97,53,92,28,33,43],
  358. [83,79,41,16,95,35,53,45,26,4,71,76,61,69,69,72,87,92,59,72,54,11,22,83,8,57,77,55,19,22],
  359. [49,34,13,31,72,77,52,70,46,41,37,6,42,66,35,6,75,33,62,57,30,14,26,31,9,95,89,13,12,90],
  360. [29,3,49,30,51,32,77,41,38,50,16,1,87,81,93,88,58,91,83,0,38,67,29,64,60,84,5,60,23,28],
  361. [79,51,13,20,89,96,25,8,39,62,86,52,49,81,3,85,86,3,61,24,72,11,49,28,8,55,23,52,65,53],
  362. [96,86,73,20,41,20,37,18,10,61,85,24,40,83,69,41,4,92,23,99,64,33,18,36,32,56,60,98,39,24],
  363. [32,62,47,80,51,66,17,1,9,30,65,75,75,88,99,92,64,53,53,86,38,51,41,14,35,18,39,25,26,32],
  364. [39,21,8,16,33,6,35,85,75,62,43,34,18,68,71,28,32,18,12,0,81,53,1,99,3,5,45,99,35,33],
  365. [19,95,89,45,75,94,92,5,84,93,34,17,50,56,79,98,68,82,65,81,51,90,5,95,33,71,46,61,14,7],
  366. [53,92,8,49,67,84,21,79,49,95,66,48,36,14,62,97,26,45,58,31,83,48,11,89,67,72,91,34,56,89],
  367. [56,76,99,92,40,8,0,16,15,48,35,72,91,46,81,14,86,60,51,7,33,12,53,78,48,21,3,89,15,79],
  368. [81,43,33,49,6,49,36,32,57,74,87,91,17,37,31,17,67,1,40,38,69,8,3,48,59,37,64,97,11,3],
  369. [98,48,77,16,2,48,57,38,63,59,79,35,16,71,60,86,71,41,14,76,80,97,77,69,4,58,22,55,26,73],
  370. [80,47,78,44,31,48,47,29,29,62,19,21,17,24,19,3,53,93,97,57,13,54,12,10,77,66,60,75,32,21],
  371. [86,63,2,13,71,38,86,23,18,15,91,65,77,65,9,92,50,0,17,42,99,80,99,27,10,99,92,9,87,84],
  372. [66,27,72,13,13,15,72,75,39,3,14,71,15,68,10,19,49,54,11,29,47,20,63,13,97,47,24,62,16,96],
  373. [42,63,83,60,49,68,9,53,75,87,40,25,12,63,0,12,0,95,46,46,55,25,89,1,51,1,1,96,80,52],
  374. [35,9,97,13,86,39,66,48,41,57,23,38,11,9,35,72,88,13,41,60,10,64,71,23,1,5,23,57,6,19],
  375. [70,61,5,50,72,60,77,13,41,94,1,45,52,22,99,47,27,18,99,42,16,48,26,9,88,77,10,94,11,92],
  376. [55,68,58,2,72,56,81,52,79,37,1,40,21,46,27,60,37,13,97,42,85,98,69,60,76,44,42,46,29,73],
  377. [73,0,43,17,89,97,45,2,68,14,55,60,95,2,74,85,88,68,93,76,38,76,2,51,45,76,50,79,56,18],
  378. [72,58,41,39,24,80,23,79,44,7,98,75,30,6,85,60,20,58,77,71,90,51,38,80,30,15,33,10,82,8]],
  379. ZZ),
  380. Matrix([
  381. [eye(29) * 2028539767964472550625641331179545072876560857886207583101,
  382. Matrix([ 4260575808093245475167216057435155595594339172099000182569,
  383. 169148395880755256182802335904188369274227936894862744452,
  384. 4915975976683942569102447281579134986891620721539038348914,
  385. 6113916866367364958834844982578214901958429746875633283248,
  386. 5585689617819894460378537031623265659753379011388162534838,
  387. 359776822829880747716695359574308645968094838905181892423,
  388. -2800926112141776386671436511182421432449325232461665113305,
  389. 941642292388230001722444876624818265766384442910688463158,
  390. 3648811843256146649321864698600908938933015862008642023935,
  391. -4104526163246702252932955226754097174212129127510547462419,
  392. -704814955438106792441896903238080197619233342348191408078,
  393. 1640882266829725529929398131287244562048075707575030019335,
  394. -4068330845192910563212155694231438198040299927120544468520,
  395. 136589038308366497790495711534532612862715724187671166593,
  396. 2544937011460702462290799932536905731142196510605191645593,
  397. 755591839174293940486133926192300657264122907519174116472,
  398. -3683838489869297144348089243628436188645897133242795965021,
  399. -522207137101161299969706310062775465103537953077871128403,
  400. -2260451796032703984456606059649402832441331339246756656334,
  401. -6476809325293587953616004856993300606040336446656916663680,
  402. 3521944238996782387785653800944972787867472610035040989081,
  403. 2270762115788407950241944504104975551914297395787473242379,
  404. -3259947194628712441902262570532921252128444706733549251156,
  405. -5624569821491886970999097239695637132075823246850431083557,
  406. -3262698255682055804320585332902837076064075936601504555698,
  407. 5786719943788937667411185880136324396357603606944869545501,
  408. -955257841973865996077323863289453200904051299086000660036,
  409. -1294235552446355326174641248209752679127075717918392702116,
  410. -3718353510747301598130831152458342785269166356215331448279,
  411. ]),],
  412. [zeros(1, 29), zeros(1, 1)],
  413. ]).to_DM().to_dense(),
  414. ZZ(2028539767964472550625641331179545072876560857886207583101),
  415. ),
  416. (
  417. 'qq_1',
  418. DM([[(1,2), 0], [0, 2]], QQ),
  419. DM([[1, 0], [0, 1]], QQ),
  420. QQ(1),
  421. ),
  422. (
  423. # Standard square case
  424. 'qq_2',
  425. DM([[0, 1],
  426. [1, 1]], QQ),
  427. DM([[1, 0],
  428. [0, 1]], QQ),
  429. QQ(1),
  430. ),
  431. (
  432. # m < n case
  433. 'qq_3',
  434. DM([[1, 2, 1],
  435. [3, 4, 1]], QQ),
  436. DM([[1, 0, -1],
  437. [0, 1, 1]], QQ),
  438. QQ(1),
  439. ),
  440. (
  441. # same m < n but reversed
  442. 'qq_4',
  443. DM([[3, 4, 1],
  444. [1, 2, 1]], QQ),
  445. DM([[1, 0, -1],
  446. [0, 1, 1]], QQ),
  447. QQ(1),
  448. ),
  449. (
  450. # m > n case
  451. 'qq_5',
  452. DM([[1, 0],
  453. [1, 3],
  454. [0, 1]], QQ),
  455. DM([[1, 0],
  456. [0, 1],
  457. [0, 0]], QQ),
  458. QQ(1),
  459. ),
  460. (
  461. # Example with missing pivot
  462. 'qq_6',
  463. DM([[1, 0, 1],
  464. [3, 0, 1]], QQ),
  465. DM([[1, 0, 0],
  466. [0, 0, 1]], QQ),
  467. QQ(1),
  468. ),
  469. (
  470. # This is intended to trigger the threshold where we give up on
  471. # clearing denominators.
  472. 'qq_large_1',
  473. qq_large_1,
  474. DomainMatrix.eye(11, QQ).to_dense(),
  475. QQ(1),
  476. ),
  477. (
  478. # This is intended to trigger the threshold where we use rref_den over
  479. # QQ.
  480. 'qq_large_2',
  481. qq_large_2,
  482. DomainMatrix.eye(11, QQ).to_dense(),
  483. QQ(1),
  484. ),
  485. (
  486. # Example with missing pivot and no replacement
  487. # This example is just enough to show a different result from the dense
  488. # and sparse versions of the algorithm:
  489. #
  490. # >>> A = Matrix([[0, 1], [0, 2], [1, 0]])
  491. # >>> A.to_DM().to_sparse().rref_den()[0].to_Matrix()
  492. # Matrix([
  493. # [1, 0],
  494. # [0, 1],
  495. # [0, 0]])
  496. # >>> A.to_DM().to_dense().rref_den()[0].to_Matrix()
  497. # Matrix([
  498. # [2, 0],
  499. # [0, 2],
  500. # [0, 0]])
  501. #
  502. 'qq_7',
  503. DM([[0, 1],
  504. [0, 2],
  505. [1, 0]], QQ),
  506. DM([[1, 0],
  507. [0, 1],
  508. [0, 0]], QQ),
  509. QQ(1),
  510. ),
  511. (
  512. # Gaussian integers
  513. 'zz_i_1',
  514. DM([[(0,1), 1, 1],
  515. [ 1, 1, 1]], ZZ_I),
  516. DM([[1, 0, 0],
  517. [0, 1, 1]], ZZ_I),
  518. ZZ_I(1),
  519. ),
  520. (
  521. # EX: test_issue_23718
  522. 'EX_1',
  523. DM([
  524. [a, b, 1],
  525. [c, d, 1]], EX),
  526. DM([[a*d - b*c, 0, -b + d],
  527. [ 0, a*d - b*c, a - c]], EX),
  528. EX(a*d - b*c),
  529. ),
  530. ]
  531. def _to_DM(A, ans):
  532. """Convert the answer to DomainMatrix."""
  533. if isinstance(A, DomainMatrix):
  534. return A.to_dense()
  535. elif isinstance(A, Matrix):
  536. return A.to_DM(ans.domain).to_dense()
  537. if not (hasattr(A, 'shape') and hasattr(A, 'domain')):
  538. shape, domain = ans.shape, ans.domain
  539. else:
  540. shape, domain = A.shape, A.domain
  541. if isinstance(A, (DDM, list)):
  542. return DomainMatrix(list(A), shape, domain).to_dense()
  543. elif isinstance(A, (SDM, dict)):
  544. return DomainMatrix(dict(A), shape, domain).to_dense()
  545. else:
  546. assert False # pragma: no cover
  547. def _pivots(A_rref):
  548. """Return the pivots from the rref of A."""
  549. return tuple(sorted(map(min, A_rref.to_sdm().values())))
  550. def _check_cancel(result, rref_ans, den_ans):
  551. """Check the cancelled result."""
  552. rref, den, pivots = result
  553. if isinstance(rref, (DDM, SDM, list, dict)):
  554. assert type(pivots) is list
  555. pivots = tuple(pivots)
  556. rref = _to_DM(rref, rref_ans)
  557. rref2, den2 = rref.cancel_denom(den)
  558. assert rref2 == rref_ans
  559. assert den2 == den_ans
  560. assert pivots == _pivots(rref)
  561. def _check_divide(result, rref_ans, den_ans):
  562. """Check the divided result."""
  563. rref, pivots = result
  564. if isinstance(rref, (DDM, SDM, list, dict)):
  565. assert type(pivots) is list
  566. pivots = tuple(pivots)
  567. rref_ans = rref_ans.to_field() / den_ans
  568. rref = _to_DM(rref, rref_ans)
  569. assert rref == rref_ans
  570. assert _pivots(rref) == pivots
  571. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  572. def test_Matrix_rref(name, A, A_rref, den):
  573. K = A.domain
  574. A = A.to_Matrix()
  575. A_rref_found, pivots = A.rref()
  576. if K.is_EX:
  577. A_rref_found = A_rref_found.expand()
  578. _check_divide((A_rref_found, pivots), A_rref, den)
  579. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  580. def test_dm_dense_rref(name, A, A_rref, den):
  581. A = A.to_field()
  582. _check_divide(A.rref(), A_rref, den)
  583. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  584. def test_dm_dense_rref_den(name, A, A_rref, den):
  585. _check_cancel(A.rref_den(), A_rref, den)
  586. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  587. def test_dm_sparse_rref(name, A, A_rref, den):
  588. A = A.to_field().to_sparse()
  589. _check_divide(A.rref(), A_rref, den)
  590. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  591. def test_dm_sparse_rref_den(name, A, A_rref, den):
  592. A = A.to_sparse()
  593. _check_cancel(A.rref_den(), A_rref, den)
  594. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  595. def test_dm_sparse_rref_den_keep_domain(name, A, A_rref, den):
  596. A = A.to_sparse()
  597. A_rref_f, den_f, pivots_f = A.rref_den(keep_domain=False)
  598. A_rref_f = A_rref_f.to_field() / den_f
  599. _check_divide((A_rref_f, pivots_f), A_rref, den)
  600. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  601. def test_dm_sparse_rref_den_keep_domain_CD(name, A, A_rref, den):
  602. A = A.to_sparse()
  603. A_rref_f, den_f, pivots_f = A.rref_den(keep_domain=False, method='CD')
  604. A_rref_f = A_rref_f.to_field() / den_f
  605. _check_divide((A_rref_f, pivots_f), A_rref, den)
  606. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  607. def test_dm_sparse_rref_den_keep_domain_GJ(name, A, A_rref, den):
  608. A = A.to_sparse()
  609. A_rref_f, den_f, pivots_f = A.rref_den(keep_domain=False, method='GJ')
  610. A_rref_f = A_rref_f.to_field() / den_f
  611. _check_divide((A_rref_f, pivots_f), A_rref, den)
  612. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  613. def test_ddm_rref_den(name, A, A_rref, den):
  614. A = A.to_ddm()
  615. _check_cancel(A.rref_den(), A_rref, den)
  616. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  617. def test_sdm_rref_den(name, A, A_rref, den):
  618. A = A.to_sdm()
  619. _check_cancel(A.rref_den(), A_rref, den)
  620. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  621. def test_ddm_rref(name, A, A_rref, den):
  622. A = A.to_field().to_ddm()
  623. _check_divide(A.rref(), A_rref, den)
  624. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  625. def test_sdm_rref(name, A, A_rref, den):
  626. A = A.to_field().to_sdm()
  627. _check_divide(A.rref(), A_rref, den)
  628. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  629. def test_ddm_irref(name, A, A_rref, den):
  630. A = A.to_field().to_ddm().copy()
  631. pivots_found = ddm_irref(A)
  632. _check_divide((A, pivots_found), A_rref, den)
  633. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  634. def test_ddm_irref_den(name, A, A_rref, den):
  635. A = A.to_ddm().copy()
  636. (den_found, pivots_found) = ddm_irref_den(A, A.domain)
  637. result = (A, den_found, pivots_found)
  638. _check_cancel(result, A_rref, den)
  639. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  640. def test_sparse_sdm_rref(name, A, A_rref, den):
  641. A = A.to_field().to_sdm()
  642. _check_divide(sdm_irref(A)[:2], A_rref, den)
  643. @pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES)
  644. def test_sparse_sdm_rref_den(name, A, A_rref, den):
  645. A = A.to_sdm().copy()
  646. K = A.domain
  647. _check_cancel(sdm_rref_den(A, K), A_rref, den)