python如何对大三角方程进行积分?
How to integrate large trigonometric equations with python?
在我的程序中,我必须重新创建 galerkin-method,我必须用它做一些我现在用 sympy.integrate
做的集成。
我的问题是,在方程包含多个三角函数或添加的 e 函数(它应该能够解决所有问题)的情况下,sympy 会永远计算。我也在使用 sympy.symbols
,因为通过这些集成,我正在创建一个必须求解的方程组。我需要一个反导数,而不仅仅是一个值的解决方案。
是否有数值积分方法或其他返回准确值的方法?
我尝试使用 sympy.Integral(equation).evalf(1)
,但错误太高或返回的十进制数太长,这让我回到了运行时间太长的状态。
函数可以如下所示:
(-4*x**3*sin(2*x) + 2*cos(x)*cos(2*x))*(cos(x) + 1)
我必须整合其中的 20 个。
如果您不需要符号积分,并且您知道积分界限,那么您可以进行数值积分。一个务实的起点是梯形法则。 https://en.wikipedia.org/wiki/Trapezoidal_rule。可以通过更精细的步骤(在范围内)任意提高准确性。
通过使用更高的阶数来提高准确性在编程上更复杂一些,但在数值上更有效。一个实现通常只有在计算时间高于编程时间时才开始有意义)
import math
import matplotlib
sin=math.sin
cos=math.cos
def f(x):
return (-4*x**3*sin(2*x) + 2*cos(x)*cos(2*x))*(cos(x) + 1)
x0 = 0 # lower bound
x1 = 2.8 # upper bound (not exactly resolved in this example)
dx = 0.01 # integration step size
F_int = 0
x=x0
while x < x1:
f_n = f(x)
f_n_plusdx = f(x+dx)
dF = 0.5*(f_n+f_n_plusdx)*dx # calc the trapezoid area
F_int += dF # sum of the integration
x+=dx # next dx.
print(F_int)
SymPy 的集成函数尝试了多种不同的集成方法,其中一种是 Risch 算法,它在某些情况下可能非常慢。还有 "manual" 积分方法,它不如 Risch 完整,但偶尔出现极度缓慢的情况较少。这里有一些描述:
https://docs.sympy.org/latest/modules/integrals/integrals.html#internals
您给出的示例中的问题是它卡在启发式中。所以让我们尝试 "manual" 代替:
In [1]: expr = (-4*x**3*sin(2*x) + 2*cos(x)*cos(2*x))*(cos(x) + 1)
In [2]: expr
Out[2]:
⎛ 3 ⎞
⎝- 4⋅x ⋅sin(2⋅x) + 2⋅cos(x)⋅cos(2⋅x)⎠⋅(cos(x) + 1)
In [3]: %time anti1 = expr.integrate(x, manual=True)
CPU times: user 39.7 s, sys: 232 ms, total: 39.9 s
Wall time: 43.1 s
In [4]: anti1
Out[4]:
3 3 3 ⌠
8⋅x ⋅cos (x) 3 2 x 4⋅sin (x) sin(4⋅x) ⎮ 2 3
──────────── + 2⋅x ⋅cos(2⋅x) - 3⋅x ⋅sin(2⋅x) - 3⋅x⋅cos(2⋅x) + ─ - ───────── + 2⋅sin(x) + 2⋅sin(2⋅x) + ──────── - 8⋅⎮ x ⋅cos (x) dx
3 2 3 8 ⌡
所以这花了 40 秒,但结果没有完全积分:manualintegrate
在那里留下了一个未计算的积分。我们可以通过调用 doit
:
使用正常的 integrate
来完成它
In [5]: %time anti1.doit()
CPU times: user 4.46 s, sys: 142 ms, total: 4.61 s
Wall time: 4.81 s
Out[5]:
3 3 2 3 2 3
8⋅x ⋅cos (x) 3 16⋅x ⋅sin (x) 2 2 2 32⋅x⋅sin (x)⋅cos(x) 112⋅x⋅cos (x)
──────────── + 2⋅x ⋅cos(2⋅x) - ───────────── - 8⋅x ⋅sin(x)⋅cos (x) - 3⋅x ⋅sin(2⋅x) - ─────────────────── - ───────────── - 3⋅x⋅c
3 3 3 9
3 2
x 284⋅sin (x) 112⋅sin(x)⋅cos (x) sin(4⋅x)
os(2⋅x) + ─ + ─────────── + ────────────────── + 2⋅sin(x) + 2⋅sin(2⋅x) + ────────
2 27 9 8
所以又花了几秒钟才得到那个结果。这现在是一个完整的反导数,我们可以验证:
In [6]: simplify(expr - _.diff(x))
Out[6]: 0
这意味着我们可以用 expr.integrate(x, manual=True).doit()
在大约 50 秒内完成这个特定的积分。
实际上,如果将此特定示例从 sin/cos 重写为 exp:
,则可以在 5 秒内完成
In [1]: expr = (-4*x**3*sin(2*x) + 2*cos(x)*cos(2*x))*(cos(x) + 1)
In [2]: %time expr.rewrite(exp).expand().integrate(x).expand().rewrite(sin).simplify()
CPU times: user 5.3 s, sys: 21.2 ms, total: 5.32 s
Wall time: 5.33 s
Out[2]:
3 2
3 3 2⋅x ⋅cos(3⋅x) 2 2 2⋅x ⋅sin(3⋅x) 4⋅x⋅cos
2⋅x ⋅cos(x) + 2⋅x ⋅cos(2⋅x) + ───────────── - 6⋅x ⋅sin(x) - 3⋅x ⋅sin(2⋅x) - ───────────── - 12⋅x⋅cos(x) - 3⋅x⋅cos(2⋅x) - ───────
3 3 9
(3⋅x) x 13⋅sin(3⋅x) sin(4⋅x)
───── + ─ + 13⋅sin(x) + 2⋅sin(2⋅x) + ─────────── + ────────
2 27 8
In [3]: simplify(expr - _.diff(x))
Out[3]: 0
尽管这个答案看起来与前一个答案不同,但使用三角恒等式重写三角表达式的方法有无数种,但它们应该等价于加法常数(根据反导数的要求)。
在我的程序中,我必须重新创建 galerkin-method,我必须用它做一些我现在用 sympy.integrate
做的集成。
我的问题是,在方程包含多个三角函数或添加的 e 函数(它应该能够解决所有问题)的情况下,sympy 会永远计算。我也在使用 sympy.symbols
,因为通过这些集成,我正在创建一个必须求解的方程组。我需要一个反导数,而不仅仅是一个值的解决方案。
是否有数值积分方法或其他返回准确值的方法?
我尝试使用 sympy.Integral(equation).evalf(1)
,但错误太高或返回的十进制数太长,这让我回到了运行时间太长的状态。
函数可以如下所示:
(-4*x**3*sin(2*x) + 2*cos(x)*cos(2*x))*(cos(x) + 1)
我必须整合其中的 20 个。
如果您不需要符号积分,并且您知道积分界限,那么您可以进行数值积分。一个务实的起点是梯形法则。 https://en.wikipedia.org/wiki/Trapezoidal_rule。可以通过更精细的步骤(在范围内)任意提高准确性。
通过使用更高的阶数来提高准确性在编程上更复杂一些,但在数值上更有效。一个实现通常只有在计算时间高于编程时间时才开始有意义)
import math
import matplotlib
sin=math.sin
cos=math.cos
def f(x):
return (-4*x**3*sin(2*x) + 2*cos(x)*cos(2*x))*(cos(x) + 1)
x0 = 0 # lower bound
x1 = 2.8 # upper bound (not exactly resolved in this example)
dx = 0.01 # integration step size
F_int = 0
x=x0
while x < x1:
f_n = f(x)
f_n_plusdx = f(x+dx)
dF = 0.5*(f_n+f_n_plusdx)*dx # calc the trapezoid area
F_int += dF # sum of the integration
x+=dx # next dx.
print(F_int)
SymPy 的集成函数尝试了多种不同的集成方法,其中一种是 Risch 算法,它在某些情况下可能非常慢。还有 "manual" 积分方法,它不如 Risch 完整,但偶尔出现极度缓慢的情况较少。这里有一些描述: https://docs.sympy.org/latest/modules/integrals/integrals.html#internals
您给出的示例中的问题是它卡在启发式中。所以让我们尝试 "manual" 代替:
In [1]: expr = (-4*x**3*sin(2*x) + 2*cos(x)*cos(2*x))*(cos(x) + 1)
In [2]: expr
Out[2]:
⎛ 3 ⎞
⎝- 4⋅x ⋅sin(2⋅x) + 2⋅cos(x)⋅cos(2⋅x)⎠⋅(cos(x) + 1)
In [3]: %time anti1 = expr.integrate(x, manual=True)
CPU times: user 39.7 s, sys: 232 ms, total: 39.9 s
Wall time: 43.1 s
In [4]: anti1
Out[4]:
3 3 3 ⌠
8⋅x ⋅cos (x) 3 2 x 4⋅sin (x) sin(4⋅x) ⎮ 2 3
──────────── + 2⋅x ⋅cos(2⋅x) - 3⋅x ⋅sin(2⋅x) - 3⋅x⋅cos(2⋅x) + ─ - ───────── + 2⋅sin(x) + 2⋅sin(2⋅x) + ──────── - 8⋅⎮ x ⋅cos (x) dx
3 2 3 8 ⌡
所以这花了 40 秒,但结果没有完全积分:manualintegrate
在那里留下了一个未计算的积分。我们可以通过调用 doit
:
integrate
来完成它
In [5]: %time anti1.doit()
CPU times: user 4.46 s, sys: 142 ms, total: 4.61 s
Wall time: 4.81 s
Out[5]:
3 3 2 3 2 3
8⋅x ⋅cos (x) 3 16⋅x ⋅sin (x) 2 2 2 32⋅x⋅sin (x)⋅cos(x) 112⋅x⋅cos (x)
──────────── + 2⋅x ⋅cos(2⋅x) - ───────────── - 8⋅x ⋅sin(x)⋅cos (x) - 3⋅x ⋅sin(2⋅x) - ─────────────────── - ───────────── - 3⋅x⋅c
3 3 3 9
3 2
x 284⋅sin (x) 112⋅sin(x)⋅cos (x) sin(4⋅x)
os(2⋅x) + ─ + ─────────── + ────────────────── + 2⋅sin(x) + 2⋅sin(2⋅x) + ────────
2 27 9 8
所以又花了几秒钟才得到那个结果。这现在是一个完整的反导数,我们可以验证:
In [6]: simplify(expr - _.diff(x))
Out[6]: 0
这意味着我们可以用 expr.integrate(x, manual=True).doit()
在大约 50 秒内完成这个特定的积分。
实际上,如果将此特定示例从 sin/cos 重写为 exp:
,则可以在 5 秒内完成In [1]: expr = (-4*x**3*sin(2*x) + 2*cos(x)*cos(2*x))*(cos(x) + 1)
In [2]: %time expr.rewrite(exp).expand().integrate(x).expand().rewrite(sin).simplify()
CPU times: user 5.3 s, sys: 21.2 ms, total: 5.32 s
Wall time: 5.33 s
Out[2]:
3 2
3 3 2⋅x ⋅cos(3⋅x) 2 2 2⋅x ⋅sin(3⋅x) 4⋅x⋅cos
2⋅x ⋅cos(x) + 2⋅x ⋅cos(2⋅x) + ───────────── - 6⋅x ⋅sin(x) - 3⋅x ⋅sin(2⋅x) - ───────────── - 12⋅x⋅cos(x) - 3⋅x⋅cos(2⋅x) - ───────
3 3 9
(3⋅x) x 13⋅sin(3⋅x) sin(4⋅x)
───── + ─ + 13⋅sin(x) + 2⋅sin(2⋅x) + ─────────── + ────────
2 27 8
In [3]: simplify(expr - _.diff(x))
Out[3]: 0
尽管这个答案看起来与前一个答案不同,但使用三角恒等式重写三角表达式的方法有无数种,但它们应该等价于加法常数(根据反导数的要求)。