LINGO 教程
是用来求解线性和非线性优化问题的简易工具。 内置了一种建立最优化模
型的语言,可以简便地表达大规模问题,利用 高效的求解器可快速求解并分析结
果。
§1 LINGO 快速入门
当你在 下开始运行 系统时,会得到类似下面的一个窗口:
外层是主框架窗口,包含了所有菜单命令和工具条,其它所有的窗口将被包含在主窗口之
下。在主窗口内的标题为 的窗口是 的默认模型窗口,建
立的模型都都要在该窗口内编码实现。下面举两个例子。
例 1.1如何在 中求解如下的 问题:
0,
6002
100
350
..
32min
21
21
1
21
21
xx
xx
x
xx
ts
xx
在模型窗口中输入如下代码:
然后点击工具条上的按钮 即可。
例 1.2使用 LINGO 软件计算 6 个发点 8 个收点的最小费用运输问题。产销单位运价
如下表。
单
位 销地
运
价
产地
!
!
!
!
"
!
!
!
#
!
$
产量
%
# " &
%
" & $ $
共 55 页
1
LINGO 教程
%
& # "
%
"
# # & # "
%
& # "
%
$ "
销量
# " " $
使用 软件,编制程序如下:
'
( 发点 $ 收点运输问题
)'
*+,-.,//, .'0*1*0)2
3+.3//3$.'*
45*+,-63+7'0)63-
)
(目标函数
8-54'0)3-7
(需求约束
89+53+5:7'
8-5*+,-57'3-56:77*5:77
!产量约束;
@for(warehouses(I):
8-53+5:7'3-56:770*1*0)2577
!这里是数据;
*)*'
0*1*0)2 ""
*#""$
0) #"&
"&$$
&#"
# #&#
&#
$"
*)*
然后点击工具条上的按钮 即可。
为了能够使用 的强大功能,接着第二节的学习吧。
§2 LINGO 中的集
对实际问题建模的时候,总会遇到一群或多群相联系的对象,比如工厂、消费者群体、交
通工具和雇工等等。 允许把这些相联系的对象聚合成集())。一旦把对象聚合
成集,就可以利用集来最大限度的发挥 建模语言的优势。
现在我们将深入介绍如何创建集,并用数据初始化集的属性。学完本节后,你对基于
建模技术的集如何引入模型会有一个基本的理解。
2.1 为什么使用集
集是 建模语言的基础,是程序设计最强有力的基本构件。借助于集,能够用
一个单一的、长的、简明的复合公式表示一系列相似的约束,从而可以快速方便地表达规
模较大的模型。
共 55 页
2
LINGO 教程
2.2 什么是集
集是一群相联系的对象,这些对象也称为集的成员。一个集可能是一系列产品、卡车
或雇员。每个集成员可能有一个或多个与之有关联的特征,我们把这些特征称为属性。属
性值可以预先给定,也可以是未知的,有待于 求解。例如,产品集中的每个产品
可以有一个价格属性;卡车集中的每辆卡车可以有一个牵引力属性;雇员集中的每位雇员
可以有一个薪水属性,也可以有一个生日属性等等。
有两种类型的集:原始集51+)3 )7和派生集5+3)7。
一个原始集是由一些最基本的对象组成的。
一个派生集是用一个或多个其它集来定义的,也就是说,它的成员来自于其它已存在
的集。
2.3 模型的集部分
集部分是 模型的一个可选部分。在 模型中使用集之前,必须在集部分
事先定义。集部分以关键字“)';开始,以“);结束。一个模型可以没有集部分,
或有一个简单的集部分,或有多个集部分。一个集部分可以放置于模型的任何地方,但是
一个集及其属性在模型约束中被引用之前必须定义了它们。
2.3.1 定义原始集
为了定义一个原始集,必须详细声明:
<集的名字
<可选,集的成员
<可选,集成员的属性
定义一个原始集,用下面的语法:
)*=.>+?).@='*))+>-)?)@
注意:用“
[]”
表示该部分内容可选。下同,不再赘述。
A)* 是你选择的来标记集的名字,最好具有较强的可读性。集名字必须严格符
合标准命名规则:以拉丁字母或下划线(?)为首字符,其后由拉丁字母(%BC)、下划
线、阿拉伯数字(,,…,&)组成的总长度不超过 个字符的字符串,且不区分大
小写。
注意:该命名规则同样适用于集成员名和属性名等的命名。
>+?) 是集成员列表。如果集成员放在集定义中,那么对它们可采取显式罗列
和隐式罗列两种方式。如果集成员不放在集定义中,那么可以在随后的数据部分定义它们。
D当显式罗列成员时,必须为每个成员输入一个不同的名字,中间用空格或逗号搁开 ,
允许混合使用。
例 2.1 可以定义一个名为 )-) 的原始集,它具有成员 :,、:、E 和
4,属性有 和 *F:
)'
)-).:,:6E4.'6*F
endsets
G当隐式罗列成员时,不必罗列出每个集成员。可采用如下语法:
)*.>+//>+.='*))+>-)?)@
这里的 member1 是集的第一个成员名,memberN 是集的最末一个成员名。LINGO 将自动
产生中间的所有成员名。LINGO 也接受一些特定的首成员名和末成员名,用于创建一些特
殊的集。列表如下:
隐式成员列表格式 示例 所产生集成员
// // 666"6
A)+F//A)+F H*+//0*+" H*+6H*+6H*+"6I6H*+"
J*2//J*2 //K+ 6L-6M6L,-6K+
),//), 0)//:* 0)636J06:*
),N*+//),N
*+
0)//:*
0)636J06:*
共 55 页
3
LINGO 教程
O集成员不放在集定义中,而在随后的数据部分来定义。
例 2.2
(集部分
)'
)-)'6*F
)
(数据部分
*)*'
)-)66*F:,
:"
E#
4
*)*
注意:开头用感叹号(
!
),末尾用分号(
;
)表示注释,可跨多行。
在集部分只定义了一个集 )-),并未指定成员。在数据部分罗列了集成员
:,、:、E 和 4,并对属性 和 *F 分别给出了值。
集成员无论用何种字符标记6它的索引都是从 开始连续计数。在 *))+>-)?) 可以
指定一个或多个集成员的属性,属性之间必须用逗号隔开。
可以把集、集成员和集属性同 H 语言中的结构体作个类比。如下图:
集 ←→ 结构体
集成员 ←→ 结构体的域
集属性 ←→ 结构体实例
内置的建模语言是一种描述性语言,用它可以描述现实世界中的一些问题,然
后再借助于 求解器求解。因此,集属性的值一旦在模型中被确定,就不可能再更
改。在 中,只有在初始部分中给出的集属性值在以后的求解中可更改。这与前面
并不矛盾,初始部分是 求解器的需要,并不是描述问题所必须的。
2.3.2 定义派生集
为了定义一个派生集,必须详细声明:
<集的名字
<父集的名字
<可选,集成员
<可选,集成员的属性
可用下面的语法定义一个派生集:
)*51*+)?)?)7=.>+?).@='*))+>-)?)@
)* 是集的名字。1*+)?)?) 是已定义的集的列表,多个时必须用逗号隔
开。如果没有指定成员列表,那么 会自动创建父集成员的所有组合作为派生集的
成员。派生集的父集既可以是原始集,也可以是其它的派生集。
例 2.3
)'
1+-0).%!.
*0,..
4.//.
*51+-0)6*0,647'
)
生成了三个父集的所有组合共八组作为 * 集的成员。列表如下:
编号 成员
5%667
5%667
5%667
" "5%667
5!667
5!667
共 55 页
4
LINGO 教程
# #5!667
$ $5!667
成员列表被忽略时,派生集成员由父集成员所有的组合构成,这样的派生集成为稠密
集。如果限制派生集的成员,使它成为父集成员所有组合构成的集合的一个子集,这样的
派生集成为稀疏集。同原始集一样,派生集成员的声明也可以放在数据部分。一个派生集
的成员列表有两种方式生成:①显式罗列;②设置成员资格过滤器。当采用方式①时,必
须显式罗列出所有要包含在派生集中的成员,并且罗列的每个成员必须属于稠密集。使用
前面的例子,显式罗列派生集的成员:
*51+-0)6*0,647.%6%6!.
如果需要生成一个大的、稀疏的集,那么显式罗列就很讨厌。幸运地是许多稀疏集的成员
都满足一些条件以和非成员相区分。我们可以把这些逻辑条件看作过滤器,在 生
成派生集的成员时把使逻辑条件为假的成员从稠密集中过滤掉。
例 2.4
sets:
!学生集:性别属性 sex,1 表示男性,0 表示女性;年龄属性 age. ;
)-).:,6:6E64.'6*F
!男学生和女学生的联系集:友好程度属性 friend,[0,1]之间的数。
495)-)6)-)7P5Q7RSRR*R5Q7RSR'9+
!男学生和女学生的友好程度大于 0.5 的集;
495497P9+5Q6Q7RFR/'
)
*)*'
6*F
0 14
0 17
0 13;
friend = 0.3 0.5 0.6;
enddata
用竖线(P)来标记一个成员资格过滤器的开始。RSR是逻辑运算符,用来判断是否
“相等”,可参考T"/Q 可看作派生集的第 个原始父集的索引,它取遍该原始父集的所有
成员;Q 可看作派生集的第 个原始父集的索引,它取遍该原始父集的所有成员;
Q,Q",……,以此类推。注意如果派生集 ! 的父集是另外的派生集 %,那么上面所说
的原始父集是集 % 向前回溯到最终的原始集,其顺序保持不变,并且派生集 % 的过滤器对
派生集 ! 仍然有效。因此,派生集的索引个数是最终原始父集的个数,索引的取值是从原
始父集到当前派生集所作限制的总和。
总的来说, 可识别的集只有两种类型:原始集和派生集。
在一个模型中,原始集是基本的对象,不能再被拆分成更小的组分。原始集可以由显
式罗列和隐式罗列两种方式来定义。当用显式罗列方式时,需在集成员列表中逐个输入每
个成员。当用隐式罗列方式时,只需在集成员列表中输入首成员和末成员,而中间的成员
由 产生。
另一方面,派生集是由其它的集来创建。这些集被称为该派生集的父集(原始集或其
它的派生集)。一个派生集既可以是稀疏的,也可以是稠密的。稠密集包含了父集成员的
所有组合(有时也称为父集的笛卡尔乘积)。稀疏集仅包含了父集的笛卡尔乘积的一个子
集,可通过显式罗列和成员资格过滤器这两种方式来定义。显式罗列方法就是逐个罗列稀
疏集的成员。成员资格过滤器方法通过使用稀疏集成员必须满足的逻辑条件从稠密集成员
中过滤出稀疏集的成员。不同集类型的关系见下图。
共 55 页
5
集
稠密集
原始集
显式罗列
稀疏集
过滤器
派生集
集类
型