这篇文章是系列的第一篇,主要介绍 AMPL 建模语言的基本使用方法。MindOpt 支持在 Windows/Linux/OSX 系统中,通过 AMPL 建立线性规划模型,并调用 MindOpt 来求解。
一、AMPL基本信息
AMPL全称为A Mathematical Programming Language,是一种描述并求解大规模复杂数学问题的代数建模语言软件。
AMPL解决数学规划问题的流程如下:
- 准备模型文件(.mod)与数据文件(.dat)。
- 使用 AMPL 读取模型与数据进行建模。
- 选择链接上的求解器(如 MindOpt)进行求解。
- 获取求解结果。
二、AMPL基本语法
下面将介绍 AMPL 的一些基本使用方法,并以一个简单的例子进行说明。
AMLP的一些基本语法规则
- 区分大小写
- 以#开始的一行表示注释
- 忽略空格
- 每个语句以分号 ";" 结尾
- :=表示赋值,=表示表达式中的等号 ,==表示判断
AMPL模型建立
AMPL用接近数学描述的语言把数学规划问题写成模型文件,以".mod"为扩展名,如 “example.mod”,然后将其中的参数写成数据文件,以“.dat”为扩展名,如 “example.dat”。
AMPL中建立一个完整的优化模型主要包含以下项:
(1)集合(set):
集合是描述变量和约束的基础,一般来说,优化表达式中的下标出自集合表示。集合可以在数据文件中进行赋值,对于比较简单的集合的定义也可以直接在模型文件中进行赋值。
声明集合的语法为:set [set name][set expression]
(2)参数(parameter):
参数是模型中需要被赋值的系数,其赋值一般在数据文件中给出,对于比较简单的参数,也可以在模型文件中直接给出。标量、向量或矩阵都可以成为参数的表达式。
参数的语法为:param [name]{index1, index2,...}{attributes}
其中 [name]是必有的,{index1}...是可选的,用来说明参数数据的大小或范围(可以使用集合来定义),{attributes}说明参数的属性,如可能的取值等等。
(3)变量(variable):
变量是优化模型求解需要求出的量,即决策变量。变量的声明与参数的声明类似。
变量的语法为:var [name]{index1, index2,...}{attributes}
(4)目标函数(objective):
线性规划的目标函数定义如下:
maximize [objective name]:sum{[index] in [index set]}[parameter]*[variable]+...
如果是最小化目标函数,将第maximize换成 minimize 即可。
(5)约束(constraint):
约束是优化问题需要满足的约束条件。
一般的线性约束的语法为:
subject to [constraints name] {index in index set}:sum{[index] in [index set]}
[parameter]*[variable]+...+{<=,>=,=}[parameter]
优化模型示例
以 MindOpt (https://solver.damo.alibaba-inc.com/doc/html/index.html) 中的 Diet问题 为例,Diet问题的目标是以最低的价格来配置一满足营养需求的食物组合,其 AMPL 模型(diet.mod)写为:
set NUTR; #set 声明集合
set FOOD;
param cost {FOOD} > 0; #param 声明参数
param f_min {FOOD} >= 0;
param f_max {j in FOOD} >= f_min[j];
param n_min {NUTR} >= 0;
param n_max {i in NUTR} >= n_min[i];
param amt {NUTR,FOOD} >= 0;
var Buy {j in FOOD} >= f_min[j], <= f_max[j]; #var 表明变量
minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j]; #minimize表明最小目标函数
subject to Diet {i in NUTR}: # subject to 表明约束
n_min[i] <= sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];
其对应的数据文件(diet.dat)如下:
set NUTR := A B1 B2 C ;
set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ;
param: cost f_min f_max :=
BEEF 3.19 0 100
CHK 2.59 0 100
FISH 2.29 0 100
HAM 2.89 0 100
MCH 1.89 0 100
MTL 1.99 0 100
SPG 1.99 0 100
TUR 2.49 0 100 ;
param: n_min n_max :=
A 700 10000
C 700 10000
B1 700 10000
B2 700 10000 ;
param amt (tr):
A C B1 B2 :=
BEEF 60 20 10 15
CHK 8 0 20 20
FISH 8 10 15 10
HAM 40 40 35 10
MCH 15 35 15 15
MTL 70 30 15 15
SPG 25 50 25 15
TUR 60 20 15 10 ;
三、运行AMPL
AMPL本身并不直接求解优化问题,它将模型转换成专门的 .nl 文件,其作用只是类似语言编译器。在读入模型文件和数据文件后调用其他能够求解各类数学规划问题的求解器(optimization solver)进行求解。AMPL支持大部分的求解器,包括MindOpt。
运行AMPL之前需要准备两个文件:
- 模型文件:用 AMPL 语言编写问题的模型(model)文件,模型文件以".mod"为扩展名,例如我们在上一节中给出的示例。
- 数据文件:优化模型中的集合和参数的具体取值可以放在模型文件中,也可以放在单独的数据文件,这样同一个抽象的优化模型可以适用不同的数据,数据文件以".dat"为扩展名。
此外,也可以编写一个包含按顺序执行求解的 AMPL 命令的批处理文件,以".run"为扩展名。
eample.run
如果没有批处理文件,也可以按照以下步骤在 AMPL 中以单个命令的方式输入:
model example.mod; #调用模型文件
data example.dat; #调用数据文件
option solver mindopt; #选择求解器
solve; #求解
四、支持的其他脚本语句
reset:清除已有的数据和模型
reset data:清除已有的数据
if...then...else:条件语句
and,or:逻辑与,逻辑或
let:赋值给参数或变量
for,repeat,while,until,break:用于循环语句
更多的关于 AMPL 建模工具的介绍请见:https://ampl.com/resources/the-ampl-book/