图片解析应用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

322 lines
16 KiB

  1. """Most of these tests come from the examples in Bronstein's book."""
  2. from sympy.integrals.risch import DifferentialExtension, derivation
  3. from sympy.integrals.prde import (prde_normal_denom, prde_special_denom,
  4. prde_linear_constraints, constant_system, prde_spde, prde_no_cancel_b_large,
  5. prde_no_cancel_b_small, limited_integrate_reduce, limited_integrate,
  6. is_deriv_k, is_log_deriv_k_t_radical, parametric_log_deriv_heu,
  7. is_log_deriv_k_t_radical_in_field, param_poly_rischDE, param_rischDE,
  8. prde_cancel_liouvillian)
  9. from sympy.polys.polymatrix import PolyMatrix as Matrix
  10. from sympy.core.numbers import Rational
  11. from sympy.core.singleton import S
  12. from sympy.core.symbol import symbols
  13. from sympy.polys.domains.rationalfield import QQ
  14. from sympy.polys.polytools import Poly
  15. from sympy.abc import x, t, n
  16. t0, t1, t2, t3, k = symbols('t:4 k')
  17. def test_prde_normal_denom():
  18. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]})
  19. fa = Poly(1, t)
  20. fd = Poly(x, t)
  21. G = [(Poly(t, t), Poly(1 + t**2, t)), (Poly(1, t), Poly(x + x*t**2, t))]
  22. assert prde_normal_denom(fa, fd, G, DE) == \
  23. (Poly(x, t, domain='ZZ(x)'), (Poly(1, t, domain='ZZ(x)'), Poly(1, t,
  24. domain='ZZ(x)')), [(Poly(x*t, t, domain='ZZ(x)'),
  25. Poly(t**2 + 1, t, domain='ZZ(x)')), (Poly(1, t, domain='ZZ(x)'),
  26. Poly(t**2 + 1, t, domain='ZZ(x)'))], Poly(1, t, domain='ZZ(x)'))
  27. G = [(Poly(t, t), Poly(t**2 + 2*t + 1, t)), (Poly(x*t, t),
  28. Poly(t**2 + 2*t + 1, t)), (Poly(x*t**2, t), Poly(t**2 + 2*t + 1, t))]
  29. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
  30. assert prde_normal_denom(Poly(x, t), Poly(1, t), G, DE) == \
  31. (Poly(t + 1, t), (Poly((-1 + x)*t + x, t), Poly(1, t, domain='ZZ[x]')), [(Poly(t, t),
  32. Poly(1, t)), (Poly(x*t, t), Poly(1, t, domain='ZZ[x]')), (Poly(x*t**2, t),
  33. Poly(1, t, domain='ZZ[x]'))], Poly(t + 1, t))
  34. def test_prde_special_denom():
  35. a = Poly(t + 1, t)
  36. ba = Poly(t**2, t)
  37. bd = Poly(1, t)
  38. G = [(Poly(t, t), Poly(1, t)), (Poly(t**2, t), Poly(1, t)), (Poly(t**3, t), Poly(1, t))]
  39. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
  40. assert prde_special_denom(a, ba, bd, G, DE) == \
  41. (Poly(t + 1, t), Poly(t**2, t), [(Poly(t, t), Poly(1, t)),
  42. (Poly(t**2, t), Poly(1, t)), (Poly(t**3, t), Poly(1, t))], Poly(1, t))
  43. G = [(Poly(t, t), Poly(1, t)), (Poly(1, t), Poly(t, t))]
  44. assert prde_special_denom(Poly(1, t), Poly(t**2, t), Poly(1, t), G, DE) == \
  45. (Poly(1, t), Poly(t**2 - 1, t), [(Poly(t**2, t), Poly(1, t)),
  46. (Poly(1, t), Poly(1, t))], Poly(t, t))
  47. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-2*x*t0, t0)]})
  48. DE.decrement_level()
  49. G = [(Poly(t, t), Poly(t**2, t)), (Poly(2*t, t), Poly(t, t))]
  50. assert prde_special_denom(Poly(5*x*t + 1, t), Poly(t**2 + 2*x**3*t, t), Poly(t**3 + 2, t), G, DE) == \
  51. (Poly(5*x*t + 1, t), Poly(0, t, domain='ZZ[x]'), [(Poly(t, t), Poly(t**2, t)),
  52. (Poly(2*t, t), Poly(t, t))], Poly(1, x))
  53. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly((t**2 + 1)*2*x, t)]})
  54. G = [(Poly(t + x, t), Poly(t*x, t)), (Poly(2*t, t), Poly(x**2, x))]
  55. assert prde_special_denom(Poly(5*x*t + 1, t), Poly(t**2 + 2*x**3*t, t), Poly(t**3, t), G, DE) == \
  56. (Poly(5*x*t + 1, t), Poly(0, t, domain='ZZ[x]'), [(Poly(t + x, t), Poly(x*t, t)),
  57. (Poly(2*t, t, x), Poly(x**2, t, x))], Poly(1, t))
  58. assert prde_special_denom(Poly(t + 1, t), Poly(t**2, t), Poly(t**3, t), G, DE) == \
  59. (Poly(t + 1, t), Poly(0, t, domain='ZZ[x]'), [(Poly(t + x, t), Poly(x*t, t)), (Poly(2*t, t, x),
  60. Poly(x**2, t, x))], Poly(1, t))
  61. def test_prde_linear_constraints():
  62. DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
  63. G = [(Poly(2*x**3 + 3*x + 1, x), Poly(x**2 - 1, x)), (Poly(1, x), Poly(x - 1, x)),
  64. (Poly(1, x), Poly(x + 1, x))]
  65. assert prde_linear_constraints(Poly(1, x), Poly(0, x), G, DE) == \
  66. ((Poly(2*x, x, domain='QQ'), Poly(0, x, domain='QQ'), Poly(0, x, domain='QQ')),
  67. Matrix([[1, 1, -1], [5, 1, 1]], x))
  68. G = [(Poly(t, t), Poly(1, t)), (Poly(t**2, t), Poly(1, t)), (Poly(t**3, t), Poly(1, t))]
  69. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
  70. assert prde_linear_constraints(Poly(t + 1, t), Poly(t**2, t), G, DE) == \
  71. ((Poly(t, t, domain='QQ'), Poly(t**2, t, domain='QQ'), Poly(t**3, t, domain='QQ')),
  72. Matrix(0, 3, [], t))
  73. G = [(Poly(2*x, t), Poly(t, t)), (Poly(-x, t), Poly(t, t))]
  74. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
  75. assert prde_linear_constraints(Poly(1, t), Poly(0, t), G, DE) == \
  76. ((Poly(0, t, domain='QQ[x]'), Poly(0, t, domain='QQ[x]')), Matrix([[2*x, -x]], t))
  77. def test_constant_system():
  78. A = Matrix([[-(x + 3)/(x - 1), (x + 1)/(x - 1), 1],
  79. [-x - 3, x + 1, x - 1],
  80. [2*(x + 3)/(x - 1), 0, 0]], t)
  81. u = Matrix([[(x + 1)/(x - 1)], [x + 1], [0]], t)
  82. DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
  83. R = QQ.frac_field(x)[t]
  84. assert constant_system(A, u, DE) == \
  85. (Matrix([[1, 0, 0],
  86. [0, 1, 0],
  87. [0, 0, 0],
  88. [0, 0, 1]], ring=R), Matrix([0, 1, 0, 0], ring=R))
  89. def test_prde_spde():
  90. D = [Poly(x, t), Poly(-x*t, t)]
  91. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
  92. # TODO: when bound_degree() can handle this, test degree bound from that too
  93. assert prde_spde(Poly(t, t), Poly(-1/x, t), D, n, DE) == \
  94. (Poly(t, t), Poly(0, t, domain='ZZ(x)'),
  95. [Poly(2*x, t, domain='ZZ(x)'), Poly(-x, t, domain='ZZ(x)')],
  96. [Poly(-x**2, t, domain='ZZ(x)'), Poly(0, t, domain='ZZ(x)')], n - 1)
  97. def test_prde_no_cancel():
  98. # b large
  99. DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
  100. assert prde_no_cancel_b_large(Poly(1, x), [Poly(x**2, x), Poly(1, x)], 2, DE) == \
  101. ([Poly(x**2 - 2*x + 2, x), Poly(1, x)], Matrix([[1, 0, -1, 0],
  102. [0, 1, 0, -1]], x))
  103. assert prde_no_cancel_b_large(Poly(1, x), [Poly(x**3, x), Poly(1, x)], 3, DE) == \
  104. ([Poly(x**3 - 3*x**2 + 6*x - 6, x), Poly(1, x)], Matrix([[1, 0, -1, 0],
  105. [0, 1, 0, -1]], x))
  106. assert prde_no_cancel_b_large(Poly(x, x), [Poly(x**2, x), Poly(1, x)], 1, DE) == \
  107. ([Poly(x, x, domain='ZZ'), Poly(0, x, domain='ZZ')], Matrix([[1, -1, 0, 0],
  108. [1, 0, -1, 0],
  109. [0, 1, 0, -1]], x))
  110. # b small
  111. # XXX: Is there a better example of a monomial with D.degree() > 2?
  112. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**3 + 1, t)]})
  113. # My original q was t**4 + t + 1, but this solution implies q == t**4
  114. # (c1 = 4), with some of the ci for the original q equal to 0.
  115. G = [Poly(t**6, t), Poly(x*t**5, t), Poly(t**3, t), Poly(x*t**2, t), Poly(1 + x, t)]
  116. R = QQ.frac_field(x)[t]
  117. assert prde_no_cancel_b_small(Poly(x*t, t), G, 4, DE) == \
  118. ([Poly(t**4/4 - x/12*t**3 + x**2/24*t**2 + (Rational(-11, 12) - x**3/24)*t + x/24, t),
  119. Poly(x/3*t**3 - x**2/6*t**2 + (Rational(-1, 3) + x**3/6)*t - x/6, t), Poly(t, t),
  120. Poly(0, t), Poly(0, t)], Matrix([[1, 0, -1, 0, 0, 0, 0, 0, 0, 0],
  121. [0, 1, Rational(-1, 4), 0, 0, 0, 0, 0, 0, 0],
  122. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  123. [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
  124. [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
  125. [1, 0, 0, 0, 0, -1, 0, 0, 0, 0],
  126. [0, 1, 0, 0, 0, 0, -1, 0, 0, 0],
  127. [0, 0, 1, 0, 0, 0, 0, -1, 0, 0],
  128. [0, 0, 0, 1, 0, 0, 0, 0, -1, 0],
  129. [0, 0, 0, 0, 1, 0, 0, 0, 0, -1]], ring=R))
  130. # TODO: Add test for deg(b) <= 0 with b small
  131. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]})
  132. b = Poly(-1/x**2, t, field=True) # deg(b) == 0
  133. q = [Poly(x**i*t**j, t, field=True) for i in range(2) for j in range(3)]
  134. h, A = prde_no_cancel_b_small(b, q, 3, DE)
  135. V = A.nullspace()
  136. R = QQ.frac_field(x)[t]
  137. assert len(V) == 1
  138. assert V[0] == Matrix([Rational(-1, 2), 0, 0, 1, 0, 0]*3, ring=R)
  139. assert (Matrix([h])*V[0][6:, :])[0] == Poly(x**2/2, t, domain='QQ(x)')
  140. assert (Matrix([q])*V[0][:6, :])[0] == Poly(x - S.Half, t, domain='QQ(x)')
  141. def test_prde_cancel_liouvillian():
  142. ### 1. case == 'primitive'
  143. # used when integrating f = log(x) - log(x - 1)
  144. # Not taken from 'the' book
  145. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
  146. p0 = Poly(0, t, field=True)
  147. p1 = Poly((x - 1)*t, t, domain='ZZ(x)')
  148. p2 = Poly(x - 1, t, domain='ZZ(x)')
  149. p3 = Poly(-x**2 + x, t, domain='ZZ(x)')
  150. h, A = prde_cancel_liouvillian(Poly(-1/(x - 1), t), [Poly(-x + 1, t), Poly(1, t)], 1, DE)
  151. V = A.nullspace()
  152. assert h == [p0, p0, p1, p0, p0, p0, p0, p0, p0, p0, p2, p3, p0, p0, p0, p0]
  153. assert A.rank() == 16
  154. assert (Matrix([h])*V[0][:16, :]) == Matrix([[Poly(0, t, domain='QQ(x)')]])
  155. ### 2. case == 'exp'
  156. # used when integrating log(x/exp(x) + 1)
  157. # Not taken from book
  158. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t, t)]})
  159. assert prde_cancel_liouvillian(Poly(0, t, domain='QQ[x]'), [Poly(1, t, domain='QQ(x)')], 0, DE) == \
  160. ([Poly(1, t, domain='QQ'), Poly(x, t, domain='ZZ(x)')], Matrix([[-1, 0, 1]], DE.t))
  161. def test_param_poly_rischDE():
  162. DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
  163. a = Poly(x**2 - x, x, field=True)
  164. b = Poly(1, x, field=True)
  165. q = [Poly(x, x, field=True), Poly(x**2, x, field=True)]
  166. h, A = param_poly_rischDE(a, b, q, 3, DE)
  167. assert A.nullspace() == [Matrix([0, 1, 1, 1], DE.t)] # c1, c2, d1, d2
  168. # Solution of a*Dp + b*p = c1*q1 + c2*q2 = q2 = x**2
  169. # is d1*h1 + d2*h2 = h1 + h2 = x.
  170. assert h[0] + h[1] == Poly(x, x, domain='QQ')
  171. # a*Dp + b*p = q1 = x has no solution.
  172. a = Poly(x**2 - x, x, field=True)
  173. b = Poly(x**2 - 5*x + 3, x, field=True)
  174. q = [Poly(1, x, field=True), Poly(x, x, field=True),
  175. Poly(x**2, x, field=True)]
  176. h, A = param_poly_rischDE(a, b, q, 3, DE)
  177. assert A.nullspace() == [Matrix([3, -5, 1, -5, 1, 1], DE.t)]
  178. p = -Poly(5, DE.t)*h[0] + h[1] + h[2] # Poly(1, x)
  179. assert a*derivation(p, DE) + b*p == Poly(x**2 - 5*x + 3, x, domain='QQ')
  180. def test_param_rischDE():
  181. DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
  182. p1, px = Poly(1, x, field=True), Poly(x, x, field=True)
  183. G = [(p1, px), (p1, p1), (px, p1)] # [1/x, 1, x]
  184. h, A = param_rischDE(-p1, Poly(x**2, x, field=True), G, DE)
  185. assert len(h) == 3
  186. p = [hi[0].as_expr()/hi[1].as_expr() for hi in h]
  187. V = A.nullspace()
  188. assert len(V) == 2
  189. assert V[0] == Matrix([-1, 1, 0, -1, 1, 0], DE.t)
  190. y = -p[0] + p[1] + 0*p[2] # x
  191. assert y.diff(x) - y/x**2 == 1 - 1/x # Dy + f*y == -G0 + G1 + 0*G2
  192. # the below test computation takes place while computing the integral
  193. # of 'f = log(log(x + exp(x)))'
  194. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
  195. G = [(Poly(t + x, t, domain='ZZ(x)'), Poly(1, t, domain='QQ')), (Poly(0, t, domain='QQ'), Poly(1, t, domain='QQ'))]
  196. h, A = param_rischDE(Poly(-t - 1, t, field=True), Poly(t + x, t, field=True), G, DE)
  197. assert len(h) == 5
  198. p = [hi[0].as_expr()/hi[1].as_expr() for hi in h]
  199. V = A.nullspace()
  200. assert len(V) == 3
  201. assert V[0] == Matrix([0, 0, 0, 0, 1, 0, 0], DE.t)
  202. y = 0*p[0] + 0*p[1] + 1*p[2] + 0*p[3] + 0*p[4]
  203. assert y.diff(t) - y/(t + x) == 0 # Dy + f*y = 0*G0 + 0*G1
  204. def test_limited_integrate_reduce():
  205. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
  206. assert limited_integrate_reduce(Poly(x, t), Poly(t**2, t), [(Poly(x, t),
  207. Poly(t, t))], DE) == \
  208. (Poly(t, t), Poly(-1/x, t), Poly(t, t), 1, (Poly(x, t), Poly(1, t, domain='ZZ[x]')),
  209. [(Poly(-x*t, t), Poly(1, t, domain='ZZ[x]'))])
  210. def test_limited_integrate():
  211. DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
  212. G = [(Poly(x, x), Poly(x + 1, x))]
  213. assert limited_integrate(Poly(-(1 + x + 5*x**2 - 3*x**3), x),
  214. Poly(1 - x - x**2 + x**3, x), G, DE) == \
  215. ((Poly(x**2 - x + 2, x), Poly(x - 1, x, domain='QQ')), [2])
  216. G = [(Poly(1, x), Poly(x, x))]
  217. assert limited_integrate(Poly(5*x**2, x), Poly(3, x), G, DE) == \
  218. ((Poly(5*x**3/9, x), Poly(1, x, domain='QQ')), [0])
  219. def test_is_log_deriv_k_t_radical():
  220. DE = DifferentialExtension(extension={'D': [Poly(1, x)], 'exts': [None],
  221. 'extargs': [None]})
  222. assert is_log_deriv_k_t_radical(Poly(2*x, x), Poly(1, x), DE) is None
  223. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2*t1, t1), Poly(1/x, t2)],
  224. 'exts': [None, 'exp', 'log'], 'extargs': [None, 2*x, x]})
  225. assert is_log_deriv_k_t_radical(Poly(x + t2/2, t2), Poly(1, t2), DE) == \
  226. ([(t1, 1), (x, 1)], t1*x, 2, 0)
  227. # TODO: Add more tests
  228. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t0, t0), Poly(1/x, t)],
  229. 'exts': [None, 'exp', 'log'], 'extargs': [None, x, x]})
  230. assert is_log_deriv_k_t_radical(Poly(x + t/2 + 3, t), Poly(1, t), DE) == \
  231. ([(t0, 2), (x, 1)], x*t0**2, 2, 3)
  232. def test_is_deriv_k():
  233. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(1/(x + 1), t2)],
  234. 'exts': [None, 'log', 'log'], 'extargs': [None, x, x + 1]})
  235. assert is_deriv_k(Poly(2*x**2 + 2*x, t2), Poly(1, t2), DE) == \
  236. ([(t1, 1), (t2, 1)], t1 + t2, 2)
  237. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(t2, t2)],
  238. 'exts': [None, 'log', 'exp'], 'extargs': [None, x, x]})
  239. assert is_deriv_k(Poly(x**2*t2**3, t2), Poly(1, t2), DE) == \
  240. ([(x, 3), (t1, 2)], 2*t1 + 3*x, 1)
  241. # TODO: Add more tests, including ones with exponentials
  242. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2/x, t1)],
  243. 'exts': [None, 'log'], 'extargs': [None, x**2]})
  244. assert is_deriv_k(Poly(x, t1), Poly(1, t1), DE) == \
  245. ([(t1, S.Half)], t1/2, 1)
  246. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2/(1 + x), t0)],
  247. 'exts': [None, 'log'], 'extargs': [None, x**2 + 2*x + 1]})
  248. assert is_deriv_k(Poly(1 + x, t0), Poly(1, t0), DE) == \
  249. ([(t0, S.Half)], t0/2, 1)
  250. # Issue 10798
  251. # DE = DifferentialExtension(log(1/x), x)
  252. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-1/x, t)],
  253. 'exts': [None, 'log'], 'extargs': [None, 1/x]})
  254. assert is_deriv_k(Poly(1, t), Poly(x, t), DE) == ([(t, 1)], t, 1)
  255. def test_is_log_deriv_k_t_radical_in_field():
  256. # NOTE: any potential constant factor in the second element of the result
  257. # doesn't matter, because it cancels in Da/a.
  258. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
  259. assert is_log_deriv_k_t_radical_in_field(Poly(5*t + 1, t), Poly(2*t*x, t), DE) == \
  260. (2, t*x**5)
  261. assert is_log_deriv_k_t_radical_in_field(Poly(2 + 3*t, t), Poly(5*x*t, t), DE) == \
  262. (5, x**3*t**2)
  263. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t/x**2, t)]})
  264. assert is_log_deriv_k_t_radical_in_field(Poly(-(1 + 2*t), t),
  265. Poly(2*x**2 + 2*x**2*t, t), DE) == \
  266. (2, t + t**2)
  267. assert is_log_deriv_k_t_radical_in_field(Poly(-1, t), Poly(x**2, t), DE) == \
  268. (1, t)
  269. assert is_log_deriv_k_t_radical_in_field(Poly(1, t), Poly(2*x**2, t), DE) == \
  270. (2, 1/t)
  271. def test_parametric_log_deriv():
  272. DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
  273. assert parametric_log_deriv_heu(Poly(5*t**2 + t - 6, t), Poly(2*x*t**2, t),
  274. Poly(-1, t), Poly(x*t**2, t), DE) == \
  275. (2, 6, t*x**5)