Scipy.optimize violating/not 尊重约束
Scipy.optimize violating/not respecting constraint
问题定义如下:
- Objective函数:最大化Z = 45x1 + 20x2
- 约束 1 (material):20x1 + 5x2 ≤ 9500
- 约束2(时间):0.04x1 + 0.12x2 ≤ 40
- 约束 3(存储):x1 + x2 ≤ 550
- 阳性:x1, x2 ≥ 0
这是按照 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 形式表述问题。
问题定义如下:
- Objective函数:最大化Z = 45x1 + 20x2
- 约束 1 (material):20x1 + 5x2 ≤ 9500
- 约束2(时间):0.04x1 + 0.12x2 ≤ 40
- 约束 3(存储):x1 + x2 ≤ 550
- 阳性:x1, x2 ≥ 0
这是按照 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 形式表述问题。