【问题标题】:Sympy series expansion with numerical integration带有数值积分的 Sympy 级数展开
【发布时间】:2018-03-11 23:23:59
【问题描述】:

我想对函数 F(e,Eo) 进行级数扩展,直到 e 的某个幂,并以数字方式对 Eo 变量进行积分。 我的想法是使用 SymPy 在e 中进行幂级数,然后使用 MPMath 对Eo 进行数值积分。

以下是示例代码。我收到无法从表达式创建 mpf 的消息。我想这个问题与 SymPy 的系列最后有一个 O(e**5) 术语有关,后来我希望数值积分显示 e 的函数而不是数字。

import sympy as sp
import numpy as np
from mpmath import *
e = sp.symbols('e')
Eo = sp.symbols('Eo')
expr = sp.sin(e-2*Eo).series(e, 0, 5)
F = lambda Eo : expr
I = quad(F, [0, 2*np.pi])
print(I)

很明显,我需要一种不同的方法,但我仍然需要对我的实际代码进行数值积分,因为它有更复杂的表达式,无法进行分析积分。

编辑:我应该为示例代码选择一个实变量的复杂函数,我正在尝试这个(扩展和集成)函数,例如:

expr = (cos(Eo) - e - I*sqrt(1 - e ** 2)*sin(Eo)) ** 2 * (cos(2*(Eo - e*sin(Eo))) + I*sin(2*(Eo - e*sin(Eo))))/(1 - e*cos(Eo)) ** 4

【问题讨论】:

  • 旁注 1:F = lambda Eo : expr 行几乎肯定不会执行您想要的操作,因为 lambda 表达式的 Eoexpr 中使用的不一样。你可能想使用F = lambda x: expr.subs(Eo,x) 或 SymPy 的 lambdify 之类的东西。
  • 旁注 2:为什么每个人都使用 MPMath 来解决各种问题?它适用于任意精度的数学,这一切都很好,而且是大多数问题不需要的东西。

标签: python sympy numerical-integration


【解决方案1】:

我希望数值积分显示 e 的函数而不是数字。

这基本上是不可能的。 您的积分要么是分析的,要么是数值的,如果它是数值的,它只会为您处理和生成数字(numericalnumber 这两个词是相似的)。

如果您想将集成拆分为数值和分析组件,您必须自己进行 - 或者希望 SymPy 根据需要自动拆分集成,which it unfortunately is not yet capable of。 我就是这样做的(细节在代码中注释):

from sympy import sin, pi, symbols, Integral
from itertools import islice

e,Eo = symbols("e Eo")
expr = sin(e-sin(2*Eo))

# Create a generator yielding the first five summands of the series.
# This avoids the O(e**5) term. 
series = islice(expr.series(e,0,None),5)

integral = 0
for power,summand in enumerate(series):
    # Remove the e from the expression
    Eo_part = summand/e**power
    # … and ensure that it worked:
    assert not Eo_part.has(e)

    # Integrate the Eo part:
    partial_integral = Eo_part.integrate((Eo,0,2*pi))

    # If the integral cannot be evaluated analytically, …
    if partial_integral.has(Integral):
        # … replace it by the numerical estimate:
        partial_integral = partial_integral.n()

    # Re-attach the e component and add it to the sum:
    integral += partial_integral*e**power

请注意,我根本没有使用 NumPy 或 MPMath(尽管 SymPy 在后台使用后者进行数值估计)。除非你真的知道自己在做什么,否则将这两者与 SymPy 混合是一个坏主意,因为它们甚至不知道 SymPy 表达式。

【讨论】:

  • 我想知道它用什么方法来估计.integrate().n()的数值。
【解决方案2】:

通过 SymPy 的polynomial module,这是一种类似于 Wrzlprmft 的答案但处理系数的方式不同的方法:

from sympy import sin, pi, symbols, Integral, Poly

def integrate_coeff(coeff):
    partial_integral = coeff.integrate((Eo, 0, 2*pi))
    return partial_integral.n() if partial_integral.has(Integral) else partial_integral

e,Eo = symbols("e Eo")
expr = sin(e-sin(2*Eo))  
degree = 5

coeffs = Poly(expr.series(e, 0, degree).removeO(), e).all_coeffs()
new_coeffs = map(integrate_coeff, coeffs)
print((Poly(new_coeffs, e).as_expr() + e**degree).series(e, 0, degree))

主要代码是三行:(1)提取e的系数直到给定程度; (2)如果必须的话,在数字上整合每一个; (3) 打印结果,将其呈现为系列而不是多项式(因此添加 e**degree 的技巧,以使 SymPy 知道系列继续)。输出:

-6.81273574401304e-108 + 4.80787886126883*e + 3.40636787200652e-108*e**2 - 0.801313143544804*e**3 - 2.12897992000408e-109*e**4 + O(e**5) 

【讨论】:

  • 不错的解决方案,但是如何优化它以便在值看起来很小时不会浪费时间计算系数?就像您在代码中使用的示例函数一样,它将系数与 e-100 阶的结果进行积分。
猜你喜欢
  • 2020-01-05
  • 1970-01-01
  • 2020-04-13
  • 2021-02-10
  • 1970-01-01
  • 2017-12-28
  • 2020-06-14
  • 1970-01-01
  • 2022-06-18
相关资源
最近更新 更多