Lingo学习笔记(一)——语法入门

运筹优化学习笔记 专栏收录该内容
2 篇文章 0 订阅

lingo常用文件格式

1、后缀“lg4”表示lingo格式的模型文件,只有lingo软件才可打开;
2、后缀“lng”表示文本格式的模型文件;
3、后缀“ldt”表示lingo数据文件;
4、后缀“ltf”表示lingo命令脚本文件;
5、后缀“lgr”表示lingo报告文件。

LINGO Solver Status窗口要素详解

窗口右侧内容介绍

在这里插入图片描述

1、Variables(变量数量):其中包括变量总数(Total)、非线性变量数(Nonlinear)、整数变量数(Integer);
2、Constraints(约束数量):包括约束总数(Total)、非线性约束个数(Nonlinear)。
3、Nonzeros(非零系数数量):包括总数(Total)、非线性约束个数(Nonlinear)。
4、Generator Memory Used(K)(内存使用量):单位为千字节(K)。
5、Elapsed Runtime(hh:mm:ss)(求解花费的时间):显示格式是“时:分:秒”。

窗口左上角内容介绍

左上角是求解器(求解程序)状态框(Solver Status)。具体介绍如下表所示:

域名含义可能的显示
Model Class当前的模型类型LP,QP,NLP,ILP,IQP等
State当前解的状态Global Optimum,Local Optimum,Feasible,Infeasible(不可行),Unbounded(无界),Interrupted(中断),Undetermined(不确定)
Objective当前解的目标函数值实数
Infeasibility当前约束不满足的总量(不是不满足的约束个数)实数(即使该值=0,当前解也可能不可行,因为这个量中没有考虑用上下界命令形式给出的约束)
Iterations到目前为止的迭代次数非负整数

窗口左下角内容介绍

左下角是扩展的求解器(求解程序)状态框(Extended Solver Status)。具体介绍如下表所示:

域名含义可能的显示
Solver Type使用的特殊求解程序B-and-B(分支定界算法);Global(全局最优求解程序);Multistart(用多个初始点求解的程序)
Best Obj到目前为止找到的可行解的最佳目标函数实数
Obj Bound目标函数值的界实数
Steps特殊求解程序当前运行步数:分支数(对B-and-B程序);子问题数(对Global程序);初始点数(对Multistart程序)非负整数
Active有效步数非负整数

Lingo的基本用法注意事项

(1)lingo中不区分大小写字母;但lingo中的变量和行名可以超过8个字符,只是不能超过32个字符,且仍然必须以字母开头。
(2)lingo解优化模型时已经假定所有变量非负(除非用限定变量取值范围的函数@free或@bnd)。
(3)尽可能采用线性表达式定义目标和约束(如果可能的话)。
(4)lingo模型是由一系列的语句组成的,即语句是组成lingo模型的基本单位。每个语句都是以分号“;”结束的,最好每一行只写一条语句。
(5)lingo中以感叹号“!”开始的是说明语句(说明语句也需要以分号“;”结束)。

Lingo模型建立基本组成要素

一般来说lingo模型的建立需要5个部分组成,也可称为5段语句。

集合段(SETS)

这部分要以“SETS:”开始,以“ENDSETS”结束,作用在于定义必要的集合变量(SET)及其元素(member,含义类似于数组的下标)和属性(attribute,含义类似于数组)。

QUARTERS/1,2,3,4/:DEM,RP,OP,INV;

其中,QUARTERS为集合名称,斜线中的内容是元素,冒号后的是属性。
关于lingo的集合段含义可以借助于数据结构课程中的广义表来理解,也就是“列表之列表”。
具体的理解从下表的结构出发:

集合元素1234
DEM(属性1)DEM(1)DEM(2)DEM(3)DEM(4)
INV(属性4)INV(1)INV(2)INV(3)INV(4)

目标与约束段

