1. 问题描述和数学规划模型
排产排程、原料采购、仓储存放等是制造业降本增效的关键问题。本节以香皂的制造为例,不同于上一篇问题01-生产多少,本例主要考虑原料采购的问题。以下数据只是用来示意如何使用MAPL建模和求解,实际的制造规划问题规模更大,建模更复杂。
集合
- 制作香皂的油脂集合 O O O
- 油脂分为两种,我们定义植物油脂集合为 O 1 O_1 O1,动物油脂集合为 O 2 O_2 O2
参数
- 油脂 j ∈ O j \in O j∈O每吨的成本 c j c_j cj
- 油脂 j ∈ O j \in O j∈O的硬度 h j h_j hj
- 植物油脂的购买量上限 b 1 b_1 b1(单位: 吨)
- 动物油脂的购买上限 b 2 b_2 b2(单位: 吨)
- 每卖出一吨香皂,盈利 r r r
- 香皂的硬度不得低于 ℓ \ell ℓ,也不得高于 u u u
变量
- x j x_j xj是某工厂要购买油脂 j ∈ O j\in O j∈O的重量(单位: 吨)
- y y y是生产的香皂量(单位: 吨)
目标
- 工厂要最大化其利润: max r y − ∑ j ∈ O c j x j \max\quad r y - \sum_{j\in O} c_j x_j maxry−∑j∈Ocjxj
约束
- 假设从油脂到香皂的转化过程中,油脂没有任何浪费,生产过程中重量守恒: ∑ j ∈ O x j = y \sum_{j\in O} x_j = y ∑j∈Oxj=y
- 植物油脂的购买总量不得超过 b 1 b_1 b1: ∑ j ∈ O 1 x j ≤ b 1 \sum_{j\in O_1} x_j \le b_1 ∑j∈O1xj≤b1
- 动物油脂的购买总量不得超过 b 2 b_2 b2: ∑ j ∈ O 2 x j ≤ b 2 \sum_{j\in O_2} x_j \le b_2 ∑j∈O2xj≤b2
- 假设从油脂到香皂的制造过程中,硬度的转化满足线性关系: ℓ y ≤ ∑ j ∈ O h j x j ≤ u y \ell y \le \sum_{j\in O} h_j x_j \le u y ℓy≤∑j∈Ohjxj≤uy
2. 使用MindOpt APL进行建模和求解
MindOpt建模语言(MindOpt Algebra Programming Language, MindOpt APL,简称为MAPL)是一种高效且通用的代数建模语言。当前主要用于数学规划问题的建模,并支持调用多种求解器求解。下面将演示如何使用MAPL将上面的数学模型公式和数据输入,生成一个求解器可求解的问题,再调用求解器去进行求解。
方法1:cell中直接输入建模代码运行
我们可以将 MindOpt APL 建模代码直接在MindOpt云上平台Notebook中的cell里运行。请注意内核(kernel)需要选MAPL。代码如下:
clear model;#清除model,多次run的时候使用
option modelname model/manufacture_02_soap1;#方便与方法2的中间文件生成在同一个目录
#---------建模-----------------
# manufacture_02_soap1.mapl
# 声明集合
set O1 := { "VEG1", "VEG2" };
set O2 := {"OIL1", "OIL2", "OIL3"};
set O := O1 + O2;
set F := {"cost", "hardness"};
# 声明参数
param data[O * F] :=
| "cost" , "hardness" |
|"VEG1" | 100 , 2.0 |
|"VEG2" | 90 , 4.5 |
|"OIL1" | 110 , 5.3 |
|"OIL2" | 105 , 7.8 |
|"OIL3" | 95 , 5.0 |;
param r := 180;
param b1 := 200;
param b2 := 150;
param l := 4;
param u := 6;
# 声明变量
var x[O] >= 0; # 括号内室字母O, 并非数字0
var y >= 0;
# 声明目标
maximize Reward: r * y - sum {<j> in O} (data[j, "cost"] * x[j]);
# 声明约束
subto Weight: sum {<j> in O} x[j] == y;
subto Hardness1: sum {<j> in O} (data[j, "hardness"] * x[j]) >= y * l;
subto Hardness2: sum {<j> in O} (data[j, "hardness"] * x[j]) <= y * u;
subto VEGBound: sum {<j> in O1} x[j] <= b1;
subto OILBound: sum {<j> in O2} x[j] <= b2;
#------------------------------
print "-----------------用MindOpt求解---------------";
option solver mindopt; # 指定求解用MindOpt求解器
solve; # 求解
display;
print "-----------------结果---------------";
print "最大利润 = ",r * y - sum {<j> in O} data[j, "cost"] * x[j];
方法2:导入.mapl文件运行建模然后求解
上面时直接在cell中运行所有的脚本,我们也可以建立个新文档,将中间建模的代码保存为manufacture_02_soap1.mapl文件。然后运行如下code,结果同方法1。
clear model;#清除model,多次run的时候使用
#------------------------------
model model/manufacture_02_soap1.mapl; #通过导入建模脚本.mapl文件进行建模
#------------------------------
print "-----------------用MindOpt求解---------------";
option solver mindopt; # 指定求解用MindOpt求解器
solve; # 求解
display;
print "-----------------结果---------------";
print "最大利润 = ", r * y - sum {<j> in O} data[j, "cost"] * x[j];
3. 结果
运行方法一、方法二代码结果一致,如下:
-----------------用MindOpt求解---------------
Running mindoptampl
wantsol=1
MindOpt Version 0.25.1 (Build date: 20230816)
Copyright (c) 2020-2023 Alibaba Cloud.
Start license validation (current time : 24-AUG-2023 19:46:39).
License validation terminated. Time : 0.006s
Model summary.
- Num. variables : 6
- Num. constraints : 5
- Num. nonzeros : 23
- Bound range : [1.5e+02,2.0e+02]
- Objective range : [9.0e+01,1.8e+02]
- Matrix range : [1.0e+00,7.8e+00]
Presolver started.
Presolver terminated. Time : 0.000s
Simplex method started.
Model fingerprint: =Y2dkV2dhdnY
Iteration Objective Dual Inf. Primal Inf. Time
0 1.54802e+05 0.0000e+00 8.6001e+00 0.01s
4 3.07500e+04 0.0000e+00 0.0000e+00 0.01s
Postsolver started.
Simplex method terminated. Time : 0.001s
OPTIMAL; objective 30750.00
4 simplex iterations
Completed.
Primal Solution:
x@VEG1 = 0.00000000
x@VEG2 = 200.000000
x@OIL1 = 0.00000000
x@OIL2 = 0.00000000
x@OIL3 = 150.000000
y = 350.000000
-----------------结果---------------
最大利润 = 30750
display指令运行时,会打印出很多求解的结果,x@name 和 y 是决策变量的取值,后面的dual solution是对偶解的值。示意如下:
Primal Solution:
x@VEG1 = 0.00000000
x@VEG2 = 200.000000
x@OIL1 = 0.00000000
x@OIL2 = 0.00000000
x@OIL3 = 150.000000
y = 350.000000
-----------------结果---------------
最大利润 = 30750
同时,在最近建模的文件所在目录或option modelname指定的位置,会生成对应的文件 .nl
和 .sol
。其中 .nl
文件是建模的问题模型文件,可被多数求解器识别,.sol
文件中存储了求解结果solution。
从打印的结果,们可以得到采用如下的采购方案时,利润最大,为30750元,生产了350吨的香皂:
x@VEG2 = 200.000000
x@OIL3 = 150.000000