数学建模:lingo专题 Lingo 讲义 数信学院 邝神芬
参考教材 1. 优化建模与lindo/lingo软件, 谢金星 薛毅 ,清华大学出版社 2.lingo 教程 (电子版) 3.运筹学(第三版) ,清华大学出版社
求解线性规划 例1.1如何在LINGO中求解如下的LP问题:
Lingo程序运行步骤:
点击红色按纽运行
Lingo简介 1.lingo由美国lindo公司开发,软件前身是lindo 6.0, 是美国芝加哥大学生linus schrage教授于1980年开发的专门用于求解数学规划的软件包,属于最优化,运筹学问题求解软件, 。 2.LINGO主要用于求解线性规划、非线性规划、二次规划和整数规划等问题,也可以用于求解一些线性和非线性方程组及代数方程求根等。 3.应用的范围包含生产线规划、运输、财务金融、投资分配、资本预算、混合排程、库存管理、资源配置等许多领域。在教学、科研和工业、商业、服务等领域得到广泛应用
lingo程序一般模板: model:!一般以model:开关,以end结束,这个可省略; sets: !这里定义集合,即变量; data: !这里定义已知数据; enddata !目标函数,为min或max; min=@sum( ) !目标函数表达式 !在min或max接着是约束表达式,以分号结束; end
为什么要学lingo? 1.lingo专注于解优化问题。 2.lingo求解优化问题非常简单易用。 3.lingo是数学建模竞赛的必备工具。 有人说,能用lingo求解的,一般也能用matlab 求解,但是:matlab求解优化问题较复杂,尤 其是整数规划,适合对优化理论非常熟悉的人, 而lingo简单易用,适合各阶层人士使用。
只要涉及最大或最小值的优化问题,都能用lingo求解
Lingo基础 一个优化问题通过以下三部分组成: 1、目标函数:一般表示成求某个数学表达式的最大值或最小值。 2、决策变量:目标函数值取决于哪些变量 3、约束条件:对变量附加一些条件限制(通常用等式或不等式表示)。(变量限制条件)
Lingo的语法规定: (1)求目标函数的最大值或最小值分别用Max=---或Min=---来表示 (2)每个语句必须以分号结束 (3)变量名必须以字母(A---Z)开头,由字母,数字和下划线组成, 长度不超过32个字符,不区分大小写; (4)可以给语句加上标号,例如[obj] Max=200*x1+300*x2; (5)以!开头,以;号结束的语句是注释语句; (6)如果对变量的取值范围没有作特殊说明,则默认所有决策变量 都非负; (7) Lingo模型以语句Model:开头,以end结束,对于比较简单的模型,这两个语句可以省略。
利用lingo求解优化问题就像直接打公式一样,那么lingo有什么要学的呢?
直接求解非常麻烦!! 例子:求
1.理解什么是集?集的数据如何定 义? 2.理解Lingo程序流,循环,求和, 判断等,懂得利用这些语法来表达复 杂的约束表达式。 3.如何对变量作约束,如求解0-1规 划,整数规划
1.多练,多实践,懂得基本语法后,多看例子。 2.学会用优化的思想来思考问题(掌握运筹学与最优化理论是基础中的基础) 如何学好lingo? 1.多练,多实践,懂得基本语法后,多看例子。 2.学会用优化的思想来思考问题(掌握运筹学与最优化理论是基础中的基础)
集合 1 为什么使用集 集是LINGO建模语言的基础,是程序设计最强有力的基本构件。借助于集,能够用一个单一的、长的、简明的复合公式表示一系列相似的约束,从而可以快速方便地表达规模较大的模型。 2 什么是集 集是一群相联系的对象,这些对象也称为集的成员。一个集可能是一系列产品、卡车或雇员。每个集成员可能有一个或多个与之有关联的特征,我们把这些特征称为属性。属性值可以预先给定,也可以是未知的,有待于LINGO求解。例如,产品集中的每个产品可以有一个价格属性;卡车集中的每辆卡车可以有一个牵引力属性;雇员集中的每位雇员可以有一个薪水属性,也可以有一个生日属性等等。 LINGO有两种类型的集:原始集(primitive set)和派生集(derived set)。 一个原始集是由一些最基本的对象组成的。 一个派生集是用一个或多个其它集来定义的,也就是说,它的成员来自于其它已存在的集。
如何定义集 集部分是LINGO模型的一个可选部分。在LINGO模型中使用集之前,必须在集部分事先定义。集部分以关键字“sets:”开始,以“endsets”结束 例1.1(例如人有姓别,性别相对某人来说的) 可定义集:human/zhangsan,lishi/:boy,girl 例2.1 可以定义一个名为students的原始集,它具有成员John、Jill、Rose和Mike,属性有sex和age: sets: students/John Jill, Rose Mike/: sex, age; endsets
lingo集基础 例3.1:要定义x1,x2,…,x100这100个变量,可定义集合xx, 写成: Sets: xx/1..100/:x; Endsets 其中XX是集合,1..100表示集合从1到100,X表示这个集合的变量,XX只作循环或程序流时才使用 注意:在MATLAB中只能用矩阵表示,这是LINGO简单的原因
students/john jill rose mike/:sex,age; endsets !数据部分; data: 集合的数据定义 !集部分; sets: students/john jill rose mike/:sex,age; endsets !数据部分; data: sex,age= 1 16 0 14 0 17 1 13; enddata
lingo集与C语言结构 可以把集、集成员和集属性同C语言中的结构体作个类比。如下图: 集 ←→ 结构体 集成员 ←→ 结构体的成员 集 ←→ 结构体 集成员 ←→ 结构体的成员 集属性 ←→ 结构体实例 即:struts stu{ int name,int age;} struts stu zhangsan;
派生集 为了定义一个派生集,必须详细声明: 派生集可理解为如何定义二维数组xij, ·集的名字 ·父集的名字 ·可选,集成员 ·可选,集成员的属性 可用下面的语法定义一个派生集: setname(parent_set_list)[/member_list/][:attribute_list];
派生集 sets: product/A B/; machine/M N/; week/1..2/; allowed(product,machine,week):x; endsets LINGO生成了三个父集的所有组合共八组作为allowed集的成员。列表如下: 编号 成员 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: !学生集:性别属性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 = 1 16 0 14 0 17 0 13; friend = 0.3 0.5 0.6; enddata
Lingo运算符 算术运算符 算术运算符是针对数值进行操作的。LINGO提供了5种二元运算符: ^ 乘方 ﹡ 乘 / 除 ﹢ 加 ﹣ 减 ^ 乘方 ﹡ 乘 / 除 ﹢ 加 ﹣ 减 LINGO唯一的一元算术运算符是取反函数“﹣”。
逻辑运算符 LINGO具有9种逻辑运算符: #not# 否定该操作数的逻辑值,#not#是一个一元运算符 #eq# 若两个运算数相等,则为true;否则为flase #ne# 若两个运算符不相等,则为true;否则为flase #gt# 若左边的运算符严格大于右边的运算符,则为true;否则为flase #ge# 若左边的运算符大于或等于右边的运算符,则为true;否则为flase #lt# 若左边的运算符严格小于右边的运算符,则为true;否则为flase #le# 若左边的运算符小于或等于右边的运算符,则为true;否则为flase #and# 仅当两个参数都为true时,结果为true;否则为flase #or# 仅当两个参数都为false时,结果为false;否则为true
常用数学函数 @abs(x) 返回x的绝对值 @sin(x) 返回x的正弦值,x采用弧度制 @cos(x) 返回x的余弦值 @tan(x) 返回x的正切值 @mod(x,y) 求x/y的余数 @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中的最小值
集合函数 @FOR (set_name:constraint_expressions) @MAX(set_name:expression) @MIN(set_name:expression) @SUM(set_name:expression) @SIZE(set_name) @IN(set_name,set_element)如果数据集set_name中包含元素set_element则返回1,否则返回0。
变量界定函数 变量界定函数实现对变量取值范围的附加限制,共4种: @bin(x) 限制x为0或1(例题参考练习题3) @bnd(L,x,U) 限制L≤x≤U @free(x) 取消对变量x的默认下界为0的限制,即x可以取任意实数 @gin(x) 限制x为整数
注意:lingo所有的函数及关键字除(min,max等极小数关键字外)其余的都要加上@ @符号 注意:lingo所有的函数及关键字除(min,max等极小数关键字外)其余的都要加上@ 如求和函数用@sum,循环@for等
@for用法 该函数用来产生对集成员的约束。基于建模语言的标量需要显式输入每个约束,不过@for函数允许只输入一个约束,然后LINGO自动产生每个集成员的约束。 例4.10 产生序列{1,4,9,16,25} model: sets: number/1..5/:x; endsets @for(number(I): x(I)=I^2); end
@for表示表达式: 1.如何遍历:x1,x2,x4,x5,x100 2.如何遍历:x3,x4,…,x100 例:除X3外所有变量+10;@for(xx(i) | i#ne#3:x+10) 2.如何遍历:x3,x4,…,x100 例:x3到x100的数+10 3.如何遍历:x1,x3,x5,...,x99 例:奇数项的数+10
@sum用法 该函数返回遍历指定的集成员的一个表达式的和。 例 求向量[5,1,3,4,6,10]前5个数的和。 model: data: N=6; enddata sets: number/1..N/:x; endsets x = 5 1 3 4 6 10; s=@sum(number(I) | I #le# 5: x); end 3.@min和@max 返回指定的集成员的一个表达式的最小值或最大值。
@for循环例子 例4.12 求向量[5,1,3,4,6,10]前5个数的最小值,后3个数的最大值。 model: sets: number/1..6/:x; endsets data: x = 5 1 3 4 6 10; enddata minv=@min(number(I) | I #le# 5: x); maxv=@max(number(I) | I #ge# 4: x); end
以下程序的作用是什么 model: sets: number/1..100/:x; endsets @for(number(I) | @mod(i,2) #eq# 0 : x(I)=I^2); @for(number(I) | @mod(i,2) #eq# 1 : x(I)=I^3); end
线性规划例子 例5.1某家具公司制造书桌、餐桌和椅子,所用的资源有三种:木料、木工和漆工。生产数据如下表所示: 若要求桌子的生产量不超过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;
例2,求解如下问题 所有变量均大于0
直接 求解: model: min=400*x1+400*x2+400*x3+400*x4+450*y1+450*y2+450*y3+450*y4+20*z1+20*z2+20*z3+20*z4; x1<=40;x2<=40;x3<=40; x1+y1-z1=30; x2+y2+z1-z2=60; x3+y3+z2-z3=75; x4+y4+z3-z4=25; @gin(x1);@gin(x2);@gin(x3);@gin(x4); @gin(y1);@gin(y2);@gin(y3);@gin(y4); @gin(z1);@gin(z2);@gin(z3);@gin(z4); end
利用lingo语法简化表达式 程序见example2.txt
求解非线性规划 model: min=100*(y-x^2)^2+(1-x)^2; x^2+y^2<=1.5; x+y>=0; 求min f(x1,x2)=100(x2-x12)2+(1-x1)2 约束条件:x12+x12≤1.5,x1+x2 ≥0 model: min=100*(y-x^2)^2+(1-x)^2; x^2+y^2<=1.5; x+y>=0; @free(x);@free(y); end
LINGO实战 使用LINGO软件计算6个发点8个收点的最小费用运输问题。产销单位运价如下表。 B1 B2 B3 B4 B5 B6 B7 单 销地 位运 价 产 地 B1 B2 B3 B4 B5 B6 B7 B8 量 A1 6 2 7 4 5 9 60 A2 3 8 55 A3 1 51 A4 43 A5 41 A6 52 销量 35 37 22 32 38
数据定义与初始化 DATA: SETS: WAREHOUSES/WH1..WH6/: CAPACITY; VENDORS/V1..V8/: DEMAND; LINKS( WAREHOUSES, VENDORS): COST, VOLUME; ENDSETS Data部分: DATA: CAPACITY = 60 55 51 43 41 52; DEMAND = 35 37 22 32 41 32 43 38; COST = 6 2 6 7 4 2 5 9 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
程序求解 !TITLE WIDGETS; MODEL: ! A 6 Warehouse 8 Vendor Transportation Problem; SETS: WAREHOUSES/WH1..WH6/: CAPACITY; VENDORS/V1..V8/: DEMAND; LINKS( WAREHOUSES, VENDORS): COST, VOLUME; ENDSETS ! Here is the data; DATA: !attribute values; CAPACITY = 60 55 51 43 41 52; DEMAND = 35 37 22 32 41 32 43 38; COST = 6 2 6 7 4 2 5 9 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 ! The objective; MIN = @SUM( LINKS( I, J): COST( I, J) * VOLUME( I, J)); ! The demand constraints; @FOR( VENDORS( J): @SUM( WAREHOUSES( I): VOLUME( I, J)) = DEMAND( J)); ! The capacity constraints; @FOR( WAREHOUSES( I): @SUM( VENDORS( J): VOLUME( I, J)) <= CAPACITY( I)); END