Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
643 views
in Technique[技术] by (71.8m points)

python - Scipy Optimization Not Running when I try to set constraints using a for loop

I was trying to minimize the objective function while using a for loop to set the constraints such that x1 = x2 = ... xn. However, the optimization doesn't seem to work. I.e. the end x still equals to the initial x. And I am getting an error message of 'Singular matrix C in LSQ subproblem'.

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

But if I append the constraints one by one, then it works perfectly, meaning the result gives me 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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

(Note: while the details are different, this question is about the same problem as Scipy.optimize.minimize SLSQP with linear constraints fails)

Your loop is

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

The problem is the use of i in the lambda expression. Python closures are "late binding". That means the value of i that is used when the function is called is not the same as the value of i when the function was created. After the loop, the value of i is 2, so the expression evaluated by all the functions created in the loop is x[2] - x[3]. (That also explains the "singular matrix C" referred to in the error message.)

One way to fix this is to make i an argument of the lambda expression whose default value is the current i:

    con = {'type': 'eq', 'fun': lambda x, i=i:  x[i] - x[i+1]}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...