lingo软件及其应用中科院_第1页
lingo软件及其应用中科院_第2页
lingo软件及其应用中科院_第3页
lingo软件及其应用中科院_第4页
lingo软件及其应用中科院_第5页
已阅读5页,还剩242页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

常用数学软件选讲2第八章Lingo软件及其应用1.Lingo中的集

2.模型的数据部分和初始部分3.Lingo函数

4.LingoWindows命令

5.Lingo与电子制表软件的连接

6.Lingo与数据库的连接7.Lingo与VisualC++的连接8.利用Lingo开发高级模型34

2Lingo中的集

对实际问题建模的时候,总会遇到一群或多群相联系的对象,比如工厂、消费者群体、交通工具和雇工等等。Lingo允许把这些相联系的对象聚合成集(sets)。一旦把对象聚合成集,就可以利用集来最大限度的发挥Lingo建模语言的优势。2.1为什么使用集2.2什么是集2.3模型的集部分2.4小结52.1为什么使用集集是Lingo建模语言的基础,是程序设计最强有力的基本构件。借助于集,能够用一个单一的、长的、简明的复合公式表示一系列相似的约束,从而可以快速方便地表达规模较大的模型。例如:对于100个货栈的运输问题,如果一个一个的写出全部约束将是可怕的工作量。货栈1的运量<=存量货栈2的运量<=存量货栈3的运量<=存量………………Lingo可以采用最为简洁的表示方法:每个货栈的运输量<=存量62.2什么是集集是一群相联系的对象,这些对象也称为集的成员。一个集可能是一系列产品、卡车或雇员。每个集成员可能有一个或多个与之有关联的特征,我们把这些特征称为属性。属性值可以预先给定,也可以是未知的,有待于Lingo求解。例如:(1)产品集中的每个产品可以有一个价格属性;(2)卡车集中的每辆卡车可以有一个牵引力属性;(3)雇员集中的每位雇员可以有一个薪水属性,也可以有一个生日属性等等。7

2Lingo中的集

2.2什么是集(续)Lingo有两种类型的集:

原始集(primitiveset)和派生集(derivedset)一个原始集是由一些最基本的对象组成的。例如:集合WAREHOUSE是有6个货栈组成

集合VENDERS是由8个销售商组成8

2Lingo中的集

2.2什么是集(续)一个派生集是用一个或多个其它集来定义的,也就是说,它的成员来自于其它已存在的例如:由6个货栈和8个销售商之间的联系而形成的集合(LINKS)就是派生集合,需要注意的是,派生集合也可以由其他派生集合生成92.3模型的集部分集部分是Lingo模型的一个可选部分。在Lingo模型中使用集之前,集部分必须事先定义。集部分以关键字“sets:”开始,以“endsets”结束。一个模型可以没有集部分,或有一个简单的集部分,或有多个集部分。一个集部分可以放置于模型的任何地方,但是一个集及其属性在模型约束中被引用之前必须定义了它们。102.3模型的集部分sets:set1/1..3/:x,y;endsetsdata:x=123;y=456;enddataSet1集合定义了两个属性x和y。x取1、2、3三个值,而y取4、5、6三个值。sets:set1/1..3/:x,y;endsetsdata:xy=142536;enddataSet1集合定义了两个属性x和y。x取1、2、3三个值,而y取4、5、6三个值。112.3模型的集部分sets:warehouses/wh1..wh6/:capacity;vendors/v1..v8/:demand;links(warehouses,vendors):cost,volume;endsetsdata:capacity=605551434152;demand=3537223241324338;cost=626742954953858252197433767392712395726555228143;enddata12

2Lingo中的集

2.3.1定义原始集定义原始集的语法集的名字[/集的成员/][:集成员的属性];注意:用“[]”表示该部分内容可选。

如果集成员放在集定义中,那么对它们可采取显式罗列和隐式罗列两种方式。如果集成员不放在集定义中,那么可以在随后的数据部分定义它们。13

2Lingo中的集

2.3.1定义原始集(续)①当显式罗列成员时,必须为每个成员输入一个不同的名字,中间用空格或逗号搁开,允许混合使用。例2.1可以定义一个名为students的原始集,它具有成员John、Jill、Rose和Mike,属性有sex和age:sets:students/JohnJill,RoseMike/:sex,age;endsets14

2Lingo中的集

2.3.1定义原始集(续)②当隐式罗列成员时,不必罗列出每个集成员。可采用如下语法:集的名字/集的成员1..集的成员N/[:集成员的属性];

隐式成员列表格式示例所产生集成员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,Jan200215

2Lingo中的集

2.3.1定义原始集(续)③集成员不放在集定义中,而在随后的数据部分来定义。!集部分;sets:students:sex,age;endsets!数据部分;data:students,sex,age=John116Jill014 Rose017 Mike113;enddata注意:开头用感叹号(!),末尾用分号(;)表示注释,可跨多行。

16

2Lingo中的集

原始集和C++语言的类比17

2Lingo中的集

2.3.2定义派生集定义派生集的语法集的名字(父集名称列表)[/集的成员/][:集成员的属性];注意:用“[]”表示该部分内容可选。

父集名称列表是已定义的集的列表,多个时必须用逗号隔开。如果没有指定成员列表,那么Lingo会自动创建父集成员的所有组合作为派生集的成员(参见下页的例子)。派生集的父集既可以是原始集,也可以是其它的派生集。

18

2Lingo中的集

2.3.2定义派生集(续)编号成员编号成员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)定义派生集的例子sets:product/AB/;machine/MN/;week/1..2/;allowed(product,machine,week):x;endsets

Lingo生成了三个父集的所有组合共八组作为allowed集的成员:19

2Lingo中的集

