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

表 5 coptampl 求解参数

参数名称

参数含义

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

是否识别 '.sosno''.ref' 后缀

sos2

是否将非凸分段线性项使用SOS2约束表示

strongbranching

strong branching的强度

submipheurlevel

基于子MIP的启发式算法的强度

threads

问题求解使用的线程数

timelimit

模型求解的时间限制

treecutlevel

搜索树生成割平面的强度

wantsol

是否生成 '.sol' 文件

请用户参考 COPT参数设置 章节查看各参数的详细使用说明。

AMPL中利用后缀存储或传递模型信息与解信息,并利用后缀实现一些扩展功能,如SOS约束的支持。 目前,coptampl 支持的后缀信息见 表 6

表 6 coptampl 后缀

后缀名

含义

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,如下所示:

表 7 coptampl 返回值

返回值

含义

0

最优解

200

模型不可行

300

模型无界

301

模型无解或无界

600

用户中止

使用示例

本节将通过一个著名的案例“Diet问题”来演示AMPL的用法。该问题目的是找到给定食物的搭配以满足不同 种类的营养元素需求,详见 AMPL官方手册

假定已知种类的食物及其定价信息如 表 8 所示:

表 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 所示:

表 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 所示:

(6)\[\begin{split}\textrm{最大化: } & \\ & \sum_{j \in J} cost_j \cdot buy_j \\ \textrm{约束: } & \\ & n\_min_i \leq \sum_{j \in J} amt_{i, j} \cdot buy_j \leq n\_max_i \,\,\, \forall i \in I \\ & f\_min_j \leq buy_j \leq f\_max_j \,\,\, \forall j \in J\end{split}\]

该问题的AMPL模型 diet.mod代码 7

代码 7 diet.mod
 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

代码 8 diet.dat
 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个单位。