首页 > 解决方案 > 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 非常接近真正的最优值(对于这组输入值,这个问题可以解析解决,对于其他值没有解析解)

标签: pythonscipyscipy-optimize

解决方案


字典约束中不支持下限和上限。您需要重新制定约束函数以尊重边界。注意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)
] 

推荐阅读