2.3.2定义派生集(续)稠密集的定义稀疏集的定义派生集成员列表方式成员列表被忽略时,派生集成员由父集成员所有的组合构成,这样的派生集成为稠密集。

如果限制派生集的成员,使它成为父集成员所有组合构成的集合的一个子集,这样的派生集成为稀疏集。

①显式罗列。 例子:allowed(product,machine,week)/AM1,AN2,BN1/;

②设置成员资格过滤器。20

2Lingo中的集

设置成员资格过滤器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;endsetsdata:sex,age=116014017013;friend=0.30.50.6;enddata21

2Lingo中的集

设置成员资格过滤器(续)用竖线(|)来标记一个成员资格过滤器的开始。#eq#是逻辑运算符,用来判断是否“相等”,可参考§4.

&1可看作派生集的第1个原始父集的索引,它取遍该原始父集的所有成员;&2可看作派生集的第2个原始父集的索引,它取遍该原始父集的所有成员;&3,&4,……,以此类推。注意:如果派生集B的父集是另外的派生集A,那么上面所说的原始父集是集A向前回溯到最终的原始集,其顺序保持不变,并且派生集A的过滤器对派生集B仍然有效。因此,派生集的索引个数是最终原始父集的个数,索引的取值是从原始父集到当前派生集所作限制的总和。

22

2Lingo中的集

2.4小结Lingo可识别的集只有两种:原始集和派生集原始集是基本的对象,不能再被拆分成更小的组分。原始集可以由显式罗列和隐式罗列两种方式来定义。当用显式罗列方式时,需在集成员列表中逐个输入每个成员。当用隐式罗列方式时,只需在集成员列表中输入首成员和末成员,而中间的成员由Lingo产生。派生集是由其它的集来创建。这些集被称为该派生集的父集(原始集或其它的派生集)。一个派生集既可以是稀疏的,也可以是稠密的。稠密集包含了父集成员的所有组合(有时也称为父集的笛卡尔乘积)。稀疏集仅包含了父集的笛卡尔乘积的一个子集,可通过显式罗列和成员资格过滤器这两种方式来定义。显式罗列方法就是逐个罗列稀疏集的成员。成员资格过滤器方法通过使用稀疏集成员必须满足的逻辑条件从稠密集成员中过滤出稀疏集的成员。23

2Lingo中的集

2.4小结Lingo集类型的示意24

2Lingo中的集上机作业

1、熟悉Lingo的安装2、简单熟悉Lingo的语法规范,并可以解题25算例:某玻璃制造厂与三个不同地点的纯碱供应商签订合同,由他们供货给三个分厂,条件是不超过合同所定的数量,但必须满足生产需要。该问题如表3-1所示。问题中所给费率是每个供应商到每个工厂之间最短路径的运输费率。求运输方案2Lingo中的集上机作业26工厂1工厂2工厂3供应量供应商1x11x12x13400供应商2x21x22x23700供应商3x31x32x33500需求量6005005003-1运输问题-供需情况供销平衡2Lingo中的集上机作业27

3模型的数据部分和初始部分

在处理模型的数据时,需要为集指派一些成员并且在Lingo求解模型之前为集的某些属性指定值。为此,Lingo为用户提供了两个可选部分:输入集成员和数据的数据部分(DataSection)和为决策变量设置初始值的初始部分(InitSection)。3.1模型的数据部分3.2模型的初始部分28

3模型的数据部分和初始部分

3.1模型的数据部分为什么需要数据部分数据部分入门数据部分提供了模型相对静止部分和数据分离的可能性。显然,这对模型的维护和维数的缩放非常便利。数据部分以关键字“data:”开始,以关键字“enddata”结束。在这里,可以指定集成员、集的属性。其语法如下:对象列=数值列;

29数据部分入门(续)对象列:包含要指定值的属性名数值列:包含要分配给对象列中的对象的值,用逗号或空格隔开。注意属性值的个数必须等于集成员的个数。看下面的例子。sets:set1/A,B,C/:X,Y;endsetsdata:

X=1,2,3;

Y=4,5,6;enddata在集set1中定义了两个属性X和Y。X的三个值是1、2和3,Y的三个值是4、5和6。30数据部分入门(续)也可采用如下例子中的复合数据声明(datastatement):sets:set1/A,B,C/:X,Y;endsetsdata:X,Y=142536;enddata看到这个例子,可能会认为X被指定了1、4和2三个值,因为它们是数值列中前三个,而正确的答案是1、2和3。假设对象列有n个对象,Lingo在为对象指定值时,首先在n个对象的第1个索引处依次分配数值列中的前n个对象,然后在n个对象的第2个索引处依次分配数值列中紧接着的n个对象,……,以此类推。模型的所有数据——属性值和集成员——被单独放在数据部分,这可能是最规范的数据输入方式。313.1模型的数据部分参数在数据部分也可以指定一些标量变量(scalarvariables)。当一个标量变量在数据部分确定时,称之为参数。data:interest_rate=.085;enddata模型中用利率8.5%作为一个参数也可以同时指定多个参数。data:interest_rate,inflation_rate=.085.03;enddata323.1模型的数据部分

实时数据处理在某些情况,对于模型中的某些数据并不是定值,我们把这种情况称为实时数据处理(whatifanalysis)data:interest_rate,inflation_rate=.085?;enddata333.1模型的数据部分

指定属性为一个值可以在数据声明的右边输入一个值来把所有的成员的该属性指定为一个值。sets:days/MO,TU,WE,TH,FR,SA,SU/:needs;endsetsdata:

needs=20;enddataLingo将用20指定days集的所有成员的needs属性。343.1模型的数据部分指定属性为一个值(续)对于多个属性的情形,也可以指定一个值sets:days/MO,TU,WE,TH,FR,SA,SU/:needs,cost;endsetsdata:

needscost=20100;enddata353.1模型的数据部分数据部分的未知数值有时只想为一个集的部分成员的某个属性指定值,而让其余成员的该属性保持未知,以便让Lingo去求出它们的最优值。在数据声明中输入两个相连的逗号表示该位置对应的集成员的属性值未知。两个逗号间可以有空格。sets:years/1..5/:capacity;endsetsdata:

capacity=,34,20,,;enddata属性capacity的第2个和第3个值分别为34和20,其余的未知。363.2模型的初始部分模型的初始数值初始部分是Lingo提供的一个可选部分。在初始部分中,可以输入初始声明(initializationstatement)。初始部分输入的值仅被Lingo求解器当作初始点来用,并且仅仅对非线性模型有用。一个初始部分以“init:”开始,以“endinit”结束。init:X,Y=0,.1;endinitY=@log(X);X^2+Y^2<=1;好的初始点会减少模型的求解时间(看迭代次数)。37

4Lingo函数

Lingo有9种类型的函数:1.

基本运算符:包括算术运算符、逻辑运算符和关系运算符2.

数学函数:三角函数和常规的数学函数3.

金融函数:Lingo提供的两种金融函数4.

概率函数:Lingo提供了大量概率相关的函数5.

变量界定函数:这类函数用来定义变量的取值范围6.

集操作函数:这类函数为对集的操作提供帮助7.

集循环函数:遍历集的元素,执行一定的操作的函数8.

数据输入输出函数:这类函数允许模型和外部数据源相联系,进行数据的输入输出9.

