AMPL接口
AMPL 是一种便捷描述大规模复杂优化问题的代数式建模语言,支持多种商业与
开源求解器,提供了丰富的数据接口与扩展功能,有着广泛的商业及学术用户群体,详见
谁在使用AMPL? 。为了方便用户在AMPL建模环境中
使用杉数求解器,我们提供了AMPL接口 coptampl
求解工具(位于COPT安装包 \bin
目录下),目前支持求解线性规划问题、
二次规划问题、二次约束规划问题和混合整数规划问题。一般来说,可以通过如下方式调用 coptampl
进行求解:
coptampl stub -AMPL
其中 stub.nl
是AMPL定义的 .nl
格式通用模型表示文件,可以通过命令 'ampl -obstub'
或者 'ampl -ogstub'
生成。问题求解完成后,coptampl
将结果写入到AMPL定义的 .sol
格式的 stub.sol
文件中,并用于AMPL的后续求解与结果分析。上述过程由AMPL自动实现,相关的
调用命令如下:
ampl: option solver coptampl;
ampl: solve;
安装说明
用户在AMPL环境下使用 coptampl
之前,需要正确安装与配置AMPL和杉数求解器,详情可参考
如何安装杉数求解器 。请进行下文所述不同操作系统下的检查以确保
已正确配置AMPL和杉数求解器。
Windows
对于Windows系统,用户需要将求解工具 coptampl.exe
和动态链接库 copt.dll
所在的
文件目录添加至用户或者系统环境变量 PATH
中,或者位于当前求解调用的相同路径下。
在命令行窗口中输入如下命令检测当前设置是否符合上述要求:
coptampl -v
若设置正确,则将在屏幕输出类似如下信息:
AMPL/x-COPT Optimizer [7.1.1] (windows-x86), driver(20220526), MP(20220526)
若命令调用失败,请仔细检查您的设置。
Linux
对于Linux系统,用户需要将求解工具 coptampl
所在的文件目录添加至环境变量 $PATH
中,
将动态链接库 libcopt.so
所在的路径添加至环境变量 $LD_LIBRARY_PATH
中。
类似地,在Linux终端中输入下述命令检测当前设置是否符合上述要求:
coptampl -v
若设置正确,则将在屏幕输出类似如下信息:
AMPL/x-COPT Optimizer [7.1.1] (linux-x86), driver(20220526), MP(20220526)
若命令调用失败,请仔细检查您的设置。
MacOS
对于MacOS操作系统,用户需要将求解工具 coptampl
所在的文件目录添加至环境变量 $PATH
中,
将动态链接库 libcopt.dylib
所在的路径添加至环境变量 $DYLD_LIBRARY_PATH
中。
同样地,在MacOS终端中输入下述命令检查当前设置是否符合上述要求:
coptampl -v
若设置正确,则将在屏幕输出类似如下信息:
AMPL/x-COPT Optimizer [7.1.1] (macos-x86), driver(20220526), MP(20220526)
若命令调用失败,请仔细检查您的设置。
求解参数与返回值
coptampl
提供了一些求解参数允许用户自定义求解行为。用户可以通过设置 copt_options
环境变量或者在AMPL中通过 option
命令来改变 coptampl
的求解参数,并可以通过下述命令
查看目前支持的所有参数:
coptampl -=
对于当前版本的 coptampl
求解工具,支持的求解参数及其含义如 表 5:
参数名称 |
参数含义 |
barhomogeneous |
是否使用齐次自对偶方法 |
bariterlimit |
内点法迭代数限制 |
barthreads |
内点法使用的线程数 |
basis |
是否读取或输出基状态 |
bestbound |
是否返回最优下界后缀信息 |
conflictanalysis |
是否使用冲突分析 |
crossoverthreads |
crossover使用的线程数 |
cutlevel |
割平面生成强度 |
divingheurlevel |
diving启发式算法的强度 |
dualize |
是否构建并求解对偶模型 |
dualperturb |
是否允许对目标函数进行扰动 |
dualprice |
指定对偶单纯形法的Pricing算法 |
dualtol |
对偶解的可行性容差 |
feastol |
变量、约束取值的可行性容差 |
heurlevel |
启发式算法强度 |
iisfind |
是否计算不可行模型的IIS并返回结果 |
iismethod |
指定计算IIS的方法 |
inttol |
变量的整数解容差 |
logging |
是否显示求解日志 |
logfile |
日志文件 |
exportfile |
导出模型文件 |
lpmethod |
求解线性规划问题的算法 |
matrixtol |
输入矩阵的系数容差 |
mipstart |
是否使用整数规划初始解 |
miptasks |
MIP求解使用的任务数 |
nodecutrounds |
搜索树节点生成割平面的次数 |
nodelimit |
整数规划求解的节点数限制 |
objno |
目标函数的序号 |
count |
是否输出的解池结果文件的数目 |
stub |
解池结果文件的前缀 |
presolve |
预求解的强度 |
relgap |
整数规划的最优相对容差 |
absgap |
整数规划的最优绝对容差 |
return_mipgap |
是否返回整数规划最优绝对或相对容差 |
rootcutlevel |
根节点生成割平面的强度 |
rootcutrounds |
根节点生成割平面的次数 |
roundingheurlevel |
rounding启发式算法的强度 |
scaling |
是否在求解前调整模型系数矩阵的系数 |
simplexthreads |
对偶单纯形法使用的线程数 |
sos |
是否识别 |
sos2 |
是否将非凸分段线性项使用SOS2约束表示 |
strongbranching |
strong branching的强度 |
submipheurlevel |
基于子MIP的启发式算法的强度 |
threads |
问题求解使用的线程数 |
timelimit |
模型求解的时间限制 |
treecutlevel |
搜索树生成割平面的强度 |
wantsol |
是否生成 |
请用户参考 COPT参数设置 章节查看各参数的详细使用说明。
AMPL中利用后缀存储或传递模型信息与解信息,并利用后缀实现一些扩展功能,如SOS约束的支持。
目前,coptampl
支持的后缀信息见 表 6 :
后缀名 |
含义 |
absmipgap |
整数规划最优绝对容差 |
bestbound |
整数规划求解结束时最好的下界 |
iis |
存储变量或约束的IIS状态 |
nsol |
输出解池的解的数目 |
ref |
指定SOS约束中变量的权重 |
relmipgap |
整数规划最优相对容差 |
sos |
存储AMPL生成的SOS约束类型 |
sosno |
指定SOS约束类型 |
sosref |
存储AMPL生成的SOS约束中变量的权重 |
sstatus |
存储线性规划求解后的基状态信息 |
关于如何在AMPL中开启SOS约束的识别扩展功能,详见AMPL官网的资料: 如何在AMPL中使用SOS约束 。
求解完成后,coptampl
在屏幕输出求解状态信息并传递返回值。通过下述命令显示返回值:
ampl: display solve_result_num;
如果未得到结果或者发生错误,coptampl
将依据 表 7 返回
非零值给AMPL,如下所示:
返回值 |
含义 |
0 |
最优解 |
200 |
模型不可行 |
300 |
模型无界 |
301 |
模型无解或无界 |
600 |
用户中止 |
使用示例
本节将通过一个著名的案例“Diet问题”来演示AMPL的用法。该问题目的是找到给定食物的搭配以满足不同 种类的营养元素需求,详见 AMPL官方手册。
假定已知种类的食物及其定价信息如 表 8 所示:
食物 |
价格 |
BEEF |
3.19 |
CHK |
2.59 |
FISH |
2.29 |
HAM |
2.89 |
MCH |
1.89 |
MTL |
1.99 |
SPG |
1.99 |
TUR |
2.49 |
每种食物及其单位营养元素含量占每天所需要的最少营养含量需求如 表 9 所示:
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 |
该问题的求解目标是找出满足至少7倍于日常营养需要的食物搭配,且价格花费最少。
综上所述,该问题的数学形式如 公式 6 所示:
该问题的AMPL模型 diet.mod
见 代码 7 :
1# The code is adopted from:
2#
3# https://github.com/Pyomo/pyomo/blob/master/examples/pyomo/amplbook2/diet.mod
4#
5# with some modification by developer of the Cardinal Optimizer
6
7set NUTR;
8set FOOD;
9
10param cost {FOOD} > 0;
11param f_min {FOOD} >= 0;
12param f_max {j in FOOD} >= f_min[j];
13
14param n_min {NUTR} >= 0;
15param n_max {i in NUTR} >= n_min[i];
16
17param amt {NUTR, FOOD} >= 0;
18
19var Buy {j in FOOD} >= f_min[j], <= f_max[j];
20
21minimize Total_Cost:
22 sum {j in FOOD} cost[j] * Buy[j];
23
24subject to Diet {i in NUTR}:
25 n_min[i] <= sum {j in FOOD} amt[i, j] * Buy[j] <= n_max[i];
求解所需的数据 diet.dat
见 代码 8 :
1# The data is adopted from:
2#
3# https://github.com/Pyomo/pyomo/blob/master/examples/pyomo/amplbook2/diet.dat
4#
5# with some modification by developer of the Cardinal Optimizer
6
7data;
8
9set NUTR := A B1 B2 C ;
10set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ;
11
12param: cost f_min f_max :=
13 BEEF 3.19 0 100
14 CHK 2.59 0 100
15 FISH 2.29 0 100
16 HAM 2.89 0 100
17 MCH 1.89 0 100
18 MTL 1.99 0 100
19 SPG 1.99 0 100
20 TUR 2.49 0 100 ;
21
22param: n_min n_max :=
23 A 700 10000
24 C 700 10000
25 B1 700 10000
26 B2 700 10000 ;
27
28param amt (tr):
29 A C B1 B2 :=
30 BEEF 60 20 10 15
31 CHK 8 0 20 20
32 FISH 8 10 15 10
33 HAM 40 40 35 10
34 MCH 15 35 15 15
35 MTL 70 30 15 15
36 SPG 25 50 25 15
37 TUR 60 20 15 10 ;
若在AMPL中调用 coptampl
进行求解,则在进入AMPL交互界面后输入下述命令:
ampl: model diet.mod;
ampl: data diet.dat;
ampl: option solver coptampl;
ampl: option copt_options 'logging 1';
ampl: solve;
coptampl
快速求解完成,并在屏幕输出求解日志及结果状态信息:
x-COPT 5.0.1: optimal solution; objective 88.2
1 simplex iterations
分析可知,coptampl
找到了问题的最优解,最优解为88.2个单位。用户可以进一步显示问题中各变量
的取值信息:
ampl: display Buy;
屏幕中输出如下信息:
Buy [*] :=
BEEF 0
CHK 0
FISH 0
HAM 0
MCH 46.6667
MTL 0
SPG 0
TUR 0
;
分析可知,当购买约46.667个单位的食物MCH时,花费最少,为88.2个单位。