Lingo 基本使用

Lingo 语法

一、 概述

1、 简介

LINGO是用来解决优化问题的一个特别好用的软件,可以快速求解线性规划、非线性规划、线性和非线性方程组等等,是数学建模中求优化问题的解不可缺少的工具之一

(1)LINGO 的数学规划模型包含目标函数、决策变量、约束条件三个要素;
(2)LINGO 程序中,每一个语句都必须要用一个英文状态下的分号结束,一个语句可以分几行输入;
(3)LINGO 的注释以英文状态的!开始,必须以英文状态下的分号结束;
(4)LINGO 的变量不区分字母的大小写,必须以字母开头,可以包含数字和下划线,不超过32 个字符;
(5)LINGO 程序中,只要定义好集合后,其他语句的顺序是任意的;
(6)LINGO 中的函数以“@”开头;
(7)LINGO 程序默认所有的变量都是非负的;
(8)LINGO 程序中"<“或”>"号与 ""或 " " 号功能相同。

2、 文件格式

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

3、 窗口详解

https://images.cnblogs.com/cnblogs_com/blogs/722174/galleries/2074790/o_220720124434_20180810095626910.png

4、 优化模型

通常,一个优化模型由以下三部分组成:

  1. 目标函数:一般表示成求某个数学表达式的最大值或最小值
  2. 决策变量:目标函数数字取决于哪些变量
  3. 约束条件:对变量附加一些条件限制(通常用等式或不等式表示)

注意:Lingo默认所有决策变量都为正数,因而变量非负条件可以不必输入

二、 基本运算符

1、 逻辑运算符

  • #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

2、 比较运算符

关系运算符与逻辑运算符中的比较时截然不同的,前者是模型中该关系运算符所指定关系为真描述,而后者仅仅判断一个该关系是否被满足

Lingo中有三种运算符:=>=、>,和<=、<,Lingo中并不支持严格小于和严格大于关系运算符

A < B => A <= B

3、 算术运算符

运算符描述
-取反
^乘方
*
/
+
-

Lingo唯一的一元算术运算符是取反运算符

运算符的优先级由高到低为:取反-》减

优先级顺序可以通过括号改变

三、 常见函数

1、 数学函数

@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 中的最小值

2、 界定函数

@bin(x) 限制x 为0 或1 — 用于0-1规划
@bnd(L,x,U) 限制L≤x≤U
@free(x) 取消对变量x 的默认下界为0 的限制,即x 可以取任意实数
@gin(x) 限制x 为整数在默认情况下,LINGO 规定变量是非负的,也就是说下界为0,上界为+∞。@free 取消了默认的下界为0的限制,使变量也可以取负值。@bnd用于设定一个变量的上下界,它也可以取消默认下界为0的约束。

3、 集循环函数

@function(setname[(set_index_list)[|conditional_qualifier]]:
expression_list);
@function相对应于下面罗列的四个集循环函数之一;setname是要遍历的集;set_index_list是集索引列表;conditional_qualifier 是用来限制集循环函数的范围,当集循环函数遍历集的每个成员时,LINGO都要对conditional_qualifier 进行评价,若结果为真,则对该成员执行@function操作,否则跳过,继续执行下一次循环。expression_list是被应用到每个集成员的表达式列表,当用的是@for函数时,expression_list 可以包含多个表达式,其间用逗号隔开。这些表达式将被作为约束加到模型中。当使用其余的三个集循环函数时, expression_list 只能有一个表达式。如果省略set_index_list ,那么在expression_list中引用的所有属性的类型都是setname集。

  1. @for
    该函数用来产生对集成员的约束。基于建模语言的标量需要显式输入每个约束。@for函数允许只输入一个约束,然后LINGO 自动产生每个集成员的约束。

  2. @sum

    该函数返回遍历指定的集成员的一个表达式的和。

  3. @min和@max
    返回指定的集成员的一个表达式的最小值或最大值。

4、 辅助函数

  1. @if(logical_condition,true_result,false_result)

    @if 函数将评价一个逻辑表达式logical_condition,如果为真返回true_ result,否则返回false_result。

  2. @warn(’text’,logical_condition),如果逻辑条件logical_condition为真,则产生一个内容为’text’的信息框

其余函数可以在用到的时候去文档查询

四、 模型建立

1、 集合段

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

为了定义一个原始集,必须详细声明:

  • 集的名字
    • 可选,集成员
    • 可选,集成员属性

定义一个原始集,用下面的语法:

setname[/member_list/][:attribute_list]

  • 括号内容表示可选

成员罗列的几种方式

  1. 显示罗列集成员:把所有成员名列出,用逗号" , "或空格分隔。
  2. 隐式罗列集成员:setname/member1..memberN/[: attribute_list]; !用".."表示省略

https://images.cnblogs.com/cnblogs_com/blogs/722174/galleries/2074790/o_220720134335_v2-d8b383a5a69ec4e28d20af7435addd7a_r.jpg

  1. 集成员不放在集定义中,而在随后的数据部分来定义

实例:

! 常用实例方法,创建一个罗列集
SETS:
	QUARTERS/1,2,3,4/:DEM,RP,OP,INV;  ! 生成四个属性,初始化值都为 [1 2 3 4]
	factory /1..6/:a, b;  ! 生成一个 1 x 6 的矩阵
	! factory 称为数组的类型名,a, b 称为数组的变量名
	plant /1..8/: c, d;  ! 生成一个 1 x 8 的矩阵
	Cooperation(factory,plant): e, f;  ! 生成一个 6 x 8 的矩阵,如果交换一个位置,则,生成一个 8 x 6 的矩阵,也可以使用 link(factory, plant)  6 x 8