这部分实际上定义了目标函数、约束条件等,但这部分并没有段的开始和结束标记,因此实际上就是除其它4个段(都有明确的段标记)外的lingo模型。
这里一般要用到函数。例如:

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);

目标函数(MIN=后面接的表达式)是用求和函数
“@SUM(集合(下标):关于集合的属性的表达式)”
的方式定义的,这个函数的功能是对语句中冒号“:”后面的表达式,按照“:”前面的集合指定的下标(元素)进行求和。
当然本例中的目标函数也可以写成:

@sum(quarters(i):400*rp(i)+450*op(i)+20*inv(i));

因为这里的@sum相当于求和符号“Σ”而"quarters(i)"相当于“i∈quarters”的含义。
约束使用循环函数“@for(集合(下标):关于集合的属性的约束关系式)”的方式定义的,意思是对冒号“:”前面的集合的每个元素(下标),冒号“:”后面的约束关系式都要成立。
可以对下标集合的元素增加一个逻辑关系式“I #GT# 1(这个限制条件与集合之间有一个竖线“|”分开,称为过滤条件)”。限制条件“I#GT#1”是一个逻辑表达式,意思就是I>1;“#GT#”是逻辑运算符号,意思是“大于”的含义。

数据段(DATA)

这部分要以“DATA:”开始,以“ENDDATA”结束,作用在于对集合的属性(数组)输入必要的常数数据。格式为:

attribute(属性)=value_list(常数列表);

常数列表中的数据之间可以用逗号“,”分开,也可以用空格分开(回车的作用也等价于一个空格)。
如果想在运行时才对参数赋值,可以在数据段使用输入语句。单着仅用于对单个变量(包括属性变量)赋值,而不能用于属性变量(数组)的单个元素。
输入语句格式为:

变量名=?;

初始段(INIT)

这部分要以“INIT:”开始,以“ENDINIT”结束,作用在于对集合的属性(数组)定义初值(因为求解算法一般是迭代算法,所以用户如果能给出一个比较好的迭代初值,对提高算法的计算效果是有益的)。初始段多用于对决策变量进行初始值赋值。
定义初值的格式:

attribute(属性)=value_list(常数列表);

计算段(CALC)

这部分要以“CALC:”开始,以“ENDCALC”结束,作用在于对一些原始数据进行计算处理(这种初始是在数据段的数据输入完成以后,lingo正式求解模型之前进行的)。
设计这个段的目的在于对一些原始数据进行预处理,得到在模型中真正需要的数据。
例如:

CALC:
T_DEM=@SUM(QUARTERS:DEM);!总需求;
A_DEM=T_DEM/@size(QUARTERS);!平均需求;
ENDCALC

其中函数@size表示集合quarters中的元素个数。如果需要的话,这两个变量就可以在程序的其它地方作为常数使用了。
请大家注意,在计算段中语句是顺序执行的,所以上面的两个语句不能交换顺序,因为计算A_DEM必须要用到T_DEM的值。此外,在计算段中只能直接使用赋值语句,而不能包含需要经过解方程或经过求解优化问题以后才能决定的变量。

派生集合

前面讲述的集合段相当于一维数组,那么如何产生更高维的数组呢?
下面以二维数组为例:
可以使用两个一维数组组合形成一个新的集合,即一个二元对。
用上面的例子中的demand和supply集合下构成一个新集合:

link(demand,supply):c;

表示集合link中的元素就是集合demand和supply的元素组成成的有序二元组,从数学上看,link就是demand和supply的笛卡尔积,也就是说:
l i n k = [ ( s , t ) ∣ s ∈ D E M A N D , t ∈ s u p p l y ] link=[(s,t)|s∈DEMAND,t∈supply] link=[(s,t)sDEMAND,tsupply]
类似于demand和supply这种直接把元素列举出来的集合,称为基本集合,也称为原始集合;而把link这种基于其它集合派生出来的二维或者多维集合称为派生集合。demand和supply称为link的父集合。

