Hi i want to integrate a function from 0 to several different upper limits (around 1000). I have written a piece of code to do this using a for loop and appending each value to an empty array. However i realise i could make the code faster by doing smaller integrals and then adding the previous integral result to the one just calculated. So i would be doing the same number of integrals, but over a smaller interval, then just adding the previous integral to get the integral from 0 to that upper limit. Heres my code at the moment:
你好,我想把一个函数从0积分到几个不同的上限(大约1000)。我已经编写了一段代码来使用for循环来完成这个操作,并将每个值追加到一个空数组中。但是我意识到我可以通过做更小的积分使代码更快,然后把之前的积分结果加到刚才计算的结果中。所以积分的个数是一样的,但是在一个更小的区间内,然后加上之前的积分得到从0到上限的积分。以下是我目前的密码:
import numpy as np #importing all relevant modules and functions
from scipy.integrate import quad
import pylab as plt
import datetime
t0=datetime.datetime.now() #initial time
num=np.linspace(0,10,num=1000) #setting up array of values for t
Lt=np.array([]) #empty array that values for L(t) are appended to
def L(t): #defining function for L
return np.cos(2*np.pi*t)
for g in num: #setting up for loop to do integrals for L at the different values for t
Lval,x=quad(L,0,g) #using the quad function to get the values for L. quad takes the function, where to start the integral from, where to end the integration
Lv=np.append(Lv,[Lval]) #appending the different values for L at different values for t
What changes do I need to make to do the optimisation technique I've suggested?
我所建议的优化技术需要做哪些更改?
2 个解决方案
#1
5
Basically, we need to keep track of the previous values of Lval
and g
. 0 is a good initial value for both, since we want to start by adding 0 to the first integral, and 0 is the start of the interval. You can replace your for loop with this:
基本上,我们需要跟踪Lval和g的先前值。0对于这两个都是一个很好的初值,因为我们想从在第一个积分上加0开始,0是区间的开始。您可以将for循环替换为以下内容:
last, lastG = 0, 0
for g in num:
Lval,x = quad(L, lastG, g)
last, lastG = last + Lval, g
Lv=np.append(Lv,[last])
In my testing, this was noticeably faster.
在我的测试中,这个速度非常快。
As @askewchan points out in the comments, this is even faster:
正如@askewchan在评论中指出的,这甚至更快:
Lv = []
last, lastG = 0, 0
for g in num:
Lval,x = quad(L, lastG, g)
last, lastG = last + Lval, g
Lv.append(last)
Lv = np.array(Lv)
#2
1
Using this function:
使用这个函数:
scipy.integrate.cumtrapz
scipy.integrate.cumtrapz
I was able to reduce time to below machine precision (very small).
我可以将时间缩短到机器精度以下(非常小)。
The function does exactly what you are asking for in a highly efficient manner. See docs for more info: https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.integrate.cumtrapz.html
函数以一种高效的方式完成您所要求的工作。更多信息请参见文档:https://docs.scipy.org/docpy -0.14.0/reference/generated/scipy.integrate.cumtrapz.html
The following code, which reproduces your version first and then mine:
以下代码,首先复制您的版本,然后复制我的版本:
# Module Declarations
import numpy as np
from scipy.integrate import quad
from scipy.integrate import cumtrapz
import time
# Initialise Time Array
num=np.linspace(0,10,num=1000)
# Your Method
t0 = time.time()
Lv=np.array([])
def L(t):
return np.cos(2*np.pi*t)
for g in num:
Lval,x=quad(L,0,g)
Lv=np.append(Lv,[Lval])
t1 = time.time()
print(t1-t0)
# My Method
t2 = time.time()
functionValues = L(num)
Lv_Version2 = cumtrapz(functionValues, num, initial=0)
t3 = time.time()
print(t3-t2)
Which consistently yields:
持续收益:
t1-t0 = O(0.1) seconds
t1-t0 = O(0.1)秒
t3-t2 = 0 seconds
t3-t2 = 0秒
#1
5
Basically, we need to keep track of the previous values of Lval
and g
. 0 is a good initial value for both, since we want to start by adding 0 to the first integral, and 0 is the start of the interval. You can replace your for loop with this:
基本上,我们需要跟踪Lval和g的先前值。0对于这两个都是一个很好的初值,因为我们想从在第一个积分上加0开始,0是区间的开始。您可以将for循环替换为以下内容:
last, lastG = 0, 0
for g in num:
Lval,x = quad(L, lastG, g)
last, lastG = last + Lval, g
Lv=np.append(Lv,[last])
In my testing, this was noticeably faster.
在我的测试中,这个速度非常快。
As @askewchan points out in the comments, this is even faster:
正如@askewchan在评论中指出的,这甚至更快:
Lv = []
last, lastG = 0, 0
for g in num:
Lval,x = quad(L, lastG, g)
last, lastG = last + Lval, g
Lv.append(last)
Lv = np.array(Lv)
#2
1
Using this function:
使用这个函数:
scipy.integrate.cumtrapz
scipy.integrate.cumtrapz
I was able to reduce time to below machine precision (very small).
我可以将时间缩短到机器精度以下(非常小)。
The function does exactly what you are asking for in a highly efficient manner. See docs for more info: https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.integrate.cumtrapz.html
函数以一种高效的方式完成您所要求的工作。更多信息请参见文档:https://docs.scipy.org/docpy -0.14.0/reference/generated/scipy.integrate.cumtrapz.html
The following code, which reproduces your version first and then mine:
以下代码,首先复制您的版本,然后复制我的版本:
# Module Declarations
import numpy as np
from scipy.integrate import quad
from scipy.integrate import cumtrapz
import time
# Initialise Time Array
num=np.linspace(0,10,num=1000)
# Your Method
t0 = time.time()
Lv=np.array([])
def L(t):
return np.cos(2*np.pi*t)
for g in num:
Lval,x=quad(L,0,g)
Lv=np.append(Lv,[Lval])
t1 = time.time()
print(t1-t0)
# My Method
t2 = time.time()
functionValues = L(num)
Lv_Version2 = cumtrapz(functionValues, num, initial=0)
t3 = time.time()
print(t3-t2)
Which consistently yields:
持续收益:
t1-t0 = O(0.1) seconds
t1-t0 = O(0.1)秒
t3-t2 = 0 seconds
t3-t2 = 0秒