2017-04-10 73 views
0

我在Python中有一個for循環,其中包含優化函數scipy.optimize.root。描述優化結果的功能outputs類對象(稱爲sol):使用Python類對象進行並行處理

import numpy as np   
import scipy.optimize as so 

def root2d(x,a,b): 
    F1 = np.exp(-np.exp(-(x[0]+x[1]))) - x[1]*(b+x[0]**2) 
    F2 = x[0]*np.cos(x[1]) + x[1]*np.sin(x[0]) - a 
    return (F1,F2) 

x0 = np.array([0.1,0.1]) # initial guess 
alist = np.linspace(-0.5,-0.3,10) 
blist = np.linspace(0.2,0.3,10) 

xlist = np.zeros(10) 
ylist = np.zeros(10) 
zlist = np.zeros(10) 

for jj in range(0,10): 

    a = alist[jj] 
    b = blist[jj] 

    sol = so.root(root2d,x0,args=(a,b),method='lm',tol=1e-9) 

    xlist[jj] = sol.x[0] # optimised value 
    ylist[jj] = sol.x[1] # optimised value 
    zlist[jj] = sol.success # was solver successful? 

# do something with xlist ylist zlist 

現在我想要並行使用this post建議的for循環。但是我不知道如何處理sol輸出,以及如何編寫上述for循環,以便它可以在這種結構中使用:

from multiprocessing import Pool 

p = Pool(4) 
xlist,ylist,zlist = zip(*p.map(so.root,range(0,10))) 

這是給定爲由諾倫版稅答案。

編輯:我想要一個HPC集羣,其中可用的Python模塊是numpy的,SciPy的,matplotlib,用Cython和mpi4py上運行我的程序(沒有這個MWE)。雖然有很多方法可以執行並行處理,但我想對現有的(串行for循環)代碼做最小的更改。

回答

2

要使用Pool,您典型地提供了一個函數,並調用Pool.map就可以了。

你的情況:

from multiprocessing import Pool 

def run(jj): 
    import scipy.optimize as so 

    a = alist[jj] 
    b = blist[jj] 

    sol = so.root(root2d,x0,args=(a,b),method='lm',tol=1e-9) 

    return sol.x[0], sol.x[1], sol.success 


if __name__ == '__main__': 

    # your declarations go here ... 

    p = Pool(4) 
    result = p.map(run, range(0,10)) 

...它給你一個元組列表,包含了解決方案...

+0

應該'x0','alist','blist'是'運行(JJ)'函數裏面?而'xlist = ylist = zlist = np.zeros(10)'應該在'p = Pool(4)'之前,我假設 –

+0

沒有。所有這些定義,包括''root2d''的函數定義都放在我放''#你的聲明去了'的地方'' –

+0

奇怪......當我這樣做時,我只是得到一個錯誤:'AttributeError:module'__main__'has沒有屬性'__spec __'' –

0

在繁體UxTLi51Nus的帖子中給出的代碼不會出現上下工夫由於某種原因,Python 3.5.2。有了一些變化,下面的代碼將出現確定...

import numpy as np 
import scipy.optimize as so 
from multiprocessing import Pool 

def root2d(x,a,b): 
    F1 = np.exp(-np.exp(-(x[0]+x[1]))) - x[1]*(b+x[0]**2) 
    F2 = x[0]*np.cos(x[1]) + x[1]*np.sin(x[0]) - a 
    return (F1,F2) 

def run(jj): 

    x0 = np.array([0.1,0.1]) # initial guess 
    alist = np.linspace(-0.5,-0.3,10) 
    blist = np.linspace(0.2,0.3,10) 

    a = alist[jj] 
    b = blist[jj] 

    sol = so.root(root2d,x0,args=(a,b),method='lm',tol=1e-9) 

    return sol.x[0], sol.x[1], sol.success 


if __name__ == '__main__': 

    xlist = np.zeros(10) 
    ylist = np.zeros(10) 
    zlist = np.zeros(10) 

    p = Pool(4) 
    result = p.map(run, range(0,10)) 
    print(result) 

我不得不把迭代值alistblist和初始猜測x0run函數內。這些被送入scipy.optimize.root求解器。有沒有錯誤,當我做到這一點,而解決方案是:

[(-0.53888782445459149, 0.043495493090149454, True), 
(-0.52328348126598456, 0.032937536902490253, True), 
(-0.50743370799474086, 0.022462155879391384, True), 
(-0.49135105437855231, 0.01203948230426068, True), 
(-0.47502920008575156, 0.001732198125265777, True), 
(-0.45846822054716679, -0.0084225504551842089, True), 
(-0.4416527225847745, -0.018336039419045602, True), 
(-0.42455931996843449, -0.027893297385455082, True), 
(-0.40720848051853215, -0.037005663686040566, True), 
(-0.38955545334271019, -0.045486751099290013, True)] 
+0

好吧,我不明白爲什麼會有這種差異,在我的系統中,當''xlist''聲明''x0'','alist''和''blist''聲明爲' ''if __name__ =='__main __''' –

+0

您甚至可以刪除''xlist'',''ylist''和''zlist''的聲明,因爲結果現在放在''result''中。BTW –