赋值规则

lingo对数据是按列赋值的,不是按行赋值的。
所以:

x,y=5,1,2,7;

语句的实际赋值顺序是 x = ( 5 , 2 ) , y = ( 1 , 7 ) x=(5,2),y=(1,7) x=(5,2),y=(1,7)

模型命名

可以在程序的开头部分用Title语句对这个模型取一个标题“Location Problem”;

model:
Title Location Problem;
...
end

对目标行([OBJ])和两类约束(DEMAND_CON、SUPPLY_CON)分别进行了命名。这是行号命名方法。

[OBJ] MIN=@SUM...;
@FOR(DEMAND(I):[DEMAND_CON]...);
@FOR(SUPPLY(I):[SUPPLY_CON]...);

稠密集合与稀疏集合

前面的例子中派生集合link的元素定义为demand和supply的笛卡尔积,即包含了两个基本集合构成的所有二元有序对。这种派生集合称为稠密集合。
在lingo中派生集合的元素可以定义为只是这个笛卡尔积的一个真子集合,这种派生集合称为稀疏集合。
例如,在进行最短路径搜索的时候采用的动态规划方法,对图进行广度优先搜索的一个例子,构造出图的邻接矩阵或者邻接表的时候可以用到。
稀疏集合构造分为两种,一个是枚举法,另一个是“元素过滤”法。所谓枚举法就是列举出派生稀疏集合中的每一个元素,而元素过滤法则是在集合定义的过程中添加过滤条件,这样就可以构造成适合的矩阵形式了。
例如:

sets:
students/S1..S8/;
pairs(students,students)| &2 #gt# &1:
benefit,match;
endsets

其中逻辑关系式“&2 #gt# &1”,意思是第2个父集合的元素的索引值(用“&2”表示)大于第1个父集合的元素的索引值(用“&1”表示)。
这里也就引出了索引的使用方法:
1、&符号索引,含义如上述解释;2、@index函数。例如:@index(S)表示元素S在集合中的索引值,实际上这个是@index(cities,S)的简写,即返回S在集合cities中的索引值。

一个代码示例

model:
sets:
	students/S1..S8/;
	pairs(students,students)| &2 #GT# &1:
	benefit,match;
endsets
data:
	benefit=
	  9 3 4 2 1 5 6
	    1 7 3 5 2 1
        4 4 2 9 2
          1 5 5 2
            8 7 6
              2 3
                4;
