test_rootoftools.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. """Tests for the implementation of RootOf class and related tools. """
  2. from sympy.polys.polytools import Poly
  3. import sympy.polys.rootoftools as rootoftools
  4. from sympy.polys.rootoftools import (rootof, RootOf, CRootOf, RootSum,
  5. _pure_key_dict as D)
  6. from sympy.polys.polyerrors import (
  7. MultivariatePolynomialError,
  8. GeneratorsNeeded,
  9. PolynomialError,
  10. )
  11. from sympy.core.function import (Function, Lambda)
  12. from sympy.core.numbers import (Float, I, Rational)
  13. from sympy.core.relational import Eq
  14. from sympy.core.singleton import S
  15. from sympy.functions.elementary.exponential import (exp, log)
  16. from sympy.functions.elementary.miscellaneous import sqrt
  17. from sympy.functions.elementary.trigonometric import tan
  18. from sympy.integrals.integrals import Integral
  19. from sympy.polys.orthopolys import legendre_poly
  20. from sympy.solvers.solvers import solve
  21. from sympy.testing.pytest import raises, slow
  22. from sympy.core.expr import unchanged
  23. from sympy.abc import a, b, x, y, z, r
  24. def test_CRootOf___new__():
  25. assert rootof(x, 0) == 0
  26. assert rootof(x, -1) == 0
  27. assert rootof(x, S.Zero) == 0
  28. assert rootof(x - 1, 0) == 1
  29. assert rootof(x - 1, -1) == 1
  30. assert rootof(x + 1, 0) == -1
  31. assert rootof(x + 1, -1) == -1
  32. assert rootof(x**2 + 2*x + 3, 0) == -1 - I*sqrt(2)
  33. assert rootof(x**2 + 2*x + 3, 1) == -1 + I*sqrt(2)
  34. assert rootof(x**2 + 2*x + 3, -1) == -1 + I*sqrt(2)
  35. assert rootof(x**2 + 2*x + 3, -2) == -1 - I*sqrt(2)
  36. r = rootof(x**2 + 2*x + 3, 0, radicals=False)
  37. assert isinstance(r, RootOf) is True
  38. r = rootof(x**2 + 2*x + 3, 1, radicals=False)
  39. assert isinstance(r, RootOf) is True
  40. r = rootof(x**2 + 2*x + 3, -1, radicals=False)
  41. assert isinstance(r, RootOf) is True
  42. r = rootof(x**2 + 2*x + 3, -2, radicals=False)
  43. assert isinstance(r, RootOf) is True
  44. assert rootof((x - 1)*(x + 1), 0, radicals=False) == -1
  45. assert rootof((x - 1)*(x + 1), 1, radicals=False) == 1
  46. assert rootof((x - 1)*(x + 1), -1, radicals=False) == 1
  47. assert rootof((x - 1)*(x + 1), -2, radicals=False) == -1
  48. assert rootof((x - 1)*(x + 1), 0, radicals=True) == -1
  49. assert rootof((x - 1)*(x + 1), 1, radicals=True) == 1
  50. assert rootof((x - 1)*(x + 1), -1, radicals=True) == 1
  51. assert rootof((x - 1)*(x + 1), -2, radicals=True) == -1
  52. assert rootof((x - 1)*(x**3 + x + 3), 0) == rootof(x**3 + x + 3, 0)
  53. assert rootof((x - 1)*(x**3 + x + 3), 1) == 1
  54. assert rootof((x - 1)*(x**3 + x + 3), 2) == rootof(x**3 + x + 3, 1)
  55. assert rootof((x - 1)*(x**3 + x + 3), 3) == rootof(x**3 + x + 3, 2)
  56. assert rootof((x - 1)*(x**3 + x + 3), -1) == rootof(x**3 + x + 3, 2)
  57. assert rootof((x - 1)*(x**3 + x + 3), -2) == rootof(x**3 + x + 3, 1)
  58. assert rootof((x - 1)*(x**3 + x + 3), -3) == 1
  59. assert rootof((x - 1)*(x**3 + x + 3), -4) == rootof(x**3 + x + 3, 0)
  60. assert rootof(x**4 + 3*x**3, 0) == -3
  61. assert rootof(x**4 + 3*x**3, 1) == 0
  62. assert rootof(x**4 + 3*x**3, 2) == 0
  63. assert rootof(x**4 + 3*x**3, 3) == 0
  64. raises(GeneratorsNeeded, lambda: rootof(0, 0))
  65. raises(GeneratorsNeeded, lambda: rootof(1, 0))
  66. raises(PolynomialError, lambda: rootof(Poly(0, x), 0))
  67. raises(PolynomialError, lambda: rootof(Poly(1, x), 0))
  68. raises(PolynomialError, lambda: rootof(x - y, 0))
  69. # issue 8617
  70. raises(PolynomialError, lambda: rootof(exp(x), 0))
  71. raises(NotImplementedError, lambda: rootof(x**3 - x + sqrt(2), 0))
  72. raises(NotImplementedError, lambda: rootof(x**3 - x + I, 0))
  73. raises(IndexError, lambda: rootof(x**2 - 1, -4))
  74. raises(IndexError, lambda: rootof(x**2 - 1, -3))
  75. raises(IndexError, lambda: rootof(x**2 - 1, 2))
  76. raises(IndexError, lambda: rootof(x**2 - 1, 3))
  77. raises(ValueError, lambda: rootof(x**2 - 1, x))
  78. assert rootof(Poly(x - y, x), 0) == y
  79. assert rootof(Poly(x**2 - y, x), 0) == -sqrt(y)
  80. assert rootof(Poly(x**2 - y, x), 1) == sqrt(y)
  81. assert rootof(Poly(x**3 - y, x), 0) == y**Rational(1, 3)
  82. assert rootof(y*x**3 + y*x + 2*y, x, 0) == -1
  83. raises(NotImplementedError, lambda: rootof(x**3 + x + 2*y, x, 0))
  84. assert rootof(x**3 + x + 1, 0).is_commutative is True
  85. def test_CRootOf_attributes():
  86. r = rootof(x**3 + x + 3, 0)
  87. assert r.is_number
  88. assert r.free_symbols == set()
  89. # if the following assertion fails then multivariate polynomials
  90. # are apparently supported and the RootOf.free_symbols routine
  91. # should be changed to return whatever symbols would not be
  92. # the PurePoly dummy symbol
  93. raises(NotImplementedError, lambda: rootof(Poly(x**3 + y*x + 1, x), 0))
  94. def test_CRootOf___eq__():
  95. assert (rootof(x**3 + x + 3, 0) == rootof(x**3 + x + 3, 0)) is True
  96. assert (rootof(x**3 + x + 3, 0) == rootof(x**3 + x + 3, 1)) is False
  97. assert (rootof(x**3 + x + 3, 1) == rootof(x**3 + x + 3, 1)) is True
  98. assert (rootof(x**3 + x + 3, 1) == rootof(x**3 + x + 3, 2)) is False
  99. assert (rootof(x**3 + x + 3, 2) == rootof(x**3 + x + 3, 2)) is True
  100. assert (rootof(x**3 + x + 3, 0) == rootof(y**3 + y + 3, 0)) is True
  101. assert (rootof(x**3 + x + 3, 0) == rootof(y**3 + y + 3, 1)) is False
  102. assert (rootof(x**3 + x + 3, 1) == rootof(y**3 + y + 3, 1)) is True
  103. assert (rootof(x**3 + x + 3, 1) == rootof(y**3 + y + 3, 2)) is False
  104. assert (rootof(x**3 + x + 3, 2) == rootof(y**3 + y + 3, 2)) is True
  105. def test_CRootOf___eval_Eq__():
  106. f = Function('f')
  107. eq = x**3 + x + 3
  108. r = rootof(eq, 2)
  109. r1 = rootof(eq, 1)
  110. assert Eq(r, r1) is S.false
  111. assert Eq(r, r) is S.true
  112. assert unchanged(Eq, r, x)
  113. assert Eq(r, 0) is S.false
  114. assert Eq(r, S.Infinity) is S.false
  115. assert Eq(r, I) is S.false
  116. assert unchanged(Eq, r, f(0))
  117. sol = solve(eq)
  118. for s in sol:
  119. if s.is_real:
  120. assert Eq(r, s) is S.false
  121. r = rootof(eq, 0)
  122. for s in sol:
  123. if s.is_real:
  124. assert Eq(r, s) is S.true
  125. eq = x**3 + x + 1
  126. sol = solve(eq)
  127. assert [Eq(rootof(eq, i), j) for i in range(3) for j in sol
  128. ].count(True) == 3
  129. assert Eq(rootof(eq, 0), 1 + S.ImaginaryUnit) == False
  130. def test_CRootOf_is_real():
  131. assert rootof(x**3 + x + 3, 0).is_real is True
  132. assert rootof(x**3 + x + 3, 1).is_real is False
  133. assert rootof(x**3 + x + 3, 2).is_real is False
  134. def test_CRootOf_is_complex():
  135. assert rootof(x**3 + x + 3, 0).is_complex is True
  136. def test_CRootOf_is_algebraic():
  137. assert rootof(x**3 + x + 3, 0).is_algebraic is True
  138. assert rootof(x**3 + x + 3, 1).is_algebraic is True
  139. assert rootof(x**3 + x + 3, 2).is_algebraic is True
  140. def test_CRootOf_subs():
  141. assert rootof(x**3 + x + 1, 0).subs(x, y) == rootof(y**3 + y + 1, 0)
  142. def test_CRootOf_diff():
  143. assert rootof(x**3 + x + 1, 0).diff(x) == 0
  144. assert rootof(x**3 + x + 1, 0).diff(y) == 0
  145. @slow
  146. def test_CRootOf_evalf():
  147. real = rootof(x**3 + x + 3, 0).evalf(n=20)
  148. assert real.epsilon_eq(Float("-1.2134116627622296341"))
  149. re, im = rootof(x**3 + x + 3, 1).evalf(n=20).as_real_imag()
  150. assert re.epsilon_eq( Float("0.60670583138111481707"))
  151. assert im.epsilon_eq(-Float("1.45061224918844152650"))
  152. re, im = rootof(x**3 + x + 3, 2).evalf(n=20).as_real_imag()
  153. assert re.epsilon_eq(Float("0.60670583138111481707"))
  154. assert im.epsilon_eq(Float("1.45061224918844152650"))
  155. p = legendre_poly(4, x, polys=True)
  156. roots = [str(r.n(17)) for r in p.real_roots()]
  157. # magnitudes are given by
  158. # sqrt(3/S(7) - 2*sqrt(6/S(5))/7)
  159. # and
  160. # sqrt(3/S(7) + 2*sqrt(6/S(5))/7)
  161. assert roots == [
  162. "-0.86113631159405258",
  163. "-0.33998104358485626",
  164. "0.33998104358485626",
  165. "0.86113631159405258",
  166. ]
  167. re = rootof(x**5 - 5*x + 12, 0).evalf(n=20)
  168. assert re.epsilon_eq(Float("-1.84208596619025438271"))
  169. re, im = rootof(x**5 - 5*x + 12, 1).evalf(n=20).as_real_imag()
  170. assert re.epsilon_eq(Float("-0.351854240827371999559"))
  171. assert im.epsilon_eq(Float("-1.709561043370328882010"))
  172. re, im = rootof(x**5 - 5*x + 12, 2).evalf(n=20).as_real_imag()
  173. assert re.epsilon_eq(Float("-0.351854240827371999559"))
  174. assert im.epsilon_eq(Float("+1.709561043370328882010"))
  175. re, im = rootof(x**5 - 5*x + 12, 3).evalf(n=20).as_real_imag()
  176. assert re.epsilon_eq(Float("+1.272897223922499190910"))
  177. assert im.epsilon_eq(Float("-0.719798681483861386681"))
  178. re, im = rootof(x**5 - 5*x + 12, 4).evalf(n=20).as_real_imag()
  179. assert re.epsilon_eq(Float("+1.272897223922499190910"))
  180. assert im.epsilon_eq(Float("+0.719798681483861386681"))
  181. # issue 6393
  182. assert str(rootof(x**5 + 2*x**4 + x**3 - 68719476736, 0).n(3)) == '147.'
  183. eq = (531441*x**11 + 3857868*x**10 + 13730229*x**9 + 32597882*x**8 +
  184. 55077472*x**7 + 60452000*x**6 + 32172064*x**5 - 4383808*x**4 -
  185. 11942912*x**3 - 1506304*x**2 + 1453312*x + 512)
  186. a, b = rootof(eq, 1).n(2).as_real_imag()
  187. c, d = rootof(eq, 2).n(2).as_real_imag()
  188. assert a == c
  189. assert b < d
  190. assert b == -d
  191. # issue 6451
  192. r = rootof(legendre_poly(64, x), 7)
  193. assert r.n(2) == r.n(100).n(2)
  194. # issue 9019
  195. r0 = rootof(x**2 + 1, 0, radicals=False)
  196. r1 = rootof(x**2 + 1, 1, radicals=False)
  197. assert r0.n(4) == Float(-1.0, 4) * I
  198. assert r1.n(4) == Float(1.0, 4) * I
  199. # make sure verification is used in case a max/min traps the "root"
  200. assert str(rootof(4*x**5 + 16*x**3 + 12*x**2 + 7, 0).n(3)) == '-0.976'
  201. # watch out for UnboundLocalError
  202. c = CRootOf(90720*x**6 - 4032*x**4 + 84*x**2 - 1, 0)
  203. assert c._eval_evalf(2) # doesn't fail
  204. # watch out for imaginary parts that don't want to evaluate
  205. assert str(RootOf(x**16 + 32*x**14 + 508*x**12 + 5440*x**10 +
  206. 39510*x**8 + 204320*x**6 + 755548*x**4 + 1434496*x**2 +
  207. 877969, 10).n(2)) == '-3.4*I'
  208. assert abs(RootOf(x**4 + 10*x**2 + 1, 0).n(2)) < 0.4
  209. # check reset and args
  210. r = [RootOf(x**3 + x + 3, i) for i in range(3)]
  211. r[0]._reset()
  212. for ri in r:
  213. i = ri._get_interval()
  214. ri.n(2)
  215. assert i != ri._get_interval()
  216. ri._reset()
  217. assert i == ri._get_interval()
  218. assert i == i.func(*i.args)
  219. def test_issue_24978():
  220. # Irreducible poly with negative leading coeff is normalized
  221. # (factor of -1 is extracted), before being stored as CRootOf.poly.
  222. f = -x**2 + 2
  223. r = CRootOf(f, 0)
  224. assert r.poly.as_expr() == x**2 - 2
  225. # An action that prompts calculation of an interval puts r.poly in
  226. # the cache.
  227. r.n()
  228. assert r.poly in rootoftools._reals_cache
  229. def test_CRootOf_evalf_caching_bug():
  230. r = rootof(x**5 - 5*x + 12, 1)
  231. r.n()
  232. a = r._get_interval()
  233. r = rootof(x**5 - 5*x + 12, 1)
  234. r.n()
  235. b = r._get_interval()
  236. assert a == b
  237. def test_CRootOf_real_roots():
  238. assert Poly(x**5 + x + 1).real_roots() == [rootof(x**3 - x**2 + 1, 0)]
  239. assert Poly(x**5 + x + 1).real_roots(radicals=False) == [rootof(
  240. x**3 - x**2 + 1, 0)]
  241. # https://github.com/sympy/sympy/issues/20902
  242. p = Poly(-3*x**4 - 10*x**3 - 12*x**2 - 6*x - 1, x, domain='ZZ')
  243. assert CRootOf.real_roots(p) == [S(-1), S(-1), S(-1), S(-1)/3]
  244. # with real algebraic coefficients
  245. assert Poly(x**3 + sqrt(2)*x**2 - 1, x, extension=True).real_roots() == [
  246. rootof(x**6 - 2*x**4 - 2*x**3 + 1, 0)
  247. ]
  248. assert Poly(x**5 + sqrt(2) * x**3 - 1, x, extension=True).real_roots() == [
  249. rootof(x**10 - 2*x**6 - 2*x**5 + 1, 0)
  250. ]
  251. r = rootof(y**5 + y**3 - 1, 0)
  252. assert Poly(x**5 + r*x - 1, x, extension=True).real_roots() ==\
  253. [
  254. rootof(x**25 - 5*x**20 + x**17 + 10*x**15 - 3*x**12 -
  255. 10*x**10 + 3*x**7 + 6*x**5 - x**2 - 1, 0)
  256. ]
  257. # roots with multiplicity
  258. assert Poly((x-1) * (x-sqrt(2))**2, x, extension=True).real_roots() ==\
  259. [
  260. S(1), sqrt(2), sqrt(2)
  261. ]
  262. def test_CRootOf_all_roots():
  263. assert Poly(x**5 + x + 1).all_roots() == [
  264. rootof(x**3 - x**2 + 1, 0),
  265. Rational(-1, 2) - sqrt(3)*I/2,
  266. Rational(-1, 2) + sqrt(3)*I/2,
  267. rootof(x**3 - x**2 + 1, 1),
  268. rootof(x**3 - x**2 + 1, 2),
  269. ]
  270. assert Poly(x**5 + x + 1).all_roots(radicals=False) == [
  271. rootof(x**3 - x**2 + 1, 0),
  272. rootof(x**2 + x + 1, 0, radicals=False),
  273. rootof(x**2 + x + 1, 1, radicals=False),
  274. rootof(x**3 - x**2 + 1, 1),
  275. rootof(x**3 - x**2 + 1, 2),
  276. ]
  277. # with real algebraic coefficients
  278. assert Poly(x**3 + sqrt(2)*x**2 - 1, x, extension=True).all_roots() ==\
  279. [
  280. rootof(x**6 - 2*x**4 - 2*x**3 + 1, 0),
  281. rootof(x**6 - 2*x**4 - 2*x**3 + 1, 2),
  282. rootof(x**6 - 2*x**4 - 2*x**3 + 1, 3)
  283. ]
  284. # roots with multiplicity
  285. assert Poly((x-1) * (x-sqrt(2))**2 * (x-I) * (x+I), x, extension=True).all_roots() ==\
  286. [
  287. S(1), sqrt(2), sqrt(2), -I, I
  288. ]
  289. # imaginary algebraic coeffs (gaussian domain)
  290. assert Poly(x**2 - I/2, x, extension=True).all_roots() ==\
  291. [
  292. S(1)/2 + I/2,
  293. -S(1)/2 - I/2
  294. ]
  295. def test_CRootOf_eval_rational():
  296. p = legendre_poly(4, x, polys=True)
  297. roots = [r.eval_rational(n=18) for r in p.real_roots()]
  298. for root in roots:
  299. assert isinstance(root, Rational)
  300. roots = [str(root.n(17)) for root in roots]
  301. assert roots == [
  302. "-0.86113631159405258",
  303. "-0.33998104358485626",
  304. "0.33998104358485626",
  305. "0.86113631159405258",
  306. ]
  307. def test_CRootOf_lazy():
  308. # irreducible poly with both real and complex roots:
  309. f = Poly(x**3 + 2*x + 2)
  310. # real root:
  311. CRootOf.clear_cache()
  312. r = CRootOf(f, 0)
  313. # Not yet in cache, after construction:
  314. assert r.poly not in rootoftools._reals_cache
  315. assert r.poly not in rootoftools._complexes_cache
  316. r.evalf()
  317. # In cache after evaluation:
  318. assert r.poly in rootoftools._reals_cache
  319. assert r.poly not in rootoftools._complexes_cache
  320. # complex root:
  321. CRootOf.clear_cache()
  322. r = CRootOf(f, 1)
  323. # Not yet in cache, after construction:
  324. assert r.poly not in rootoftools._reals_cache
  325. assert r.poly not in rootoftools._complexes_cache
  326. r.evalf()
  327. # In cache after evaluation:
  328. assert r.poly in rootoftools._reals_cache
  329. assert r.poly in rootoftools._complexes_cache
  330. # composite poly with both real and complex roots:
  331. f = Poly((x**2 - 2)*(x**2 + 1))
  332. # real root:
  333. CRootOf.clear_cache()
  334. r = CRootOf(f, 0)
  335. # In cache immediately after construction:
  336. assert r.poly in rootoftools._reals_cache
  337. assert r.poly not in rootoftools._complexes_cache
  338. # complex root:
  339. CRootOf.clear_cache()
  340. r = CRootOf(f, 2)
  341. # In cache immediately after construction:
  342. assert r.poly in rootoftools._reals_cache
  343. assert r.poly in rootoftools._complexes_cache
  344. def test_RootSum___new__():
  345. f = x**3 + x + 3
  346. g = Lambda(r, log(r*x))
  347. s = RootSum(f, g)
  348. assert isinstance(s, RootSum) is True
  349. assert RootSum(f**2, g) == 2*RootSum(f, g)
  350. assert RootSum((x - 7)*f**3, g) == log(7*x) + 3*RootSum(f, g)
  351. # issue 5571
  352. assert hash(RootSum((x - 7)*f**3, g)) == hash(log(7*x) + 3*RootSum(f, g))
  353. raises(MultivariatePolynomialError, lambda: RootSum(x**3 + x + y))
  354. raises(ValueError, lambda: RootSum(x**2 + 3, lambda x: x))
  355. assert RootSum(f, exp) == RootSum(f, Lambda(x, exp(x)))
  356. assert RootSum(f, log) == RootSum(f, Lambda(x, log(x)))
  357. assert isinstance(RootSum(f, auto=False), RootSum) is True
  358. assert RootSum(f) == 0
  359. assert RootSum(f, Lambda(x, x)) == 0
  360. assert RootSum(f, Lambda(x, x**2)) == -2
  361. assert RootSum(f, Lambda(x, 1)) == 3
  362. assert RootSum(f, Lambda(x, 2)) == 6
  363. assert RootSum(f, auto=False).is_commutative is True
  364. assert RootSum(f, Lambda(x, 1/(x + x**2))) == Rational(11, 3)
  365. assert RootSum(f, Lambda(x, y/(x + x**2))) == Rational(11, 3)*y
  366. assert RootSum(x**2 - 1, Lambda(x, 3*x**2), x) == 6
  367. assert RootSum(x**2 - y, Lambda(x, 3*x**2), x) == 6*y
  368. assert RootSum(x**2 - 1, Lambda(x, z*x**2), x) == 2*z
  369. assert RootSum(x**2 - y, Lambda(x, z*x**2), x) == 2*z*y
  370. assert RootSum(
  371. x**2 - 1, Lambda(x, exp(x)), quadratic=True) == exp(-1) + exp(1)
  372. assert RootSum(x**3 + a*x + a**3, tan, x) == \
  373. RootSum(x**3 + x + 1, Lambda(x, tan(a*x)))
  374. assert RootSum(a**3*x**3 + a*x + 1, tan, x) == \
  375. RootSum(x**3 + x + 1, Lambda(x, tan(x/a)))
  376. def test_RootSum_free_symbols():
  377. assert RootSum(x**3 + x + 3, Lambda(r, exp(r))).free_symbols == set()
  378. assert RootSum(x**3 + x + 3, Lambda(r, exp(a*r))).free_symbols == {a}
  379. assert RootSum(
  380. x**3 + x + y, Lambda(r, exp(a*r)), x).free_symbols == {a, y}
  381. def test_RootSum___eq__():
  382. f = Lambda(x, exp(x))
  383. assert (RootSum(x**3 + x + 1, f) == RootSum(x**3 + x + 1, f)) is True
  384. assert (RootSum(x**3 + x + 1, f) == RootSum(y**3 + y + 1, f)) is True
  385. assert (RootSum(x**3 + x + 1, f) == RootSum(x**3 + x + 2, f)) is False
  386. assert (RootSum(x**3 + x + 1, f) == RootSum(y**3 + y + 2, f)) is False
  387. def test_RootSum_doit():
  388. rs = RootSum(x**2 + 1, exp)
  389. assert isinstance(rs, RootSum) is True
  390. assert rs.doit() == exp(-I) + exp(I)
  391. rs = RootSum(x**2 + a, exp, x)
  392. assert isinstance(rs, RootSum) is True
  393. assert rs.doit() == exp(-sqrt(-a)) + exp(sqrt(-a))
  394. def test_RootSum_evalf():
  395. rs = RootSum(x**2 + 1, exp)
  396. assert rs.evalf(n=20, chop=True).epsilon_eq(Float("1.0806046117362794348"))
  397. assert rs.evalf(n=15, chop=True).epsilon_eq(Float("1.08060461173628"))
  398. rs = RootSum(x**2 + a, exp, x)
  399. assert rs.evalf() == rs
  400. def test_RootSum_diff():
  401. f = x**3 + x + 3
  402. g = Lambda(r, exp(r*x))
  403. h = Lambda(r, r*exp(r*x))
  404. assert RootSum(f, g).diff(x) == RootSum(f, h)
  405. def test_RootSum_subs():
  406. f = x**3 + x + 3
  407. g = Lambda(r, exp(r*x))
  408. F = y**3 + y + 3
  409. G = Lambda(r, exp(r*y))
  410. assert RootSum(f, g).subs(y, 1) == RootSum(f, g)
  411. assert RootSum(f, g).subs(x, y) == RootSum(F, G)
  412. def test_RootSum_rational():
  413. assert RootSum(
  414. z**5 - z + 1, Lambda(z, z/(x - z))) == (4*x - 5)/(x**5 - x + 1)
  415. f = 161*z**3 + 115*z**2 + 19*z + 1
  416. g = Lambda(z, z*log(
  417. -3381*z**4/4 - 3381*z**3/4 - 625*z**2/2 - z*Rational(125, 2) - 5 + exp(x)))
  418. assert RootSum(f, g).diff(x) == -(
  419. (5*exp(2*x) - 6*exp(x) + 4)*exp(x)/(exp(3*x) - exp(2*x) + 1))/7
  420. def test_RootSum_independent():
  421. f = (x**3 - a)**2*(x**4 - b)**3
  422. g = Lambda(x, 5*tan(x) + 7)
  423. h = Lambda(x, tan(x))
  424. r0 = RootSum(x**3 - a, h, x)
  425. r1 = RootSum(x**4 - b, h, x)
  426. assert RootSum(f, g, x).as_ordered_terms() == [10*r0, 15*r1, 126]
  427. def test_issue_7876():
  428. l1 = Poly(x**6 - x + 1, x).all_roots()
  429. l2 = [rootof(x**6 - x + 1, i) for i in range(6)]
  430. assert frozenset(l1) == frozenset(l2)
  431. def test_issue_8316():
  432. f = Poly(7*x**8 - 9)
  433. assert len(f.all_roots()) == 8
  434. f = Poly(7*x**8 - 10)
  435. assert len(f.all_roots()) == 8
  436. def test__imag_count():
  437. from sympy.polys.rootoftools import _imag_count_of_factor
  438. def imag_count(p):
  439. return sum(_imag_count_of_factor(f)*m for f, m in
  440. p.factor_list()[1])
  441. assert imag_count(Poly(x**6 + 10*x**2 + 1)) == 2
  442. assert imag_count(Poly(x**2)) == 0
  443. assert imag_count(Poly([1]*3 + [-1], x)) == 0
  444. assert imag_count(Poly(x**3 + 1)) == 0
  445. assert imag_count(Poly(x**2 + 1)) == 2
  446. assert imag_count(Poly(x**2 - 1)) == 0
  447. assert imag_count(Poly(x**4 - 1)) == 2
  448. assert imag_count(Poly(x**4 + 1)) == 0
  449. assert imag_count(Poly([1, 2, 3], x)) == 0
  450. assert imag_count(Poly(x**3 + x + 1)) == 0
  451. assert imag_count(Poly(x**4 + x + 1)) == 0
  452. def q(r1, r2, p):
  453. return Poly(((x - r1)*(x - r2)).subs(x, x**p), x)
  454. assert imag_count(q(-1, -2, 2)) == 4
  455. assert imag_count(q(-1, 2, 2)) == 2
  456. assert imag_count(q(1, 2, 2)) == 0
  457. assert imag_count(q(1, 2, 4)) == 4
  458. assert imag_count(q(-1, 2, 4)) == 2
  459. assert imag_count(q(-1, -2, 4)) == 0
  460. def test_RootOf_is_imaginary():
  461. r = RootOf(x**4 + 4*x**2 + 1, 1)
  462. i = r._get_interval()
  463. assert r.is_imaginary and i.ax*i.bx <= 0
  464. def test_is_disjoint():
  465. eq = x**3 + 5*x + 1
  466. ir = rootof(eq, 0)._get_interval()
  467. ii = rootof(eq, 1)._get_interval()
  468. assert ir.is_disjoint(ii)
  469. assert ii.is_disjoint(ir)
  470. def test_pure_key_dict():
  471. p = D()
  472. assert (x in p) is False
  473. assert (1 in p) is False
  474. p[x] = 1
  475. assert x in p
  476. assert y in p
  477. assert p[y] == 1
  478. raises(KeyError, lambda: p[1])
  479. def dont(k):
  480. p[k] = 2
  481. raises(ValueError, lambda: dont(1))
  482. @slow
  483. def test_eval_approx_relative():
  484. CRootOf.clear_cache()
  485. t = [CRootOf(x**3 + 10*x + 1, i) for i in range(3)]
  486. assert [i.eval_rational(1e-1) for i in t] == [
  487. Rational(-21, 220), Rational(15, 256) - I*805/256,
  488. Rational(15, 256) + I*805/256]
  489. t[0]._reset()
  490. assert [i.eval_rational(1e-1, 1e-4) for i in t] == [
  491. Rational(-21, 220), Rational(3275, 65536) - I*414645/131072,
  492. Rational(3275, 65536) + I*414645/131072]
  493. assert S(t[0]._get_interval().dx) < 1e-1
  494. assert S(t[1]._get_interval().dx) < 1e-1
  495. assert S(t[1]._get_interval().dy) < 1e-4
  496. assert S(t[2]._get_interval().dx) < 1e-1
  497. assert S(t[2]._get_interval().dy) < 1e-4
  498. t[0]._reset()
  499. assert [i.eval_rational(1e-4, 1e-4) for i in t] == [
  500. Rational(-2001, 20020), Rational(6545, 131072) - I*414645/131072,
  501. Rational(6545, 131072) + I*414645/131072]
  502. assert S(t[0]._get_interval().dx) < 1e-4
  503. assert S(t[1]._get_interval().dx) < 1e-4
  504. assert S(t[1]._get_interval().dy) < 1e-4
  505. assert S(t[2]._get_interval().dx) < 1e-4
  506. assert S(t[2]._get_interval().dy) < 1e-4
  507. # in the following, the actual relative precision is
  508. # less than tested, but it should never be greater
  509. t[0]._reset()
  510. assert [i.eval_rational(n=2) for i in t] == [
  511. Rational(-202201, 2024022), Rational(104755, 2097152) - I*6634255/2097152,
  512. Rational(104755, 2097152) + I*6634255/2097152]
  513. assert abs(S(t[0]._get_interval().dx)/t[0]) < 1e-2
  514. assert abs(S(t[1]._get_interval().dx)/t[1]).n() < 1e-2
  515. assert abs(S(t[1]._get_interval().dy)/t[1]).n() < 1e-2
  516. assert abs(S(t[2]._get_interval().dx)/t[2]).n() < 1e-2
  517. assert abs(S(t[2]._get_interval().dy)/t[2]).n() < 1e-2
  518. t[0]._reset()
  519. assert [i.eval_rational(n=3) for i in t] == [
  520. Rational(-202201, 2024022), Rational(1676045, 33554432) - I*106148135/33554432,
  521. Rational(1676045, 33554432) + I*106148135/33554432]
  522. assert abs(S(t[0]._get_interval().dx)/t[0]) < 1e-3
  523. assert abs(S(t[1]._get_interval().dx)/t[1]).n() < 1e-3
  524. assert abs(S(t[1]._get_interval().dy)/t[1]).n() < 1e-3
  525. assert abs(S(t[2]._get_interval().dx)/t[2]).n() < 1e-3
  526. assert abs(S(t[2]._get_interval().dy)/t[2]).n() < 1e-3
  527. t[0]._reset()
  528. a = [i.eval_approx(2) for i in t]
  529. assert [str(i) for i in a] == [
  530. '-0.10', '0.05 - 3.2*I', '0.05 + 3.2*I']
  531. assert all(abs(((a[i] - t[i])/t[i]).n()) < 1e-2 for i in range(len(a)))
  532. def test_issue_15920():
  533. r = rootof(x**5 - x + 1, 0)
  534. p = Integral(x, (x, 1, y))
  535. assert unchanged(Eq, r, p)
  536. def test_issue_19113():
  537. eq = y**3 - y + 1
  538. # generator is a canonical x in RootOf
  539. assert str(Poly(eq).real_roots()) == '[CRootOf(x**3 - x + 1, 0)]'
  540. assert str(Poly(eq.subs(y, tan(y))).real_roots()
  541. ) == '[CRootOf(x**3 - x + 1, 0)]'
  542. assert str(Poly(eq.subs(y, tan(x))).real_roots()
  543. ) == '[CRootOf(x**3 - x + 1, 0)]'