2016-06-13 2 views
1

は、以下の(凸)最適化問題を考えてみて失敗します。Scipy.optimize.minimize SLSQPは

最適化(ベクトル)の変数は、 bは行列とベクトルあり、 xyAある
minimize 0.5 * y.T * y 
s.t.  A*x - b == y 

それぞれ適切な寸法のものである。制約関数が便利「アレイ出力」関数であること

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のダウンロードからSLSQP方法を使用して解を求めます。

ここでは、制約の配列出力関数の代わりに、原則として同等の「スカラー出力」制約関数のセットを使用することができます(実際には、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へのすべてのコールは、修正はなく、ラムダ関数クロージャの制約を定義辞書にargs辞書要素を使用することで19

に等しい第2引数でなされていますこれにより、最小化は動作します:

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 

あなたはまた、所望のデを有する第2引数でラムダ式を使用することでリンク先の記事で行われた提案を、使用することができます障害の値:

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

ご回答いただきありがとうございます。 – Stelios