Ampl学习
熟悉一下ampl的语法.
表达式系统
Indexing expressions
索引表达式用于构造一个用于索引的多维集合,
因此他是通过{}
包裹, 中间使用,
分割的多个set
expressions.
indexing: |
比如: {A, B}
{1..3, B}
{i in A, B} # i可以给后续使用.
{i in A, j in B}
Common expressions
通用表达式主要表示数学运算等内容
expr: |
例子reduction op + indexing expr + (expr binary-op expr):
sum {i in Prod} cost[i] * Make[i]
Logical expressions
逻辑表达式是需要返回true或false的表达式
lexpr: |
Set expressions
set表达式专门用于构造set sexpr:
{ [ member [ , member . . . ] ] }
sexpr set-op sexpr # set-op is `union`, `diff`, `symdiff`, `inter`, `cross`
opname indexing sexpr # opname is `union` or `inter`
expr .. expr [ by expr ] # .. 表示线性增长, 可以添加by来指定stride
setof indexing member # member是指set元素构造, setof也就是利用indexing来构造包含有member的set.
if lexpr then sexpr else sexpr
( sexpr )
interval
infinite-set
indexing # indexing表达式也属于set expr的一种
interval:
interval [ a , b ] # {x: a ≤ x ≤ b}
interval ( a , b ] # {x: a < x ≤ b}
interval [ a , b ) # {x: a ≤ x < b}
interval ( a , b ) # {x: a < x < b}
integer [ a , b ] # {x: a ≤ x ≤ b and x ∈ I}
integer ( a , b ] # {x: a < x ≤ b and x ∈ I}
integer [ a , b ) # {x: a ≤ x < b and x ∈ I}
integer ( a , b ) # {x: a < x < b and x ∈ I}
例子: ampl: set y = setof {i in 1..5} (i,iˆ2);
ampl: display y;
set y := (1,1) (2,4) (3,9) (4,16) (5,25);
声明系统
声明系统的通用格式如下:
\[ \begin{aligned} entity\ name\ alias_{opt}\ indexing{opt}\ body{opt}; \end{aligned} \]
这里entity有set, param, var, arc, minimize, maximize, subject to, node
,
这里alias
是=
号.
Set declarations
\[ \begin{aligned} set\ name\ alias_{opt}\ indexing{opt}\ attributes{opt}; \end{aligned} \]
这里attributes
: attribute:
dimen n
within sexpr
= sexpr
default sexpr
Parameter declarations
\[ \begin{aligned} param\ name\ alias_{opt}\ indexing{opt}\ attributes{opt}; \end{aligned} \]
attribute: |
这里symbolic表示可能是字符串或者数值
Variable declarations
\[ \begin{aligned} var\ name\ alias_{opt}\ indexing{opt}\ attributes{opt}; \end{aligned} \]
attribute: |
编程逻辑
set的理解
如果对应python中的概念, 实际ampl中的set应该是一个展平的list, list中的元素为tuple, 这个tuple就是member, set的维度指的是member这个tuple的维度. 比如这个例子, set就是多个2维的tuple组成的list, 多维的var或者param实际上就是将set A的元素作为key来索引:
ap.eval('set A = {1..2, 2..3};') |
下标索引
只用通过set构造出来的var和param才能使用下标索引, 对于set本身, 需要进行排序后通过内置函数进行访问, 而且ordered只支持1维的set.
ap.eval('set D = {3..1 by -1} ordered;') |
数据加载
对于参数来说, 指定十分麻烦, 但是还好ampl的python
api提供了通过list/dict/pandas的方式来辅助指定参数: ap.eval("param domain { 1..3 };")
ap.param['domain'] = [2048, 384, 8192]
ap.display('domain')
domain [*] :=
1 2048
2 384
3 8192
;
中间变量定义
通常我们会定义一个中间变量为别的计算计算的结果,
实际上这些中间变量也都是通过约束来表示的, 在ortools里面是给我们封装好了,
但是在ampl中需要分两步定义: var loadA integer;
subject to LoadA_c : loadA = m * k;