Scipy.optimize violating/not 尊重约束

Scipy.optimize violating/not respecting constraint

问题定义如下:

这是按照 Python 中的以下步骤完成的:

# import libraries
import numpy as np
import scipy.optimize as so

# Initialization
bnds = ((0, 550), (0, 550))
initial = np.asarray([400, 150])

# objective function
def maxZ(x_in, sign=1.0):
    x1, x2 = x_in[0:2]
    return sign * (45 * x1 + 20 * x2)

# constraints
def Cmaterial(x_in):
    x1, x2 = x_in[0:2]
    return 20 * x1 + 5 * x2 - 9500

def Ctime(x_in):
    x1, x2 = x_in[0:2]
    return 0.04 * x1 + 0.12 * x2 - 40

def Cstorage(x_in):
    x1, x2 = x_in[0:2]
    return x1 + x2 - 550

# constraint terms
con1 = {'type':'ineq', 'fun':Cmaterial}
con2 = {'type':'ineq', 'fun':Ctime}
con3 = {'type':'ineq', 'fun':Cstorage}
cons = [con1, con2, con3]

# Optimization
out = so.minimize(maxZ, initial, method='SLSQP', bounds=bnds, constraints=cons, args=(1.0,))
print(f"Optimum solution occurs at {out.x}, where Z = {out.fun}")
print(f"Material: {Cmaterial(out.x) + 9500}")
print(f"Production time: {Ctime(out.x) + 40}")
print(f"Storage: {Cstorage(out.x) + 550}")

结果是:

Optimum solution occurs at [427.27272727 190.90909091], where Z = 23045.45454545614
Material: 9500.00000000076
Production time: 40.00000000000009
Storage: 618.1818181818464

我已经通过图解法和Excel验证了预期的结果应该是x1 = 450, x2 = 100.

Scipy.optimize的结果是 x1 = 427.27, x2 = 190.91.

我的问题:x1 + x2 ≤ 550 的存储约束显然被违反了,因为结果是 618.18。这可能是什么原因?

首先,您需要将最大化问题转化为最小化问题,即 maxZ 中的 sign 参数应该是 -1.0,而不是 1.0。另请注意,scipy.optimize.minimize 期望 g(x) >= 0 的不等式约束,而不是 g(x) <= 0。因此,您必须相应地转换约束:

con1 = {'type':'ineq', 'fun': lambda x: -1.0*Cmaterial(x)}
con2 = {'type':'ineq', 'fun': lambda x: -1.0*Ctime(x)}
con3 = {'type':'ineq', 'fun': lambda x: -1.0*Cstorage(x)}
cons = [con1, con2, con3]

out = so.minimize(maxZ, initial, method='SLSQP', bounds=bnds, constraints=cons, args=(-1.0,))

产生您预期的解决方案。最后但同样重要的是,这是一个线性优化问题 (LP),因此应该用 scipy.optimize.linprog 来解决。但是,这需要您以标准的 LP 形式表述问题。