SLSQP 不遵守约束
SLSQP doesn't respect constraints
我有这个非线性优化问题
import math
from scipy.optimize import minimize
# Constants
mud = 0.6
fyd_mm2 = 1.1
fxd_mm2 = 3.5
# Inputs
Nxd_norm = 0.5
ratio_lwhw = 2
tw = 0.15
hw = 3
# derived constants
fyd = fyd_mm2*1e6
fxd = fxd_mm2*1e6
# derived inputs
lw = hw * ratio_lwhw
Nxd = Nxd_norm * lw * tw * fxd
def ey2v(x):
return (lw-x[0])/2
def ey2m(x):
return (lw-x[1])/2
def alpha(x):
return x[2]
def Nxdv(x):
delta = 0
if ey2v(x) == ey2m(x):
delta = 0.0000001
return Nxd*ey2m(x)/(hw*math.tan(alpha(x))-ey2v(x)+ey2m(x)+delta)
def Nxdm(x):
return Nxd-Nxdv(x)
def VRd(x):
return Nxdv(x)*math.tan(alpha(x))
# x = l2v, l2m, alpha
def F(x):
alpha = x[2]
ey2m = (lw-x[1])/2
ey2v = (lw-x[0])/2
# avoid possible null division
delta = 0
if ey2v == ey2m:
delta = 0.0000001
Nxdv = Nxd*ey2m/(hw*math.tan(alpha)-ey2v+ey2m+delta)
VRd = Nxdv*math.tan(alpha)
r = VRd/lw/fyd/tw
return -r
x0 = (4.1, 5.1, 0.54)
con1 = lambda x: Nxdv(x)/x[0]/math.cos(alpha(x))/math.cos(alpha(x))
con2 = lambda x: Nxdm(x)/x[1]
con3 = lambda x: math.tan(x[2])
con4 = lambda x: x[0]+math.tan(x[2])*hw
cons = [{'type': 'ineq', 'fun': con1, 'ub': fyd*tw, 'lb': 0 },
{'type': 'ineq', 'fun': con2, 'ub': (fxd-fyd)*tw, 'lb': 0 },
{'type': 'ineq', 'fun': con3, 'ub': mud, 'lb': -100000 },
{'type': 'ineq', 'fun': con4, 'ub': lw, 'lb': -10000 }]
res = minimize(F, [lw/2, lw/4, 0.4], method='SLSQP', constraints=cons)
print(res)
print('con1: ', con1(res.x), ', con2: ', con2(res.x), ', con3: ', con3(res.x), ', con4: ', con4(res.x))
print('con1: ', fyd*tw, ', con2: ', (fxd-fyd)*tw, ', con3: ', mud, ', con4: ', lw)
问题是,这段代码产生了这个:
fun: -1.5909091565619955
jac: array([ 1.56119466e-04, 0.00000000e+00, -3.17994511e+00])
message: 'Optimization terminated successfully'
nfev: 543
nit: 87
njev: 85
status: 0
success: True
x: array([ 7.23940719e-09, -1.01853916e+04, 7.06858349e+00])
con1: 435118518573387.75 , con2: -3.869023343449402e-09 , con3: 1.0000000412925607 , con4: 3.0000001311170896
con1: 165000.0 , con2: 360000.0 , con3: 0.6 , con4: 6
所以它说成功了,但是显然不满足条件(最后两行)。为什么?顺便说一句,x0 被选择为非常接近真正的最优值(这个问题可以针对这组输入值解析解决,对于其他值没有解析解决方案)
不支持字典约束中的下限和上限。您需要重新制定约束函数以尊重边界。请注意,lb <= fun(x) <= ub
等同于约束 fun(x) - lb >= 0
和 ub - fun(x) >= 0
。或者,您可以使用 NonlinearConstraint
个对象:
from scipy.optimize import NonlinearConstraint
cons = [
NonlinearConstraint(con1, 0, fyd*tw),
NonlinearConstraint(con2, 0, (fxd-fyd)*tw),
NonlinearConstraint(con3, -100000, mud),
NonlinearConstraint(con4, -10000, lw)
]
我有这个非线性优化问题
import math
from scipy.optimize import minimize
# Constants
mud = 0.6
fyd_mm2 = 1.1
fxd_mm2 = 3.5
# Inputs
Nxd_norm = 0.5
ratio_lwhw = 2
tw = 0.15
hw = 3
# derived constants
fyd = fyd_mm2*1e6
fxd = fxd_mm2*1e6
# derived inputs
lw = hw * ratio_lwhw
Nxd = Nxd_norm * lw * tw * fxd
def ey2v(x):
return (lw-x[0])/2
def ey2m(x):
return (lw-x[1])/2
def alpha(x):
return x[2]
def Nxdv(x):
delta = 0
if ey2v(x) == ey2m(x):
delta = 0.0000001
return Nxd*ey2m(x)/(hw*math.tan(alpha(x))-ey2v(x)+ey2m(x)+delta)
def Nxdm(x):
return Nxd-Nxdv(x)
def VRd(x):
return Nxdv(x)*math.tan(alpha(x))
# x = l2v, l2m, alpha
def F(x):
alpha = x[2]
ey2m = (lw-x[1])/2
ey2v = (lw-x[0])/2
# avoid possible null division
delta = 0
if ey2v == ey2m:
delta = 0.0000001
Nxdv = Nxd*ey2m/(hw*math.tan(alpha)-ey2v+ey2m+delta)
VRd = Nxdv*math.tan(alpha)
r = VRd/lw/fyd/tw
return -r
x0 = (4.1, 5.1, 0.54)
con1 = lambda x: Nxdv(x)/x[0]/math.cos(alpha(x))/math.cos(alpha(x))
con2 = lambda x: Nxdm(x)/x[1]
con3 = lambda x: math.tan(x[2])
con4 = lambda x: x[0]+math.tan(x[2])*hw
cons = [{'type': 'ineq', 'fun': con1, 'ub': fyd*tw, 'lb': 0 },
{'type': 'ineq', 'fun': con2, 'ub': (fxd-fyd)*tw, 'lb': 0 },
{'type': 'ineq', 'fun': con3, 'ub': mud, 'lb': -100000 },
{'type': 'ineq', 'fun': con4, 'ub': lw, 'lb': -10000 }]
res = minimize(F, [lw/2, lw/4, 0.4], method='SLSQP', constraints=cons)
print(res)
print('con1: ', con1(res.x), ', con2: ', con2(res.x), ', con3: ', con3(res.x), ', con4: ', con4(res.x))
print('con1: ', fyd*tw, ', con2: ', (fxd-fyd)*tw, ', con3: ', mud, ', con4: ', lw)
问题是,这段代码产生了这个:
fun: -1.5909091565619955
jac: array([ 1.56119466e-04, 0.00000000e+00, -3.17994511e+00])
message: 'Optimization terminated successfully'
nfev: 543
nit: 87
njev: 85
status: 0
success: True
x: array([ 7.23940719e-09, -1.01853916e+04, 7.06858349e+00])
con1: 435118518573387.75 , con2: -3.869023343449402e-09 , con3: 1.0000000412925607 , con4: 3.0000001311170896
con1: 165000.0 , con2: 360000.0 , con3: 0.6 , con4: 6
所以它说成功了,但是显然不满足条件(最后两行)。为什么?顺便说一句,x0 被选择为非常接近真正的最优值(这个问题可以针对这组输入值解析解决,对于其他值没有解析解决方案)
不支持字典约束中的下限和上限。您需要重新制定约束函数以尊重边界。请注意,lb <= fun(x) <= ub
等同于约束 fun(x) - lb >= 0
和 ub - fun(x) >= 0
。或者,您可以使用 NonlinearConstraint
个对象:
from scipy.optimize import NonlinearConstraint
cons = [
NonlinearConstraint(con1, 0, fyd*tw),
NonlinearConstraint(con2, 0, (fxd-fyd)*tw),
NonlinearConstraint(con3, -100000, mud),
NonlinearConstraint(con4, -10000, lw)
]