最优解
优化模型的三个要素
- 决策变量
- 目标函数
- 约束条件
决策变量和约束条件可以有多个,但目标只有一个
我们可以使用Excel的solver插件或Python的scipy库等,来求解最优解
案例1
某自行车厂有2款产品,A产品利润150元,B产品利润160元
生产A产品和B产品分别需要如下工时,单位:小时
型号 | 车架 | 车轮和踏板 | 组装 |
---|---|---|---|
A产品 | 4 | 1.5 | 1 |
B产品 | 5 | 2 | 0.8 |
假设下一周生产可用工时已定,那么A产品和B产品分别生产多少量,才能实现利润最大化
生产步骤 | 可用工时 |
---|---|
车架制造 | 5610 |
车轮和踏板 | 2200 |
组装 | 1200 |
第一步,确定决策变量
- a - 要生产A产品的数量
- b - 要生产B产品的数量
第二步,定义目标函数
目标函数:150a + 160b
通过调整a和b的值,来实现利润最大化
第三步,确定约束条件
4a + 5b <= 5610
1.5a + 2b <= 2200
1a + 0.8b <= 1200
a >= 0 && b >= 0
a和b都为整数(整数不做约束,会增加优化算法的复杂度,直接在返回值的转换下并人为验证下结果是否有误差)
import numpy as np
from scipy import optimize
# 目标函数(计算结果)
def calcNumber(x):
return 150 * x[0] + 160 * x[1]
# 目标函数(minimize是求最小值的,我们需要的是最大值,所以将计算结果取反)
def objective(x):
return -calcNumber(x)
# 约束条件(ineq表示大于等于(eq表示等于),fun表示约束函数)
cons = (
{'type': 'ineq', 'fun': lambda x: 5610 - (4 * x[0] + 5 * x[1])},
{'type': 'ineq', 'fun': lambda x: 2200 - (1.5 * x[0] + 2 * x[1])},
{'type': 'ineq', 'fun': lambda x: 1200 - (1 * x[0] + 0.8 * x[1])},
{'type': 'ineq', 'fun': lambda x: x[0]},
{'type': 'ineq', 'fun': lambda x: x[1]}
)
# 初始猜测值
x0 = np.array([100, 200])
# 最优解计算(SLSQP表示使用最小二乘法,disp:True显示收敛信息)
res = optimize.minimize(objective, x0, method='SLSQP', constraints=cons, options={"disp": True})
print(res)
# 输出计算结果
print(calcNumber([int(x) for x in res.x]))
案例2
某饮料公司有3个仓库,共有65吨混合饮料,下个月必须运送到配送中心,以便留出新的库存空间
A仓库15吨,B仓库20吨,C仓库30吨
然后该公司的配送中心也有发货的需求,到货量至少满足如下需求
D配送中心10吨,E配送中心13吨,F配送中心20吨
但是不同仓库和配送中心的距离不同,所以运输成本也是不同的,单位:元/吨
发货/收货 | D配送中心 | E配送中心 | F配送中心 |
---|---|---|---|
A仓库 | 105 | 135 | 153 |
B仓库 | 110 | 140 | 137 |
C仓库 | 130 | 132 | 115 |
在不考虑单车荷载量的情况下,如何运输才能实现运输成本最低
第一步,确定决策变量
- ad - A仓库往D配送中心运输
- ae - A仓库往E配送中心运输
- af - A仓库往F配送中心运输
- bd - B仓库往D配送中心运输
- be - B仓库往E配送中心运输
- bf - B仓库往F配送中心运输
- cd - C仓库往D配送中心运输
- ce - C仓库往E配送中心运输
- cf - C仓库往F配送中心运输
第二步,定义目标函数
目标函数: 105ad + 135ae + 153af + 110bd + 140be + 137bf + 130cd + 132ce + 115cf
通过调整ad到cf的值,来实现成本最小化
第三步,确定约束条件
ad + ae + af = 15
bd + be + bf = 20
cd + ce + cf = 30
ad + bd + cd >= 10
ae + be + ce >= 13
af + bf + cf >= 20
ad到cf的值全部 >= 0
import numpy as np
from scipy import optimize
# 目标函数
def targetFunction(x):
return 105 * x[0] + 135 * x[1] + 153 * x[2] + 110 * x[3] + 140 * x[4] + 137 * x[5] + 130 * x[6] + 132 * x[7] + 115 * \
x[8]
# 约束条件,变量大于0在bounds中约束
cons = (
{'type': 'eq', 'fun': lambda x: x[0] + x[1] + x[2] - 15},
{'type': 'eq', 'fun': lambda x: x[3] + x[4] + x[5] - 20},
{'type': 'eq', 'fun': lambda x: x[6] + x[7] + x[8] - 30},
{'type': 'ineq', 'fun': lambda x: x[0] + x[3] + x[6] - 10},
{'type': 'ineq', 'fun': lambda x: x[1] + x[4] + x[7] - 13},
{'type': 'ineq', 'fun': lambda x: x[2] + x[5] + x[8] - 20}
)
# 初始化猜测值
x0 = np.array([10] * 9)
# 9个变量的取值范围(最小值0,最大值不限制)
bounds = [(0, None)] * 9
# 最优解计算
res = optimize.minimize(targetFunction, x0, method='SLSQP', constraints=cons, bounds=bounds, options={"disp": True})
print(res)
# 输出结果
print(targetFunction(res.x))