最优解

优化模型的三个要素

  • 决策变量
  • 目标函数
  • 约束条件

决策变量和约束条件可以有多个,但目标只有一个

我们可以使用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))

results matching ""

    No results matching ""