辅助函数:各种杂类函数384.1基本运算符4.1.1算数运算符算术运算符是针对数值进行操作的。LINGO提供了5种二元运算符:^乘方﹡乘/除﹢加﹣减Lingo唯一的一元算术运算符是取反函数“﹣”。算术运算符示例:2﹣5/3,(2﹢4)/5等等。394.1.2逻辑运算符在Lingo中,逻辑运算符主要用于集循环函数的条件表达式中,来控制在函数中哪些集成员被包含,哪些被排斥。在创建稀疏集时用在成员资格过滤器中。(#not#否定该操作数的逻辑值,#not#是一个一元运算符)运算符为TRUE时条件运算符为TRUE时条件#eq#若两个运算数相等#ne#若两个运算符不相等#gt#若左边的运算符严格大于右边的运算符#ge#若左边的运算符大于或等于右边的运算符#lt#若左边的运算符严格小于右边的运算符#le#若左边的运算符小于或等于右边的运算符#and#仅当两个参数都为true时#or#仅当两个参数都为true时404.1.2逻辑运算符(续)这些运算符的优先级由高到低为:高

#not##eq##ne##gt##ge##lt##le#低

#and##or#逻辑运算符示例:2#gt#3#and#4#gt#2,其结果为假(0)。414.1.3关系运算符(1)Lingo有三种关系运算符:“=”、“<=”和“>=”。(2)Lingo并不支持严格小于和严格大于关系运算符。(3)Lingo中还能用“<”表示小于等于关系,“>”表示大于等于关系。(4)如让A严格小于B,那么:A+ε<=B,424.2数学函数Lingo提供了大量的标准数学函数:@abs(x)返回x的绝对值@sin(x)返回x的正弦值,x采用弧度制@cos(x)返回x的余弦值@tan(x)返回x的正切值@exp(x)返回常数e的x次方@log(x)返回x的自然对数@lgm(x)返回x的gamma函数的自然对数@sign(x)如果x<0返回-1;否则,返回1@floor(x)返回x的整数部分。当x>=0时,返回不超过x的最大整数;当x<0时,返回不低于x的最大整数。@smax(x1,x2,…,xn)返回x1,x2,…,xn中的最大值@smin(x1,x2,…,xn)返回x1,x2,…,xn中的最小值434.2数学函数 - 模型实例A B C DE a b x给定一个直角三角形,求包含该三角形的最小正方形。其中:求最小的正方形就相当于求如下的最优化问题:

444.2数学函数 - 模型实例(续)Lingo代码如下:model:sets:object/1..3/:f;endsetsdata:a,b=3,4;!两个直角边长,修改很方便;enddataf(1)=a*@sin(x);f(2)=b*@cos(x);f(3)=a*@cos(x)+b*@sin(x);min=@smax(f(1),f(2),f(3));@bnd(0,x,1.57); 限制0≤x≤1.57end454.3金融函数1.@fpa(I,n)-贷款买房问题贷款金额50000元,贷款年利率5.31%,采取分期付款方式(每年年末还固定金额,直至还清)。问拟贷款10年,每年需偿还多少元?Lingo代码如下:50000=x*@fpa(.0531,10);答案是x=6573.069元。464.3金融函数2.@fpl(I,n)--函数解释返回如下情形的净现值:单位时段利率为I,第n个时段支付单位费用。@fpl(I,n)的计算公式为:细心的同学可以发现这两个函数间的关系:474.4概率函数1.@pbn(p,n,x)

二项分布的累积分布函数 当n和(或)x不是整数时,用线性插值法进行计算。2.@pcx(n,x)

自由度为n的分布的累积分布函数。3.@peb(a,x)当到达负荷为a,服务系统有x个服务器且允许无穷排队时的Erlang繁忙概率。4.@pel(a,x)当到达负荷为a,服务系统有x个服务器且不允许排队时的Erlang繁忙概率。5.@pfd(n,d,x)

自由度为n和d的F分布的累积分布函数。6.@pfs(a,x,c)当负荷上限为a,顾客数为c,平行服务器数量为x时,有限源的Poisson服务系统的等待或返修顾客数的期望值。a是顾客数乘以平均服务时间,再除以平均返修时间。当c和(或)x不是整数时,采用线性插值进行计算。48

4Lingo函数

4.4概率函数(续)7.@phg(pop,g,n,x) 超几何(Hypergeometric)分布的累积分布函数。pop表示产品总数,g是正品数。从所有产品中任意取出n(n≤pop)件。pop,g,n和x都可以是非整数,这时采用线性插值进行计算。8.@ppl(a,x) Poisson分布的线性损失函数,即返回max(0,z-x)的期望值,其中随机变量z服从均值为a的Poisson分布。9.@pps(a,x) 均值为a的Poisson分布的累积分布函数。当x不是整数时,采用线性插值进行计算。10.@psl(x) 单位正态线性损失函数,即返回max(0,z-x)的期望值,其中随机变量z服从标准正态分布。11.@psn(x) 标准正态分布的累积分布函数。12.@ptd(n,x) 自由度为n的t分布的累积分布函数。49

4Lingo函数

4.4概率函数(续)13.@qrand(seed)产生服从(0,1)区间的拟随机数。@qrand只允许在模型的数据部分使用,它将用拟随机数填满集属性。通常,声明一个m×n的二维表,m表示运行实验的次数,n表示每次实验所需的随机数的个数。在行内,随机数是独立分布的;在行间,随机数是非常均匀的。这些随机数是用“分层取样”的方法产生的。

504.5变量界定函数变量界定函数实现对变量取值范围的附加限制,共4种:@bin(x)限制x为0或1@bnd(L,x,U)限制L≤x≤U@free(x)取消对变量x的默认下界为0的限制,即x可以取任意实数@gin(x)限制x为整数在默认情况下,Lingo规定变量是非负的,也就是说下界为0,上界为+∞。@free取消了默认的下界为0的限制,使变量也可以取负值。@bnd用于设定一个变量的上下界,它也可以取消默认下界为0的约束。514.6集处理函数1.@in(set_name,primitive_index_1[,primitive_index_2,…]) 如果元素在指定集中,返回1;否则返回0。全集为I,B是I的一个子集,C是B的补集。sets:I/x1..x4/;B(I)/x2/;C(I)|#not#@in(B,&1);endsets524.6集处理函数2.@index([set_name,]primitive_set_element)该函数返回在集set_name中原始集成员primitive_set_element的索引。如果set_name被忽略,那么Lingo将返回与primitive_set_element匹配的第一个原始集成员的索引。如果找不到,则产生一个错误。sets:!如何确定集成员(B,Y)属于派生集S3。S1/ABC/;S2/XYZ/;S3(S1,S2)/AX,AZ,BY,CX/;endsetsX=@in(S3,@index(S1,B),@index(S2,Y));sets: !表明有时为@index指定集是必要的。girls/debble,sue,alice/;boys/bob,joe,sue,fred/;endsetsI1=@index(sue);!I1的值是2I2=@index(boys,sue);!I2的值是3建议在使用@index函数时最好指定集。533.@wrap(index,limit)利用@wrap函数可以将变量的值限制在集合的索引范围之内。在集合循环函数里,当集合的最后一个元素出现后,使用@wrap函数就可以转到集合的第一个元素的索引。该函数返回j=index-k*limit,其中k是一个整数,取适当值保证j落在区间[1,limit]内。该函数相当于index模limit再加1。该函数在循环、多阶段计划编制中特别有用。(参见算例和职员分配模型)类似C++取模函数:doublej=fmod(index,limit);544.@size(set_name)该函数返回集set_name的成员个数。在模型中明确给出集大小时最好使用该函数。它的使用使模型更加数据中立,集大小改变时也更易维护。sets:S1/ABC/;S2/XYZ/;S3(S1,S2)/AX,AZ,BY,CX/;S4(S1,S2);EndsetsA=@size(S1);B=@size(S2);C=@size(S3);D=@size(S4);用Lingo看看ABCD应该是多少?554.7集循环函数(重要)集循环函数遍历整个集进行操作。其语法为@function(setname[(set_index_list)[|conditional_qualifier]]:expression_list);@function相应于下面罗列的四个集循环函数之一(@for、@sum、@max、@min);setname是要遍历的集;set_index_list是集索引列表;conditional_qualifier是用来限制集循环函数的范围,当集循环函数遍历集的每个成员时,LINGO都要对conditional_qualifier进行评价,若结果为真,则对该成员执行@function操作,否则跳过,继续执行下一次循环。564.7集循环函数(续)集循环函数遍历整个集进行操作。其语法为@function(setname[(set_index_list)[|conditional_qualifier]]:expression_list);expression_list是被应用到每个集成员的表达式列表,当用的是@for函数时,expression_list可以包含多个表达式,其间用逗号隔开。这些表达式将被作为约束加到模型中。当使用其余的三个集循环函数时,expression_list只能有一个表达式。如果省略set_index_list,那么在expression_list中引用的所有属性的类型都是setname集。571.@for该函数用来产生对集成员的约束。基于建模语言的标量需要显式输入每个约束,不过@for函数允许只输入一个约束,然后LINGO自动产生每个集成员的约束。例如产生序列(程序演示,产生什么序列)model:sets:number/1..5/:x;endsets@for(number(I):x(I)=I^2);end582.@sum该函数返回遍历指定的集成员的一个表达式的和。例如:求向量[5,1,3,4,6,10]前5个数的和。model:data:N=6;enddatasets:number/1..N/:x;endsetsdata:x=5134610;enddatas=@sum(number(I)|I#le#5:x);end593.@min和@max返回指定的集成员的一个表达式的最小值或最大值。例:求向量[5,1,3,4,6,10]前5个数的最小值,后3个数的最大值。model:data:N=6;enddatasets:number/1..N/:x;endsetsdata:x=5134610;enddataminv=@min(number(I)|I#le#5:x);maxv=@max(number(I)|I#ge#N-2:x);end60集循环函数的复杂例子职员时序安排模型一项工作一周7天都需要有人(比如护士工作),每天(周一至周日)所需的最少职员数为20、16、13、16、19、14和12,并要求每个职员一周连续工作5天(注意这里我们考虑稳定后的情况,不考虑临时工)。在满足每天对职员需求的前提下,需要决定每天需要雇佣多少职员,以使一周所雇佣的总人数最少。如何构造对应的Lingo模型?(1):相应的集合是什么?其属性又是什么?(2):哪个属性是数据及哪个属性是变量?(3):如何确定目标函数及约束条件?61相应的集合是什么?其属性又是什么?我们只有一个基本集合:一周的每一天。SETS: DAYS/MONTUEWEDTHUFRISATSUN/:REQUIRED,START;ENDSETSDAYS的两个属性。第一个是每天对职员的需求,第二个是每天开始雇佣的职员的人数。分别记为REQUIRED和START。62哪个属性是数据及哪个属性是变量?REQUIRED显然是给定的,所以它是数据;START是我们要确定的,所以它是变量。一旦确定了哪个属性是数据,就可以对数据进行赋值。DATA: REQUIRED=20161316191412;ENDDATA63确定目标函数:如何确定目标函数及约束条件?MIN=@SUM(DAYS(I):START(I));约束条件:每天当班的职员数要大于等于当天对职员的需求数,对一周的每天都是如此。“每天当班的职员数”如何计算?64“每天当班的职员数”如何计算?为了计算出当天工作的职员人数,我们要求出当天开始雇佣的职员人数及前4天开始雇佣人数之和。5天前和6天前开始雇佣的人数不得记入。转化成为Lingo语言:@FOR(DAYS(J): @SUM(DAYS(I)|I#LE#5:START(J-I+1)) >=REQUIRED(J));眼睛要睁大点,看清楚!65为什么会出错?66研究一下周四的情况,进行举例说明:星期四在DAYS中的索引为4,将星期四那天工作的职员人数的约束写出来是:START(4-1+1)+START(4-2+1)+START(4-3+1)+START(4-4+1)+START(4-5+1)>=REQUIRED(4);化简后为:START(4)+START(3)+START(2)+START(1)+START(0)>=REQUIRED(4);67START(0)索引是越界的!对于小于等于零的任何索引都对应到一周的某一天。具体地说,0对应SUN(7);-1对应SAT(6)……如何来完成这个任务?--它就是@WRAP!@FOR(DAYS(J): @SUM(DAYS(I)|I#LE#5: START(@WRAP(J-I+1,7))) >=REQUIRED(J));对于多周期计划模型中的索引问题,@WRAP正好适用。68最终的LINGO优化模型:SETS:!定义集合;DAYS/MONTUEWEDTHUFRISATSUN/:REQUIRED,START;ENDSETSDATA:!给集合里的数据部分赋值;REQUIRED=20161316191412;ENDDATAMIN=@SUM(DAYS(I):START(I));!给定目标函数;!给出约束条件:约束条件:每天当班的职员数要大于等于当天对职员的需求数;@FOR(DAYS(J): @SUM(DAYS(I)|I#LE#5: START(@WRAP(J-I+1,7))) >=REQUIRED(J));69职员的雇佣计划:星期MONTUEWEDTHUFRISATSUN开始雇佣人数8206330从求解报告的需求约束盈余看,每一天的松弛量都是零。这意味着职员人数都不超过需求,即每天工作的人数与需求正好相等(没有闲人)。如果采用人工排布会是什么样子?70配料模型:

在该模型中,人们将几种物品混合在一起制成多种产品。各种产品对各种物品都有一个最低的质量要求。在满足质量要求的前提下,如何确定产品的数量以获得最大利润。71CHESS食品公司销售4种品牌的坚果混合制品。它们的名字是Pawn(士兵)、Knight(武士)、Bishop(主教)和King(国王)。每一种产品对Peanuts(花生)和Cashews(腰果)有一定的比例要求。如下列出了各种产品每磅所含两种坚果的重量(单位:盎司),以及每种产品的销售价格。PawnKnightBishopKingPeanuts(oz.)151062Cashews(oz.)161014SellingPrice2345产品质量要求及单价72CHESS食品公司每天可以从供应商那里得到70磅的花生(Peanuts)和250磅的腰果(Cashews)。我们的问题:每天在不超过供应量的前提下,每种品牌的产品各生产多少?可使得总收益达到最大?注意:1磅=16盎司=0.454千克,1盎司=28.375克如何构造集合?

如何构造目标函数?

如何构造约束?73SETS:

NUTS/PEANUTS,CASHEWS/:SUPPLY;

BRANDS/PAWN,KNIGHT,BISHOP,KING/:PRICE,PRODUCE;

ENDSETS

集合NUTS有唯一一个属性SUPPLY,用于表示每天的坚果供应量(磅);

集合BRANDS有两个属性PRICE和PRODUCE。这里,PRICE表示每种产品的销售价格,PRODUCE是决策变量,表示每天每种产品应该生产多少。

此外,我们还需要一个集合。为了输入品牌公式,需要构造一个二维表格,构造一个NUTS和BRANDS的派生集合。

FORMULA(NUTS,BRANDS):OUNCES;

集合名称为FORMULA,它有唯一一个属性OUNCES。74定义数据域:

DATA:

SUPPLY=750250;

PRICE=2345;

OUNCES=151062

161014;

ENDDATA

目标函数:总收益最大

MAX=@SUM(BRANDS(I):PRICE(I)*PRODUCE(I));

约束条件:每天使用的坚果数量不超过每天的供应量

@FOR(NUTS(I):

@SUM(BRANDS(J):

OUNCES(I,J)*PRODUCE(J)/16)<=SUPPLY(I));

左边的求和除以16是将单位“盎司”转换为“磅”75SETS:NUTS/PEANUTS,CASHEWS/:SUPPLY;BRANDS/PAWN,KNIGHT,BISHOP,KING/:PRICE,PRODUCE;FORMULA(NUTS,BRANDS):OUNCES;ENDSETSDATA:SUPPLY=750250;PRICE=2345;OUNCES=151062161014;ENDDATAMAX=@SUM(BRANDS(I):PRICE(I)*PRODUCE(I));@FOR(NUTS(I):@SUM(BRANDS(J):OUNCES(I,J)*PRODUCE(J)/16)<=SUPPLY(I));7677用Lingo求解背包问题

78构造集合

SETS:ITEMS/ANT_REPEL,BEER,BLANKET,BRATWURST,BROWNIES,FRISBEE,SALAD,WATERMELON/:

INCLUDE,WEIGHT,RATING;ENDSETS

属性INCLUDE为一个0-1变量,说明该物品是否包含在背包中,用于野餐。WEIGHT说明每一物品的重量,而RATING存储着该物品的指数值79构造模型(目标函数)

MAX=@SUM(ITEMS:RATING*INCLUDE);在这里没有明确说明ITEMS的具体变量,此处是要对所有的ITEMS进行操作80SETS:ITEMS/ANT_REPEL,BEER,BLANKET,BRATWURST,BROWNIES,FRISBEE,SALAD,WATERMELON/:INCLUDE,WEIGHT,RATING;ENDSETSDATA:WEIGHTRATING=1239433831016541010;KNAPSACK_CAPACITY=15;ENDDATAMAX=@SUM(ITEMS:RATING*INCLUDE);@SUM(ITEMS:WEIGHT*INCLUDE)<=KNAPSACK_CAPACITY;@FOR(ITEMS:@BIN(INCLUDE));81PERT(工程评价与审查技术)模型:我们将建立一个PERT模型,以确定在一个新产品的生产流程中的关键作业线路。PERT技术很简单,但是很实用。该技术源于20世纪60年代。当时主要是为了帮助管理人员跟踪大工程的进展。82假设WirelessWidget公司计划向市场投放一种新产品--TheSolarWidget。为了保证准时投放市场,WirelessWidget公司要对主要作业进行PERT分析,其目的是找出关键作业路线。位于关键路线上的作业必须按时完成,这样才能保证WirelessWidget公司的产品及时投放市场,各项作业及预计完成时间如下:

Task(作业)Weeks(时间)FinalizeDesign(确定方案)10ForecastDemand(预测需求)14SurveyCompetition(调查竞争)3SetPrice(确定价格)3ScheduleProductionRun(确定生产时间)7CostOut(成本核算)4TrainSalesmen(训练销售人员)1083产品作业优先关系84可以构造如下的集合:TASKS/DESIGN,FORECAST,SURVEY,PRICE,SCHEDULE,COSTOUT,TRAIN/:TIME,ES,LS,SLACK;对于集合的4个属性,它们的解释如下:TIME完成作业的时间ES作业最早开始时间LS作业最迟开始时间SLACK作业LS和ES之间相差的时间85在模型中输入优先关系:PRED(TASK,TASK)/ DESIGN,FORECAST, DESIGN,SURVEY, FORECAST,PRICE, FORECAST,SCHEDULE, SURVEY,PRICE, SCHEDULE,COSTOUT, PRICE,TRAIN, COSTOUT,TRAIN/;86给出数据域部分的内容DATA:

TIME=10,14,3,3,7,4,10;ENDDATA此时我们有三个属性需要计算:最早开始(ES)、最迟开始(LS)和松弛时间(SLACK)。关键计算ES、LS,SLACK是两者之差。87计算ES(最早开始时间):对于一项作业来说,作业t的最早开始时间等于作业t的所有紧前作业的最早开始时间加上它自身完成时间之和的最大值。@FOR(TASKS(J)|J#GT#1: ES(J)=@MAX(PRED(I,J):ES(I)+TIME(I)));88计算LS(最迟开始时间)

:对于一项作业来说,作业t的最迟开始时间等于作业t的所有紧后作业的最早开始时间与作业t自身完成时间之差的最小值。@FOR(TASKS(I)|I#LT#LTASK: LS(I)=@MIN(PRED(I,J):ES(J)-TIME(I)));最后一项作业没有紧后作业,忽略89计算SLACK(松弛时间):@FOR(TASKS(I):SLACK(I)=LS(I)-ES(I));对于作业1的开始时间可以取任意值,咱们取0。最后一项作业的最迟开始时间不用计算。对于最后一个作业,最迟开始时间和最早开始时间应该是一致的。ES(1)=0;LS(7)=ES(7);90SETS:TASKS/DESIGN,FORECAST,SURVEY,PRICE,SCHEDULE,COSTOUT,TRAIN/:TIME,ES,LS,SLACK;PRED(TASKS,TASKS)/DESIGN,FORECAST,DESIGN,SURVEY,FORECAST,PRICE,FORECAST,SCHEDULE,SURVEY,PRICE,SCHEDULE,COSTOUT,PRICE,TRAIN,COSTOUT,TRAIN/;ENDSETSDATA:TIME=10,14,3,3,7,4,10;ENDDATA@FOR(TASKS(J)|J#GT#1:ES(J)=@MAX(PRED(I,J):ES(I)+TIME(I)));@FOR(TASKS(I)|I#LT#LTASK:LS(I)=@MIN(PRED(I,J):LS(J)-TIME(I)););@FOR(TASKS(I):SLACK(I)=LS(I)-ES(I));ES(1)=0;LTASK=@SIZE(TASKS);LS(LTASK)=ES(LTASK);91匹配模型(采用元素过滤器):假设你是公司规划部经理,该部门有8个分析专家,正打算搬入新的办公地点。新办公地点共有4个办公室。你需要将专家配成4对,每一对分配一个新的办公室。基于以往的观察,有些专家在一起合作得很好,而有些在一起则不行。为了部门安宁,你也许想找出一种匹配,使得在一起的专家发生冲突的可能性最小。为了这一目的,要计算出匹配专家的不相容等级分。等级从1到10,某个专家匹配的等级分为1意味着两个专家合作得非常好。反之,等级分为10意味着两个专家不能一起共事。92专家123456781-93421562--1735213---442924----15525-----8766------237-------4专家不相容等级分由于专家I和专家J的匹配与专家J和专家I的匹配是一样的,所以我们只给出表中斜对角线上方的数据。大家好好讨论如何当经理的问题!93构造8个专家构成的基本集合:

ANALYSTS/1..8/;最终含有匹配关系的派生集合

PAIRS(ANALYSTS,ANALYSTS);由于这个集合里含有(I,J)、(J,I)以及(I,I)。需要去掉后面两个。

PAIRS(ANALYSTS,ANALYSTS)| &2#GT#&1;通过过滤器,斜线上方的元素记入了集合PAIRS。94给集合PAIRS定义两个属性,第一个属性是匹配不相容等级分RATING;第二个属性表明专家I是否与专家J匹配MATCH。PAIRS(ANALYSTS,ANALYSTS)| &2#GT#&1:RATING,MATCH;我们用下面的数据域(由上面列出的不相容等级分)初始化属性RATING.DATA:

RATING=9342156 173521 44292 1552 876 23 4;95我们让MATCH(I,J)取值为1来表示将专家I与专家J匹配,否则MATCH(I,J)取值为0。这样,属性MATCH就是模型的决策变量。我们的目的就是要使得所有最终匹配的不相容等级分的总和最小。

MIN=@SUM(PAIRS(I,J): RATING(I,J)*MATCH(I,J));约束条件:对于每一个专家,他只与另外一个专家匹配。@FOR(ANALYSTS(I):@SUM(PAIRS(J,K)|J#EQ#I#OR#K#EQ#I: MATCH(J,K))=1);961:采用条件过滤器(J#EQ#I#OR#K#EQ#I)和@SUM函数。对于每一位专家I,我们求出所有含有I的MATCH变量的和并让其值等于1,保证专家I将与且只与另一个专家匹配。2:如果I和J匹配,我们就让MATCH(I,J)取值为1;否则就为0。@BIN函数限制了MATCH(I,J)的取值。@FOR(PAIRS(I,J):@BIN(MATCH(I,J)));模型的特色97SETS:ANALYSTS/1..8/;PAIRS(ANALYSTS,ANALYSTS)|&2#GT#&1:RATING,MATCH;ENDSETSDATA:RATING=9342156173521442921552876234;ENDDATAMIN=@SUM(PAIRS(I,J):RATING(I,J)*MATCH(I,J));@FOR(ANALYSTS(I):@SUM(PAIRS(J,K)|J#EQ#I#OR#K#EQ#I:MATCH(J,K))=1);@FOR(PAIRS(I,J):@BIN(MATCH(I,J)));98

MIN9MATCH(1,2)+3MATCH(1,3)+4MATCH(1,4)+2MATCH(1,5)+MATCH(1,6)+5MATCH(1,7)+6MATCH(1,8)+MATCH(2,3)+7MATCH(2,4)+3MATCH(2,5)+5MATCH(2,6)+2MATCH(2,7)+MATCH(2,8)+4MATCH(3,4)+4MATCH(3,5)+2MATCH(3,6)+9MATCH(3,7)+2MATCH(3,8)+MATCH(4,5)+5MATCH(4,6)+5MATCH(4,7)+2MATCH(4,8)+8MATCH(5,6)+7MATCH(5,7)+6MATCH(5,8)+2MATCH(6,7)+3MATCH(6,8)+4MATCH(7,8)SUBJECTTO2]MATCH(1,2)+MATCH(1,3)+MATCH(1,4)+MATCH(1,5)+MATCH(1,6)+MATCH(1,7)+MATCH(1,8)=13]MATCH(1,2)+MATCH(2,3)+MATCH(2,4)+MATCH(2,5)+MATCH(2,6)+MATCH(2,7)+MATCH(2,8)=14]MATCH(1,3)+MATCH(2,3)+MATCH(3,4)+MATCH(3,5)+MATCH(3,6)+MATCH(3,7)+MATCH(3,8)=15]MATCH(1,4)+MATCH(2,4)+MATCH(3,4)+MATCH(4,5)+MATCH(4,6)+MATCH(4,7)+MATCH(4,8)=16]MATCH(1,5)+MATCH(2,5)+MATCH(3,5)+MATCH(4,5)+MATCH(5,6)+MATCH(5,7)+MATCH(5,8)=17]MATCH(1,6)+MATCH(2,6)+MATCH(3,6)+MATCH(4,6)+MATCH(5,6)+MATCH(6,7)+MATCH(6,8)=18]MATCH(1,7)+MATCH(2,7)+MATCH(3,7)+MATCH(4,7)+MATCH(5,7)+MATCH(6,7)+MATCH(7,8)=19]MATCH(1,8)+MATCH(2,8)+MATCH(3,8)+MATCH(4,8)+MATCH(5,8)+MATCH(6,8)+MATCH(7,8)=1ENDINTEMATCH(1,2)INTEMATCH(1,3)INTEMATCH(1,4)INTEMATCH(1,5)INTEMATCH(1,6)INTEMATCH(1,7)INTEMATCH(1,8)INTEMATCH(2,3)INTEMATCH(2,4)INTEMATCH(2,5)INTEMATCH(2,6)INTEMATCH(2,7)INTEMATCH(2,8)INTEMATCH(3,4)INTEMATCH(3,5)INTEMATCH(3,6)INTEMATCH(3,7)INTEMATCH(3,8)INTEMATCH(4,5)INTEMATCH(4,6)INTEMATCH(4,7)INTEMATCH(4,8)INTEMATCH(5,6)INTEMATCH(5,7)INTEMATCH(5,8)INTEMATCH(6,7)INTEMATCH(6,8)INTEMATCH(7,8)展开后的模型99最终解的情况:前面的解答告诉我们,最优匹配的不相容等级分是6分。最优解匹配为:(1,6)、(2,7)、(3,8)、(4,5)对集合函数的认识更加深刻?1004.7输入和输出函数输入和输出函数可以把模型和外部数据比如文本文件、数据库和电子表格等连接起来。1011.@file函数@FILE是一个接口函数,利用它可以从外部文本文件中读出数据,可以至于模型的任何位置。这样就可以将集合域和数据域里的数据合并到文本文件里。该函数的语法格式为@file(’filename’)。这里filename是文件名,可以采用相对路径和绝对路径两种表示方式。以第一章运输问题的例子来讲解@file函数的用法。例中有两处涉及到数据:第一个地方是集部分的6个warehouses集成员和8个vendors集成员;第二个地方是数据部分的capacity,demand和cost数据。为了使数据和我们的模型完全分开,我们把它们移到外部的文本文件中。修改模型代码以便于用@file函数把数据从文本文件中拖到模型中来。修改后(修改处代码红色加粗)的模型代码如下:102SETS:WAREHOUSES/@FILE('WIDGETS2.LDT')/:CAPACITY;VENDORS/@FILE('WIDGETS2.LDT')/:DEMAND;LINKS(WAREHOUSES,VENDORS):COST,VOLUME;ENDSETSMIN=@SUM(LINKS(I,J):COST(I,J)*VOLUME(I,J));@FOR(VENDORS(J):@SUM(WAREHOUSES(I):VOLUME(I,J))=DEMAND(J));@FOR(WAREHOUSES(I):@SUM(VENDORS(J):VOLUME(I,J))<=CAPACITY(I));DATA:CAPACITY=@FILE('WIDGETS2.LDT');DEMAND=@FILE('WIDGETS2.LDT');COST=@FILE('WIDGETS2.LDT');ENDDATA103模型的所有数据来自于WIDGETS2.LDT文件。其内容如下:WH1WH2WH3WH4WH5WH6~!warehouses成员;V1V2V3V4V5V6V7V8~!vendors成员;605551434152~!产量;3537223241324338~!销量;