enddata
[obj] max=@sum(pairs(i,j):benefit(i,j)*match(i,j));
@for(students(i):[constraints]
	@sum(pairs(j,k)| j #EQ# i #OR# k #EQ# i: match(j,k))=1);
@for(pairs(i,j):@bin(match(i,j)));
end

lingo中的运算符

算术运算符

lingo中的算术运算符分为:
加(+),减(-),乘(*),除(/),求幂(^)
逻辑运算结果只有“真”和“假”两个值。
lingo中用数字1代表TRUE,其他值都是FALSE。在lingo中,逻辑运算表达式通常作为过滤条件使用。

逻辑运算符

lingo中的逻辑运算符有9种,可以分为两类:
(1)#and#(与),#or#(或),#not#(非):这三个运算是逻辑值之间的运算,也就是它们操作对象本身必须已经是逻辑值或逻辑表达式,计算结果也是逻辑值。
(2)#eq#(等于),#ne#(不等于),#gt#(大于),#ge#(大于等于),#lt#(小于),#le#(小于等于):这6个操作实际上是“数与数”之间的比较,也就是它们操作的对象本身必须是两个数(或相应的表达式),而逻辑表达式计算得到的结果是逻辑值。

关系运算符

关系运算符表示的是“数与数之间”的大小,因此在lingo中用来表示优化模型的约束条件,所以可以认为不是真正的运算操作符。
lingo中的关系运算符有三种:
<(即<=,小于等于);=(等于);>(即>=,大于等于)。
请注意区分关系运算符和“数与数之间”进行比较的6个逻辑运算符的不同之处。
一般而言,关系运算符常常出现在约束优化模型的约束中,而逻辑运算符多用于对集合进行约束和过滤。

运算符的优先级

同一个优先级按从左到右的顺序执行;如果有括号“()”,则括号内的表达式优先进行计算。

优先级运算符
最高(1)#not# 、 -(负号)
2^
3* , /
4+,-(减法)
5#eq#,#ne#,#gt#,#ge#,#lt#,#le#
6#and#,#or#
7<,=,>

集合使用小结

基本集合

基本集合的定义形式为:(凡是在方括号“[]”中的内容,表示是可选的项,即该项可以有也可以没有):

setname[/member_list][:attribute_list];

其中,setname为定义的集合名,member_list为元素列表,attribute_list为属性列表。元素列表可以采用显式列举法(即直接将所有元素全部列出,元素之间用逗号或空格分开),也可以采用隐式列举法。隐式列举法可以有几种不同格式:

基本集合的隐式列举法

类型隐式列举格式示例示例集合表示的元素
数字型1…n1…51,2,3,4,5
字符-数字型stringM…stringNCar101…car208car101,car102,…,car208
日期(星期)型dayM…dayNMON…FRIMON,TUE,WED,THU,FRI
月份型monthM…monthNOCT…JANOCT,NOV,DEC,JAN
年份-月份型monthYearM…monthYearNJAN2002DEC2001,JAN2002

上面的语法还说明元素列表和属性列表都是可选的。当属性列表不在集合定义中出现时,这样的集合往往只是为了将来在程序中作为一个循环变量来使用,或者作为构造更复杂的派生集合的父集合使用。(例如在介绍稠密集合中的students集合)。而当元素列表不在基本集合的定义中出现时,则必须在程序的数据段以赋值语句的方式直接给出元素列表。
例如:

sets:
	quarters:dem,rp,op,inv;
	!注意没有给出集合的元素列表;
endsets
data:
	quarters dem=1 40 2 60 3 75 4 25;
	!注意lingo按列赋值的特点;
enddata

派生集合

派生集合的一般定义格式为:

setname(parent_set_list)[/member_list/][:attribute_list];

与基本集合相比只是多了一个parent_set_list(父集合列表)。父集合列表中的集合(如:set1,set2,…)称为派生集合setname的父集合。它们本身也可以是派生集合。当元素列表(member_list)不在集合定义中出现时,还可以在程序的数据段的以赋值语句的方式给出元素列表;若在程序的数据段也不以赋值语句的方式给出元素列表,则认为定义的是稠密集合,即父集合中所有元素的有序组合(笛卡尔积)都是setname的元素。当元素列表在集合定义中出现时,又有“元素列表法”(直接列出元素)和“元素过滤法”(利用过滤条件)两种不同方式。

参考文献

谢金星,薛毅. 优化建模与LINDO/LINGO软件. 北京:清华大学出版社,2018.

  • 4
    点赞
  • 7
    评论
  • 17
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
LINGO是用来求解线性和非线性优化问题的简易工具。LINGO内置了种建立最优化模型的语言,可以简便地表达大规模问题,利用LINGO高效的求解器可快速求解并分析结果。 §1 LINGO快速入门 当你在windows下开始运行LINGO系统时,会得到类似下面的个窗口: 外层是主框架窗口,包含了所有菜单命令和工具条,其它所有的窗口将被包含在主窗口之下。在主窗口内的标题为LINGO Model – 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=60 55 51 43 41 52; demand=35 37 22 32 41 32 43 38; cost=6 2 6 7 4 2 9 5 4 9 5 3 8 5 8 2 5 2 1 9 7 4 3 3 7 6 7 3 9 2 7 1 2 3 9 5 7 2 6 5 5 5 2 2 8 1 4 3; enddata end 然后点击工具条上的按钮 即可。 为了能够使用LINGO的强大功能,接着第二节的学习吧。 §2 LINGO中的集 对实际问题建模的时候,总会遇到群或多群相联系的对象,比如工厂、消费者群体、交通工具和雇工等等。LINGO允许把这些相联系的对象聚合成集sets旦把对象聚合成集,就可以利用集来最大限度的发挥LINGO建模语言的优势。 现在我们将深入介绍如何创建集,并用数据初始化集的属性。学完本节后,你对基于建模技术的集如何引入模型会有个基本的理解。 2.1 为什么使用集 集是LINGO建模语言的基础,是程序设计最强有力的基本构件。借助于集,能够用个单的、长的、简明的复合公式表示系列相似的约束,从而可以快速方便地表达规模较大的模型。 2.2 什么是集 集是群相联系的对象,这些对象也称为集的成员。个集可能是系列产品、卡车或雇员。每个集成员可能有个或多个与之有关联的特征,我们把这些特征称为属性。属性值可以预先给定,也可以是未知的,有待于LINGO求解。例如,产品集中的每个产品可以有个价格属性;卡车集中的每辆卡车可以有个牵引力属性;雇员集中的每位雇员可以有个薪水属性,也可以有个生日属性等等。 LINGO有两种类型的集:原始集(primitive set)和派生集(derived set)。 个原始集是由些最基本的对象组成的。 个派生集是用个或多个其它集来定义的,也就是说,它的成员来自于其它已存在的集。 2.3 模型的集部分 集部分是LINGO模型的个可选部分。在LINGO模型中使用集之前,必须在集部分事先定义。集部分以关键字“sets:”开始,以“endsets”结束。个模型可以没有集部分,或有个简单的集部分,或有多个集部分。个集部分可以放置于模型的任何地方,但是个集及其属性
第八章 目标规划模型····································· 8.1 线性规划与目标规划······································ 8.1.1 线性规划建模与目标规划建模······················· 8.1.2 线性规划建模的局限性····························· 8.2 目标规划的数学模型······································· 8.2.1 目标规划的基本概念······························ 8.2.2 目标规划模型的建立······························· 8.2.3 目标规划的般模型······························· 8.2.4 求解目标规划的序贯式算法························· 8.3 目标规划模型的实例······································ 8.4 数据包络分析············································ 8.4.1 数据包络分析的基本概念··························· 8.4.2 RC2模型········································ 8.4.3 数据包络分析的求解······························ 习题8························································ 第九章 对策论模型······································ 9.1 二人常数和对策模型······································· 9.1.1 二人零和对策····································· 9.1.2 二人常数和对策··································· 9.2 二人常数和非对策········································· 9.2.1 纯对策问题······································ 9.2.2 混合对策问题···································· 9.3 n人合作对策初步········································· 习题9······················································ 第十章 排队论模型······································· 10.1 排队服务系统的基本概念·································· 10.1.1 排队的例子及基本概念···························· 10.1.2 符号表示········································· 10.1.3 描述排队系统的主要数量指标······················· 10.1.4 与排队论模型有关的LINGO函数···················· 10.2 等待制排队模型·········································· 10.2.1 等待制排队模型的基本参数························ 10.2.2 等待制排队模型的计算实例························ 10.3 损失制排队模型·········································· 5 10.3.1 损失制排队模型的基本公式······················ 10.3.2 损失制排队模型的计算实例······················· 10.4 混合制排队模型········································ 10.4.1 混合制排队模型的基本公式······················ 10.4.2 混合制排队模型的基本参数······················ 10.4.3 混合制排队模型的计算实例························ 10.5 闭合式排队模型········································ 10.5.1 闭合式排队模型的基本参数························· 10.5.2 闭合式排队模型的计算实例························ 10.6 排队系统的最优化模型··································· 10.6.1 系统服务时间的确定······························ 10.6.2 系统服务台的确定··························
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值