Sympy 集成 运行 出错,但 Mathematica 工作正常

Sympy integration running into error, but Mathematica works fine

我正在尝试使用 sympy 对一个方程求积分,但计算总是出错: TypeError: cannot add <class 'sympy.matrices.immutable.ImmutableDenseMatrix'> and <class 'sympy.core.numbers.Zero'>

然而,当我在 Mathematica 中对同一个方程求积分时,我得到了我想要的结果。 我希望有人能解释一下 sympy 背后发生的事情,以及它的集成与 Mathematica 的集成有何不同。

因为涉及到很多方程,所以我只打算 post 方程的 Python 表示,这些方程用于组成积分中调用的变量。为了确定积分是一个问题,我独立检查了每个涉及的方程,并确保结果在 Python 和 Mathematica 之间匹配。我可以确认只有集成失败。

Python 中的集成变量设置:

import numpy as np
import sympy as sym
from sympy import I, Matrix, integrate
from sympy.integrals import Integral
from sympy.functions import exp
from sympy.physics.vector import cross, dot

c_speed = 299792458
lambda_u = 0.01
k_u = (2 * np.pi)/lambda_u
K_0 = 0.2
gamma_0 = 2.0
beta_0 = sym.sqrt(1 - 1 / gamma_0**2)
t = sym.symbols('t')
t_start = (-2 * lambda_u) / c_speed
t_end = (3 * lambda_u) / c_speed

beta_x_of_t = sym.Piecewise( (0.0, sym.Or(t < t_start, t > t_end)),
                             ((-1 * K_0)/gamma_0 * sym.sin(k_u * c_speed * t), sym.And(t_start <= t, t <= t_end)) )

beta_z_of_t = sym.Piecewise( (beta_0, sym.Or(t < t_start, t > t_end)),
                             (beta_0 * (1 - K_0**2/ (4 * beta_0 * gamma_0**2)) + K_0**2 / (4 * beta_0 * gamma_0**2) * sym.sin(2 * k_u * c_speed * t), sym.And(t_start <= t, t <= t_end)) )

beta_xp_of_t = sym.diff(beta_x_of_t, t)

beta_zp_of_t = sym.diff(beta_z_of_t, t)

Python 积分:

n = Matrix([(0, 0, 1)])
beta = Matrix([(beta_x_of_t, 0, beta_z_of_t)])
betap = Matrix([(beta_xp_of_t, 0, beta_zp_of_t)])

def rad(n, beta, betap):
  return integrate(n.cross((n-beta).cross(betap)), (t, t_start, t_end))

rad(n, beta, betap)
# Output is the error above

Mathematica 集成:

rad[n_, beta_, betap_] :=
 NIntegrate[
  Cross[n, Cross[n - beta, betap]]
  , {t, tstart, tend}, AccuracyGoal -> 3]

rad[{0, 0, 1}, {betax[t], 0, betaz[t]}, {betaxp[t], 0, betazp[t]}]
# Output is {0.00150421, 0., 0.}

我确实看到类似的问题,例如 this one and ,但我不完全确定它们是否与这里相关(第二个 link 似乎更接近匹配,但不太合适).

当你使用不精确的浮点数时(甚至使用 np.pi 而不是 sym.pi),当 sympy 试图找到精确的符号解时,sympy 的表达式变得相当疯狂,常量如 6.67e-11 与更大的值混合。

这里尝试使用更多的符号表达式,并且只对函数的x坐标进行积分

import sympy as sym
from sympy import I, Matrix, integrate, S
from sympy.integrals import Integral
from sympy.functions import exp
from sympy.physics.vector import cross, dot

c_speed = 299792458
lambda_u = S(1) / 100
k_u = (2 * sym.pi) / lambda_u
K_0 = S(2) / 100
gamma_0 = 2
beta_0 = sym.sqrt(1 - S(1) / gamma_0 ** 2)
t = sym.symbols('t')
t_start = (-2 * lambda_u) / c_speed
t_end = (3 * lambda_u) / c_speed

beta_x_of_t = sym.Piecewise((0, sym.Or(t < t_start, t > t_end)),
                            ((-1 * K_0) / gamma_0 * sym.sin(k_u * c_speed * t), sym.And(t_start <= t, t <= t_end)))

beta_z_of_t = sym.Piecewise((beta_0, sym.Or(t < t_start, t > t_end)),
                            (beta_0 * (1 - K_0 ** 2 / (4 * beta_0 * gamma_0 ** 2)) + K_0 ** 2 / (
                                        4 * beta_0 * gamma_0 ** 2) * sym.sin(2 * k_u * c_speed * t),
                             sym.And(t_start <= t, t <= t_end)))

beta_xp_of_t = sym.diff(beta_x_of_t, t)

beta_zp_of_t = sym.diff(beta_z_of_t, t)

n = Matrix([(0, 0, 1)])
beta = Matrix([(beta_x_of_t, 0, beta_z_of_t)])
betap = Matrix([(beta_xp_of_t, 0, beta_zp_of_t)])

func = n.cross((n - beta).cross(betap))[0]

print(integrate(func, (t, t_start, t_end)))

这不会给出错误,并且只输出零。

Lambdify 可用于将函数转换为 numpy,并绘制它。

func_np = sym.lambdify(t, func)

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import quad

t_start_np = float(t_start.evalf())
t_end_np = float(t_end.evalf())

ts = np.linspace(t_start_np, t_end_np, 100000)
plt.plot(ts, func_np(ts))
print("approximate integral (np.trapz):", np.trapz(ts, func_np(ts)))
print("approximate integral (scipy's quad):", quad(func_np, t_start_np, t_end_np))

这输出:

approximate integral (np.trapz): 0.04209721470548062
approximate integral (scipy's quad): (-2.3852447794681098e-18, 5.516333374450447e-10)

注意 y 轴上的大值和 x 轴上的小值。这些值以及 matematica 的值很可能是舍入误差。