【问题标题】:Need help making a sum calculation faster in python需要帮助在 python 中更快地进行总和计算
【发布时间】:2020-06-21 22:41:34
【问题描述】:

这是我总结的一段代码。它包括一个积分。里面的所有变量都有浮点或整数值。

import numpy as np
import math
import scipy.integrate
from mpmath import nsum, inf

sum1 = nsum(lambda m: (1/(math.factorial(m))*((ra/a1)**(2*m))*(1/(math.factorial((m+1)-1)))*(scipy.integrate.quad(lambda u:((u**((m+1)-1))*(math.exp(-u))) ,0,(d**2)/(4*(a1**2)),limit = 50))[0]),[0,100])

有什么办法可以加快速度吗?我需要能够循环数百次。目前需要一个多小时。这是原始的完整方程式。我在这里粘贴的代码部分只是方程中的第一个总和(sigma),其中 m 从 0 变为无穷大。我在这里的代码中将它从 0 到 100 临时更改为 m。

非常感谢!

更新:

我尝试了不同的方法。我认为那些发表评论的人是对的,而我之前错误地使用了 scipy。我想我已经解决了。就我的目的而言,它仍然很慢,但现在几百次重复只需要 30 分钟。 (我也猜你可以使用“def”结构或“lambda”结构来通过quad)。如果您对更快地完成这样的事情有任何建议,我将不胜感激,但我感谢你们帮助找到答案。

for m in range(0,100):

    # def integrand(u,m):
    #     return (u**((m+1)-1))*(math.exp(-u)) 

    f = lambda u,m:(u**((m+1)-1))*(math.exp(-u)) 
    
    sumfunc =1/(math.factorial(m))*((ra/a1)**(2*m))*(1/(math.factorial((m+1)-1)))*scipy.integrate.quad(f,0,(d**2)/(4*(a1**2)),args=(m,))[0] 
    
    tosum.append(sumfunc)
    
sum1 = sum(tosum)

【问题讨论】:

  • 这写得不正确,这就是为什么它需要一个多小时。 scipy 中的 quad 函数实际上非常快。到目前为止,我不知道您要做什么,所以我帮不上什么忙,但是如果您添加完整的方程式,您正在尝试以书面形式编写代码 - 我也许可以更正您的代码。跨度>
  • 你能写出你想解出的方程式吗?代码很难阅读,也很难理解你想要做什么。将来您可能还想在发布之前使用Black 格式化这么长的代码。
  • 知道了,谢谢,我已将原始方程式包含在原始帖子中。抱歉我的问题不清楚

标签: python math sum integral notation


【解决方案1】:
  1. mpmath知道gammainc,使用它;
  2. npsum 很聪明,不要试图变得更聪明,只是求和到无穷大。它会做一些花哨的计算,以便在需要时停止;
  3. 如果你关心精度,尽量使用mpmath类型

代码如下:

from mpmath import *

a1 = mpf('0.62')
ra = mpf('0.99')

def the_sum(d, a, **kwargs): # added `a` for reuse in the complete formula
    r_ = (ra / a) ** 2
    d_ = d ** 2 / (4 * a ** 2)
    return nsum(
        lambda m: r_ ** m / factorial(m) * gammainc(m + 1, 0, d_, regularized=True),
        [0, inf],
        **kwargs
    )

还有一些基准

%time [sum_OP(d) for d in range(5)]                                                                                                                                                                
CPU times: user 684 ms, sys: 2.97 ms, total: 687 ms
Wall time: 685 ms
[mpf('0.0'),
 mpf('0.93752967676144794'),
 mpf('5.3589089548240878'),
 mpf('10.711751972234245'),
 mpf('12.600516476806067')]

%time [the_sum(d, a1) for d in range(5)]                                                                                                                                                               
CPU times: user 28.7 ms, sys: 1.3 ms, total: 30 ms
Wall time: 28.8 ms
[mpf('0.0'),
 mpf('0.93752967676144794'),
 mpf('5.3589089548240905'),
 mpf('10.711751972234246'),
 mpf('12.600516476806067')]

如果你真的想让事情变得更快,想要比nsum 更聪明,并且确信它会在这种情况下工作(我愿意),你可以告诉它使用direct 方法:

 %time [the_sum(d, a1, method='d') for d in range(5)]                                                                                                                                               
CPU times: user 20.7 ms, sys: 613 µs, total: 21.3 ms
Wall time: 20.9 ms
[mpf('0.0'),
 mpf('0.93752967676144794'),
 mpf('5.3589089548240905'),
 mpf('10.711751972234246'),
 mpf('12.600516476806067')]

最后,你似乎不需要任何多精度,不需要使用 mpmath,并坚持使用一些低精度版本:

a1 = 0.62
ra = 0.99
def sum_low_prec(d, a):
    return sum(
        (ra/a)**(2*m) / (math.factorial(m)) * scipy.special.gammainc(m + 1, (d**2)/(4*(a**2)))
         for m in range(30)
    )

%time [sum_low_prec(d, a1) for d in range(5)]                                                                                                                                                     
CPU times: user 871 µs, sys: 3 µs, total: 874 µs
Wall time: 877 µs
[0.0,
 0.9375296767614478,
 5.358908954824089,
 10.711751972234243,
 12.600516476806066]

【讨论】:

  • 感谢每个选项的细分。信息量很大
猜你喜欢
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
  • 2017-08-17
相关资源
最近更新 更多