-314-附录三运筹学的LINGO软件§1简介LINGO软件有多种版本,如LINDO,GINO和LINGO(包括LINGONL)软件。LINDO是一种专门用于求解数学规划问题的优化计算软件包,版权现在由美国LINDO系统公司(LindoSystemInc.)所拥有。LINDO软件包的特点是程序执行速度快,易于方便地输入、修改、求解和分析一个数学规划(优化问题),因此LINDO在教学,科研和工业界得到广泛应用。有关该软件的发行版本,发行价格和其它昀新信息都可以从LINDO系统公司的INTERNET网络站点获取,该站点还提供部分LINDO软件的演示版本或测试版本。LINDO由美国芝加哥大学的LinusSchrage教授首先开发,随后又推出了GINO,LINGO,LINGONL(又称LINGO2)和“what’sbest!”等优化软件,现在一般仍用LINDO作为这些软件的统称。各组件的功能各有侧重,分别简要介绍如下:(i)LINDO是LinearInteractiveandDiscreteOptimizer字首的缩写形式,可以用来求解线性规划(LP—LinearProgramming),整数规划(IP—IntegerProgramming)和二次规划(QP—QuadraticProgramming)问题。(ii)GINO是GeneralInteractiveOptimizer字首的缩写形式,可以用来求解非线性规划(NLP-----Non-LinearProgramming)问题,也可用于求解一些线性和非线性方程(组)以及代数方程求根等。GINO中包含了各种一般的数学函数(包括大量的概率函数),可供使用者建立问题模型时调用。(iii)LINGO可以用来求解线性,非线性和整数规划问题。(iv)LINGONL(LINGO2)可以用来求解线性,非线性和整数规划问题。与LINDO和GINO不同的是,LINGO和LINGONL(LINGO2)包含了內置的建模语言,允许以简练,直观的方式描述较大规模的优化问题,模型中所需的数据可以以一定格式保存在独立的文件中。(v)“what’sbest!”组件主要用于数据文件是由电子表格软件(如LUTOS1-2-3和MSOFFICE等)生成的情形。LINDO软件包有多种版本,但其软件內核和使用方法基本上是类似的。下面介绍LINGO组件的基本使用方法。§2LINGO快速入门当你在windows下开始运行LINGO系统时,会得到一个窗口:外层是主框架窗口,包含了所有菜单命令和工具条,其它所有的窗口将被包含在主窗口之下。在主窗口内的标题为LINGOModel–LINGO1的窗口是LINGO的默认模型窗口,建立的模型都都要在该窗口内编码实现。下面举两个例子。例2.1如何在LINGO中求解如下的LP问题:2132minxx+s.t.⎪⎪⎩⎪⎪⎨⎧≥≤+≥≥+0,60021003502121121xxxxxxx由于LINGO中已假设所有的变量是非负的,所以非负约束不必再输入到计算机中,-315-LINGO也不区分变量中的大小写字符(任何小写字符将被转换为大写字符);约束条件中的”=”及”=”可用””及””代替。在模型窗口中输入如下代码:min=2*x1+3*x2;x1+x2350;x1100;2*x1+x2600;然后点击工具条上的按钮即可。例2.2使用LINGO软件计算6个发点8个收点的昀小费用运输问题。产销单位运价如下表。单位销地运价产地B1B2B3B4B5B6B7B8产量A16267425960A24953858255A35219743351A47673927143A52395726541A65522814352销量3537223241324338使用LINGO软件,编制程序如下:model:!6发点8收点运输问题;sets:warehouses/wh1..wh6/:capacity;vendors/v1..v8/:demand;links(warehouses,vendors):cost,volume;endsets!目标函数;min=@sum(links:cost*volume);!需求约束;@for(vendors(J):@sum(warehouses(I):volume(I,J))=demand(J));!产量约束;@for(warehouses(I):@sum(vendors(J):volume(I,J))=capacity(I));!这里是数据;data:capacity=605551434152;demand=3537223241324338;cost=62674295-316-4953858252197433767392712395726555228143;enddataend然后点击工具条上的按钮即可。Lingo模型由4个部分构成:目标与约束,集合,数据,初始。Lingo中的集合类型见下图:Lingo中有三类运算符:算术运算符,逻辑运算符和关系运算符。运算符的优先级见下表:优先级运算符昀高#NOT#,-(负号)^*,/+,-(减号)#EQ#,#NE#,#GE#,#GT#,#LE#,#LT##AND#,#OR#昀低,=,注意使用Lingo中的四个集合循环函数:FOR,SUM,MAX,MIN。在Lingo中可以使用外部数据文件,有如下几种方法:(1)复制-粘贴方法(Copy-Paste);(2)@FILE输入数据,@TEXT输出数据;(3)@OLE函数与电子表格软件(如EXCEL)连接;(4)@ODBC函数与数据库连接。§3LINGO中的集对实际问题建模的时候,总会遇到一群或多群相联系的对象,比如工厂、消费者群体、交通工具和雇工等等。LINGO允许把这些相联系的对象聚合成集(sets)。一旦把对象聚合成集,就可以利用集来昀大限度的发挥LINGO建模语言的优势。-317-3.1什么是集集是一群相联系的对象,这些对象也称为集的成员。一个集可能是一系列产品、卡车或雇员。每个集成员可能有一个或多个与之有关联的特征,我们把这些特征称为属性。属性值可以预先给定,也可以是未知的,有待于LINGO求解。例如,产品集中的每个产品可以有一个价格属性;卡车集中的每辆卡车可以有一个牵引力属性;雇员集中的每位雇员可以有一个薪水属性,也可以有一个生日属性等等。LINGO有两种类型的集:原始集(primitiveset)和派生集(derivedset)。一个原始集是由一些昀基本的对象组成的。一个派生集是用一个或多个其它集来定义的,也就是说,它的成员来自于其它已存在的集。3.2模型的集部分集部分是LINGO模型的一个可选部分。在LINGO模型中使用集之前,必须在集部分事先定义。集部分以关键字“sets:”开始,以“endsets”结束。一个模型可以没有集部分,或有一个简单的集部分,或有多个集部分。一个集部分可以放置于模型的任何地方,但是一个集及其属性在模型约束中被引用之前必须定义了它们。3.2.1定义原始集为了定义一个原始集,必须详细声明:·集的名字·可选,集的成员·可选,集成员的属性定义一个原始集,用下面的语法:setname[/member_list/][:attribute_list];注意:用“[]”表示该部分内容可选。下同,不再赘述。Setname是你选择的来标记集的名字,昀好具有较强的可读性。集名字必须严格符合标准命名规则:以拉丁字母或下划线(_)为首字符,其后由拉丁字母(A—Z)、下划线、阿拉伯数字(0,1,…,9)组成的总长度不超过32个字符的字符串,且不区分大小写。注意:该命名规则同样适用于集成员名和属性名等的命名。Member_list是集成员列表。如果集成员放在集定义中,那么对它们可采取显式罗列和隐式罗列两种方式。如果集成员不放在集定义中,那么可以在随后的数据部分定义它们。①当显式罗列成员时,必须为每个成员输入一个不同的名字,中间用空格或逗号搁开,允许混合使用。例3.1可以定义一个名为students的原始集,它具有成员John、Jill、Rose和Mike,属性有sex和age:sets:students/JohnJill,RoseMike/:sex,age;endsets②当隐式罗列成员时,不必罗列出每个集成员。可采用如下语法:setname/member1..memberN/[:attribute_list];这里的member1是集的第一个成员名,memberN是集的昀末一个成员名。LINGO将自动产生中间的所有成员名。LINGO也接受一些特定的首成员名和末成员名,用于创建一些特殊的集。列表如下:隐式成员列表格式示例所产生集成员-318-1..n1..51,2,3,4,5StringM..StringNCar2..car14Car2,Car3,Car4,…,Car14DayM..DayNMon..FriMon,Tue,Wed,Thu,FriMonthM..MonthNOct..JanOct,Nov,Dec,JanMonthYearM..MonthYearNOct2001..Jan2002Oct2001,Nov2001,Dec2001,Jan2002③集成员不放在集定义中,而在随后的数据部分来定义。例3.2!集部分;sets:students:sex,age;endsets!数据部分;data:students,sex,age=John116Jill014Rose017Mike113;enddata注意:开头用感叹号(!),末尾用分号(;),!表示注释,可跨多行。在集部分只定义了一个集students,并未指定成员。在数据部分罗列了集成员John、Jill、Rose和Mike,并对属性sex和age分别给出了值。集成员无论用何种字符标记,它的索引都是从1开始连续计数。在attribute_list可以指定一个或多个集成员的属性,属性之间必须用逗号隔开。可以把集、集成员和集属性同C语言中的结构体作个类比。如下图:集←→结构体集成员←→结构体的域集属性←→结构体实例LINGO内置的建模语言是一种描述性语言,用它可以描述现实世界中的一些问题,然后再借助于LINGO求解器求解。因此,集属性的值一旦在模型中被确定,就不可能再更改。在LINGO中,只有在初始部分中给出的集属性值在以后的求解中可更改。这与前面并不矛盾,初始部分是LINGO求解器的需要,并不是描述问题所必须的。3.2.2定义派生集为了定义一个派生集,必须详细声明:·集的名字·父集的名字·可选,集成员·可选,集成员的属性可用下面的语法定义一个派生集:setname(parent_set_list)[/member_list/][:attribute_list];setname是集的名字。parent_set_list是已定义的集的列表,多个时必须用逗号隔开。如果没有指定成员列表,那么LINGO会自动创建父集成员的所有组合作为派生集的成员。派生集的父集既可以是原始集,也可以是其它的派生集。例3.3sets:product/AB/;machine/MN/;-319-week/1..2/;allowed(product,machine,week):x;endsetsLINGO生成了三个父集的所有组合共八组作为allowed集的成员。列表如下:编号成员1(A,M,1)2(A,M,2)3(A,N,1)4(A,N,2)5(B,M,1)6(B,M,2)7(B,N,1)8(B,N,2)成员列表被忽略时,派生集成员由父集成员所有的组合构成,这样的派生集成为稠密集。如果限制派生集的成员,使它成为父集成员所有组合构成的集合的一个子集,这样的派生集成为稀疏集。同原始集一样,派生集成员的声明也可以放在数据部分。一个派生集的成员列表有两种方式生成:①显式罗列;②设置成员资格过滤器。当采用方式①时,必须显式罗列出所有要包含在派生集中的成员,并且罗列的每个成员必须属于稠密集。使用前面的例子,显式罗列派生集的成员: