2016-06-13 149 views
1

考慮以下(凸)的最優化問題:Scipy.optimize.minimize SLSQP線性約束失敗

minimize 0.5 * y.T * y 
s.t.  A*x - b == y 

其中優化(矢量)變量xyAb是一個矩陣和向量,分別具有適當的尺寸。

下面的代碼查找容易使用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的輸出(同樣Ab,和初始值與上述列表):

# 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(如數值公差)。

如果有人對此問題有一些解釋,我將不勝感激。

回答

3

您已經遇到了"late binding closures" gotcha

cons_per_i = [{'type':'eq', 'fun': cons_i, 'args': (i,)} for i in np.arange(m)] 

:所有以cons_i呼叫正在與第二個參數等於19

一個修復程序是使用args字典元件在定義的約束,而不是lambda函數封閉字典制成由此,最小化的工作原理:

In [417]: sol2 = minimize(obj, x0 = z0, constraints = cons_per_i, method = 'SLSQP', options={'disp': True}) 
Optimization terminated successfully. (Exit mode 0) 
      Current function value: 2.1223622086 
      Iterations: 6 
      Function evaluations: 192 
      Gradient evaluations: 6 

您還可以使用鏈接的文章,這是使用lambda表達式與具有所期望的德第二個參數中所提出的建議故障值:

cons_per_i = [{'type':'eq', 'fun': lambda z, i=i: cons_i(z, i)} for i in np.arange(m)] 
+0

非常感謝您的幫助! – Stelios