lingo入门

您所在的位置:网站首页 lingo能解决什么类型的数学问题 lingo入门

lingo入门

2024-07-16 04:33| 来源: 网络整理| 查看: 265

目录

前言

一、集是什么?

1、定义一个原始集

2、定义一个派生集

二、模型的数据部分和初始部分

总结

前言

对实际问题建模的时候,总会遇到一群或多群相联系的对象,比如工厂、消费者群体、 交通工具和雇工等等。LINGO 允许把这些相联系的对象聚合成集(sets)。一旦把对象聚合成集,就可以利用集来最大限度的发挥 LINGO 建模语言的优势。集是 LINGO 建模语言的基础,是程序设计最强有力的基本构件。借助于集,能够用一个单一的、长的、简明的复合公式表示一系列相似的约束,从而可以快速方便地表达规模较大的模型。

一、集是什么?

集是一群相联系的对象,这些对象也称为集的成员。一个集可能是一系列产品、卡车或 雇员。每个集成员可能有一个或多个与之有关联的特征,我们把这些特征称为属性。例如,产品集中的每个产品可以有一个价格属性;卡车集中的每辆卡车可以有一个牵引力属性;雇员集中的每位雇员可以有一个 薪水属性,也可以有一个生日属性等等。(PS:属性值可以预先给定,也可以是未知的,有待于 LINGO 求解。)

当然,你可以用c语言来类比:

集 ←→ 结构体

集成员 ←→ 结构体的域

集属性 ←→ 结构体实例

 集的类型

总的来说,LINGO 可识别的集只有两种类型:原始集和派生集。

一个原始集是由一些最基本的对象组成的。

一个派生集是用一个或多个其它集来定义的,也就是说,它的成员来自于其它已存在的集。

1、定义一个原始集

注意:集部分以关键字“sets:”开始,以“endsets”结束。原始集,定于语法:

setname/member_list(成员变量)/:attribute_list(属性)

当然Member_list 是集成员列表。如果集成员放在集定义中,那么对它们可采取显式罗列和隐式罗列两种方式。如果集成员不放在集定义中,那么可以在随后的数据部分定义它们。

① 当显式罗列成员时,必须为每个成员输入一个不同的名字,中间用空格或逗号搁开, 允许混合使用。

② 当隐式罗列成员时,不必罗列出每个集成员。可采用如下语法: setname/member1..memberN/attribute_list;

这里的 member1 是集的第一个成员名,memberN 是集的最末一个成员名。LINGO 将自动产生中间的所有成员名。LINGO 也接受一些特定的首成员名和末成员名,用于创建一些特殊的集。 

下面我们定义一个原始集:

注释为开头用感叹号(!),末尾用分号(;)表示注释,可跨多行。

!这个表示注释; data: students,sex,age= John 1 16 Jill 0 14 Rose 0 17 Mike 1 13; enddata 2、定义一个派生集

派生集的语法定义:

setname(parent_set_list)/member_list/attribute_list;

setname 是集的名字。parent_set_list 是已定义的集的列表,多个时必须用逗号隔开。 如果没有指定成员列表,那么 LINGO 会自动创建父集成员的所有组合作为派生集的成员。派生集的父集既可以是原始集,也可以是其它的派生集。

sets: product/A B/; machine/M N/; week/1..2/; allowed(product,machine,week):x; endsets

运行之后结果为

 成员列表被忽略时,派生集成员由父集成员所有的组合构成,这样的派生集成为稠密集。 如果限制派生集的成员,使它成为父集成员所有组合构成的集合的一个子集,这样的派生集成为稀疏集。同原始集一样,派生集成员的声明也可以放在数据部分。一个派生集的成员列表有两种方式生成:①显式罗列;②设置成员资格过滤器。当采用方式①时,必须显式罗列出所有要包含在派生集中的成员,并且罗列的每个成员必须属于稠密集。使用前面的例子, 显式罗列派生集的成员:

allowed(product,machine,week)/A M 1,A N 2,B N 1/;

如果需要生成一个大的、稀疏的集,那么显式罗列就很讨厌。幸运地是许多稀疏集的成员都 满足一些条件以和非成员相区分。我们可以把这些逻辑条件看作过滤器,在 LINGO 生成派生集的成员时把使逻辑条件为假的成员从稠密集中过滤掉。

例如:

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

用竖线(|)来标记一个成员资格过滤器的开始。#eq#是逻辑运算符,用来判断是否“相等”。

&1 可看作派生集的第 1 个原始父集的索引,它取遍该原始父集的所有成 员;&2 可看作派生集的第 2 个原始父集的索引,它取遍该原始父集的所有成员;&3,&4,„„, 以此类推。

注意如果派生集 B 的父集是另外的派生集 A,那么上面所说的原始父集是集 A 向前回溯到最终的原始集,其顺序保持不变,并且派生集 A(linkmf) 的过滤器对派生集 B(linkmf2) 仍然有效。

 我们可以注意到X(JOHN,ROSE)和X(JOHN,MIKE)被筛选出来了。

二、模型的数据部分和初始部分

在处理模型的数据时,需要为集指派一些成员并且在 LINGO 求解模型之前为集的某些属 性指定值。为此,LINGO 为用户提供了两个可选部分:输入集成员和数据的数据部分(Data Section)和为决策变量设置初始值的初始部分(Init Section)。

1、模型的数据部分

数据部分以关键字“data:”开始,以关键字“enddata”结束。

在这里,可以指定集成员、集的属性。其语法如下: object_list = value_list;例如:

sets: set1/A,B,C/: X,Y; endsets data: X=1,2,3; Y=4,5,6; enddata

当然,在某些情况,对于模型中的某些数据并不是定值。譬如模型中有一个通货膨胀率的参数, 我们想在 2%至 6%范围内,对不同的值求解模型,来观察模型的结果对通货膨胀的依赖有多 么敏感。我们把这种情况称为实时数据处理(what if analysis)。LINGO 有一个特征可方 便地做到这件事。 在本该放数的地方输入一个问号(?)。

data: interest_rate,inflation_rate = .085 ?; enddata

每一次求解模型时,LINGO 都会提示为参数 inflation_rate 输入一个值。在 WINDOWS 操作 系统下,将会接收到一个类似下面的对话框:

直接输入一个值再点击 OK 按钮,LINGO 就会把输入的值指定给 inflation_rate,然后继续 求解模型。 除了参数之外,也可以实时输入集的属性值,但不允许实时输入集成员名。

数据部分的未知数值

有时只想为一个集的部分成员的某个属性指定值,而让其余成员的该属性保持未知,以便让LINGO 去求出它们的最优值。在数据声明中输入两个相连的逗号表示该位置对应的集成 员的属性值未知。两个逗号间可以有空格。

sets: years/1..5/: capacity; endsets data: capacity = ,34,20,,; enddata

 模型的初始部分

初始部分是 LINGO 提供的另一个可选部分。在初始部分中,可以输入初始声明 (initialization statement),和数据部分中的数据声明相同。对实际问题的建模时,初始部分并不起到描述模型的作用,在初始部分输入的值仅被 LINGO 求解器当作初始点来用,并且仅仅对非线性模型有用。和数据部分指定变量的值不同,LINGO 求解器可以自由改变初 始部分初始化的变量的值。

 一个初始部分以“init:”开始,以“endinit”结束。

初始部分的初始声明规则和数据 部分的数据声明规则相同。也就是说,我们可以在声明的左边同时初始化多个集属性,可以把集属性初始化为一个值,可以用问号实现实时数据处理,还可以用逗号指定未知数值。好的初始点会减少模型的求解时间。

init: X, Y = 0, .1; endinit Y=@log(X); X^2+Y^2


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3