LIMGO例题.docx
《LIMGO例题.docx》由会员分享,可在线阅读,更多相关《LIMGO例题.docx(93页珍藏版)》请在冰豆网上搜索。
![LIMGO例题.docx](https://file1.bdocx.com/fileroot1/2023-2/2/ab86a393-2b7c-418c-9aeb-017127df7219/ab86a393-2b7c-418c-9aeb-017127df72191.gif)
LIMGO例题
L
下面看一个稍微复杂一点儿的例子。
例4.13职员时序安排模型一项工作一周7天都需要有人(比如护士工作),每天(周一至周日)所需的最少职员数为20、16、13、16、19、14和12,并要求每个职员一周连续工作5天,试求每周所需最少职员数,并给出安排。
注意这里我们考虑稳定后的情况。
model:
sets:
days/mon..sun/:
required,start;
endsets
data:
!
每天所需的最少职员数;
required=20161316191412;
enddata
!
最小化每周所需职员数;
min=@sum(days:
start);
@for(days(J):
@sum(days(I)|I#le#5:
start(@wrap(J+I+2,7)))>=required(J));
end
计算的部分结果为
Globaloptimalsolutionfoundatiteration:
0
Objectivevalue:
22.00000
VariableValueReducedCost
REQUIRED(MON)20.000000.000000
REQUIRED(TUE)16.000000.000000
REQUIRED(WED)13.000000.000000
REQUIRED(THU)16.000000.000000
REQUIRED(FRI)19.000000.000000
REQUIRED(SAT)14.000000.000000
REQUIRED(SUN)12.000000.000000
START(MON)8.0000000.000000
START(TUE)2.0000000.000000
START(WED)0.0000000.3333333
START(THU)6.0000000.000000
START(FRI)3.0000000.000000
START(SAT)3.0000000.000000
START(SUN)0.0000000.000000
从而解决方案是:
每周最少需要22个职员,周一安排8人,周二安排2人,周三无需安排人,周四安排6人,周五和周六都安排3人,周日无需安排人。
4.8输入和输出函数
输入和输出函数可以把模型和外部数据比如文本文件、数据库和电子表格等连接起来。
1.@file函数
该函数用从外部文件中输入数据,可以放在模型中任何地方。
该函数的语法格式为@file(’filename’)。
这里filename是文件名,可以采用相对路径和绝对路径两种表示方式。
@file函数对同一文件的两种表示方式的处理和对两个不同的文件处理是一样的,这一点必须注意。
例4.14以例1.2来讲解@file函数的用法。
注意到在例1.2的编码中有两处涉及到数据。
第一个地方是集部分的6个warehouses集成员和8个vendors集成员;第二个地方是数据部分的capacity,demand和cost数据。
为了使数据和我们的模型完全分开,我们把它们移到外部的文本文件中。
修改模型代码以便于用@file函数把数据从文本文件中拖到模型中来。
修改后(修改处代码黑体加粗)的模型代码如下:
model:
!
6发点8收点运输问题;
sets:
warehouses/@file('1_2.txt')/:
capacity;
vendors/@file('1_2.txt')/:
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=@file('1_2.txt');
demand=@file('1_2.txt');
cost=@file('1_2.txt');
enddata
end
模型的所有数据来自于1_2.txt文件。
其内容如下:
!
warehouses成员;
WH1WH2WH3WH4WH5WH6~
!
vendors成员;
V1V2V3V4V5V6V7V8~
!
产量;
605551434152~
!
销量;
3537223241324338~
!
单位运输费用矩阵;
62674259
49538582
52197433
76739271
23957265
55228143
把记录结束标记(~)之间的数据文件部分称为记录。
如果数据文件中没有记录结束标记,那么整个文件被看作单个记录。
注意到除了记录结束标记外,模型的文本和数据同它们直接放在模型里是一样的。
我们来看一下在数据文件中的记录结束标记连同模型中@file函数调用是如何工作的。
当在模型中第一次调用@file函数时,LINGO打开数据文件,然后读取第一个记录;第二次调用@file函数时,LINGO读取第二个记录等等。
文件的最后一条记录可以没有记录结束标记,当遇到文件结束标记时,LINGO会读取最后一条记录,然后关闭文件。
如果最后一条记录也有记录结束标记,那么直到LINGO求解完当前模型后才关闭该文件。
如果多个文件保持打开状态,可能就会导致一些问题,因为这会使同时打开的文件总数超过允许同时打开文件的上限16。
当使用@file函数时,可把记录的内容(除了一些记录结束标记外)看作是替代模型中@file(’filename’)位置的文本。
这也就是说,一条记录可以是声明的一部分,整个声明,或一系列声明。
在数据文件中注释被忽略。
注意在LINGO中不允许嵌套调用@file函数。
2.@text函数
该函数被用在数据部分用来把解输出至文本文件中。
它可以输出集成员和集属性值。
其语法为
@text([’filename’])
这里filename是文件名,可以采用相对路径和绝对路径两种表示方式。
如果忽略filename,那么数据就被输出到标准输出设备(大多数情形都是屏幕)。
@text函数仅能出现在模型数据部分的一条语句的左边,右边是集名(用来输出该集的所有成员名)或集属性名(用来输出该集属性的值)。
我们把用接口函数产生输出的数据声明称为输出操作。
输出操作仅当求解器求解完模型后才执行,执行次序取决于其在模型中出现的先后。
例4.15借用例4.12,说明@text的用法。
model:
sets:
days/mon..sun/:
required,start;
endsets
data:
!
每天所需的最少职员数;
required=20161316191412;
@text('d:
\out.txt')=days'至少需要的职员数为'start;
enddata
!
最小化每周所需职员数;
min=@sum(days:
start);
@for(days(J):
@sum(days(I)|I#le#5:
start(@wrap(J+I+2,7)))>=required(J));
end
3.@ole函数
@OLE是从EXCEL中引入或输出数据的接口函数,它是基于传输的OLE技术。
OLE传输直接在内存中传输数据,并不借助于中间文件。
当使用@OLE时,LINGO先装载EXCEL,再通知EXCEL装载指定的电子数据表,最后从电子数据表中获得Ranges。
为了使用OLE函数,必须有EXCEL5及其以上版本。
OLE函数可在数据部分和初始部分引入数据。
@OLE可以同时读集成员和集属性,集成员最好用文本格式,集属性最好用数值格式。
原始集每个集成员需要一个单元(cell),而对于n元的派生集每个集成员需要n个单元,这里第一行的n个单元对应派生集的第一个集成员,第二行的n个单元对应派生集的第二个集成员,依此类推。
@OLE只能读一维或二维的Ranges(在单个的EXCEL工作表(sheet)中),但不能读间断的或三维的Ranges。
Ranges是自左而右、自上而下来读。
例4.16
sets:
PRODUCT;!
产品;
MACHINE;!
机器;
WEEK;!
周;
ALLOWED(PRODUCT,MACHINE,WEEK):
x,y;!
允许组合及属性;
endsets
data:
rate=0.01;
PRODUCT,MACHINE,WEEK,ALLOWED,x,y=@OLE('D:
\IMPORT.XLS');
@OLE('D:
\IMPORT.XLS')=rate;
enddata
代替在代码文本的数据部分显式输入形式,我们把相关数据全部放在如下电子数据表中来输入。
下面是D:
\IMPORT.XLS的图表。
除了输入数据之外,我们也必须定义Ranges名:
PRODUCT,MACHINE,WEEK,ALLOWED,x,y.明确的,我们需要定义如下的Ranges名:
NameRange
PRODUCTB3:
B4
MACHINEC3:
C4
WEEKD3:
D5
ALLOWEDB8:
D10
XF8:
F10
YG8:
G10
rateC13
为了在EXCEL中定义Ranges名:
①按鼠标左键拖曳选择Range,
②释放鼠标按钮,
③选择“插入|名称|定义”,
④输入希望的名字,
⑤点击“确定”按钮。
我们在模型的数据部分用如下代码从EXECL中引入数据:
PRODUCT,MACHINE,WEEK,ALLOWED,x,y=@OLE('D:
\IMPORT.XLS');
@OLE('D:
\IMPORT.XLS')=rate;
等价的描述为
PRODUCT,MACHINE,WEEK,ALLOWED,x,y
=@OLE('D:
\IMPORT.XLS',PRODUCT,MACHINE,WEEK,ALLOWED,x,y);
@OLE('D:
\IMPORT.XLS',rate)=rate;
这一等价描述使得变量名和Ranges不同亦可。
4.@ranged(variable_or_row_name)
为了保持最优基不变,变量的费用系数或约束行的右端项允许减少的量。
5.@rangeu(variable_or_row_name)
为了保持最优基不变,变量的费用系数或约束行的右端项允许增加的量。
6.@status()
返回LINGO求解模型结束后的状态:
0GlobalOptimum(全局最优)
1Infeasible(不可行)
2Unbounded(无界)
3Undetermined(不确定)
4Feasible(可行)
5InfeasibleorUnbounded(通常需要关闭“预处理”选项后重新求解模型,以确定模型究竟是不可行还是无界)
6LocalOptimum(局部最优)
7LocallyInfeasible(局部不可行,尽管可行解可能存在,但是LINGO并没有找到一个)
8Cutoff(目标函数的截断值被达到)
9NumericError(求解器因在某约束中遇到无定义的算术运算而停止)
通常,如果返回值不是0、4或6时,那么解将不可信,几乎不能用。
该函数仅被用在模型的数据部分来输出数据。
例4.17
model:
min=@sin(x);
data:
@text()=@status();
enddata
end
部分计算结果为:
Localoptimalsolutionfoundatiteration:
33
Objectivevalue:
-1.000000
6
VariableValueReducedCost
X4.7123880.000000
结果中的6就是@status()返回的结果,表明最终解是局部最优的。
7.@dual
@dual(variable_or_row_name)返回变量的判别数(检验数)或约束行的对偶(影子)价格(dualprices)。
4.9辅助函数
1.@if(logical_condition,true_result,false_result)
@if函数将评价一个逻辑表达式logical_condition,如果为真,返回true_result,否则返回false_result。
例4.18求解最优化问题
其LINGO代码如下:
model:
min=fx+fy;
fx=@if(x#gt#0,100,0)+2*x;
fy=@if(y#gt#0,60,0)+3*y;
x+y>=30;
end
2.@warn(’text’,logical_condition)
如果逻辑条件logical_condition为真,则产生一个内容为’text’的信息框。
例4.19示例。
model:
x=1;
@warn('x是正数',x#gt#0);
end
§5LINGOWINDOWS命令
5.1文件菜单(FileMenu)
1.1.新建(New)
从文件菜单中选用“新建”命令、单击“新建”按钮或直接按F2键可以创建一个新的“Model”窗口。
在这个新的“Model”窗口中能够输入所要求解的模型。
2.2.打开(Open)
从文件菜单中选用“打开”命令、单击“打开”按钮或直接按F3键可以打开一个已经存在的文本文件。
这个文件可能是一个Model文件。
3.3.保存(Save)
从文件菜单中选用“保存”命令、单击“保存”按钮或直接按F4键用来保存当前活动窗口(最前台的窗口)中的模型结果、命令序列等保存为文件。
4.4.另存为...(SaveAs...)
从文件菜单中选用“另存为...”命令或按F5键可以将当前活动窗口中的内容保存为文本文件,其文件名为你在“另存为...”对话框中输入的文件名。
利用这种方法你可以将任何窗口的内容如模型、求解结果或命令保存为文件。
5.5.关闭(Close)
在文件菜单中选用“关闭”(Close)命令或按F6键将关闭当前活动窗口。
如果这个窗口是新建窗口或已经改变了当前文件的内容,LINGO系统将会提示是否想要保存改变后的内容。
6.6.打印(Print)
在文件菜单中选用“打印”(Print)命令、单击“打印”按钮或直接按F7键可以将当前活动窗口中的内容发送到打印机。
7.7.打印设置(PrintSetup...)
在文件菜单中选用“打印设置...”命令或直接按F8键可以将文件输出到指定的打印机。
8.8.打印预览(PrintPreview)
在文件菜单中选用“打印预览...”命令或直接按Shift+F8键可以进行打印预览。
9.9.输出到日志文件(LogOutput...)
从文件菜单中选用“LogOutput...”命令或按F9键打开一个对话框,用于生成一个日志文件,它存储接下来在“命令窗口”中输入的所有命令。
10.提交LINGO命令脚本文件(TakeCommands...)
从文件菜单中选用“TakeCommands...”命令或直接按F11键就可以将LINGO命令脚本(commandscript)文件提交给系统进程来运行。
11.引入LINGO文件(ImportLingoFile...)
从文件菜单中选用“ImportLingoFile...”命令或直接按F12键可以打开一个LINGO格式模型的文件,然后LINGO系统会尽可能把模型转化为LINGO语法允许的程序。
12.退出(Exit)
从文件菜单中选用“Exit”命令或直接按F10键可以退出LINGO系统。
5.2编辑菜单(EditMenu)
1.1.恢复(Undo)
从编辑菜单中选用“恢复”(Undo)命令或按Ctrl+Z组合键,将撤销上次操作、恢复至其前的状态。
2.2.剪切(Cut)
从编辑菜单中选用“剪切”(Cut)命令或按Ctrl+X组合键可以将当前选中的内容剪切至剪贴板中。
3.3.复制(Copy)
从编辑菜单中选用“复制”(Copy)命令、单击“复制”按钮或按Ctrl+C组合键可以将当前选中的内容复制到剪贴板中。
4.4.粘贴(Paste)
从编辑菜单中选用“粘贴”(Paste)命令、单击“粘贴”按钮或按Ctrl+V组合键可以将粘贴板中的当前内容复制到当前插入点的位置。
5.5.粘贴特定..(PasteSpecial。
。
)
与上面的命令不同,它可以用于剪贴板中的内容不是文本的情形。
6.6.全选(SelectAll)
从编辑菜单中选用“SelectAll”命令或按Ctrl+A组合键可选定当前窗口中的所有内容。
7.7.匹配小括号(MatchParenthesis)
从编辑菜单中选用“MatchParenthesis”命令、单击“MatchParenthesis”按钮或按Ctrl+P组合键可以为当前选中的开括号查找匹配的闭括号。
8.8.粘贴函数(PasteFunction)
从编辑菜单中选用“PasteFunction”命令可以将LINGO的内部函数粘贴到当前插入点。
5.3LINGO菜单
1.1.求解模型(Slove)
从LINGO菜单中选用“求解”命令、单击“Slove”按钮或按Ctrl+S组合键可以将当前模型送入内存求解。
2.2.求解结果...(Solution...)
从LINGO菜单中选用“Solution...”命令、单击“Solution...”按钮或直接按Ctrl+O组合键可以打开求解结果的对话框。
这里可以指定查看当前内存中求解结果的那些内容。
3.3.查看...(Look...)
从LINGO菜单中选用“Look...”命令或直接按Ctrl+L组合键可以查看全部的或选中的模型文本内容。
4.4.灵敏性分析(Range,Ctrl+R)
用该命令产生当前模型的灵敏性分析报告:
研究当目标函数的费用系数和约束右端项在什么范围(此时假定其它系数不变)时,最优基保持不变。
灵敏性分析是在求解模型时作出的,因此在求解模型时灵敏性分析是激活状态,但是默认是不激活的。
为了激活灵敏性分析,运行LINGO|Options…,选择GeneralSolverTab,在DualComputations列表框中,选择PricesandRanges选项。
灵敏性分析耗费相当多的求解时间,因此当速度很关键时,就没有必要激活它。
下面我们看一个简单的具体例子。
例5.1某家具公司制造书桌、餐桌和椅子,所用的资源有三种:
木料、木工和漆工。
生产数据如下表所示:
每个书桌
每个餐桌
每个椅子
现有资源总数
木料
8单位
6单位
1单位
48单位
漆工
4单位
2单位
1.5单位
20单位
木工
2单位
1.5单位
0.5单位
8单位
成品单价
60单位
30单位
20单位
若要求桌子的生产量不超过5件,如何安排三种产品的生产可使利润最大?
用DESKS、TABLES和CHAIRS分别表示三种产品的生产量,建立LP模型。
max=60*desks+30*tables+20*chairs;
8*desks+6*tables+chairs<=48;
4*desks+2*tables+1.5*chairs<=20;
2*desks+1.5*tables+.5*chairs<=8;
tables<=5;
求解这个模型,并激活灵敏性分析。
这时,查看报告窗口(ReportsWindow),可以看到如下结果。
Globaloptimalsolutionfoundatiteration:
3
Objectivevalue:
280.0000
VariableValueReducedCost
DESKS2.0000000.000000
TABLES0.0000005.000000
CHAIRS8.0000000.000000
RowSlackorSurplusDualPrice
1280.00001.000000
224.000000.000000
30.00000010.00000
40.00000010.00000
55.0000000.000000
“Globaloptimalsolutionfoundatiteration:
3”表示3次迭代后得到全局最优解。
“Objectivevalue:
280.0000”表示最优目标值为280。
“Value”给出最优解中各变量的值:
造2个书桌(desks),0个餐桌(tables),8个椅子(chairs)。
所以desks、chairs是基变量(非0),tables是非基变量(0)。
“SlackorSurplus”给出松驰变量的值:
第1行松驰变量=280(模型第一行表示目标函数,所以第二行对应第一个约束)
第2行松驰变量=24
第3行松驰变量=0
第4行松驰变量=0
第5行松驰变量=5
“ReducedCost”列出最优单纯形表中判别数所在行的变量的系数,表示当变量有微小变动时,目标函数的变化率。
其中基变量的reducedcost值应为0,对于非基变量Xj,相应的reducedcost值表示当某个变量Xj增加一个单位时目标函数减少的量(max型问题)。
本例中:
变量tables对应的reducedcost值为5,表示当非基变量tables的值从0变为1时(此时假定其他非基变量保持不变,但为了满足约束条件,基变量显然会发生变化),最优的目标函数值=280-5=275。
“DUALPRICE”(对偶价格)表示当对应约束有微小变动时,目标函数的变化率。
输出结果中对应于每一个约束有一个对偶价格。
若其数值为p,表示对应约束中不等式右端项若增加1个单位,目标函数将增加p个单位(max型问题)。
显然,如果在最优解处约束正好取等号(也就是“紧约束”,也称为有效约束或起作用约束),对偶价格值才可能不是0。
本例中:
第3、4行是紧约束,对应的对偶价格值为10,表示当紧约束
3)4DESKS+2TABLES+1.5CHAIRS<=20
变为3)4DESKS+2TABLES+1.5CHAIRS<=21
时,目标函数值=280+10=290。
对第4行也类似。
对于非紧约束(如本例中第2、5行是非紧约束),D