混合整数线性规划问题的解决方案¶
本例介绍如何解决混合整数线性规划(MILP)问题。这里给出了使用问题导向法制定问题的典型步骤。
安装库¶
如果您的环境中没有安装最新版本的JuMP
软件包,请取消注释并运行下面的方框:
Pkg.add(["GLPK", "JuMP"])
#Pkg.add("JuMP");
要在安装完成后启动新版本的程序库,请单击 "我的账户 "按钮:
然后点击 "停止 "按钮:
按下 "Start Engee "按钮重新启动会话:
任务描述¶
您需要混合不同化学成分的钢材,生产出 25 吨具有特定化学成分的钢材。生产出的钢材应含有总重量 5%的碳和 5%的钼,即 1.25 吨碳和 1.25 吨钼。
优化问题的目标是最大限度地降低混钢成本。
有四种不同的钢锭可供购买。每种钢锭只能购买一个。
| 钢锭 | 重量(吨) | 碳含量 | 钼含量 | 每吨成本 | ----------- | ----------- | ----------- | ----------- | ----------- | | 1 | 5 | 5 | 5 | 3 |$350 | | 2 | 3 | 4 | 3 | $330 | | 3 | 4 | 4 | 5 | 4 |$310 | | 4 | 6 | 3 | 4 | $280 |
此外,还出售三种等级的合金钢和一种等级的废钢。合金钢和废钢可零散购买。
| 合金 | 碳含量 | 钼含量 | 每吨成本 | ----------- | ----------- | ----------- | ----------- | | 1 | 8 | 8 | 6 |$500 | | 2 | 7 | 7 | $450 | | 3 | 6 | 8 |$400 | | Лом | 3 | 9 | $| 100 |
连接图书馆¶
连接图书馆JuMP
:
using JuMP;
连接求解器库GLPK
:
using GLPK;
创建优化问题¶
使用函数Model()
创建一个优化问题,并在括号中指定求解器的名称:
steel_prob = Model(GLPK.Optimizer)
创建变量ingots
,包含四个值(根据可购买的钢锭数量)。由于钢锭不能以小数购买,因此指定变量类型为Int
。所有变量的下限都是 0,因为我们不能购买负数。每块钢锭只有一份,因此该变量的上限为 1。
@variable(steel_prob, ingots[1:4], Int; lower_bound = 0, upper_bound = 1);
创建一个变量alloys
,其中包含三个值(根据可供购买的合金数量)。我们将把废钢单独列为一个变量。由于可购买的合金数量为零,因此无需指定变量类型。
@variable(steel_prob, alloys[1:3], lower_bound = 0);
为废钢创建变量scrap
。由于废钢可以按小数购买,因此无需指定变量类型。
@variable(steel_prob, scrap, lower_bound = 0);
由于每个钢锭的重量不同,必须先创建变量weightIngots
来计算购买钢锭的成本。计算每个组件的成本,然后创建变量cost
,其中包含购买组件的总成本。作为问题解决方案的一部分,我们将找出该变量的最小值。
weightIngots = [5,3,4,6];
costIngots = weightIngots.*[350,330,310,280];
costAlloys = [500,450,400];
costScrap = 100;
cost = sum(costIngots.*ingots) + sum(costAlloys.*alloys) + sum(costScrap*scrap)
创建一个目标函数,使成本最小化,以解决我们的优化问题:
@objective(steel_prob, Min, cost)
创建一个变量totalWeight
,其中包含所有组件的总重量:
totalWeight = sum(weightIngots.*ingots) + sum(alloys) + scrap
计算钢中碳的总重量:
carbonIngots = [5,4,5,3]/100;
carbonAlloys = [8,7,6]/100;
carbonScrap = 3/100;
totalCarbon = sum((weightIngots.*carbonIngots).*ingots) + sum(carbonAlloys.*alloys) + sum(carbonScrap.*scrap)
计算钢中钼的总质量:
molybIngots = [3,3,4,4]/100;
molybAlloys = [6,7,8]/100;
molybScrap = 9/100;
totalMolyb = sum((weightIngots.*molybIngots).*ingots) + sum(molybAlloys.*alloys) + sum(molybScrap.*scrap)
制定条件¶
为解决优化问题设定的第一个条件是,获得的钢材总重量应为 25 吨:
@constraint(steel_prob, C1, totalWeight == 25)
设置优化问题的第二个求解条件,即所得钢材中碳的总重量应为 1.25 吨:
@constraint(steel_prob, C2, totalCarbon == 1.25)
设定优化问题的第三个求解条件,即所得钢中钼的总重量应为 1.25 吨:
@constraint(steel_prob, C3, totalMolyb == 1.25)
问题的解决方案¶
解决优化问题:
optimize!(steel_prob)
检查是否找到了最优解:
if !is_solved_and_feasible(steel_prob)
error("Solver did not find an optimal solution")
end
将感兴趣的值保存在变量中。您可以使用函数round
,对过于精确的数值进行四舍五入。
ingots_value = value.(ingots);
alloys_value = round.(value.(alloys); digits = 3);
scrap_value = round(value.(scrap); digits = 3);
fval = objective_value(steel_prob);
输出优化结果:
println("Ingots: ", ingots_value)
println("Alloys: ", alloys_value)
println("Scrap: ", scrap_value)
println("Objective Value: ", fval)
最佳购买价格为 8495 美元。因此,应购买钢锭 1、2 和 4,但不应购买钢锭 3。同时购买 7.25 吨合金 1、0.25 吨合金 3 和 3.5 吨废钢。
结论¶
在本例中,我们解决了一个混合整数线性规划问题,并找到了以最低成本生产 25 吨化学成分符合要求的钢材所需的最佳部件组和数量。