如何优化辛积分的数值计算?

2024-09-28 03:14:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我对SymPy来说是个新手,希望有人能指出优化我代码的方法

我需要数值计算一个有点复杂的表达式,小数点很高(150–300),每个参数集需要30秒或更长的时间,考虑到要计算的参数空间,这非常长

我将lambdifympmath后端一起使用,并将meijerg=True用于集成处理,它显著降低了运行时间。还有其他方法可以使用吗?理想情况下,最好将评估时间推到1秒以下。我的代码是:

import mpmath
from mpmath import mpf, mp
mp.dps = 150 # ideally would like to have this set to 300 
import numpy as np
from sympy import besselj, symbols, hankel2, legendre, sin, cos, tan, summation, I
from sympy import  lambdify, expand, Integral
import time
x, alpha, k, m,n, r1, R, theta = symbols('x alpha k m n r1 R theta')

r1 = (R*cos(alpha))/cos(theta) #

Imn_part1 = (n*hankel2(n-1,k*r1)-(n+1)*hankel2(n+1,k*r1))*legendre(n, cos(theta))*cos(theta)
Imn_part2 = n*(n+1)*hankel2(n, k*r1)*(legendre(n-1, cos(theta)-legendre(n+1, cos(theta))))/k*r1
Imn_parts = expand(Imn_part1+Imn_part2)
Imn_expr = expand(Imn_parts*legendre(m,cos(theta))*(r1**2/R**2)*tan(theta))
Imn = Integral(Imn_expr, (theta, 0, alpha)).doit(meijerg=True)

# the lambdified expression
Imn_lambdify = lambdify([m,n,k,R,alpha], Imn,'mpmath')

向函数提供数字输入时–需要很长时间(30 s-40 s)

substitute_dict = {'alpha':mpf(np.radians(10)), 'k':5,'R':mpf(0.1), 'm':20,'n':10}

print('starting calculation...')
start = time.time()
output = Imn_lambdify(substitute_dict['m'],
             substitute_dict['n'],
             substitute_dict['k'],
             substitute_dict['R'],
            substitute_dict['alpha'])
print(time.time()-start)

使用的操作系统/软件包版本:

  • Linux Mint 19.2
  • Python 3.8.5
  • 第1.7.1节
  • 数学硕士1.2.1

Tags: fromimportalphatime时间cosdictr1
1条回答
网友
1楼 · 发布于 2024-09-28 03:14:07

设置meijerg=True刚刚导致Symphy在计算积分时没有那么努力。它仍然无法计算它,但它已将它拆分为5个子积分,如果打印Imn,您可以看到这些子积分。您不妨将其作为一个整数(去掉doit()):

Imn = Integral(Imn_expr, (theta, 0, alpha))

对我来说,分裂积分的计算速度要快一点,但速度也差不多

Imn = Integral(simplify(Imn_expr), (theta, 0, alpha))

最终,让事情变慢的是你使用的位数。如果你实际上不需要这些数字,你就不应该使用它们。请注意,mpmath将在内部自动提高精度,以避免取消,因此无需自己这样做。我得到了与默认dps为15的值相同的值(更少的数字)作为150

您可以尝试将值直接替换到表达式中(如果它们没有更改),并查看SymPy是否可以使用它们进一步简化Imn_表达式

另一方面,您使用的是机器浮动的np.radians(10),因为NumPy使用的是浮动。这完全违背了将最终答案计算为150位的目的,因为该输入参数仅精确到15位。考虑使用{{CD5}}来获得一个与您指定的位数正确的值。

相关问题 更多 >

    热门问题