2012-08-09 62 views
3

我正在使用嵌套的scipy.integrate.quad调用来集成2维积分。被积函数由numpy函数组成 - 所以传递给它一个输入数组要比效率更高,而不是循环输入并为每个输入调用一次 - 由于numpy的数组,它的速度要快2个数量级。如何调用python scipy quad与数组输入

但是,如果我想将我的integrand只整合到一个维度上 - 但是在其他维度上输入的数据会下降 - 看起来像'scipy'quadpack软件包无法做到无论numpy如何处理阵列输入。有没有其他人看到过这种情况 - 或者找到了解决方法 - 或者我误解了它。我从四得到的错误是:

Traceback (most recent call last): 
    File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 159, in <module> 
    fnIntegrate_x(0, 1, NCALLS_SET, True) 
    File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 35, in fnIntegrate_x 
    I = Integrate_x(yarray) 
    File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 23, in Integrate_x 
    return quad(Integrand, 0, np.pi/2, args=(y))[0] 
    File "C:\Python27\lib\site-packages\scipy\integrate\quadpack.py", line 247, in quad 
    retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points) 
    File "C:\Python27\lib\site-packages\scipy\integrate\quadpack.py", line 312, in _quad 
    return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit) 
quadpack.error: Supplied function does not return a valid float. 

我已经把的我尝试下面做一个卡通版 - 什么我实际上做了一个比较复杂的积但这是gyst。

肉在顶部 - 底部正在做基准测试以显示我的观点。

import numpy as np 
import time 

from scipy.integrate import quad 


def Integrand(x, y): 
    ''' 
     Integrand 
    ''' 
    return np.sin(x)*np.sin(y) 

def Integrate_x(y): 
    ''' 
     Integrate over x given (y) 
    ''' 
    return quad(Integrand, 0, np.pi/2, args=(y))[0] 



def fnIntegrate_x(ystart, yend, nsteps, ArrayInput = False): 
    ''' 

    ''' 

    yarray = np.arange(ystart,yend, (yend - ystart)/float(nsteps)) 
    I = np.zeros(nsteps) 
    if ArrayInput : 
     I = Integrate_x(yarray) 
    else : 
     for i,y in enumerate(yarray) : 

      I[i] = Integrate_x(y) 

    return y, I 




NCALLS_SET = 1000 
NSETS = 10 

SETS_t = np.zeros(NSETS) 

for i in np.arange(NSETS) : 

    XInputs = np.random.rand(NCALLS_SET, 2) 

    t0 = time.time() 
    for x in XInputs : 
     Integrand(x[0], x[1]) 
    t1 = time.time() 
    SETS_t[i] = (t1 - t0)/NCALLS_SET 

print "Benchmarking Integrand - Single Values:" 
print "NCALLS_SET: ", NCALLS_SET 
print "NSETS: ", NSETS  
print "TimePerCall(s): ", np.mean(SETS_t) , np.std(SETS_t)/ np.sqrt(SETS_t.size)   
print "TotalTime: ",np.sum(SETS_t) * NCALLS_SET 
''' 
Benchmarking Integrand - Single Values: 
NCALLS_SET: 1000 
NSETS: 10 
TimePerCall(s): 1.23999834061e-05 4.06987868647e-06 
''' 








NCALLS_SET = 1000 
NSETS = 10 

SETS_t = np.zeros(NSETS) 

for i in np.arange(NSETS) : 

    XInputs = np.random.rand(NCALLS_SET, 2) 

    t0 = time.time() 
    Integrand(XInputs[:,0], XInputs[:,1]) 
    t1 = time.time() 
    SETS_t[i] = (t1 - t0)/NCALLS_SET 

print "Benchmarking Integrand - Array Values:" 
print "NCALLS_SET: ", NCALLS_SET 
print "NSETS: ", NSETS  
print "TimePerCall(s): ", np.mean(SETS_t) , np.std(SETS_t)/ np.sqrt(SETS_t.size)   
print "TotalTime: ",np.sum(SETS_t) * NCALLS_SET 
''' 
Benchmarking Integrand - Array Values: 
NCALLS_SET: 1000 
NSETS: 10 
TimePerCall(s): 2.00009346008e-07 1.26497018465e-07 
''' 












NCALLS_SET = 1000 
NSETS = 100 

SETS_t = np.zeros(NSETS) 

for i in np.arange(NSETS) : 


    t0 = time.time() 
    fnIntegrate_x(0, 1, NCALLS_SET, False) 
    t1 = time.time() 
    SETS_t[i] = (t1 - t0)/NCALLS_SET 

print "Benchmarking fnIntegrate_x - Single Values:" 
print "NCALLS_SET: ", NCALLS_SET 
print "NSETS: ", NSETS  
print "TimePerCall(s): ", np.mean(SETS_t) , np.std(SETS_t)/ np.sqrt(SETS_t.size)   
print "TotalTime: ",np.sum(SETS_t) * NCALLS_SET 
''' 
NCALLS_SET: 1000 
NSETS: 100 
TimePerCall(s): 0.000165750000477 8.61204306241e-07 
TotalTime: 16.5750000477 
''' 








NCALLS_SET = 1000 
NSETS = 100 

SETS_t = np.zeros(NSETS) 

for i in np.arange(NSETS) : 


    t0 = time.time() 
    fnIntegrate_x(0, 1, NCALLS_SET, True) 
    t1 = time.time() 
    SETS_t[i] = (t1 - t0)/NCALLS_SET 

print "Benchmarking fnIntegrate_x - Array Values:" 
print "NCALLS_SET: ", NCALLS_SET 
print "NSETS: ", NSETS  
print "TimePerCall(s): ", np.mean(SETS_t) , np.std(SETS_t)/ np.sqrt(SETS_t.size)   

''' 
**** Doesn't work!!!! ***** 
Traceback (most recent call last): 
    File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 159, in <module> 
    fnIntegrate_x(0, 1, NCALLS_SET, True) 
    File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 35, in fnIntegrate_x 
    I = Integrate_x(yarray) 
    File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 23, in Integrate_x 
    return quad(Integrand, 0, np.pi/2, args=(y))[0] 
    File "C:\Python27\lib\site-packages\scipy\integrate\quadpack.py", line 247, in quad 
    retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points) 
    File "C:\Python27\lib\site-packages\scipy\integrate\quadpack.py", line 312, in _quad 
    return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit) 
quadpack.error: Supplied function does not return a valid float. 

''' 

回答

1

可以通过numpy.vectorize函数。我有这个问题很长一段时间,然后来到这个向量化函数。

,你可以使用它像这样:

vectorized_function = numpy.vectorize(your_function)

输出= vectorized_function(your_array_input)

+0

酷派,将在某个时候尝试这一点 - 它是自一会我看了这段代码 - 但可能在未来会有用。 – JPH 2015-07-08 19:09:19

1

害怕我在这里回答我的问题。我不认为这是可能的。看起来像quad是某种库的某种端口,它是用别的方式编写的 - 因此它是内部的库,它定义了如何完成工作 - 所以如果不重新设计库本身,可能无法做我想做的事。

对于有多个D集成的时间问题的其他人,我发现最好的方法是使用专用的集成库。我发现“古巴”似乎有一些非常高效的多维集成程序。

http://www.feynarts.de/cuba/

这些程序用C语言编写,所以我结束了使用痛饮与他们交谈 - 最终也为了提高效率重新写我在C积 - 这加快东西负载....