Pulp之三:官网上的应用样例(4)-Blending Problem (混合问题)
We're going to make some sausages!
We have the following ingredients available to us:
Ingredient Cost (€/kg) Availability (kg)
Pork 4.32 30
Wheat 2.46 20
Starch 1.86 17
We'll make 2 types of sausage:
Economy (>40% Pork)
Premium (>60% Pork)
One sausage is 50 grams (0.05 kg)
According to government regulations, the most starch we can use in our sausages is 25%
We have a contract with a butcher, and have already purchased 23 kg pork, that will go bad if it's not used.
We have a demand for 350 economy sausages and 500 premium sausages.
We need to figure out how to most cost effectively blend our sausages.
Let's model our problem
pe = Pork in the economy sausages (kg)
we = Wheat in the economy sausages (kg)
se = Starch in the economy sausages (kg)
pp = Pork in the premium sausages (kg)
wp = Wheat in the premium sausages (kg)
sp = Starch in the premium sausages (kg)
We want to minimise costs such that:
Cost = 0.72(pe + pp) + 0.41(we + wp) + 0.31(se + sp)
With the following constraints:
pe + we + se = 350 * 0.05
pp + wp + sp = 500 * 0.05
pe ≥ 0.4(pe + we + se)
pp ≥ 0.6(pp + wp + sp)
se ≤ 0.25(pe + we + se)
sp ≤ 0.25(pp + wp + sp)
pe + pp ≤ 30
we + wp ≤ 20
se + sp ≤ 17
pe + pp ≥ 23
问题描述:
假设有如下3种原料(ingredients)猪肉、小麦和淀粉,它们各自的价格和数量如下表:
原料 成本 (€/kg) 数量 (kg)
猪肉 pork 4.32 30
小麦 wheat 2.46 20
淀粉 starch 1.86 17
我们可以用这些原料(sausage_types)制作两种烤肠:
economy便宜的 (猪肉含量>40%)
premium贵的 (猪肉含量>60%)
每根香肠重量为50克(0.05 kg)。政府部门规定淀粉的含量不能超过25%。另外我们和一个屠宰场签定了合约,
至少要购买23kg的猪肉。我们的客户向我们订购了350个便宜的烤肠和500个贵的烤肠,
现在我们需要设计这两种烤肠里3种原料的比例,目标是用最少的成本。
"""
import pulp
# Instantiate our problem class
model = pulp.LpProblem("Cost_minimising_blending_problem", pulp.LpMinimize)
# Construct our decision variable lists
sausage_types = ['economy', 'premium']
ingredients = ['pork', 'wheat', 'starch']
ing_weight = pulp.LpVariable.dicts("weight kg",
((i, j) for i in sausage_types for j in ingredients),
lowBound=0,
cat='Continuous')
# 先定义目标函数:Objective Function
model += (
pulp.lpSum([
4.32 * ing_weight[(i, 'pork')]
+ 2.46 * ing_weight[(i, 'wheat')]
+ 1.86 * ing_weight[(i, 'starch')]
for i in sausage_types])
)
# 约束
# 350个便宜的和500个贵的烤肠,每个0.05 kg
model += pulp.lpSum([ing_weight['economy', j] for j in ingredients]) == 350 * 0.05
model += pulp.lpSum([ing_weight['premium', j] for j in ingredients]) == 500 * 0.05
# 便宜的烤肠猪肉占比大于pork,贵的大于60%,
# 其实pulp.lpSum([ing_weight['economy', j] for j in ingredients]) == 350 * 0.05
# 改成350 * 0.05更简单
model += ing_weight['economy', 'pork'] >= (
0.4 * pulp.lpSum([ing_weight['economy', j] for j in ingredients]))
model += ing_weight['premium', 'pork'] >= (
0.6 * pulp.lpSum([ing_weight['premium', j] for j in ingredients]))
# 淀粉比率小于25%
model += ing_weight['economy', 'starch'] <= (
0.25 * pulp.lpSum([ing_weight['economy', j] for j in ingredients]))
model += ing_weight['premium', 'starch'] <= (
0.25 * pulp.lpSum([ing_weight['premium', j] for j in ingredients]))
# 我们最多用30kg猪肉,20kg小麦和17kg淀粉
model += pulp.lpSum([ing_weight[i, 'pork'] for i in sausage_types]) <= 30
model += pulp.lpSum([ing_weight[i, 'wheat'] for i in sausage_types]) <= 20
model += pulp.lpSum([ing_weight[i, 'starch'] for i in sausage_types]) <= 17
# 我们已经预定了23kg猪肉,所以一定要用掉
model += pulp.lpSum([ing_weight[i, 'pork'] for i in sausage_types]) >= 23
#前面我们用+号来表示线性约束,但是现在我们要对很多个变量进行线性约束,这个时候就需要用到pulp.lpSum函数来简化。
#比如第一个约束:我们当然可以这样来写:
#model += [ing_weight['economy', 'pork'] + [ing_weight['economy', 'wheat'] + ing_weight['economy', 'starch'] == 350 * 0.05
#如果变量成百上千,那这行代码就上万列了,而且写起来也得累死。我们用lpSum就简单的多:
#model += pulp.lpSum([ing_weight['economy', j] for j in ingredients]) = 350 * 0.05
#然后就是求解和输出结果:
# Solve our problem
model.solve()
print(pulp.LpStatus[model.status])
for var in ing_weight:
var_value = ing_weight[var].varValue
print("The weight of {0} in {1} sausages is {2} kg".format(var[1], var[0], var_value))
total_cost = pulp.value(model.objective)
print("The total cost is €{} for 350 economy sausages and 500 premium sausages".format(round(total_cost, 2)))
运行结果: