test_polyclasses.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. """Tests for OO layer of several polynomial representations. """
  2. from sympy.functions.elementary.miscellaneous import sqrt
  3. from sympy.polys.domains import ZZ, QQ
  4. from sympy.polys.polyclasses import DMP, DMF, ANP
  5. from sympy.polys.polyerrors import (CoercionFailed, ExactQuotientFailed,
  6. NotInvertible)
  7. from sympy.polys.specialpolys import f_polys
  8. from sympy.testing.pytest import raises
  9. f_0, f_1, f_2, f_3, f_4, f_5, f_6 = [ f.to_dense() for f in f_polys() ]
  10. def test_DMP___init__():
  11. f = DMP([[0], [], [0, 1, 2], [3]], ZZ)
  12. assert f.rep == [[1, 2], [3]]
  13. assert f.dom == ZZ
  14. assert f.lev == 1
  15. f = DMP([[1, 2], [3]], ZZ, 1)
  16. assert f.rep == [[1, 2], [3]]
  17. assert f.dom == ZZ
  18. assert f.lev == 1
  19. f = DMP({(1, 1): 1, (0, 0): 2}, ZZ, 1)
  20. assert f.rep == [[1, 0], [2]]
  21. assert f.dom == ZZ
  22. assert f.lev == 1
  23. def test_DMP___eq__():
  24. assert DMP([[ZZ(1), ZZ(2)], [ZZ(3)]], ZZ) == \
  25. DMP([[ZZ(1), ZZ(2)], [ZZ(3)]], ZZ)
  26. assert DMP([[ZZ(1), ZZ(2)], [ZZ(3)]], ZZ) == \
  27. DMP([[QQ(1), QQ(2)], [QQ(3)]], QQ)
  28. assert DMP([[QQ(1), QQ(2)], [QQ(3)]], QQ) == \
  29. DMP([[ZZ(1), ZZ(2)], [ZZ(3)]], ZZ)
  30. assert DMP([[[ZZ(1)]]], ZZ) != DMP([[ZZ(1)]], ZZ)
  31. assert DMP([[ZZ(1)]], ZZ) != DMP([[[ZZ(1)]]], ZZ)
  32. def test_DMP___bool__():
  33. assert bool(DMP([[]], ZZ)) is False
  34. assert bool(DMP([[1]], ZZ)) is True
  35. def test_DMP_to_dict():
  36. f = DMP([[3], [], [2], [], [8]], ZZ)
  37. assert f.to_dict() == \
  38. {(4, 0): 3, (2, 0): 2, (0, 0): 8}
  39. assert f.to_sympy_dict() == \
  40. {(4, 0): ZZ.to_sympy(3), (2, 0): ZZ.to_sympy(2), (0, 0):
  41. ZZ.to_sympy(8)}
  42. def test_DMP_properties():
  43. assert DMP([[]], ZZ).is_zero is True
  44. assert DMP([[1]], ZZ).is_zero is False
  45. assert DMP([[1]], ZZ).is_one is True
  46. assert DMP([[2]], ZZ).is_one is False
  47. assert DMP([[1]], ZZ).is_ground is True
  48. assert DMP([[1], [2], [1]], ZZ).is_ground is False
  49. assert DMP([[1], [2, 0], [1, 0]], ZZ).is_sqf is True
  50. assert DMP([[1], [2, 0], [1, 0, 0]], ZZ).is_sqf is False
  51. assert DMP([[1, 2], [3]], ZZ).is_monic is True
  52. assert DMP([[2, 2], [3]], ZZ).is_monic is False
  53. assert DMP([[1, 2], [3]], ZZ).is_primitive is True
  54. assert DMP([[2, 4], [6]], ZZ).is_primitive is False
  55. def test_DMP_arithmetics():
  56. f = DMP([[2], [2, 0]], ZZ)
  57. assert f.mul_ground(2) == DMP([[4], [4, 0]], ZZ)
  58. assert f.quo_ground(2) == DMP([[1], [1, 0]], ZZ)
  59. raises(ExactQuotientFailed, lambda: f.exquo_ground(3))
  60. f = DMP([[-5]], ZZ)
  61. g = DMP([[5]], ZZ)
  62. assert f.abs() == g
  63. assert abs(f) == g
  64. assert g.neg() == f
  65. assert -g == f
  66. h = DMP([[]], ZZ)
  67. assert f.add(g) == h
  68. assert f + g == h
  69. assert g + f == h
  70. assert f + 5 == h
  71. assert 5 + f == h
  72. h = DMP([[-10]], ZZ)
  73. assert f.sub(g) == h
  74. assert f - g == h
  75. assert g - f == -h
  76. assert f - 5 == h
  77. assert 5 - f == -h
  78. h = DMP([[-25]], ZZ)
  79. assert f.mul(g) == h
  80. assert f * g == h
  81. assert g * f == h
  82. assert f * 5 == h
  83. assert 5 * f == h
  84. h = DMP([[25]], ZZ)
  85. assert f.sqr() == h
  86. assert f.pow(2) == h
  87. assert f**2 == h
  88. raises(TypeError, lambda: f.pow('x'))
  89. f = DMP([[1], [], [1, 0, 0]], ZZ)
  90. g = DMP([[2], [-2, 0]], ZZ)
  91. q = DMP([[2], [2, 0]], ZZ)
  92. r = DMP([[8, 0, 0]], ZZ)
  93. assert f.pdiv(g) == (q, r)
  94. assert f.pquo(g) == q
  95. assert f.prem(g) == r
  96. raises(ExactQuotientFailed, lambda: f.pexquo(g))
  97. f = DMP([[1], [], [1, 0, 0]], ZZ)
  98. g = DMP([[1], [-1, 0]], ZZ)
  99. q = DMP([[1], [1, 0]], ZZ)
  100. r = DMP([[2, 0, 0]], ZZ)
  101. assert f.div(g) == (q, r)
  102. assert f.quo(g) == q
  103. assert f.rem(g) == r
  104. assert divmod(f, g) == (q, r)
  105. assert f // g == q
  106. assert f % g == r
  107. raises(ExactQuotientFailed, lambda: f.exquo(g))
  108. def test_DMP_functionality():
  109. f = DMP([[1], [2, 0], [1, 0, 0]], ZZ)
  110. g = DMP([[1], [1, 0]], ZZ)
  111. h = DMP([[1]], ZZ)
  112. assert f.degree() == 2
  113. assert f.degree_list() == (2, 2)
  114. assert f.total_degree() == 2
  115. assert f.LC() == ZZ(1)
  116. assert f.TC() == ZZ(0)
  117. assert f.nth(1, 1) == ZZ(2)
  118. raises(TypeError, lambda: f.nth(0, 'x'))
  119. assert f.max_norm() == 2
  120. assert f.l1_norm() == 4
  121. u = DMP([[2], [2, 0]], ZZ)
  122. assert f.diff(m=1, j=0) == u
  123. assert f.diff(m=1, j=1) == u
  124. raises(TypeError, lambda: f.diff(m='x', j=0))
  125. u = DMP([1, 2, 1], ZZ)
  126. v = DMP([1, 2, 1], ZZ)
  127. assert f.eval(a=1, j=0) == u
  128. assert f.eval(a=1, j=1) == v
  129. assert f.eval(1).eval(1) == ZZ(4)
  130. assert f.cofactors(g) == (g, g, h)
  131. assert f.gcd(g) == g
  132. assert f.lcm(g) == f
  133. u = DMP([[QQ(45), QQ(30), QQ(5)]], QQ)
  134. v = DMP([[QQ(1), QQ(2, 3), QQ(1, 9)]], QQ)
  135. assert u.monic() == v
  136. assert (4*f).content() == ZZ(4)
  137. assert (4*f).primitive() == (ZZ(4), f)
  138. f = DMP([[1], [2], [3], [4], [5], [6]], ZZ)
  139. assert f.trunc(3) == DMP([[1], [-1], [], [1], [-1], []], ZZ)
  140. f = DMP(f_4, ZZ)
  141. assert f.sqf_part() == -f
  142. assert f.sqf_list() == (ZZ(-1), [(-f, 1)])
  143. f = DMP([[-1], [], [], [5]], ZZ)
  144. g = DMP([[3, 1], [], []], ZZ)
  145. h = DMP([[45, 30, 5]], ZZ)
  146. r = DMP([675, 675, 225, 25], ZZ)
  147. assert f.subresultants(g) == [f, g, h]
  148. assert f.resultant(g) == r
  149. f = DMP([1, 3, 9, -13], ZZ)
  150. assert f.discriminant() == -11664
  151. f = DMP([QQ(2), QQ(0)], QQ)
  152. g = DMP([QQ(1), QQ(0), QQ(-16)], QQ)
  153. s = DMP([QQ(1, 32), QQ(0)], QQ)
  154. t = DMP([QQ(-1, 16)], QQ)
  155. h = DMP([QQ(1)], QQ)
  156. assert f.half_gcdex(g) == (s, h)
  157. assert f.gcdex(g) == (s, t, h)
  158. assert f.invert(g) == s
  159. f = DMP([[1], [2], [3]], QQ)
  160. raises(ValueError, lambda: f.half_gcdex(f))
  161. raises(ValueError, lambda: f.gcdex(f))
  162. raises(ValueError, lambda: f.invert(f))
  163. f = DMP([1, 0, 20, 0, 150, 0, 500, 0, 625, -2, 0, -10, 9], ZZ)
  164. g = DMP([1, 0, 0, -2, 9], ZZ)
  165. h = DMP([1, 0, 5, 0], ZZ)
  166. assert g.compose(h) == f
  167. assert f.decompose() == [g, h]
  168. f = DMP([[1], [2], [3]], QQ)
  169. raises(ValueError, lambda: f.decompose())
  170. raises(ValueError, lambda: f.sturm())
  171. def test_DMP_exclude():
  172. f = [[[[[[[[[[[[[[[[[[[[[[[[[[1]], [[]]]]]]]]]]]]]]]]]]]]]]]]]]
  173. J = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
  174. 18, 19, 20, 21, 22, 24, 25]
  175. assert DMP(f, ZZ).exclude() == (J, DMP([1, 0], ZZ))
  176. assert DMP([[1], [1, 0]], ZZ).exclude() == ([], DMP([[1], [1, 0]], ZZ))
  177. def test_DMF__init__():
  178. f = DMF(([[0], [], [0, 1, 2], [3]], [[1, 2, 3]]), ZZ)
  179. assert f.num == [[1, 2], [3]]
  180. assert f.den == [[1, 2, 3]]
  181. assert f.lev == 1
  182. assert f.dom == ZZ
  183. f = DMF(([[1, 2], [3]], [[1, 2, 3]]), ZZ, 1)
  184. assert f.num == [[1, 2], [3]]
  185. assert f.den == [[1, 2, 3]]
  186. assert f.lev == 1
  187. assert f.dom == ZZ
  188. f = DMF(([[-1], [-2]], [[3], [-4]]), ZZ)
  189. assert f.num == [[-1], [-2]]
  190. assert f.den == [[3], [-4]]
  191. assert f.lev == 1
  192. assert f.dom == ZZ
  193. f = DMF(([[1], [2]], [[-3], [4]]), ZZ)
  194. assert f.num == [[-1], [-2]]
  195. assert f.den == [[3], [-4]]
  196. assert f.lev == 1
  197. assert f.dom == ZZ
  198. f = DMF(([[1], [2]], [[-3], [4]]), ZZ)
  199. assert f.num == [[-1], [-2]]
  200. assert f.den == [[3], [-4]]
  201. assert f.lev == 1
  202. assert f.dom == ZZ
  203. f = DMF(([[]], [[-3], [4]]), ZZ)
  204. assert f.num == [[]]
  205. assert f.den == [[1]]
  206. assert f.lev == 1
  207. assert f.dom == ZZ
  208. f = DMF(17, ZZ, 1)
  209. assert f.num == [[17]]
  210. assert f.den == [[1]]
  211. assert f.lev == 1
  212. assert f.dom == ZZ
  213. f = DMF(([[1], [2]]), ZZ)
  214. assert f.num == [[1], [2]]
  215. assert f.den == [[1]]
  216. assert f.lev == 1
  217. assert f.dom == ZZ
  218. f = DMF([[0], [], [0, 1, 2], [3]], ZZ)
  219. assert f.num == [[1, 2], [3]]
  220. assert f.den == [[1]]
  221. assert f.lev == 1
  222. assert f.dom == ZZ
  223. f = DMF({(1, 1): 1, (0, 0): 2}, ZZ, 1)
  224. assert f.num == [[1, 0], [2]]
  225. assert f.den == [[1]]
  226. assert f.lev == 1
  227. assert f.dom == ZZ
  228. f = DMF(([[QQ(1)], [QQ(2)]], [[-QQ(3)], [QQ(4)]]), QQ)
  229. assert f.num == [[-QQ(1)], [-QQ(2)]]
  230. assert f.den == [[QQ(3)], [-QQ(4)]]
  231. assert f.lev == 1
  232. assert f.dom == QQ
  233. f = DMF(([[QQ(1, 5)], [QQ(2, 5)]], [[-QQ(3, 7)], [QQ(4, 7)]]), QQ)
  234. assert f.num == [[-QQ(7)], [-QQ(14)]]
  235. assert f.den == [[QQ(15)], [-QQ(20)]]
  236. assert f.lev == 1
  237. assert f.dom == QQ
  238. raises(ValueError, lambda: DMF(([1], [[1]]), ZZ))
  239. raises(ZeroDivisionError, lambda: DMF(([1], []), ZZ))
  240. def test_DMF__bool__():
  241. assert bool(DMF([[]], ZZ)) is False
  242. assert bool(DMF([[1]], ZZ)) is True
  243. def test_DMF_properties():
  244. assert DMF([[]], ZZ).is_zero is True
  245. assert DMF([[]], ZZ).is_one is False
  246. assert DMF([[1]], ZZ).is_zero is False
  247. assert DMF([[1]], ZZ).is_one is True
  248. assert DMF(([[1]], [[2]]), ZZ).is_one is False
  249. def test_DMF_arithmetics():
  250. f = DMF([[7], [-9]], ZZ)
  251. g = DMF([[-7], [9]], ZZ)
  252. assert f.neg() == -f == g
  253. f = DMF(([[1]], [[1], []]), ZZ)
  254. g = DMF(([[1]], [[1, 0]]), ZZ)
  255. h = DMF(([[1], [1, 0]], [[1, 0], []]), ZZ)
  256. assert f.add(g) == f + g == h
  257. assert g.add(f) == g + f == h
  258. h = DMF(([[-1], [1, 0]], [[1, 0], []]), ZZ)
  259. assert f.sub(g) == f - g == h
  260. h = DMF(([[1]], [[1, 0], []]), ZZ)
  261. assert f.mul(g) == f*g == h
  262. assert g.mul(f) == g*f == h
  263. h = DMF(([[1, 0]], [[1], []]), ZZ)
  264. assert f.quo(g) == f/g == h
  265. h = DMF(([[1]], [[1], [], [], []]), ZZ)
  266. assert f.pow(3) == f**3 == h
  267. h = DMF(([[1]], [[1, 0, 0, 0]]), ZZ)
  268. assert g.pow(3) == g**3 == h
  269. h = DMF(([[1, 0]], [[1]]), ZZ)
  270. assert g.pow(-1) == g**-1 == h
  271. def test_ANP___init__():
  272. rep = [QQ(1), QQ(1)]
  273. mod = [QQ(1), QQ(0), QQ(1)]
  274. f = ANP(rep, mod, QQ)
  275. assert f.rep == [QQ(1), QQ(1)]
  276. assert f.mod == [QQ(1), QQ(0), QQ(1)]
  277. assert f.dom == QQ
  278. rep = {1: QQ(1), 0: QQ(1)}
  279. mod = {2: QQ(1), 0: QQ(1)}
  280. f = ANP(rep, mod, QQ)
  281. assert f.rep == [QQ(1), QQ(1)]
  282. assert f.mod == [QQ(1), QQ(0), QQ(1)]
  283. assert f.dom == QQ
  284. f = ANP(1, mod, QQ)
  285. assert f.rep == [QQ(1)]
  286. assert f.mod == [QQ(1), QQ(0), QQ(1)]
  287. assert f.dom == QQ
  288. f = ANP([1, 0.5], mod, QQ)
  289. assert all(QQ.of_type(a) for a in f.rep)
  290. raises(CoercionFailed, lambda: ANP([sqrt(2)], mod, QQ))
  291. def test_ANP___eq__():
  292. a = ANP([QQ(1), QQ(1)], [QQ(1), QQ(0), QQ(1)], QQ)
  293. b = ANP([QQ(1), QQ(1)], [QQ(1), QQ(0), QQ(2)], QQ)
  294. assert (a == a) is True
  295. assert (a != a) is False
  296. assert (a == b) is False
  297. assert (a != b) is True
  298. b = ANP([QQ(1), QQ(2)], [QQ(1), QQ(0), QQ(1)], QQ)
  299. assert (a == b) is False
  300. assert (a != b) is True
  301. def test_ANP___bool__():
  302. assert bool(ANP([], [QQ(1), QQ(0), QQ(1)], QQ)) is False
  303. assert bool(ANP([QQ(1)], [QQ(1), QQ(0), QQ(1)], QQ)) is True
  304. def test_ANP_properties():
  305. mod = [QQ(1), QQ(0), QQ(1)]
  306. assert ANP([QQ(0)], mod, QQ).is_zero is True
  307. assert ANP([QQ(1)], mod, QQ).is_zero is False
  308. assert ANP([QQ(1)], mod, QQ).is_one is True
  309. assert ANP([QQ(2)], mod, QQ).is_one is False
  310. def test_ANP_arithmetics():
  311. mod = [QQ(1), QQ(0), QQ(0), QQ(-2)]
  312. a = ANP([QQ(2), QQ(-1), QQ(1)], mod, QQ)
  313. b = ANP([QQ(1), QQ(2)], mod, QQ)
  314. c = ANP([QQ(-2), QQ(1), QQ(-1)], mod, QQ)
  315. assert a.neg() == -a == c
  316. c = ANP([QQ(2), QQ(0), QQ(3)], mod, QQ)
  317. assert a.add(b) == a + b == c
  318. assert b.add(a) == b + a == c
  319. c = ANP([QQ(2), QQ(-2), QQ(-1)], mod, QQ)
  320. assert a.sub(b) == a - b == c
  321. c = ANP([QQ(-2), QQ(2), QQ(1)], mod, QQ)
  322. assert b.sub(a) == b - a == c
  323. c = ANP([QQ(3), QQ(-1), QQ(6)], mod, QQ)
  324. assert a.mul(b) == a*b == c
  325. assert b.mul(a) == b*a == c
  326. c = ANP([QQ(-1, 43), QQ(9, 43), QQ(5, 43)], mod, QQ)
  327. assert a.pow(0) == a**(0) == ANP(1, mod, QQ)
  328. assert a.pow(1) == a**(1) == a
  329. assert a.pow(-1) == a**(-1) == c
  330. assert a.quo(a) == a.mul(a.pow(-1)) == a*a**(-1) == ANP(1, mod, QQ)
  331. c = ANP([], [1, 0, 0, -2], QQ)
  332. r1 = a.rem(b)
  333. (q, r2) = a.div(b)
  334. assert r1 == r2 == c == a % b
  335. raises(NotInvertible, lambda: a.div(c))
  336. raises(NotInvertible, lambda: a.rem(c))
  337. # Comparison with "hard-coded" value fails despite looking identical
  338. # from sympy import Rational
  339. # c = ANP([Rational(11, 10), Rational(-1, 5), Rational(-3, 5)], [1, 0, 0, -2], QQ)
  340. assert q == a/b # == c
  341. def test_ANP_unify():
  342. mod = [QQ(1), QQ(0), QQ(-2)]
  343. a = ANP([QQ(1)], mod, QQ)
  344. b = ANP([ZZ(1)], mod, ZZ)
  345. assert a.unify(b)[0] == QQ
  346. assert b.unify(a)[0] == QQ
  347. assert a.unify(a)[0] == QQ
  348. assert b.unify(b)[0] == ZZ
  349. def test___hash__():
  350. # issue 5571
  351. # Make sure int vs. long doesn't affect hashing with Python ground types
  352. assert DMP([[1, 2], [3]], ZZ) == DMP([[int(1), int(2)], [int(3)]], ZZ)
  353. assert hash(DMP([[1, 2], [3]], ZZ)) == hash(DMP([[int(1), int(2)], [int(3)]], ZZ))
  354. assert DMF(
  355. ([[1, 2], [3]], [[1]]), ZZ) == DMF(([[int(1), int(2)], [int(3)]], [[int(1)]]), ZZ)
  356. assert hash(DMF(([[1, 2], [3]], [[1]]), ZZ)) == hash(DMF(([[int(1),
  357. int(2)], [int(3)]], [[int(1)]]), ZZ))
  358. assert ANP([1, 1], [1, 0, 1], ZZ) == ANP([int(1), int(1)], [int(1), int(0), int(1)], ZZ)
  359. assert hash(
  360. ANP([1, 1], [1, 0, 1], ZZ)) == hash(ANP([int(1), int(1)], [int(1), int(0), int(1)], ZZ))