图片解析应用
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.

109 lines
2.7 KiB

  1. """Numerical Methods for Holonomic Functions"""
  2. from sympy.core.sympify import sympify
  3. from sympy.holonomic.holonomic import DMFsubs
  4. from mpmath import mp
  5. def _evalf(func, points, derivatives=False, method='RK4'):
  6. """
  7. Numerical methods for numerical integration along a given set of
  8. points in the complex plane.
  9. """
  10. ann = func.annihilator
  11. a = ann.order
  12. R = ann.parent.base
  13. K = R.get_field()
  14. if method == 'Euler':
  15. meth = _euler
  16. else:
  17. meth = _rk4
  18. dmf = []
  19. for j in ann.listofpoly:
  20. dmf.append(K.new(j.rep))
  21. red = [-dmf[i] / dmf[a] for i in range(a)]
  22. y0 = func.y0
  23. if len(y0) < a:
  24. raise TypeError("Not Enough Initial Conditions")
  25. x0 = func.x0
  26. sol = [meth(red, x0, points[0], y0, a)]
  27. for i, j in enumerate(points[1:]):
  28. sol.append(meth(red, points[i], j, sol[-1], a))
  29. if not derivatives:
  30. return [sympify(i[0]) for i in sol]
  31. else:
  32. return sympify(sol)
  33. def _euler(red, x0, x1, y0, a):
  34. """
  35. Euler's method for numerical integration.
  36. From x0 to x1 with initial values given at x0 as vector y0.
  37. """
  38. A = sympify(x0)._to_mpmath(mp.prec)
  39. B = sympify(x1)._to_mpmath(mp.prec)
  40. y_0 = [sympify(i)._to_mpmath(mp.prec) for i in y0]
  41. h = B - A
  42. f_0 = y_0[1:]
  43. f_0_n = 0
  44. for i in range(a):
  45. f_0_n += sympify(DMFsubs(red[i], A, mpm=True))._to_mpmath(mp.prec) * y_0[i]
  46. f_0.append(f_0_n)
  47. sol = []
  48. for i in range(a):
  49. sol.append(y_0[i] + h * f_0[i])
  50. return sol
  51. def _rk4(red, x0, x1, y0, a):
  52. """
  53. Runge-Kutta 4th order numerical method.
  54. """
  55. A = sympify(x0)._to_mpmath(mp.prec)
  56. B = sympify(x1)._to_mpmath(mp.prec)
  57. y_0 = [sympify(i)._to_mpmath(mp.prec) for i in y0]
  58. h = B - A
  59. f_0_n = 0
  60. f_1_n = 0
  61. f_2_n = 0
  62. f_3_n = 0
  63. f_0 = y_0[1:]
  64. for i in range(a):
  65. f_0_n += sympify(DMFsubs(red[i], A, mpm=True))._to_mpmath(mp.prec) * y_0[i]
  66. f_0.append(f_0_n)
  67. f_1 = [y_0[i] + f_0[i]*h/2 for i in range(1, a)]
  68. for i in range(a):
  69. f_1_n += sympify(DMFsubs(red[i], A + h/2, mpm=True))._to_mpmath(mp.prec) * (y_0[i] + f_0[i]*h/2)
  70. f_1.append(f_1_n)
  71. f_2 = [y_0[i] + f_1[i]*h/2 for i in range(1, a)]
  72. for i in range(a):
  73. f_2_n += sympify(DMFsubs(red[i], A + h/2, mpm=True))._to_mpmath(mp.prec) * (y_0[i] + f_1[i]*h/2)
  74. f_2.append(f_2_n)
  75. f_3 = [y_0[i] + f_2[i]*h for i in range(1, a)]
  76. for i in range(a):
  77. f_3_n += sympify(DMFsubs(red[i], A + h, mpm=True))._to_mpmath(mp.prec) * (y_0[i] + f_2[i]*h)
  78. f_3.append(f_3_n)
  79. sol = []
  80. for i in range(a):
  81. sol.append(y_0[i] + h * (f_0[i]+2*f_1[i]+2*f_2[i]+f_3[i])/6)
  82. return sol