62674259!单位运输费用矩阵;4953858252197433767392712395726555228143把记录结束标记(~)之间的数据文件部分称为记录。如果数据文件中没有记录结束标记,那么整个文件被看作单个记录。注意到除了记录结束标记外,模型的文本和数据同它们直接放在模型里是一样的。文本文件的注释被忽略,在一个模型中最多可以调用16个文本数据文件1042.@text函数该函数被用在数据部分用来把解输出至文本文件中。它可以输出集成员和集属性值。其语法为@text([’filename’])这里filename是文件名,可以采用相对路径和绝对路径两种表示方式。如果忽略filename,那么数据就被输出到标准输出设备(大多数情形都是屏幕)。@text函数仅能出现在模型数据部分的一条语句的左边,右边是集名(用来输出该集的所有成员名)或集属性名(用来输出该集属性的值)。我们把用接口函数产生输出的数据声明称为输出操作。输出操作仅当求解器求解完模型后才执行,执行次序取决于其在模型中出现的先后。1052.@text函数--计算例子例1:@TEXT(‘RESULTS.TXT’)=X;将变量X的值(可能是向量)送入文件RESULTS.TXT例2:@TEXT()=START;在这个例子里,缺省了文件名,将使变量START的值出现在屏幕上1062.@text函数--计算例子SETS:DAYS/MONTUEWEDTHUFRISATSUN/:REQUIRED,START;ENDSETSDATA:REQUIRED=20161316191412;

