当我尝试使用 for 循环设置约束时,Scipy 优化未运行

dic*_*119 1 python optimization scipy

我试图在使用 for 循环来设置约束的同时最小化目标函数,使得 x1 = x2 = ... xn。但是,优化似乎不起作用。即结束 x 仍然等于初始 x。我收到了“LSQ 子问题中的奇异矩阵 C”的错误消息。

covariance_matrix = np.matrix([[0.159775519, 0.022286316, 0.00137635, -0.001861736],
                     [0.022286316, 0.180593862, -5.5578e-05, 0.00451056], 
                     [0.00137635, -5.5578e-05, 0.053093075, 0.02240866], 
                     [-0.001861736, 0.00451056, 0.02240866, 0.053778594]]) 

x0 = np.matrix([0.2,0.2,0.3,0.4])


fun = lambda x: x.dot(covariance_matrix).dot(x.transpose())
cons = np.array([])
for i in range(0,x0.size-1):
    con = {'type': 'eq', 'fun': lambda x:  x[i] - x[i+1]}    
    cons = np.append(cons, con)

con = {'type': 'eq', 'fun': lambda x:  sum(x)-1}   
cons = np.append(cons, con) 

solution = minimize(fun,x0,method='SLSQP',constraints = cons)


solution message:   Singular matrix C in LSQ subproblem
solution status:   6
solution success:   False
Run Code Online (Sandbox Code Playgroud)

但是如果我一一附加约束,那么它就可以完美运行,这意味着结果给了我 x1 = x2 = x3 = x4

con1 = {'type': 'eq', 'fun': lambda x:  sum(x)-1}   
con2 = {'type': 'eq', 'fun': lambda x:  x[1]-x[0]}   
con3 = {'type': 'eq', 'fun': lambda x:  x[2]-x[1]}   
con4 = {'type': 'eq', 'fun': lambda x:  x[3]-x[2]}   
cons = np.append(cons, con1) 
cons = np.append(cons, con2) 
cons = np.append(cons, con3) 
cons = np.append(cons, con4) 

solution message:   Optimization terminated successfully.
solution status:   0
solution success:   True
Run Code Online (Sandbox Code Playgroud)

War*_*ser 5

(注意:虽然细节不同,但这个问题与Scipy.optimize.minimize SLSQP with linear constraints failed 大致相同)

你的循环是

for i in range(0,x0.size-1):
    con = {'type': 'eq', 'fun': lambda x:  x[i] - x[i+1]}    
    cons = np.append(cons, con)
Run Code Online (Sandbox Code Playgroud)

问题是i在 lambda 表达式中的使用。 Python 闭包是“后期绑定”。这意味着i调用函数时使用的值与i创建函数时使用的值不同。循环后, 的值为i2,因此循环中创建的所有函数计算的表达式为x[2] - x[3]。(这也解释了错误消息中提到的“奇异矩阵 C”。)

解决此问题的一种方法是为ilambda 表达式创建一个参数,其默认值为 current i

    con = {'type': 'eq', 'fun': lambda x, i=i:  x[i] - x[i+1]}
Run Code Online (Sandbox Code Playgroud)

  • 完美的答案! (2认同)