Python Scipy最小化成功终止,但不’;不满足不等式约束
我试图最小化函数0.5*(x^2+y^2),受一系列形式为x a1+y a2+a3 z>=1的不等式约束(N=20)。溶液应在x=0.50251,y=-0.5846,z=0.36787左右。例程以消息“Optimization terminated successfully”(优化已成功终止)终止,但超过一半的约束未得到遵守。我还尝试了不同的解算器,得到了相同的结果 缩放目标函数会改变解,但不会收敛到预期解Python Scipy最小化成功终止,但不’;不满足不等式约束,python,scipy-optimize-minimize,Python,Scipy Optimize Minimize,我试图最小化函数0.5*(x^2+y^2),受一系列形式为x a1+y a2+a3 z>=1的不等式约束(N=20)。溶液应在x=0.50251,y=-0.5846,z=0.36787左右。例程以消息“Optimization terminated successfully”(优化已成功终止)终止,但超过一半的约束未得到遵守。我还尝试了不同的解算器,得到了相同的结果 缩放目标函数会改变解,但不会收敛到预期解 from scipy.optimize import minimize import n
from scipy.optimize import minimize
import numpy as np
Pct=np.array([[-0.664, 3.179],[ 0.231, -2.044],[-2.493, 3.25 ],[ 0.497, -0.654],[-1.27, 1.248],[-1.185, 1.814],[-1.843, 4.386],[-1.616, 1.401],[ 0.052, -1.232],[-3.145, 0.404],[ 0.672, -1.655],[ 2.202, -1.888],[ 4.084, -1.067],[ 1.006, -1.671],[-2.255, 1.51 ],[-1.264, 1.663],[ 1.897, -2.217],[ 1.843, -1.276],[-1.693, 1.623],[ 2.297, -1.709]])
Sid=np.array([-1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1])
# func to be minimized
def OptFunc(x):
return 0.5*(x[0]**2+x[1]**2)
def JacOptFunc(x):
return np.array([x[0],x[1],0.0])
# Constraints
c=[]
for i in range(len(Sid)):
c+=[{'type': 'ineq', 'fun': lambda x: Sid[i]*(x[0]*Pct[i,0]+x[1]*Pct[i,1]+x[2])-1 }]
cons=tuple(c)
# start optimization
res = minimize(OptFunc,(0.3,-0.2,0.1),constraints=cons,method='SLSQP',jac=JacOptFunc)
#expected solution should be around
# [0.5025062702615434, -0.584685257866671, 0.36787016514022236]
print("-->",res.message)
print("solution ",res.x,flush=True)
print("Check Constraints")
cons=list(cons)
for i in range(len(cons)):
lokfun=c[i]['fun']
print("Constraint # ",i," value: ",lokfun(res.x))
预期的结果就在眼前
x=0.50251,y=-0.5846,z=0.36787
但我得到以下输出:
--> Optimization terminated successfully.
solution [-1.14580677e-04 -1.16285140e-04 1.00006446e+00]
Check Constraints
Constraint # 0 value: -1.9997708716077622
Constraint # 1 value: 0.0002756791862408292
Constraint # 2 value: -1.999972183420499
Constraint # 3 value: 8.356438220613605e-05
Constraint # 4 value: -2.0000648541023893
Constraint # 5 value: -1.9999892973558606
Constraint # 6 value: -1.9997656060620763
Constraint # 7 value: -2.000086707390163
Constraint # 8 value: 0.00020176559401496874
Constraint # 9 value: -2.0003778375289833
Constraint # 10 value: 0.00017991418852214558
Constraint # 11 value: 3.1700190727068644e-05
Constraint # 12 value: -0.0002794107423930159
Constraint # 13 value: 0.00014350480474445426
Constraint # 14 value: -2.000147249362345
Constraint # 15 value: -2.0000159082853974
Constraint # 16 value: 0.00010490510804150865
Constraint # 17 value: 1.6681482228886324e-06
Constraint # 18 value: -2.0000697148012767
Constraint # 19 value: -1.354516498963676e-11
我对scipy.optimize知之甚少,但我能发现一个问题
for i in range(len(Sid)):
c+=[{'type': 'ineq', 'fun': lambda x: Sid[i]*(x[0]*Pct[i,0]+x[1]*Pct[i,1]+x[2])-1 }]
问题在于Python闭包是后期绑定的,这意味着每个约束中i
的值实际上是在循环完成后计算的。实际上,您实际上施加了相同的(最后一个)约束20次。看
一个可能的解决方案:
from scipy.optimize import minimize
import numpy as np
Pct=np.array([[-0.664, 3.179],[ 0.231, -2.044],[-2.493, 3.25 ],[ 0.497, -0.654],[-1.27, 1.248],[-1.185, 1.814],[-1.843, 4.386],[-1.616, 1.401],[ 0.052, -1.232],[-3.145, 0.404],[ 0.672, -1.655],[ 2.202, -1.888],[ 4.084, -1.067],[ 1.006, -1.671],[-2.255, 1.51 ],[-1.264, 1.663],[ 1.897, -2.217],[ 1.843, -1.276],[-1.693, 1.623],[ 2.297, -1.709]])
Sid=np.array([-1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1])
# func to be minimized
def OptFunc(x):
return 0.5*(x[0]**2+x[1]**2)
def JacOptFunc(x):
return np.array([x[0],x[1],0.0])
# Constraints
def constraint_maker(i=0): # i MUST be an optional keyword argument, else it will not work
def constraint(x):
return Sid[i]*(x[0]*Pct[i,0]+x[1]*Pct[i,1]+x[2])-1
return constraint
c=[]
for i in range(len(Sid)):
c+=[{'type': 'ineq', 'fun': constraint_maker(i)}]
cons=tuple(c)
# start optimization
res = minimize(OptFunc,(0.3,-0.2,0.1),constraints=cons,method='SLSQP',jac=JacOptFunc)
#expected solution should be around
# [0.5025062702615434, -0.584685257866671, 0.36787016514022236]
print("-->",res.message)
print("solution ",res.x)
print("Check Constraints")
cons=list(cons)
for i in range(len(cons)):
lokfun=c[i]['fun']
print("Constraint # ",i," value: ",lokfun(res.x))
导致
--> Optimization terminated successfully.
solution [ 0.52374351 -0.56495542 0.37021863]
Check Constraints
Constraint # 0 value: 0.7735403550593944
Constraint # 1 value: 0.6459722649608017
Constraint # 2 value: 1.7715790719554194
Constraint # 3 value: 8.137268636687622e-11
Constraint # 4 value: -2.2235047136831554e-10
Constraint # 5 value: 0.27524657110337936
Constraint # 6 value: 2.0729351509689136
Constraint # 7 value: 0.2676534344356165
Constraint # 8 value: 0.09347837249122604
Constraint # 9 value: 0.5051967055706261
Constraint # 10 value: 0.6571754935710583
Constraint # 11 value: 1.5901376792721638
Constraint # 12 value: 2.1119945643862095
Constraint # 13 value: 0.8411451130595076
Constraint # 14 value: 0.6639056792092357
Constraint # 15 value: 0.23131403951409935
Constraint # 16 value: 1.6162662427554526
Constraint # 17 value: 1.0563610395273058
Constraint # 18 value: 0.43340178883510116
Constraint # 19 value: 1.5387662919992176
非常感谢你。你知道为什么它没有出现在检查约束输出中(我引用了相同的元组)。这些值不同,因此i值似乎在那里发生了变化,但在最小化函数调用中没有变化?@Emi可能是由于lambda求值的诡计(即,如果lambda绑定发生多次)?不过这只是一个粗略的猜测,我没有真正的想法。@Leporello再次感谢。@Emi如果您的问题得到解决,请接受此答案,将问题标记为已回答:)