@TEXT('OUT.TXT')=START;ENDDATAMIN=@SUM(DAYS(I):START(I));@FOR(DAYS(J):@SUM(DAYS(I)|I#LE#5:START(@WRAP(J-I+1,7)))>=REQUIRED(J));1073.@ranged(variable_or_row_name)@ranged函数输出特指变量在目标函数中系数的允许减少量或特指行右边资源的允许减少量。例如,假设一个模型具有下面的数据域:DATA@TEXT(‘C:\OUTPUT.TXT’)=X,@RANDED(X);ENDDATA当求解模型时,变量X的值和它的目标系数的允许减少量将写入文件OUTPUT.TXT之中。借助输出语句左边的函数,可以将输出发送到一个文件、电子表格、数据库和内存区域。1084.@rangeu(variable_or_row_name)@rangeu函数输出特指变量在目标函数中系数的允许增加量或特指行右边资源的允许增加量。例如,假设一个模型具有下面的数据域:DATA @TEXT(‘C:\OUTPUT.TXT’)=X,@RANDEU(X);ENDDATA当求解模型时,变量X的值和它的目标系数的允许减少量将写入文件OUTPUT.TXT之中。借助输出语句左边的函数,可以将输出发送到一个文件、电子表格、数据库和内存区域。1095.@statu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论