考慮以下(凸)的最優化問題:Scipy.optimize.minimize SLSQP線性約束失敗
minimize 0.5 * y.T * y
s.t. A*x - b == y
其中優化(矢量)變量x
和y
和A
,b
是一個矩陣和向量,分別具有適當的尺寸。
下面的代碼查找容易使用SLSQP
方法從SciPy的一個解決方案:
import numpy as np
from scipy.optimize import minimize
# problem dimensions:
n = 10 # arbitrary integer set by user
m = 2 * n
# generate parameters A, b:
np.random.seed(123) # for reproducibility of results
A = np.random.randn(m,n)
b = np.random.randn(m)
# objective function:
def obj(z):
vy = z[n:]
return 0.5 * vy.dot(vy)
# constraint function:
def cons(z):
vx = z[:n]
vy = z[n:]
return A.dot(vx) - b - vy
# constraints input for SLSQP:
cons = ({'type': 'eq','fun': cons})
# generate a random initial estimate:
z0 = np.random.randn(n+m)
sol = minimize(obj, x0 = z0, constraints = cons, method = 'SLSQP', options={'disp': True})
Optimization terminated successfully. (Exit mode 0) Current function value: 2.12236220865 Iterations: 6 Function evaluations: 192 Gradient evaluations: 6
注意,約束函數是一個方便的「點陣 - 輸出」功能。
現在,原則上可以使用一組等效的'標量輸出'約束函數(實際上,scipy.optimize文檔僅討論這種類型的約束函數作爲輸入到minimize
)。
下面是對應的約束集然後minimize
的輸出(同樣A
,b
,和初始值與上述列表):
# this is the i-th element of cons(z):
def cons_i(z, i):
vx = z[:n]
vy = z[n:]
return A[i].dot(vx) - b[i] - vy[i]
# listable of scalar-output constraints input for SLSQP:
cons_per_i = [{'type':'eq', 'fun': lambda z: cons_i(z, i)} for i in np.arange(m)]
sol2 = minimize(obj, x0 = z0, constraints = cons_per_i, method = 'SLSQP', options={'disp': True})
Singular matrix C in LSQ subproblem (Exit mode 6) Current function value: 6.87999270692 Iterations: 1 Function evaluations: 32 Gradient evaluations: 1
顯然,算法失敗(返回的目標值實際上是給定初始化的目標值),我覺得有點奇怪。請注意,運行[cons_per_i[i]['fun'](sol.x) for i in np.arange(m)]
顯示使用陣列輸出約束公式獲得的sol.x
滿足所有標量輸出約束條件cons_per_i
(如數值公差)。
如果有人對此問題有一些解釋,我將不勝感激。
非常感謝您的幫助! – Stelios