目录
前言
LINGO 有 9 种类型的函数: 1. 基本运算符:包括算术运算符、逻辑运算符和关系运算符 2.数学函数:三角函数和常规的数学函数 3.金融函数:LINGO 提供的两种金融函数 4.概率函数:LINGO 提供了大量概率相关的函数 5.变量界定函数:这类函数用来定义变量的取值范围 6. 集操作函数:这类函数为对集的操作提供帮助 7.集循环函数:遍历集的元素,执行一定的操作的函数 8.数据输入输出函数:这类函数允许模型和外部数据源相联系,进行数据的输入输出 9.辅助函数:各种杂类函数
一、基本运算符
主要为^ 乘方 ﹡ 乘 / 除 ﹢ 加 ﹣ 减 。LINGO 唯一的一元算术运算符是取反函数“﹣”。运算的次序可以用圆括号“()”来 改变。
二、逻辑运算符
在 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
三、数学函数
LINGO 提供了大量的标准数学函数:
@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 时,返回不超过 x 的最大整数;当 x<0 时,返回不低于 x 的最大整数
@smax(x1,x2,„,xn) 返回 x1,x2,„,xn 中的最大值
@smin(x1,x2,„,xn) 返回 x1,x2,„,xn 中的最小值
四、金融函数
目前 LINGO 提供了两个金融函数。
1.@fpa(I,n)
返回如下情形的净现值:单位时段利率为 I,连续 n 个时段支付,每个时段支付单位费 用。若每个时段支付 x 单位的费用,则净现值可用 x 乘以@fpa(I,n)算得。@fpa 的计算公式为
净现值就是在一定时期内为了获得一定收益在该时期初所支付的实际费用。
例如贷款金额 50000 元,贷款年利率 5.31%,采取分期付款方式(每 年年末还固定金额,直至还清)。问拟贷款 10 年,每年需偿还多少元? LINGO 代码如下:
50000 = x * @fpa(.0531,10); 答案是 x=6573.069 元。
2、@fpl(I,n)
返回如下情形的净现值:单位时段利率为 I,第 n 个时段支付单位费用。@fpl(I,n)的 计算公式为
,两函数关系为:
五、概率函数
1.@pbn(p,n,x) 二项分布的累积分布函数。当 n 和(或)x不是整数时,用线性插值法进行计算。
2.@pcx(n,x) 自由度为 n 的 χ 2分布的累积分布函数。
3.@peb(a,x) 当到达负荷为 a,服务系统有 x 个服务器且允许无穷排队时的 Erlang 繁忙概率。
4.@pel(a,x) 当到达负荷为 a,服务系统有 x 个服务器且不允许排队时的 Erlang 繁忙概率。
5.@pfd(n,d,x) 自由度为 n 和 d 的 F 分布的累积分布函数。
6.@pfs(a,x,c) 当负荷上限为 a,顾客数为 c,平行服务器数量为x时,有限源的Poisson 服务系统的等待或返修顾客数的期望值。a 是顾客数乘以平均服务时间,再除以平均返修时间。当 c 和 (或)x不是整数时,采用线性插值进行计算。
7.@phg(pop,g,n,x) 超几何(Hypergeometric)分布的累积分布函数。pop 表示产品总数,g 是正品数。从所有产品中任意取出n(n≤pop)件。pop,g,n 和 x 都可以是非整数,这时采用线性插值进行计算。
8.@ppl(a,x) Poisson 分布的线性损失函数,即返回 max(0,z-x)的期望值,其中随机变量 z 服从均值 为 a 的 Poisson 分布。
9.@pps(a,x) 均值为 a 的 Poisson 分布的累积分布函数。当 x 不是整数时,采用线性插值进行计算。
10.@psl(x) 单位正态线性损失函数,即返回 max(0,z-x)的期望值,其中随机变量 z 服从标准正态 分布。
11.@psn(x) 标准正态分布的累积分布函数。
12.@ptd(n,x) 自由度为 n 的 t 分布的累积分布函数。
13.@qrand(seed) 产生服从(0,1)区间的拟随机数。@qrand只允许在模型的数据部分使用,它将用拟随机 数填满集属性。通常,声明一个 m×n 的二维表,m 表示运行实验的次数,n 表示每次实验所 需的随机数的个数。在行内,随机数是独立分布的;在行间,随机数是非常均匀的。这些随 机数是用“分层取样”的方法产生的。
14.@rand(seed) 返回 0 和 1 间的伪随机数,依赖于指定的种子。典型用法是 U(I+1)=@rand(U(I))。注 意如果 seed 不变,那么产生的随机数也不变。
六、变量界定函数
变量界定函数实现对变量取值范围的附加限制,共 4 种:
@bin(x) 限制 x 为 0 或 1
@bnd(L,x,U) 限制 L≤x≤U
@free(x) 取消对变量 x 的默认下界为 0 的限制,即 x 可以取任意实数
@gin(x) 限制 x 为整数
在默认情况下,LINGO 规定变量是非负的,也就是说下界为 0,上界为+∞。@free 取消 了默认的下界为 0 的限制,使变量也可以取负值。@bnd 用于设定一个变量的上下界,它也可 以取消默认下界为 0 的约束。
七、集操作函数
LINGO 提供了几个函数帮助处理集。
1.@in(set_name,primitive_index_1 [,primitive_index_2,„]) 如果元素在指定集中,返回 1;否则返回 0。
2.@index([set_name,] primitive_set_element) 该函数返回在集 set_name 中原始集成员 primitive_set_element 的索引。如果 set_name 被忽略,那么 LINGO 将返回与 primitive_set_element 匹配的第一个原始集成员的索引。如 果找不到,则产生一个错误。
3.@wrap(index,limit) 该函数返回 j=index-k*limit,其中 k 是一个整数,取适当值保证 j 落在区间[1,limit] 内。该函数相当于 index 模 limit 再加 1。该函数在循环、多阶段计划编制中特别有用。
@warp(i,j)中j相当于一个边界,
当i对j求余不等于0时,@warp(i,j)返回i%j
当i对j求余等于0时,@warp(i,j)返回j
即利用@warp(i,j)可以形成从1到j的循环。
4.@size(set_name) 该函数返回集 set_name 的成员个数。在模型中明确给出集大小时最好使用该函数。它 的使用使模型更加数据中立,集大小改变时也更易维护。
八、集循环函数
集循环函数遍历整个集进行操作。
其语法为 @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 返回指定的集成员的一个表达式的最小值或最大值。
九、输入和输出函数
输入和输出函数可以把模型和外部数据比如文本文件、数据库和电子表格等连接起来。
1.@file 函数
该函数用从外部文件中输入数据,可以放在模型中任何地方。该函数的语法格式为 @file(’filename’)。这里 filename 是文件名,可以采用相对路径和绝对路径两种表示方 式。@file 函数对同一文件的两种表示方式的处理和对两个不同的文件处理是一样的,这一 点必须注意。
model:
!6 发点 8 收点运输问题;
sets:
warehouses/ @file('1_2.txt') /: capacity;
vendors/ @file('1_2.txt') /: 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 = @file('1_2.txt') ;
demand = @file('1_2.txt') ;
cost = @file('1_2.txt') ;
enddata
end
模型的所有数据来自于 1_2.txt 文件。其内容如下:
!warehouses 成员;
WH1 WH2 WH3 WH4 WH5 WH6 ~
!vendors 成员;
V1 V2 V3 V4 V5 V6 V7 V8 ~
!产量;
60 55 51 43 41 52 ~
!销量;
35 37 22 32 41 32 43 38 ~
!单位运输费用矩阵;
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
把记录结束标记(~)之间的数据文件部分称为记录。如果数据文件中没有记录结束标 记,那么整个文件被看作单个记录。注意到除了记录结束标记外,模型的文本和数据同它们 直接放在模型里是一样的。
我们来看一下在数据文件中的记录结束标记连同模型中@file 函数调用是如何工作的。 当在模型中第一次调用@file 函数时,LINGO 打开数据文件,然后读取第一个记录;第二次 调用@file 函数时,LINGO 读取第二个记录等等。文件的最后一条记录可以没有记录结束标 记,当遇到文件结束标记时,LINGO 会读取最后一条记录,然后关闭文件。如果最后一条记 录也有记录结束标记,那么直到 LINGO 求解完当前模型后才关闭该文件。如果多个文件保持 打开状态,可能就会导致一些问题,因为这会使同时打开的文件总数超过允许同时打开文件 的上限 16。
当使用@file 函数时,可把记录的内容(除了一些记录结束标记外)看作是替代模型中 @file(’filename’)位置的文本。这也就是说,一条记录可以是声明的一部分,整个声明, 或一系列声明。在数据文件中注释被忽略。注意在 LINGO 中不允许嵌套调用@file 函数。
2.@text 函数
该函数被用在数据部分用来把解输出至文本文件中。它可以输出集成员和集属性值。其 语法为 @text([’filename’]) 这里 filename 是文件名,可以采用相对路径和绝对路径两种表示方式。如果忽略 filename, 那么数据就被输出到标准输出设备(大多数情形都是屏幕)。@text 函数仅能出现在模型数 据部分的一条语句的左边,右边是集名(用来输出该集的所有成员名)或集属性名(用来输 出该集属性的值)。 我们把用接口函数产生输出的数据声明称为输出操作。输出操作仅当求解器求解完模型 后才执行,执行次序取决于其在模型中出现的先后。
3.@ole 函数
@OLE 是从 EXCEL 中引入或输出数据的接口函数,它是基于传输的 OLE 技术。OLE 传输直 接在内存中传输数据,并不借助于中间文件。当使用@OLE 时,LINGO 先装载 EXCEL,再通知 EXCEL 装载指定的电子数据表,最后从电子数据表中获得 Ranges。为了使用 OLE 函数,必须 有 EXCEL5 及其以上版本。OLE 函数可在数据部分和初始部分引入数据。
@OLE 可以同时读集成员和集属性,集成员最好用文本格式,集属性最好用数值格式。 原始集每个集成员需要一个单元(cell),而对于 n 元的派生集每个集成员需要 n 个单元,这 里第一行的 n 个单元对应派生集的第一个集成员,第二行的 n 个单元对应派生集的第二个集 成员,依此类推。
@OLE 只能读一维或二维的 Ranges(在单个的 EXCEL 工作表(sheet)中),但不能读间断的或三维的 Ranges。Ranges 是自左而右、自上而下来读。
4.@ranged(variable_or_row_name) 为了保持最优基不变,变量的费用系数或约束行的右端项允许减少的量。
5.@rangeu(variable_or_row_name) 为了保持最优基不变,变量的费用系数或约束行的右端项允许增加的量。
6.@status() 返回 LINGO 求解模型结束后的状态:
0 Global Optimum(全局最优)
1 Infeasible(不可行)
2 Unbounded(无界)
3 Undetermined(不确定)
4 Feasible(可行)
5 Infeasible or Unbounded(通常需要关闭“预处理”选项后重新求解模型,以确 定模型究竟是不可行还是无界)
6 Local Optimum(局部最优)
7 Locally Infeasible(局部不可行,尽管可行解可能存在,但是 LINGO 并没有找到 一个)
8 Cutoff(目标函数的截断值被达到)
9 Numeric Error(求解器因在某约束中遇到无定义的算术运算而停止) 通常,如果返回值不是 0、4 或 6 时,那么解将不可信,几乎不能用。该函数仅被用在 模型的数据部分来输出数据。
7.@dual @dual(variable_or_row_name)返回变量的判别数(检验数)或约束行的对偶(影子) 价格(dual prices)。
十、辅助函数
1.@if(logical_condition,true_result,false_result) @if 函数将评价一个逻辑表达式 logical_condition,如果为真,返回 true_ result, 否则返回 false_result。
2.@warn(’text’,logical_condition) 如果逻辑条件 logical_condition 为真,则产生一个内容为’text’的信息框。
总结
这里主要介绍的是函数的学习,后面如果可以的话会具体去分析一些试题来做讲解。