[英]Python - Problem minimizing a constrained function with scipy.minimize
我試圖最小化采用算法scipy.optimize.minimize
。 function 涉及最小化3*N
參數,其中N
是輸入。 更具體地說,我的最小化參數在三個 arrays H = H[0],H[1],...,H[N-1]
, a = a[0],a[1],...,a[N-1]
給出a = a[0],a[1],...,a[N-1]
和b = b[0],b[1],...,b[N-1]
我僅將它們連接到一個名為mins
的數組中,其中len(mins)=3*N
。
這些參數也受到如下約束:
0 <= H and sum(H) = 0.5
0 <= a <= Pi/2
0 <= b <= Pi/2
因此,我的約束代碼如下:
import numpy as np
# constraints on x:
def Hlhs(mins): # left hand side
return np.diag(np.ones(N)) @ mins.reshape(3,N)[0]
def Hrhs(mins): # right hand side
return np.sum(mins.reshape(3,N)[0]) - 0.5
con1H = {'type': 'ineq', 'fun': lambda H: Hlhs(H)}
con2H = {'type': 'eq', 'fun': lambda H: Hrhs(H)}
# constraints on a:
def alhs(mins):
return np.diag(np.ones(N)) @ mins.reshape(3,N)[1]
def arhs(mins):
return -np.diag(np.ones(N)) @ mins.reshape(3,N)[1] + (np.ones(N))*np.pi/2
con1a = {'type': 'ineq', 'fun': lambda a: alhs(a)}
con2a = {'type': 'ineq', 'fun': lambda a: arhs(a)}
# constraints on b:
def blhs(mins):
return np.diag(np.ones(N)) @ mins.reshape(3,N)[2]
def brhs(mins):
return -np.diag(np.ones(N)) @ mins.reshape(3,N)[2] + (np.ones(N))*np.pi/2
con1b = {'type': 'ineq', 'fun': lambda b: blhs(b)}
con2b = {'type': 'ineq', 'fun': lambda b: brhs(b)}
我的 function 將其他參數(並采用N=3
)最小化,由(如果太長,我很抱歉)給出:
gamma = 17
C = 85
T = 0
Hf = 0.5
Li = 2
Bi = 1
N = 3
def FUN(mins):
H, a, b = mins.reshape(3,N)
S1 = 0; S2 = 0
B = np.zeros(N); L = np.zeros(N);
for i in range(N):
sbi=Bi; sli=Li
for j in range(i+1):
sbi += 2*H[j]*np.tan(b[j])
sli += 2*H[j]*np.tan(a[j])
B[i]=sbi
L[i]=sli
for i in range(N):
S1 += (C*(1-np.sin(a[i])) + T*np.sin(a[i])) * (Bi*H[i]+H[i]**2*np.tan(b[i]))/np.cos(a[i]) + \
(C*(1-np.sin(b[i])) + T*np.sin(b[i])) * (Li*H[i]+H[i]**2*np.tan(a[i]))/np.cos(b[i])
S2 += (gamma*H[0]/12)*(Bi*Li + 4*(B[0]-H[0]*np.tan(b[0]))*(L[0]-H[0]*np.tan(a[0])) + B[0]*L[0])
j=1
while j<(N):
S2 += (gamma*H[j]/12)*(B[j-1]*L[j-1] + 4*(B[j]-H[j]*np.tan(b[j]))*(L[j]-H[j]*np.tan(a[j])) + B[j]*L[j])
j += 1
F = 2*(S1+S2)
return F
最后,采用初始猜測值作為 0,最小化由下式給出:
x0 = np.zeros(3*N)
res = scipy.optimize.minimize(FUN,x0,constraints=(con1H,con2H,con1a,con2a,con1b,con2b),tol=1e-25)
我的問題是:
a)觀察結果res
,即使我有約束使它們為正,一些值也變為負值。 最小化的成功是False
,消息是: Positive directional derivative for linesearch
。 此外,結果與預期的最小值相差甚遠。
b) 采用method='trust-constr'
我得到的值更接近於我的預期,但失敗了,並且消息The maximum number of function evaluations is exceeded.
. 有什么辦法可以改善這一點嗎?
我知道有一個最小值非常接近這些值:
H = [0.2,0.15,0.15]
a = [1.0053,1.0053,1.2566]
b = [1.0681,1.1310,1.3195]
其中 function 的值為123,45
。 我已經檢查了 function 幾次,它似乎工作正常。 誰能幫我找出我的問題在哪里? 我試圖改變xtol
和maxiter
但沒有成功。 先感謝您!
這里有一些提示:
您的初始點x0
不可行,因為它不滿足約束sum(H) = 0.5
。 提供一個可行的初始點應該可以解決您的第一個問題。
除了約束sum(H) = 0.5
,所有約束都是變量的簡單界限。 一般來說,建議minimize
minimum 的bounds
參數傳遞變量邊界。 您可以像這樣簡單地定義並傳遞所有邊界
from scipy.optimize import minimize
import numpy as np
# ..your variables and functions ..
bounds = [(0, None)]*N + [(0, np.pi/2)]*2*N
x0 = np.zeros(3*N)
x0[0] = 0.5
res = minimize(FUN, x0, constraints=(con2H,), bounds=bounds,
method="trust-constr", options={'maxiter': 20000})
其中每個元組包含每個變量的下限和上限。
from cyipopt import minimize_ipopt
# rest as above
res = minimize_ipopt(FUN, x0, constraints=(con2H,), bounds=bounds)
這給了我一個目標值為 122.9 的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.