Lingo介绍
Lingo是美国LINDO系统公司(Lindo Symtem Inc)开发的求解数学规划系列软件中的一个(其他软件为LINGDO,GINO,What’s Best等),它的主要功能是求解大型线性、非线性和整数规划问题,目前的版本是lingo11.0。
lingo分为Demo、solve suite、hyper、industrial、extended等六类不同版本,只有Demo版本是免费的,其他版本需要向LINDO系统公司(在中国的代理商)购买,Lingo的不同版本对模型的变量总数、非线性变量个数、整型变量个数和约束条件的数量做出不同的限制(其中extended版本无限制)。
Lingo的主要功能特色为:
(1)既能求解线性规划,也有较强的求解非线性规划的能力; (2)输入模型简练直观; (3)运行速度快、计算能力强;
(4)内置建模语言,提供几十种内部函数,从而能以较少语句,较直观的方式描述较大规模的优化模型;
(5)将集合的概念引入编程语言,很容易将实际问题转换为Lingo语言;
(6)能方便地与excel、数据库等其他软件交换数据。
学校图书馆40本《lingo和excel在数学建模中的应用》,袁新生、邵大宏、郁时炼 主编,科学出版社
1 第 页,共10页
Lingo程序设计简要说明
在数学建模中会遇到如规划类的题型,在这种模型中总存在着一个目标,并希望这个目标的取值尽可能的大或小,同时与这个目标有关的一系列变量之间存在一些约束。在构造出目标函数和约束条件的表达式后,我们需要对求出这个最值和各变量的取值。一般我们用LINGO来对模型进行求解,本文将通过举一个简单的例子,围绕这个例子逐步学习LINGO的使用。LINGO只是一个求解工具,我们主要的任务还是模型的建立!
当你在windows下开始运行LINGO系统时,会得到类似下面的一个窗口:
外层是主框架窗口,包含了所有菜单命令和工具条,其它所有的窗口将被包含在主窗口之下。在主窗口内的标题为LINGO Model – LINGO1的窗口是LINGO的默认模型窗口,建立的模型都都要在该窗口内编码实现。 示例:求解线性规划问题:
max z=x1+x2+x3+x4+x5+x6+x7+x8
+ 7 x2 + 4 x3 + 5 x4 + 5 x5 + 6 x6 + 9 x7 + 3 x8 + 4?15?x1? ? + 8 x2 + 5 x3 + 6 x4 + 7 x5 + 2 x6 + 5 x7 + 4 x8 + 9?38?2 x1??3 x1 + 5 x2 + 6 x3 + 9 x4 + 5 x5 + 4 x6 + 4 x7 + 5 x8 + 8?27???4 x1 + 7 x2 + 2 x3 + 5 x4 + 8 x5 + 8 x6 + 7 x7 + 6 x8 + 4?44 ?? + 5 x2 + 4 x3 + 4 x4 + 4 x5 + 5 x6 + x7 + 7 x8 + 6 ?15?5 x1? ? + 8 x2 + 8 x3 + 7 x4 + 5 x5 + 6 x6 + 2 x7 + 8 x8 + 9?26?6 x1
求解这个模型的相应LINGO程序代码如下: 程序一:
max= x1+x2+x3+x4+x5+x6+x7+x8;
x1 + 7*x2 + 4*x3 + 5*x4 + 5*x5 + 6*x6 + 9*x7 + 3*x8 + 4??15; 2*x1 + 8*x2 + 5*x3 + 6*x4 + 7*x5 + 2*x6 + 5*x7 + 4*x8 + 9??38; 3*x1 + 5*x2 + 6*x3 + 9*x4 + 5*x5 + 4*x6 + 4*x7 + 5*x8 + 8??27; 4*x1 + 7*x2 + 2*x3 + 5*x4 + 8*x5 + 8*x6 + 7*x7 + 6*x8 + 4??44; 5*x1 + 5*x2 + 4*x3 + 4*x4 + 4*x5 + 5*x6 + x7 + 7*x8 + 6 ??15; 6*x1 + 8*x2 + 8*x3 + 7*x4 + 5*x5 + 6*x6 + 2*x7 + 8*x8 + 9??26;
注:然后点击工具条上的按钮 即可。本模型的最优解为2.636364
2 第 页,共10页
程序二: SETS: xb1 /1..8/:x; xb2 /1..6/ :b,c; xb3 (xb2,xb1):a; ENDSETS DATA:
a= 1 7 4 5 5 6 9 3 2 8 5 6 7 2 5 4 3 5 6 9 5 4 4 5 4 7 2 5 8 8 7 6 5 5 4 4 4 5 1 7 6 8 8 7 5 6 2 8; b= 15 38 27 44 15 26; c= 4 9 8 4 6 9; ENDDATA MAX=@sum( xb1(i) :x(i) ); @for( xb2(i): @sum( xb1(j) : a(i,j)*x(j) ) +c(i)<= b(i);
);
注:然后点击工具条上的按钮 即可。本模型的最优解为2.636364
注意:(1)在lingo中输入的各种符号一定要是英文状态下输入,不能是中文输入状态下的符号。例如正确输入 xb3 (xb2,xb1):a; 错误输入 xb3 (xb2,xb1):a; (2)Lingo中不区分字母大小写
一.变量、常量定义
在lingo中变量在使用前是无需定义也可以使用的。在描述类似xi,aij带有下标的变量时,我们可以在使用时一一例举,即,x1,x2,x3….x8, 但这样显然很麻烦(刚接触LINGO的时候大部分是这样使用的)。Lingo中可以使用sets 来预先定义这些变量,然后就可以在loop语句方便地访问这一组变量,也可以用小x(2), a(2,3)的形式访问个别变量,这和C语言中的数组是类似的。
1.SETS的使用:
为了定义xi,aij,那么首先要确定下标i和j的取值范围。
在lingo中用sets来表示。 代码: SETS : Xb1 /1..8/ ; Xb2 /1..6/ ; ENDSETS
其中 xb1、xb2分别为下标1..8 ,1..6的名字(sets_name),这些名字在loop语句中要使用。对于sets_name一般将它命名为有意义的名称,这个sets_name必须以字母或下划线(_)开始。
二维下标是在两个一维下标定义的基础上给定的,定义 a(i,j)下标的代码如下:
3 第 页,共10页
SETS : Xb1 /1..8/; Xb2 /1..6/ ; Xb3 (xb2,xb1); ENDSETS
(关于下标的定义还有其他的方法,请参考LINGO的help文件,自行学习)
现在下标已经定义完成了,定义数组变量时则需在下标后加上冒号再写上变量名,代码如下:
SETS : Xb1 /1..8/:x,c,b ; Xb2 /1..6/ ; Xb3 (xb2,xb1):a; ENDSETS
2.DATA的使用(常量定义):
在lingo中把常量理解为已经被给定某常数的变量,在DATA 中对一些变量赋值,使之成为常量。
代码如下: SETS: xb1 /1..8/:x; xb2 /1..6/ :b,c; xb3 (xb2,xb1):a; ENDSETS DATA:
a= 1 7 4 5 5 6 9 3 2 8 5 6 7 2 5 4 3 5 6 9 5 4 4 5 4 7 2 5 8 8 7 6 5 5 4 4 4 5 1 7 6 8 8 7 5 6 2 8; b= 15 38 27 44 15 26; c= 4 9 8 4 6 9; ENDDATA
请尝试着在lingo中输入以上代码后点击solve按钮,查看执行结果。 这些变量的值在规划求解中始终不变,也即为常量。 3.变量类型: Lingo中变量被默认为大于等于0的浮点型变量,在解决某些问题对变量有特殊的要求,需要重新定义其变量类型。下面介绍几个常用的:
①变量不受大于等于的限制,即也可以取到负值: 用 @Free( x ); 语句。 ②变量为整型 : 用 @Gin( x ); 语句。
③变量为二进制数,即取值非0即1:
用 @Bin( x ); 语句。
其中x 是要改变类型的变量。 更多请见lingo的help文件。
4 第 页,共10页
二.Loop语句
Lingo提供的FOR、SUM、MAX 、MIN语句会使我们更轻松地表达多种约束表达式,同时也避免了大量的输入工作。 1.for语句: a) 假定我们要定义xi为整型变量,一般我们需要写下如下代码:
@GIN(X(1)) ; @GIN(X(2)) ;
@GIN(X(3)) ;
@GIN(X(4)) ;
@GIN(X(5)) ;
@GIN(X(6)) ;
@GIN(X(7)) ;
@GIN(X(8)) ;
显然这太麻烦了。使用for语句 @for( xb1( i ) : @GIN( x( i ) ));
就可以替代上面的输入工作。其中xb1 在上述代码中已经定义过,变量i是索引变量。
FOR语句格式:
@FOR( SETS_NAME ( 索引变量 ) ) :循环部分表达式 )
@for( xb1( i ) : @GIN( x( i ) )); 下面我们用C语言来帮助理解,以便我们更好地理解。
For( i=1;i<=8;i++)
{ @gin( x(i) ); }
@for 语句中冒号前面的部分 xb1( i ) 说明索引变量 i 将从1 递增到到8 ;冒号后面是循环的内容,可以是一个语句,也可以是多个语句用分号隔开。 b) 上面介绍的是一维的循环,二维循环也与之类似,例如:
@for( xb3(i , j) : @gin( a(i,j)));
用C语言解释为:
For(i=;i<=8;i++) For(j=1;j<=6;j++) { @gin( a(i,j)); }
2.SUM语句:
在约束条件表达式中经常用到∑,lingo提供的SUM语句能方便地表达,但必须要以SETS为基础。
SUM语句格式和FOR语句类似:
@SUM( SETS_NAME ( 索引变量 ) ) :被累加部分表达式 )
其中累加部分表达式只能是一条语句。
SUM语句不可以像FOR语句那样作为单独的一句话出现,一般将它和另一个常量或表达式比较大小,例:
@SUM(SETS_NAME ( 索引变量 ) ) :被累加部分表达式 )<=常量(表达式); 有时为了程序看上去更简洁,可以这样写:
VName=@SUM(SETS_NAME ( 索引变量 ) ) :被累加部分表达式 ); VName<=常量(表达式);
这样VName 将代表整个∑表达式,这样将有可能会影响程序运行速度,一般这样的
5 第 页,共10页