LINGO 中建立的优化模型可以由5个部分组成,或称为 5 段(section):
(1)集合段(SETS):这部分要以“SETS:”开始,以“ENDSETS”结束,作用在于定义必要的集合变量(SET)及其元素(member,含义类似于数组的下标)和属性(attribute, 含义类似于数组)。
(2)目标与约束段:这部分实际上定义了目标函数、约束条件等,但这部分并不有段的 开始和结束标记,因此实际上就是除其他 4 个段(都有明确的段标记)外的 LINGO 模型。 这里一般要用到LINGO 的内部函数尤其是与集合相关的求和函数@SUM和循环函数@FOR 等,可在具体使用中体会其功能和用法。
(3)数据段(DATA):这部分要以“DATA:”开始,以“ENDDATA”结束,作用在于对集合的属性(数组)输入必要的常数数据。格式为: attribrte(属性)=value_list(常数列表); 常数列表(value_list)中数据之间可以用逗号“,”分开,也可以用空格分开(回车的作用也等价 于一个空格),如上面对 DEM 的赋值也可以写成“DEM=40 60 75 25;” 在 LINGO 模型中,如果想在运行时才对参数赋值,可以在数据段使用输入语句.。但这仅用于对单个变量赋值,而不能用于属性变量(数组),输入语句格式为:“变量名=?;”。例如, 上面的例子中如果需要在求解模型时才给出初始库存量(记为 A),则可以在模型中数据段写上语句: A=?; 在求解时 LINGO 系统给出提示界面,等待用户输入变量 A 的数值。当然,此时的约束语句 INV(1)=10+RP(1)+OP(1)-DEM(1); 也应该改写成 INV(1)=A+RP(1)+OP(1)-DEM(1); 这样,模型就可以计算任意初始库存量(而不仅仅只能计算初始库存量为 10)的情况了。
(4)初始段(INIT):这部分要以“INIT:”开始,以“ENDINIT”结束,作用在于对集合的属性(数组)定义初值(因为求解算法一般是迭代算法,所以用户如果能给出一个比较好迭代初值,对提高算法的计算效果是有益的)。如果有一个接近最优解的初值,对 LINGO 求解模型是有帮助的。定义初值的格式为 attribute(属性)= value_list(常数列表); 这与数据段中的用法是类似的。
(5)计算段(CALC):这部分要以“CALC:”开始,以“ENDCALC”结束,作用在于对一些原始数据进行计算处理(这种处理是在数据段的数据输入完成以后、LINGO 开始 正式求解模型之前进行的)。为什么要设计这个段?这是因为在实际问题中,输入的数据通常是原始数据,不一定能在模型中直接使用,我们就可以在这个段对这些原始数据进行一定的“预处理”,得到我们模型中真正需要的数据。 请大家注意,在计算段中语句是顺序执行的,所以上面的一两个语句不能交换顺序,
LINGO 中的逻辑运算符有 9 种,可以分为两类:
(1)#OR#(或),#AND#(与),#NOD#(非):这 3 个运算是逻辑值之间的运算,也就是它们操作的对象本身 必须已经是逻辑值或逻辑表达式..计算结果也是逻辑值
(2)#EQ#(等于).#NE#(不等于),#GT#(大于),#GE#(大于等于),#LT#(小于).#LE#(小于等于):
参考实例:
min=@sum(hz(i):@sum(hz(j):@sum(cl(k):c(i,j)*x(i,j,k)))); @for(cl(k):@sum(hz(i)|i#gt#1:g(i)*y(k,i))<=q(k)); @for(hz(i)|i#gt#1:@sum(cl(k):y(k,i))=1); y(1,1)+y(2,1)=2; @for(hz(i):@for(cl(k):@sum(hz(j)|j#ne#i:x(j,i,k))=y(k,i))); @for(hz(i):@for(cl(k):@sum(hz(j)|j#ne#i:x(i,j,k))=y(k,i))); @for(hz(i):@for(hz(j):@for(cl(k):@bin(x(i,j,k))))); @for(cl(k):@for(link2(i,j)|i#ne#j#and#j#ne#1:u(k,i)-u(k,j)+10*x(i,j,k)<=9)); @for(link1(k,i):@bin(y(k,i)));
变量定界函数对变量的取值范围附加限制,共有以下四种函数:
@BND(L,X,U):限制 L〈=X〈=U。注意 LINGO 中命令 SLB,SUB 类似函数@SLB 和 @SUM. @BIN(X):即限制 X 为 0 或 1。注意 LINGO 中这个函数的名字却不是@INT(X).
@FREE(X):取消对 X 的符号限制(即可取负数、0 后正数)。
@GIN(X):限制 X 为整数。