! Cooperation大工厂是由factory和plant两家小工厂合并而办,可生产6×8的矩阵
ENDSETS

! 初始化数据
DATA:
	a = 1, 2, 3, 4, 5, 6
	
ENDDATA:

需要赋值的矩阵必须赋满,不能给6个元素的矩阵只赋3个数值。
Lingo中可以给矩阵赋整数,也可以赋小数。

2、 目标和约束段

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

MIN = @SUM(QUARTERS:400*RP+450*OP+20*INV);  ! @sum为一个求和函数,对这个一维数组求400*RP + 450*OP + 20*INV 的和,第一个参数传入集合的类型
@FOR(QUARTERS(I):RP(I)<40);  ! 对 QUARTERS 进行遍历,传入类型名称,后面是操作,同时自动遍历PR里面的内容
@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);

五、 案例

1、 运输与选址

某公司有6个建筑工地,位置坐标为(ai, bi) (单位:公里),水泥日用量di (单位:吨)

i 1 2 3 4 5 6

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

现有2料场,位于A (5, 1), B (2, 7),记(xj,yj),j=1,2, / i=1~6日储量ej各有20吨。

假设料场和工地之间有直线道路,制定每天的供应计划,即从A, B两料场分别向各工地运送多少吨水泥,使总的吨公里数最小。

取决策变量c_ij表示i工地从j料场运来的水泥量。模型(线性模型)为:

min ∑ j = 1 2 ∑ i = 1 6 c i j ( x j − a i ) 2 + ( y j − b i ) 2 s . t { ∑ j = 1 2 c i j = d i . i = 1 , 2 , . . . , 6 ∑ i = 1 6 c i j ≤ e j , j = 1 , 2 \text{min} \sum_{j=1}^2{\sum_{i=1}^6{c_{ij}\sqrt{(x_j-a_i)^2+(y_j-b_i)^2}}}\\ s.t\left\{\begin{matrix} \sum_{j=1}^2 c_{ij}=d_i. i=1,2,...,6 \\ \sum_{i=1}^6 c_{ij} \le e_j,j=1,2 \end{matrix}\right. minj=12i=16cij(xjai)2+(yjbi)2 s.t{j=12cij=di.i=1,2,...,6i=16cijej,j=1,2
则,求解可得:

MODEL:
SETS:
    demand/1..6/: a, b, d;
    supply/1,2/:e, x, y;
    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;
    x=5 2;
    y=1 7;
    e=20 20;
ENDDATA
    MIN=@SUM(link(i, j):c(i, j)*@SQRT((a(i)-x(j))^2+(b(i)-y(j))^2));  ! express;
    @FOR(demand(i):@SUM(supply(j):c(i,j))=d(i));  ! condition1;
    @FOR(supply(j):@SUM(demand(i):c(i,j)) < e(j));  ! condition2;
END

2、 最优选择

某钻井队要从10个可供选择的井位中确定5个钻井探油,使总的钻探费用为最小。若10个井位的代号为s1,s2…,s10,相应的钻探费用c1,c2,…,c10为5,8,10,6,9,5,7,6,10,8.并且井位选择上要满足下列限制条件:
(1) 或选择s1和s7,或选择钻探s9;
(2) 选择了s3或s4就不能选s5,或反过来也一样;
(3) 在s5,s6,s7,s8中最多只能选两个.

试建立这个问题的整数规划模型,确定选择的井位。

可以采用真值表建立约束条件表达式

取0-1变量s_i,若s_i=1,则表示选取第i个井,若s_i=0,则表示不选取第i个井。建立数学模型如下:
min ∑ i = 1 10 s i c i s . t { ( s 1 + s 7 − 2 ) ( s 9 ) = 0 s 3 s 5 + s 4 s 5 = 0 s 5 + s 6 + s 7 + s 8 ≤ 2 ∑ i = 1 10 s i = 5 s i ∈ 0 , 1 ( i = 1 , 2 , . . . , 10 ) \text{min} \sum_{i=1}^{10} {s_ic_i}\\ s.t \left\{\begin{matrix} (s_1+s_7 - 2)(s_9)=0 \\ s_3s_5+s_4s_5=0\\ s_5+s_6+s_7+s_8 \le 2\\ \sum_{i=1}^{10}s_i=5\\ s_i \in {0, 1}(i=1,2,...,10)\end{matrix}\right. mini=110sicis.t (s1+s72)(s9)=0s3s5+s4s5=0s5+s6+s7+s82i=110si=5si0,1(i=1,2,...,10)
则,求解可得:

MODEL:
SETS:
    var/1..10/:s,c;  ! 创建集合
ENDSETS
DATA:
    c=5 8 10 6 9 5 7 6 10 8;  ! 给集合赋值
ENDDATA
    MIN = @SUM(var(i):s(i)*c(i));  ! 求解结果
    (s(1)+s(7)-2)*s(9) = 0;  ! 条件1
    s(3)*s(5)+s(4)*s(5)=0;  ! 条件2
    s(5)+s(6)+s(7)+s(8)<2;  ! 条件3
    @SUM(var(i):s(i))=5;  ! 条件4
    @FOR(var(i):@BIN(s(i)));  ! 条件5,使用for循环对s的每一个值进行约束,1代表true
END
  • 50
    点赞
  • 431
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SteveKenny

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值