LINGO教程.docx
- 文档编号:8692462
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:106
- 大小:390.53KB
LINGO教程.docx
《LINGO教程.docx》由会员分享,可在线阅读,更多相关《LINGO教程.docx(106页珍藏版)》请在冰豆网上搜索。
LINGO教程
第0章LINGO概述
优化问题可以说是人们在工程技术、经济管理和科学研究等领域中最常遇到的一类问题。
设计师要在满足强度要求等条件下选择材料的尺寸,使结构总量最轻;公司经理要根据生产成本和市场需求确定产品价格,使所获得的利润最高;投资者要选择一些股票、债券“下注”,使收益最大,而风险最小。
许多生产计划与管理分配问题都可以归纳为最优化问题,最优化模型是数学建模中应用最广泛的模型之一,其内容包括线性规划、非线性规划、整数线性规划、动态规划、多目标规划、决策规划等。
有些人习惯于依赖过去的经验解决面临的优化问题,认为这样切实可行,并且没有太大的风险。
但是这种处理过程常常会融入决策者太多的主观因素,从而无法确认结果的最优性。
也有人习惯于作大量的试验反复比较,认为这样真实可靠,但是显然需要花费很多资金和人力,而且得到的最优结果基本上跑不出原来设计的试验范围。
为了更准确的达到结果的最有性,接下来本文将讨论的是用数学建模的方法来处理优化问题,即建立和求解所谓的优化模型。
虽然由于建模时要作适当的简化,可能使得结果不一定完全可行或达到实际的最优,但是它基于客观规律和数据,又不需要多大的费用。
如果在建模的基础上再辅之以适当的经验和试验,就可以期望得到实际问题的一个比较圆满的回答。
在决策科学化、定量化的呼声日益高涨的今天,这无疑是符合时代潮流和形式发展需要的。
一、基本介绍
1、优化模型的三要素
(1)决策变量,通常是某一问题需要求解的未知量,用
维向量
表示,当对
赋值后它通常称为该问题的一个解;
(2)目标函数,通常是某一问题需要优化(最大或最小)的那个目标的数学表达式,它是决策变量
的函数,可以抽象的记作
;
(3)约束条件,由该问题对决策变量的现实条件给出,即
允许的取值范围为
,
称为可行域,常用一组关于
的等式
和(或)不等式
来界定,分别称为等式约束和不等式约束。
于是,优化模型从数学上可以表述为:
(1)
(2)
(3)
这里opt最优化的意思,可以是min(求极大,即minamize的缩写)或max(求极小,即minamize的缩写)的两者之一;s.t.(即subjectto)“受约束于”之意。
2、优化模型的基本类型
(1.)决策变量x的所有分量xi均为连续数值
a)f,hi,gi都是线性函数,则为线性规划(LP)
b)f,hi,gi至少有一个是非线性,则为非线性规划(NLP)
c)f是二次函数,hi,gi都是线性,则为二次规划(QP)
(2.)决策变量x的的一个或多个分量xi取离散值
a)x的至少一个分量只取整数数值,则为整数规划(IP)
b)x的分量限定只取整数0或1,则为0-1规划(ZOP)
(3.)此外,为了解决实际问题的需要,还可以分为:
单目标规划,多目标规划,动态规划,多层规划等。
3、LINGO软件的介绍
这套软件包由美国芝加哥大学的LinusScharge教授于1980年前后开发,专门用于求解最优化问题,后经不断完善和扩充,并成立LINDO公司进行商业化运作,取得了巨大的成功。
全球《财富》杂志500强的企业中,一半以上使用该公司产品,其中前25强企业中有23家使用该产品。
该软件包功能强大,版本也很多,而我们使用的只是演示版(试用版),演示版与正式版功能基本上是类似的,只是能够求解问题的规模受到限制,总变量数不超过30个,这在我们目前的使用过程中,基本上是足够。
Lingo是英文LinearInteractiveandGeneralOptimizer字首的缩写,即“交互式的线性和通用优化求解器”,它可以用来求解线性规划(LP)和二次规划(QP,还可以用来求解非线性规划。
Lingo最大特色在于可以允许决策变量是整数,而且执行速度很快;Lingo实际上还是一种建模语言,即使对优化方面的专业知识了解不多的用户,也能方便的进行输入、求解,并能快速的得到复杂优化问题的高质量的解。
关于Lingo的基本用法的几点注意事项:
1Lingo中变量不区分大小写,变量名可以超过8个,不能超过32个,需以字母开头;
2用Lingo解优化模型时已假定所有变量非负(除非用限定变量范围的函数@free或@bnd另行说明);
3变量可以放在约束条件右端,同时数字也可以放在约束条件左边;
4Lingo模型语句由一系列语句组成,每一个语句都必须以“;”结尾;
5Lingo中以“!
”开始的是说明语句,说明语句也以“;”结束。
在Lingo中建立的优化模型可以引用大量的内部函数这些函数都以@符号打头,其用法比较简单,我们一一列出:
基本数学函数:
@ABS(X):
绝对值函数,返回X的绝对值;
@EXP(X):
指数函数(以自然对数e为底),返回eX的值;
@LOG(X):
自然对数函数,返回X的自然对数值;
@POW(X,Y):
指数函数,返回XY的值;
@SQR(X):
平方函数,返回X2的值;
@SQRT(X):
平方根函数,返回X的平方根;
@FLOOR(X):
取整函数,返回X的整数部分(向靠近0的方向取);
@SMAX(X):
取最大值,返回一列数(LIST)的最大值;
@SMIN(X):
取最大小值,返回一列数(LIST)的最小值;
三角函数:
@COS(X),@SIN(X),@TAN(X);
变量定界函数
@BND(L,X,U):
限制L<=X<=U.注意,Lingo中没有与Lindo命令SLB、SUB类似的函数@SLB、@SUB.
@BIN(X):
限制X为0或1。
注意Lindo中的命令是INT,但Lingo中这个函数却不是@INT.
@FREE(X):
取消对X的符号限制(即可取负数,0或正数).
@GIN(X):
限制X为整数.
二、具体的模型求解
1、简单的优化模型及lingo求解
例1、背包问题
一个旅行者的背包最多只能装6kg物品.现有4件物品的重量和价值分别为2kg,3kg,3kg,4kg,1元,1.2元,0.9元,1.1元.应携带那些物品使得携带物品的价值最大?
建模:
记xj为旅行者携带第j件物品的件数,取值只能为0或1.
求目标函数f=x1+1.2x2+0.9x3+1.1x4在约束条件2x1+3x2+3x3+4x46下的最大值.
用Lingo软件求解0-1规划
Model:
Max=x1+1.2*x2+0.9*x3+1.1*x4;
2*x1+3*x2+3*x3+4*x4<=6;
@int(x1);
@int(x2);
@int(x3);
@int(x4);
end
例2、飞船装载问题
设有n种不同类型的科学仪器希望装在登月飞船上,令cj>0表示每件第j类仪器的科学价值;aj>0表示每件第j类仪器的重量.每类仪器件数不限,但装载件数只能是整数.飞船总载荷不得超过数b.设计一种方案,使得被装载仪器的科学价值之和最大.建模记xj为第j类仪器的装载数.
求目标函数f=jcjxj在约束条件jajxjb,xj为正整数,下的最大值.
用分枝定界法求解整数规划问题
基本思想:
反复划分可行域并确定最优值的界限,将原问题不断地分枝为若干个子问题,且缩小最优质的取值范围,直到求得最优解.
例:
求目标函数f=3x1+2x2在约束条件:
2x1+3x214,2x1+x29,x1x2为自然数下的最大值.
用Lingo软件求解整数规划
model:
max=3*x1+2*x2;
2*x1+3*x2<=14;
2*x1+x2<=9;
@gin(x1);
@gin(x2);
end
LINGO是用来求解线性和非线性优化问题的简易工具。
LINGO内置了一种建立最优化模型的语言,可以简便地表达大规模问题,利用LINGO高效的求解器可快速求解并分析结果。
第1章LINGO快速入门
当你在windows下开始运行LINGO系统时,会得到类似下面的一个窗口:
外层是主框架窗口,包含了所有菜单命令和工具条,其它所有的窗口将被包含在主窗口之下。
在主窗口内的标题为LINGOModel–LINGO1的窗口是LINGO的默认模型窗口,建立的模型都都要在该窗口内编码实现。
下面举两个例子。
例1.1如何在LINGO中求解如下的LP问题:
在模型窗口中输入如下代码:
min=2*x1+3*x2;
x1+x2>=350;
x1>=100;
2*x1+x2<=600;
然后点击工具条上的按钮即可。
例1.2使用LINGO软件计算6个发点8个收点的最小费用运输问题。
产销单位运价如下表。
单
位销地
运
价
产地
B1
B2
B3
B4
B5
B6
B7
B8
产量
A1
6
2
6
7
4
2
5
9
60
A2
4
9
5
3
8
5
8
2
55
A3
5
2
1
9
7
4
3
3
51
A4
7
6
7
3
9
2
7
1
43
A5
2
3
9
5
7
2
6
5
41
A6
5
5
2
2
8
1
4
3
52
销量
35
37
22
32
41
32
43
38
使用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
49538582
52197433
76739271
23957265
55228143;
enddata
end
然后点击工具条上的按钮即可。
为了能够使用LINGO的强大功能,接着第二节的学习吧。
第2章LINGO中的集
对实际问题建模的时候,总会遇到一群或多群相联系的对象,比如工厂、消费者群体、交通工具和雇工等等。
LINGO允许把这些相联系的对象聚合成集(sets)。
一旦把对象聚合成集,就可以利用集来最大限度的发挥LINGO建模语言的优势。
现在我们将深入介绍如何创建集,并用数据初始化集的属性。
学完本节后,你对基于建模技术的集如何引入模型会有一个基本的理解。
2.1为什么使用集
集是LINGO建模语言的基础,是程序设计最强有力的基本构件。
借助于集,能够用一个单一的、长的、简明的复合公式表示一系列相似的约束,从而可以快速方便地表达规模较大的模型。
2.2什么是集
集是一群相联系的对象,这些对象也称为集的成员。
一个集可能是一系列产品、卡车或雇员。
每个集成员可能有一个或多个与之有关联的特征,我们把这些特征称为属性。
属性值可以预先给定,也可以是未知的,有待于LINGO求解。
例如,产品集中的每个产品可以有一个价格属性;卡车集中的每辆卡车可以有一个牵引力属性;雇员集中的每位雇员可以有一个薪水属性,也可以有一个生日属性等等。
LINGO有两种类型的集:
原始集(primitive set)和派生集(derivedset)。
一个原始集是由一些最基本的对象组成的。
一个派生集是用一个或多个其它集来定义的,也就是说,它的成员来自于其它已存在的集。
2.3模型的集部分
集部分是LINGO模型的一个可选部分。
在LINGO模型中使用集之前,必须在集部分事先定义。
集部分以关键字“sets:
”开始,以“endsets”结束。
一个模型可以没有集部分,或有一个简单的集部分,或有多个集部分。
一个集部分可以放置于模型的任何地方,但是一个集及其属性在模型约束中被引用之前必须定义了它们。
2.3.1定义原始集
为了定义一个原始集,必须详细声明:
·集的名字
·可选,集的成员
·可选,集成员的属性
定义一个原始集,用下面的语法:
setname[/member_list/][:
attribute_list];
注意:
用“[]”表示该部分内容可选。
下同,不再赘述。
Setname是你选择的来标记集的名字,最好具有较强的可读性。
集名字必须严格符合标准命名规则:
以拉丁字母或下划线(_)为首字符,其后由拉丁字母(A—Z)、下划线、阿拉伯数字(0,1,…,9)组成的总长度不超过32个字符的字符串,且不区分大小写。
注意:
该命名规则同样适用于集成员名和属性名等的命名。
Member_list是集成员列表。
如果集成员放在集定义中,那么对它们可采取显式罗列和隐式罗列两种方式。
如果集成员不放在集定义中,那么可以在随后的数据部分定义它们。
①当显式罗列成员时,必须为每个成员输入一个不同的名字,中间用空格或逗号搁开,允许混合使用。
例2.1可以定义一个名为students的原始集,它具有成员John、Jill、Rose和Mike,属性有sex和age:
sets:
students/JohnJill,RoseMike/:
sex,age;
endsets
②当隐式罗列成员时,不必罗列出每个集成员。
可采用如下语法:
setname/member1..memberN/[:
attribute_list];
这里的member1是集的第一个成员名,memberN是集的最末一个成员名。
LINGO将自动产生中间的所有成员名。
LINGO也接受一些特定的首成员名和末成员名,用于创建一些特殊的集。
列表如下:
隐式成员列表格式
示例
所产生集成员
1..n
1..5
1,2,3,4,5
StringM..StringN
Car2..car14
Car2,Car3,Car4,…,Car14
DayM..DayN
Mon..Fri
Mon,Tue,Wed,Thu,Fri
MonthM..MonthN
Oct..Jan
Oct,Nov,Dec,Jan
MonthYearM..MonthYearN
Oct2001..Jan2002
Oct2001,Nov2001,Dec2001,Jan2002
③集成员不放在集定义中,而在随后的数据部分来定义。
例2.2
!
集部分;
sets:
students:
sex,age;
endsets
!
数据部分;
data:
students,sex,age=John116
Jill014
Rose017
Mike113;
enddata
注意:
开头用感叹号(!
),末尾用分号(;)表示注释,可跨多行。
在集部分只定义了一个集students,并未指定成员。
在数据部分罗列了集成员John、Jill、Rose和Mike,并对属性sex和age分别给出了值。
集成员无论用何种字符标记,它的索引都是从1开始连续计数。
在attribute_list可以指定一个或多个集成员的属性,属性之间必须用逗号隔开。
可以把集、集成员和集属性同C语言中的结构体作个类比。
如下图:
集←→结构体
集成员←→结构体的域
集属性←→结构体实例
LINGO内置的建模语言是一种描述性语言,用它可以描述现实世界中的一些问题,然后再借助于LINGO求解器求解。
因此,集属性的值一旦在模型中被确定,就不可能再更改。
在LINGO中,只有在初始部分中给出的集属性值在以后的求解中可更改。
这与前面并不矛盾,初始部分是LINGO求解器的需要,并不是描述问题所必须的。
2.3.2定义派生集
为了定义一个派生集,必须详细声明:
·集的名字
·父集的名字
·可选,集成员
·可选,集成员的属性
可用下面的语法定义一个派生集:
setname(parent_set_list)[/member_list/][:
attribute_list];
setname是集的名字。
parent_set_list是已定义的集的列表,多个时必须用逗号隔开。
如果没有指定成员列表,那么LINGO会自动创建父集成员的所有组合作为派生集的成员。
派生集的父集既可以是原始集,也可以是其它的派生集。
例2.3
sets:
product/AB/;
machine/MN/;
week/1..2/;
allowed(product,machine,week):
x;
endsets
LINGO生成了三个父集的所有组合共八组作为allowed集的成员。
列表如下:
编号成员
1(A,M,1)
22 (A,M,2)
33 (A,N,1)
44 (A,N,2)
55 (B,M,1)
66 (B,M,2)
77 (B,N,1)
88 (B,N,2)
成员列表被忽略时,派生集成员由父集成员所有的组合构成,这样的派生集成为稠密集。
如果限制派生集的成员,使它成为父集成员所有组合构成的集合的一个子集,这样的派生集成为稀疏集。
同原始集一样,派生集成员的声明也可以放在数据部分。
一个派生集的成员列表有两种方式生成:
①显式罗列;②设置成员资格过滤器。
当采用方式①时,必须显式罗列出所有要包含在派生集中的成员,并且罗列的每个成员必须属于稠密集。
使用前面的例子,显式罗列派生集的成员:
allowed(product,machine,week)/AM1,AN2,BN1/;
如果需要生成一个大的、稀疏的集,那么显式罗列就很讨厌。
幸运地是许多稀疏集的成员都满足一些条件以和非成员相区分。
我们可以把这些逻辑条件看作过滤器,在LINGO生成派生集的成员时把使逻辑条件为假的成员从稠密集中过滤掉。
例2.4
sets:
!
学生集:
性别属性sex,1表示男性,0表示女性;年龄属性age.;
students/John,Jill,Rose,Mike/:
sex,age;
!
男学生和女学生的联系集:
友好程度属性friend,[0,1]之间的数。
;
linkmf(students,students)|sex(&1)#eq#1#and#sex(&2)#eq#0:
friend;
!
男学生和女学生的友好程度大于0.5的集;
linkmf2(linkmf)|friend(&1,&2)#ge#0.5:
x;
endsets
data:
sex,age=116
014
017
013;
friend=0.30.50.6;
enddata
用竖线(|)来标记一个成员资格过滤器的开始。
#eq#是逻辑运算符,用来判断是否“相等”,可参考§4.&1可看作派生集的第1个原始父集的索引,它取遍该原始父集的所有成员;&2可看作派生集的第2个原始父集的索引,它取遍该原始父集的所有成员;&3,&4,……,以此类推。
注意如果派生集B的父集是另外的派生集A,那么上面所说的原始父集是集A向前回溯到最终的原始集,其顺序保持不变,并且派生集A的过滤器对派生集B仍然有效。
因此,派生集的索引个数是最终原始父集的个数,索引的取值是从原始父集到当前派生集所作限制的总和。
总的来说,LINGO可识别的集只有两种类型:
原始集和派生集。
在一个模型中,原始集是基本的对象,不能再被拆分成更小的组分。
原始集可以由显式罗列和隐式罗列两种方式来定义。
当用显式罗列方式时,需在集成员列表中逐个输入每个成员。
当用隐式罗列方式时,只需在集成员列表中输入首成员和末成员,而中间的成员由LINGO产生。
另一方面,派生集是由其它的集来创建。
这些集被称为该派生集的父集(原始集或其它的派生集)。
一个派生集既可以是稀疏的,也可以是稠密的。
稠密集包含了父集成员的所有组合(有时也称为父集的笛卡尔乘积)。
稀疏集仅包含了父集的笛卡尔乘积的一个子集,可通过显式罗列和成员资格过滤器这两种方式来定义。
显式罗列方法就是逐个罗列稀疏集的成员。
成员资格过滤器方法通过使用稀疏集成员必须满足的逻辑条件从稠密集成员中过滤出稀疏集的成员。
不同集类型的关系见下图。
第3章模型的数据部分和初始部分
在处理模型的数据时,需要为集指派一些成员并且在LINGO求解模型之前为集的某些属性指定值。
为此,LINGO为用户提供了两个可选部分:
输入集成员和数据的数据部分(DataSection)和为决策变量设置初始值的初始部分(InitSection)。
3.1模型的数据部分
3.1.1数据部分入门
数据部分提供了模型相对静止部分和数据分离的可能性。
显然,这对模型的维护和维数的缩放非常便利。
数据部分以关键字“data:
”开始,以关键字“enddata”结束。
在这里,可以指定集成员、集的属性。
其语法如下:
object_list=value_list;
对象列(object_list)包含要指定值的属性名、要设置集成员的集名,用逗号或空格隔开。
一个对象列中至多有一个集名,而属性名可以有任意多。
如果对象列中有多个属性名,那么它们的类型必须一致。
如果对象列中有一个集名,那么对象列中所有的属性的类型就是这个集。
数值列(value_list)包含要分配给对象列中的对象的值,用逗号或空格隔开。
注意属性值的个数必须等于集成员的个数。
看下面的例子。
例3.1
sets:
set1/A,B,C/:
X,Y;
endsets
data:
X=1,2,3;
Y=4,5,6;
enddata
在集set1中定义了两个属性X和Y。
X的三个值是1、2和3,Y的三个值是4、5和6。
也可采用如下例子中的复合数据声明(datastatement)实现同样的功能。
例3.2
sets:
set1/A,B,C/:
X,Y;
endsets
data:
X,Y=14
25
36;
enddata
看到这个例子,可能会认为X被指定了1、4和2三个值,因为它们是数值列中前三个,而正确的答案是1、2和3。
假设对象
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- LINGO 教程