lingo编程.docx
- 文档编号:3364848
- 上传时间:2022-11-22
- 格式:DOCX
- 页数:13
- 大小:29.05KB
lingo编程.docx
《lingo编程.docx》由会员分享,可在线阅读,更多相关《lingo编程.docx(13页珍藏版)》请在冰豆网上搜索。
lingo编程
lingo编程
启航系列之数学建模启航系列之数学建模
培训资料培训资料
Lindo和Lingo是美国Lindo系统公司开发的一套专门用于求解最优化问题的软件
包。
Lindo用于求解线性规划和二次规划问题,Lingo除了具有Lindo的全部功能外,还可以用于求解非线性规划问题,也可以用于一些线性和非线性方程(组)的求解,等等。
Lindo和Lingo软件的最大特色在于可以允许优化模型中的决策变量是整数(即整数规划),而且执行速度很快。
Lingo实际上还是最优化问题的一种建模语言,包括许多常用的函数可供使用者建立优化
模型时调用,并提供与其他数据文件(如文本文件、Excel电子表格文件、数据库文件等)的
接口,易于方便地输入、求解和分析大规模最优化问题。
由于这些特点,Lindo系统公司的线性、非线性和整数规划求解程序已经被全世界数千万的公
司用来做最大化利润和最小化成本的分析。
应用的范围包含生产线规划、运输、财务金融、
投资分配、资本预算、混合排程、库存管理、资源配置等等...
Lindo/Lingo软件作为著名的专业优化软件,其功能比较强、计算效果比较好,与那些包
含部分优化功能的非专业软件相比,通常具有明显的优势。
此外,Lindo/Lingo软件使用起来非常简便,很容易学会,在优化软件(尤其是运行于个人电脑上的优化软件)市场占有很
大份额,在国外运筹学类的教科书中也被广泛用做教学软件。
1.Lingo
优化模型
连续优化整数规划
优化模型二次规划非线性规划
2.lingo例1用Lingo解决一个二次规划问题
22max982770.32xxxxxx,,,,121122
xx,,100,12,stxx..2,,12
xx,0,为整数,12
解:
在lingo命令行中输入如下代码,x1+x2<=100;
!
一个简单例子;
max=98*x1+277*X2-x1*x1-0.3*X1*x2-2*X2*x2;
x1-2*x2<=0;
@gin(x1);@gin(x2);
按求解键得到结果如下,
Globaloptimalsolutionfound.
Objectivevalue:
11077.50
Extendedsolversteps:
0
Totalsolveriterations:
44
VariableValueReducedCost
X135.00000-8.500002
X265.00000-6.500004
在这个例子里要注意如下一些细节:
对本例结果的解释:
找到全局最优解,使得目标函数值为
xx,对应变量,的值分别为和,11077.50356512
对应变量xx,的影子价格分别为,。
8.500002,6.50000412
所谓的,就是指对应的变量增加1单位,其他变量无变化时目标函数改变的
单位数。
3.Lingo
(1)、尽量使用实数优化模型,尽量减少整数变量和整数约束;
(2)、尽量使用光滑优化模型,尽量避免使用非光滑函数。
比如应尽量避免使用绝对
值函数,符号函数,求最大最小值函数,取整函数等;
(3)、尽量使用线性优化模型,尽量减少非线性约束和非线性变量的个数;
(4)、合理设定变量的上下界,尽可能给出变量的初始值;
(5)、模型中使用的单位的数量级要适当。
系数最大数和最小数的绝对值超过1000倍以上会弹出警告信息。
4.Lingo
4.1集合的基本用法和lingo模型的基本要素
Lingo虽然使用方便,但是如果要解决几万个,几十万个变量的优化问题时,我们总
不能一个一个地列出x1,x2,„,x1000来解决,而这样的问题在实际企业的应用中也是经
常遇到的。
好在Lingo中设计了集合语言来表示大规模变量的输入,只需一行文字就可以
建立起含有大规模变量的目标函数和成千上万条约束。
而Lingo的早期版本软件Lindo却不包含这样的功能。
现通过下例来对Lingo的集合、属性概念进行介绍。
例2SAILCO公司需要决定决定下四个季度的帆船生产量。
下四个季度的帆船需求量
分别为40条,60条,75条,25条,这些需求必须按时满足。
每个季度正常的生产能力是
40条帆船,每条帆船的生产费用为400美元。
如果加班生产,每条船的生产费用为450美元。
每个季度末,每条船的库存费用为20美元。
假定生产提前期为0,初始库存为10条船。
如何安排生产可使总费用最小?
分析与解:
用DEM、RP、OP、INV分别表示需求量,正常生产的产量,加班生产的产
量,库存量。
则DEM、RP、OP、INV对每个季度都应有一个对应的值,也就是说他们都应
该是一个由4个元素组成的数组,其中DEM已知,而RP,OP,INV未知。
现在我们可以写
出该问题的模型:
min{400()450()20()}.RPIOPIINVI,,,I,1,2,3,4
RPII()40,1,2,3,4;,,
INVIINVIRPIOPIDEMII()
(1)()()(),1,2,3,4;,,,,,,
INV(0)10;,
此外还有各变量非负的约束。
记4个季度组成的集合QUARTERS,{1,2,3,4},他们就是DEM、RP、OP、INV等变量的下标集合,对于,,IQUARTERSDEMIRPIOPIINVI(),(),(),(),都有值与之对
应。
LINGO正是充分利用这种数组及其下标的关系,引入了“集合”与“属性”的概念。
本例中我们把QUARTERS,{1,2,3,4}称之为,DEM、RP、OP、INV称为集合
QUARTERS,{1,2,3,4}具有的(即定义在该集合上的属性)。
下图表示了这种集合与属性的关系。
集合QUARTERS的属性
DEMRPOPINV
1234
集合QUARTERS
DEMDEM
(1)DEM
(2)DEM(3)DEM(4)定义在集合RPRP
(1)RP
(2)RP(3)RP(4)QUARTERS上OPOP
(1)OP
(2)OP(3)OP(4)的属性INVINV
(1)INV
(2)INV(3)INV(4)
下面我们看看Lingo中具体如何定义集合及其属性。
下面是例2的Lingo代码:
Model:
Sets:
QUARTERS/1,2,3,4/:
DEM,RP,OP,INV;
Endsets
Min=@sum(QUARTERS:
400*RP+450*OP+20*INV);
@for(QUARTERS(I):
RP(I)<=40;);
@for(QUARTERS(I)|I#GT#1:
INV(I)=INV(I-1)+RP(I)+OP(I)-DEM(I););
INV
(1)=10+RP
(1)+OP
(1)-DEM
(1);
DATA:
DEM=40,60,75,25;
Enddata
End
我们总结一下上面代码的特点:
(1)、模型以“MODEL:
”开始,以“END”结束。
它们之间由语句组成,可以分成三步
分。
(2)、集合定义部分以“SETS:
”开始,以“ENDSETS”结束。
中间定义了集合和相应属
性。
语句“QUARTERS/1,2,3,4/:
DEM,RP,OP,INV;”定义了集合QUARTERS,以及该集合的属性DEM、RP、OP、INV,其结果正是上表里面的16个变量名。
可以定义空集合,比如“Emptyset/1,2,3,4/;”空集合的用法将在派生集中讲述。
(3)、数据输入部分以“DATA:
”开始,以“ENDDATA”结束,语句“DEM=40,60,75,25;”给出了常量DEM的值,即DEM
(1)=40,DEM
(2)=60,DEM(3)=75,DEM(4)=25.语句“DEM=40,60,75,25;”也可以写成语句“DEM=40607525;”即数据之间可以用逗号或空格
分开。
(4)、其他部分,给出了目标函数和约束。
其中目标函数(“min=”后面所接的表达式)
是用求和函数
“@sum(集合(下标)|指标过滤条件:
关于集合的属性的表达式)”
的方式定义的,这个函数的功能是对语句冒号“:
”后面的表达式,按照“:
”前面的集合指
定的下标元素进行求和。
本例中目标函数也可以写成
“Min=@sum(QUARTERS(i):
400*RP(i)+450*OP(i)+20*INV(i))”
而“QUARTERS(i)”相当于“”,而由于iQUARTERS,,这里“@sum”相当于求和符号
本例中已默认对所有的QUARTERS的元素求和,所以实例中可以将下标i省略。
约束是用循环函数“@for(集合(下标):
关于集合的属性的约束关系式)”的方式定义的,意思是对于“:
”前面的集合的每个元素(下标),冒号“:
”后面的约束关系式都要成
立。
但对于INVIINVIRPIOPIDEMII()
(1)()()(),1,2,3,4,,,,,,这个约束,实际上I=1时要用到变量INV(0),但我们定义属性变量的时候是从I=1开始的,即INV(0)是一个常数,为了区别I=1和I=2,3,4,我们要将I=1的约束单独列出来,而对I=2,3,4的约束我们对集合下标做了的约束,即用了“#GT#1”(这个限制条件与集合之间有一个I,1
竖线“|”分开,称为过滤条件),“I#GT#1”就表示,“#GT#”是lingo中的逻辑表达式。
I,1
小结一下lingo模型最基本的组成要素:
(1):
以“SETS:
”开始,以“ENDSETS”结束。
作用在于定义必要的集
合和属性。
注意一个细节,我们可以定义QUARTERS/1,2,3,4/,若QUARTERS
有1000个元素,我们也不必将其一一列出,而可以简写为
QUARTERS/1..1000/.
(2):
这部分不像其他部分,没有段的开始和结束的标记。
因此
是除去其他段以外的所有语句。
(3):
以“DATA:
”开始,以“ENDDATA”结束,作用在于对集合的属性
输入必要的常数数据,格式为:
属性=常数列表;常数列表中的常数或以
逗号“,”分开,或以空格分开“”.
(4):
以“INIT:
”开始,以“ENDINIT”结束。
作用在于对集合的属性
定义初值。
因为求解算法是迭代算法,所以一个好的初值可以让程序更快
解决。
定义初值的格式为:
属性=常数列表;
(5):
以“CALC:
”开始,以“ENDCALC”结束,作用在于对一些原始数
据进行计算处理,这种处理是在输入数据后,求解模型前进行的。
例如,
对上面的例子,如果我们希望可以得到全年的总需求和季度平均需求,可
以增加这个段:
CALC:
T_DEM=@sum(QUARTERS:
DEM);!
总需求;
A_DEM=T_DEM/@size(QUARTERS);!
平均需求;
ENDCALC
要注意的是计算段中语句是按顺序执行的,故上面的两个语句不能调换。
4.2基本集合与派生集合
例3建筑工地的位置(用平面坐标a,b表示,单位:
km)及水泥日用量d(单位:
t)用下表给出。
目前两个临时料厂位于P(5,1),Q(2,7),日储量各有20t。
求从A,B两料厂分别向各工地运送多少水泥,使总的吨公里数最小。
两个新的料场应建在何处,节省的吨公
里数有多大?
工地编号123456
a1.258.750.55.7537.25
b1.250.754.7556.57.75
d3547611
(,)xy(,)abdi,1,...,6,解:
记工地的位置为水泥日用量为,料场位置为,日储jjiii
量为ej,1,2,c,从料场j向工地i的运送量为,这个优化问题的解为:
jij
2622min()()fcxayb,,,,,,ijjiji11ji,,2
ijistcdi..,1,...,6,,,1j,6
ijj1cej,,,1,2i,,
尝试将这个模型输入lingo时,利用前面介绍的集合概念,显然可以定义需求点demand和供应点supply两个集合,分别有6个和2个元素。
但是决策变量c是同时与supply和ijdemand相关的属性,这该如何定义呢?
其实我们可以定义一个由二元对组成的新的集合,然后将c定义为该集合的属性。
具ij
体代码如下:
model:
sets:
demand/1..6/:
a,b,d;
supply/1..2/:
x,y,e;
link(demand,supply):
c;
endsets
data:
a=1.25,8.75,0.5,5.75,3,7.25;
b=1.25,0.75,4.75,5,6.5,7.75;
d=3,5,4,7,6,11;
e=20,20;
enddata
init:
x,y=5,1,2,7;
endinit
min=@sum(link(i,j):
c(i,j)*((x(j)-a(i))^2+(y(j)-b(i))^2)^(1/2));
@for(demand(i):
@sum(supply(j):
c(i,j))=d(i););
@for(supply(i):
@sum(demand(j):
c(j,i))<=e(i););
@for(supply:
@free(x);@free(y););
End
我们在集合段定义了三个集合,其中link是在前两个集合demand和supply的基础上定义的集合。
语句link(demand,supply):
c;表示集合link中的元素就是集合demand和linkstsdemandtsupply,,,{(,)|,}
supply的元素合成的有序二元组。
从数学上看就是因此其属性c也就是6*2的矩阵。
像link这样基于其他集合而派生出来的二维或多维集合我们称之为本模型初始段中的语句“x,y=5,1,2,7”实际的赋值顺序是xy,,(5,2),(1,7),也就是说lingo对数据是按列赋值的,这点要注意了,当然也可以写成“x=5,2;y=1,7”
4.3稠密集合与稀疏集合
我们已经介绍了基本集合和派生集合。
例3中我们把派生集合link的元素定义为demand和supply的笛卡尔积,即包含了两个基本集合构成的所有的二元有序对。
这种派
生集称为,有时候一些属性肯能只在某些有序对上有意义,我们只要定义有意义
的集合,这就产生了的概念。
例4求下图中城市S至T的最短路径。
A16656B1C1587
A236T8S
7B2C26394A3
解:
用lingo解决最短路问题,代码如下。
集合段定义的cities是基本集合,L是对应的属性变量。
Roads是由cities派生的集合,由于只有一部分城市之间有路相连,所以
不应该把它定义为稠密集合,只能通过枚举定义成一个稀疏集合。
model:
sets:
cities/s,a1,a2,a3,b1,b2,c1,c2,t/:
L;!
L表示最优行驶路线的线长;
roads(cities,cities)/
s,a1s,a2s,a3
a1,b1a1,b2a2,b1a2,b2a3,b1a3,b2
b1,c1b1,c2b2,c1b2,c2
c1,tc2,t/:
D;!
D表示两城市间的直接距离;
endsets
data:
D=633
658674
6789
56;
L=0,,,,,,,,;
enddata
@for(cities(i)|i#GT#@index(s):
L(i)=@min(roads(j,i):
L(j)+D(j,i));
);
end
从本例可以看出,lingo程序可以没有目标函数。
因此lingo可以用来解方程组和不等式组。
此外在数据段我们对L进行赋值,但只有L(S)=0是已知的,所以后面的值为空(但位置必须留下来,逗号“,”一个也不能少)。
虽然集合cities中的元素不是数字,但当它以cities(i)的形式出现在循环中时,引
用下标i实际上仍是一个整数。
也就是说,i指的正是元素在集合中的位置,一般称为元
素的索引。
我们用@index(i)来返回元素i的索引。
从上例可以看出定义稀疏集合时用枚举其元素的方法给出的。
但当元素比较多时,这
就麻烦了。
我们可以用“元素过滤法”来定义稀疏集合。
例5某班8名同学准备分成4个调查队(每队两人)前往4个地区进行社会调查。
假
设这8名同学两两之间组队的效率如下图所示,问如何组队效率最高?
学生S1S2S3S4S5S6S7S8S19342156S2173521S344292S41552S5876S623S74
解:
本例的数学模型如下
max{(,)*(,)};benefitIJmatchIJ,IJ,
stmatchJK..{(,)}1,I=1,2,...,8,,JIKI,,或
matchJK(,){0,1},
model:
sets:
students/s1..s8/;
pairs(students,students)|&2#GT#&1:
benefit,match;
endsets
data:
benefit=
9342156
173521
44292
1552
876
23
4;
enddata
max=@sum(pairs(i,j):
benefit(i,j)*match(i,j));
@for(students(i):
@sum(pairs(j,k)|j#EQ#i#OR#k#EQ#i:
match(j,k))=1);
@for(pairs(i,j):
@bin(match(i,j)));
End
上面代码中逻辑关系式“&2#GT#&1”表示第二个父集合的元素的缩索引值大于第一个
元素的索引值。
这样pairs中的元素刚好对应于上面表中的严格上三角部分的二维下标了。
读者还应该注意数据段对benefit的赋值方式,体会lingo是按照列的顺序对变量元素进
行赋值的。
4.4集合的使用小结
小结一下集合的用法
(1)、集合的不同类型和关系
集合
派生集合基本集合
稀疏集合稠密集合
元素列表法元素过滤法直接列举法隐式列举法
(2)、集合的定义方法([]中的内容是可选项)
基本集合:
setname[/member_list/][:
attribute_list];
派生集合:
setname(parent_set_list)[/member_list/][:
attribute_list];
5.Lingo
5.1运算符与优先级
算术运算符:
,,(求幂),/^
逻辑运算符:
(1)#AND#(与),#OR#(或),#NOT#(非)
(2)#EQ#(等于),#NE#(不等于),#GT#(大于),#GE#(大于等于),#LT#(小于),
#LE#(小于等于)
关系运算符:
,,
运算符的优先级
最高#NOT#-(负号)
^
*/
+-
#EQ#,#NE#,#GT#,#GE#,#LT#,#LE#
#AND#,#OR#
最低<=>
5.2Lingo函数
(1)、基本数学函数
@abs(x):
绝对值函数
@cos(x):
余弦函数
x@exp(x):
指数函数,返回e
@floor(x):
取整函数
@LGM(x):
返回x的伽玛函数的自然对数值
@LOG(x):
自然对数函数
@MOD(x,y):
模函数,返回x对y取模的结果,即x除以y的余数
y@pow(x,y):
指数函数,返回x
@sign(x):
符号函数
@sin(x):
正弦函数
@smax(list):
最大值函数,返回一列数list的最大值@smin(list):
最小值函数
@sqr(x):
平方函数
@sqrt(x):
平方根函数
@tan(x):
正切函数
(2)、集合循环函数
集合循环函数一般调用格式为:
@function(setname[(set_index_list)[|condition]]:
expression_list);
其中function是函数名,setname是集合名,set_index_list是集合索引列表,condition
是逻辑表达式的过滤条件。
expression_list是一个表达式。
集合循环函数有如下5个:
@for():
对集合的每个元素独立地生成表达式
@max():
返回集合上的表达式的最大值
@min():
返回集合上的表达式的最小值
@prod():
返回集合上的表达式的积
@sum():
返回集合上的表达式的和
(3)、集合操作函数
@index([set_name,]primitive_set_element)
该函数给出了元素primitive_set_element在集合set_name中的索引值(即对集合众一个对应元素的顺序编号),如果省略set_name,Lingo会按模型中定义的集合顺序找到第一
个含有元素primitive_set_element的集合并返回索引值。
@in(set_name,primitive_index1[,primitive_index2,…])
这个函数用来判断一个集合中是否含有某个索引值。
如果集合set_name中包含索引值primitive_index1[,primitive_index2,…]所表示的对应元素,则返回1,否则返回0。
索引用&1,&2或@index函数等形式给出。
这里&1表示对应于第一个父集合的元素的索引值。
@wrap(I,N)
当I位于区间[1,N]时直接返回I,一般的,返回J=I-K*N,其中J位于区间[1,N],K为整数。
可见这个函数类似于用I对N取模,即当@mod(I,N)>1时@wrap(I,N)=@mod(I,N),但当@mod(I,N)=0时@wrap(I,N)=N.此函数对N<1无意义。
该函数主要用来防止集合的索引
值越界。
@size(set_name)
返回集合set_name的元素个数。
(4)、变量定界函数
对没有定界的变量,Lingo一致默认为非负变量。
LXU,,@bnd(L,X,U):
限制@bin(x):
限制x只能取0或1
@free(x):
取消对x的符号限制
@gin(x):
限制x为整数
(5)、其他函数
@if(logical_condition,true_result,false_result)
当逻辑表达式logical_condition的结果为真时,返回true_result,否则返回false_result,例如a=@if(x#LT#100,20,15)表示如果x小于100则a等于20,否则a等于15。
Lingo主要的内容就介绍到这里了,希望大家有时间自己找一些题目动手演练一下~~
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- lingo 编程