SLSQP 不尊重约束



我有一个非线性优化问题

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 >= 0ub - 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)
] 

最新更新