GAMS用户手册中文翻译第215章.docx
- 文档编号:25395115
- 上传时间:2023-06-08
- 格式:DOCX
- 页数:159
- 大小:2.27MB
GAMS用户手册中文翻译第215章.docx
《GAMS用户手册中文翻译第215章.docx》由会员分享,可在线阅读,更多相关《GAMS用户手册中文翻译第215章.docx(159页珍藏版)》请在冰豆网上搜索。
GAMS用户手册中文翻译第215章
第二章GAMS指南
2.1引言
本书的介绍部分将给出一个详细的例子,介绍如何使用GAMS来描述、求解和分析一个简单的小型优化问题。
加利福尼亚州蒙特里海军研究院的RichardE.Rosenthal写了这个指南。
这个例子对GAMS及其特性给出了一个快速但全面的概述。
许多内容可参考书本的其它部分,但它们仅仅是告诉你要去哪里寻找更详细的细节。
这里的材料在不参考书本其余部分的情况下,单独阅读也能带来诸多益处。
例子是一个线性规划的运输问题,在优化技术的发展历史中,它充当了“试验动物”的角色。
(例如,见Dantzig,1963)。
这是用来说明像GAMS这样的代数建模语言的强大功能的一个很好选择,因为运输问题,不管多复杂,它都拥有一个简单的,可利用的代数结构。
你将看到如果要考虑一个更大的运输问题,我们要给出的GAMS输入文件中几乎所有的语句都将保持不便。
在这个大家熟悉的运输问题中,我们给定几个厂商和几个市场对单一商品的供给和需求,同时给定将商品从工厂运到市场的单位运输成本。
经济问题是:
应该从每个工厂向每个市场运输多少,才能最小化总的运输成本。
这个问题的代数表达式通常以与下列相同的格式给出:
指数:
=工厂
=市场
给定数据:
=工厂i的商品供给(cases)
=市场j的商品需求
=工厂i到市场j之间的单位运输成本($/case)
决策变量:
=从工厂i向市场j运输的商品数量(case)
其中,
,foralli,j
约束条件:
工厂i的供给限制:
foralli(cases)
满足市场j的需求:
forallj(cases)
目标函数:
($K)
值得注意的是这个简单的例子揭示了一些我们一般认为是好习惯的建模惯例,它与GAMS的设计是一致的。
首先,模型的所有实体是通过类型识别(和分组)的。
其次,实体顺序的选择应该使得符号在被定义之前没有被引用到。
第三,所有实体单位是详细设定的。
第四,单位被选择为一定度量比例,它使得优化程序碰到的数字有相对小的绝对数量级。
(这里,符号$K表示千美元)。
实体类型的名称对不同建模者可能不同。
例如,经济学家使用外生变量和内生变量这两个术语来分别表示给定的数据和决策变量。
在GAMS中,采用的术语如下:
指数被称为集合(sets),给定数据被称为参数(parameters),决策变量被称为变量(variables),限制条件和目标函数被称为方程(equations)。
运输问题的GAMS表达式几乎与上面的代数表达式相同。
但是,最重要的不同之处在于GAMS版本能够由计算机阅读并执行。
表2.1运输问题的数据(改编自Dantzig,1963)
作为运输问题的一个例子,假设有两个罐头厂和三个市场,数据在表2.1中给出。
运输距离用千英里表示,运输成本假设为每case每千英里$90.00。
这个问题的GAMS表达式如下:
如果你将包含上述语句的文件作为GAMS程序的输入文件,那么这个运输模型将被读取并求解。
细节将根据在不同计算机上如何调用GAMS而有所不同,但是,调用GAMS的最简单的(不带任何虚饰)方式是在输入文件名之前输入单词GAMS。
你将看到许多简洁的行,它描述了GAMS的进展情况,包括输出被写入的文件的名称。
当GAMS完成之后,检查这个文件,如果运行良好,那么最优的运输量将显示在其底部,结果如下:
你也将得到如下边际成本(单纯形乘子):
这些结果表明,从Seattle到Topeka的最优运输量是零,但如果你坚持要运输一单位的话,最优成本将增加$0.036$K(也即$36.00)。
(你能从最优运输量和给定数据证明这个数字是正确的吗?
)
2.2GAMS模型的结构
在这个指南的剩余部分中,我们将以上述的例子作为参考讨论GAMS模型的基本成分。
基本成分列在表2.2中。
表2.2GAMS模型的基本成分
.
GAMS模型中存在可选的输入成分,如错误数据的编辑检查和结果的定制报告要求。
其它可选的高级特征包括存储和恢复旧模型,在一次运行中生成多个模型等,但该指南只讨论基本成分。
在处理单个成分之前,我们给出几个综合的注释。
1.GAMS模型是用GAMS语言书写的语句集合。
控制语句顺序的唯一规则是模型实体不能在其被声明存在之前被引用;
2.GAMS语句能够以用户喜好的几乎任何方式来进行编排。
一个语句存在于多行,植入空白行以及一行存在多个语句都是可行的。
你将从该指南的例子中得到什么是被允许的概念,但其准确的规则将在下一章给出。
3.如果你是GAMS的初级用户,那么你应该用分号终止每个语句,如同本例一样。
GAMS编辑器不区分大小写字母,因此你能够自由使用大小写中任一种。
4.注释对数学模型的有效性是至关重要的。
如果注释被植入模型本身,而不是分开书写,那么它将更加有用(也更加精确)。
至少存在两种方式在GAMS模型中插入注释。
首先,任何在第一列以星号开始的行都被GAMS编辑器认为是注释行。
第二,也许是更重要的一点,解释性文本能够插入到具体的GAMS语句之中。
运输模型中所有的小写单词是第二种文件形式的例子。
5.正如你从上面输入成分列表中看到的,GAMS实体的创建包含两个步骤:
声明(declaration)和赋值(assignment)或定义(definition)。
声明意味着宣布某些东西的存在,并给其一个名称。
赋值或定义意味着给这些东西一个具体的值或具体的形式。
在方程中,你必须在单独的GAMS语句中进行声明和定义。
然而,对于所有的GAMS实体,你可以选择在同一个语句中,或在不同的语句中进行声明和赋值。
6.给模型实体的名称必须以字母开头,后面跟随最多为30个的字母或数字。
2.3集合
集合(sets)是GAMS模型的基本建筑模块,它对应于模型算术表达式中的指数。
上面的运输模型仅包含一个集合语句:
语句是能够自我解释的。
我们声明了两个集合,起名为i和j,同时对集合赋予如下元素:
你必须注意GAMS格式和常用的数学格式之间在罗列集合元素上的差别。
GAMS采用斜杠“/”,而不是大括号“{}”来描绘集合,这仅仅是因为并非所有的计算机键盘都有大括号键。
应该注意的还有多单词名称,如‘NewYork’是不允许的,因此必须插入连字符号。
上述集合语句中的小写单词称为文本(text)。
文本是可选的。
它仅为了内部说明而存在,在模型中没有正式的目的。
GAMS编辑器并不试图解释这些文本,而是储存这些文本,并在你觉得方便的时候把它复制给你。
并没有必要将集合i和集合j的创建放在同一个语句中。
我们可将它们放到如下分开的语句中:
空格和空行的布置(以及大小写的选择)取决于你的偏好。
每个GAMS用户往往使用自己格式上的习惯。
(单数set的使用也取决于你自己,在一个进行单一声明的语句中使用set,和在一个进行多个声明的语句中使用sets仅是英语好的表现,但单数和复数对GAMS而言是相同的。
)
当你对一个集合赋予元素的时候,可采用一个方便的特性,即使用星号。
这在元素是一个序列的情况下使用。
例如,下列是GAMS中的合法set语句。
这里结果是赋值:
应该注意的是集合元素是作为字符串进行存储的,因为t的元素不是数字。
另一个方便的特性是alias语句,它用于给前面声明的集合起另外一个名称。
看下面例子:
名称tp就像在数学符号中的t’。
在相同集合中的元素之间存在相互联系的模型中,这个语句是非常有用的。
上述语句中集合i,j,t和m是静态集合的例子,也即,这些集合的元素直接由用户赋值,并且不再改变。
GAMS有几种创建动态集合的功能,它要求集合的元素在集合理论和逻辑运算的执行中是可变的。
动态集合将在第12章讨论。
另一个有价值的高级特性是多维集合,这将在4.5节讨论。
2.4数据
这个运输问题的GAMS模型说明了所有三种允许用于输入数据的基本格式。
这三种格式是:
下面三个小节将依次讨论每种格式。
2.4.1清单数据输入
第一种格式可由例子的第一个parameters语句说明,它表示如下:
这个语句有多个结果。
再次,它也是能自我解释的,但详细分析它们是值得的。
这个语句声明两个参数的存在,并给定名称a和b,宣布它们的定义域分别为i和j(定义域是这样一个集合或一组集合:
参数,变量或方程被定义在这个或这些集合上)。
这个语句也给出了每个参数对应的解释性文本,并赋值给i和j中每个元素对应的参数a(i)和b(j)。
如果你喜欢的话,也完全可以将这个语句分成如下两个语句:
在采用list格式时应该记住的几点:
1.定义域元素及其各自参数值的罗列可采用任何你喜欢的形式。
唯一的规则是整个列表必须在斜杠之中,元素值对必须由逗号分开,或在不同行输入。
2.元素值列表之前的名称,定义域和文本与元素值列表之间不用分号分开。
这是因为当你使用list格式的时候,相同的语句被用于声明和赋值。
(元素值列表本身是无法被GAMS解释的,这将导致一个错误信息。
)
3.GAMS编辑器有一个非常有用的特性,称为定义域检查,它保证列表中的每个定义域元素在实际中是引用集合的元素。
例如,如果你在声明集合i的语句中正确地拼写了‘Seattle’,而在随后的元素值列表中拼错为‘Seatle’,那么GAMS编辑器将给出一个错误信息,说明元素‘Seatle’并不属于集合i。
4.零是所有参数的默认值。
因此,你只要将非零的参数输入元素值列表中即可,而且可以以任何方式输入。
5.常数被认为是没有定义域的参数,用Scalar语句进行声明和赋值,它包含只有一个值的退化的列表,参见如下运输模型中的语句:
如果参数的定义域有两个或更多维度,它仍然可采用list格式输入数据。
这在输入稀疏数组(几乎没有非零值)和超稀疏数组(几乎没有区别于零的非零值)的时候非常有用。
2.4.2表格数据输入
在某些时候,大模型的许多输入数据可从相对较小的数字表中推导而得。
这样,拥有表格形式的数据输入就非常有用。
一个两维表格(矩阵)的例子可由上述运输模型提供:
这个语句的结果是声明参数d,并将其定义域设定为由i和j的笛卡儿积形成的有序对集合。
在适当的标题下,这个语句也给出了d的值。
如果在表格中有空格输入,那么它们被理解为零。
与list格式相同,GAMS将进行定义域检查以确保表格的行和列的名称是所用集合的元素。
输入无法在一行中实现的多列表格以及输入两维以上的表格的格式将在第5章讨论。
2.4.3直接赋值数据输入
数据输入的直接赋值方式与列表(list)方式和表格(table)方式的不同之处在于,它将参数声明和参数赋值分开到不同语句中。
运输模型包含了这种赋值方式:
应该强调的是在第一行的末尾出现了分号。
没有这个分号,GAMS编辑器将试图将这两行视为一个相同的语句。
(GAMS将无法识别一个正确的解释,因此它会给你一个简洁但非常有帮助的错误信息。
)
上面的第一个语句是要声明参数c,设定定义域(i,j),并给出一些解释性文本。
第二个语句赋值给c(i,j),令其值为参数f和d(i,j)的乘积。
很自然,在GAMS中,只有你已经在前面的语句中赋值给f和d(i,j),这个语句才是合法的。
上面的直接赋值适用于定义域c中的所有(i,j)对。
如果你要对定义域中的具体元素进行赋值,你可用引号将元素名称括起来。
例如:
这是一个合法的GAMS赋值语句。
同一个参数可赋值多次。
每个赋值语句马上生效,并覆盖任何前面的值。
(相反,相同的参数不能声明超过一次。
这是GAMS的一个错误检查方式,以保证你不会对两个不同的事物使用相同的名称。
)
赋值语句的右边可以包含各种数学表达式以及内嵌的函数。
如果你熟悉程序设计语言如FORTRAN或C语言,那么你将会很适应在GAMS中书写赋值语句。
(但是,记住GAMS有很多FORTRAN和C语言所没有的高效率的地方,例如,我们可以在不构建‘doloops’结构的情况下,对所有(i,j)赋值给c(i,j))。
GAMS标准的运算函数将在后面介绍。
这里是一些合法的赋值语句。
所有情况下,我们都假设左边的参数已经被声明过,右边参数已经在前面的语句中赋值过。
后面要介绍的求和算子和乘积算子也可用于直接赋值中。
2.5变量
用GAMS表示的模型的决策变量(或说是内生变量)必须采用Variables语句声明。
每个变量给定一个名称,一个定义域(如果需要的话)和文本。
运输模型包含了如下varialbles语句:
这个语句声明了与每个(i,j)对应的运输变量。
(你将在第8章看到GAMS是如何处理这种典型的现实情况的,也即只有(i,j)的一个子集在运输中是被允许的。
)
Z变量的声明不带定义域,因为这是一个标量。
每个GAMS优化模型必须包含这样一个变量作为被最小化或最大化的量。
一旦被声明,每个变量就必须赋予一个类型。
允许的类型在表2.3中给出。
表2.3允许的变量类型
作为优化目标的变量必须是标量,并且为free类型。
在我们的运输模型中,z处于默认的free类型下,但x(i,j)通过如下语句被限制为非负:
应该注意的是x的定义域在类型赋值中不能重复。
定义域中的所有输入自动有相同的变量类型。
2.10节将描述如何给变量赋予下边界,上边界和初始值。
2.6方程
GAMS代数建模语言的强大功能在方程以及包含在所构建模型中限制不等式的构建中体现的淋漓尽致。
这是因为只要一组方程或不等式有相同的代数结构,这个组中的所有方程或限制式都能同时构建,而不用单独构建。
2.6.1方程声明
方程必须在分开的语句中进行声明和定义。
声明的格式与GAMS其它实体一样。
首先是关键字Equations,而后是要声明的一组或多组方程或不等式的名称,定义域和文本。
我们的运输模型中包含下列方程声明:
记住单词Equation在GAMS中有非常广阔的意思。
它包含等式和不等式关系,单一名称的GAMS方程能指向一个或多个这些关系。
例如,cost没有定义域,因此它是单个方程。
但supply却指向定义在定义域i上的一组不等式。
2.6.2GAMS的求和符号(乘积符号)
在说明方程定义之前,我们描述GAMS中的求和符号。
记住GAMS是为标准键盘和逐行输入阅读设计的,因此不可能(它对用户来说,也不方便)使用标准的数学符号来进行求和。
GAMS中的求和符号可用于单一或复合表达式。
这个格式是基于通常的概念建立的,也即求和是对两个变量的算子:
sum(indexofsummation,summand)。
一个逗号格开了两个变量,如果第一个变量需要有一个逗号,那么它必须用括号括起来。
第二个变量可以是任何数学表达式,甚至可以包含另一个求和算子。
作为一个例子,运输问题包含了如下表达式:
这等价于
。
一个稍微复杂一点的求和用于如下例子:
这等价于
。
最后一个表达式也能够写成如下一个嵌套式的求和:
11.3节中,我们将描述如何使用dollar算子对求和算子施加限制,使得满足具体条件的i和j中的元素包含在求和中。
GAMS中乘积的定义使用的是与求和完全相同的格式,将sum换成prod即可。
例如:
这等价于:
求和算子和乘积算子可用于参数的直接赋值语句中。
例如:
2.6.3方程定义
由于其多样性,方程定义是GAMS中最复杂的语句。
方程定义的成分,按顺序包括:
1.被定义方程的名称
2.定义域
3.定义域限制条件(可选的)
4.符号‘..’
5.左边表达式
6.关系算子:
=l=,=e=,=g=
7.右边表达式
运输例子包含三个语句:
以下是要记住的几点:
Ø采用一个GAMS语句创建多个方程的能力是由定义域控制的。
例如,demand限制式的定义将导致对定义域上每个元素创建一个限制式,如下从GAMS输出中的摘录所示:
Ø这里的主要思想是:
不论我们是在求解上面的小型例子,还是在求解有20000个节点的实际问题,GAMS所需的限制式是完全相同的。
每种情况下,用户只要输入一个普通的代数方程表达式,然后GAMS就创建了适用于手上例子的具体方程(使用一些其它的优化包,上面的摘录将成为输入的一部分,而不是输出的一部分。
)
Ø许多实际问题中,由于存在某种例外,一些方程定义域中的元素必须被忽略,或者必须区别于其它方程。
GAMS能够方便地调节这种结构上的缺失,通过使用一个称为dollar或“such-that”算子的强大特征来实现,这个特征在这里不进行讨论。
定义域限制特征是绝对必要的,它用于将实际模型的大小保持在可解的范围内。
Ø关系算子有如下含义:
Ø理解‘=’和‘=e=’之间的区别是非常重要的。
‘=’符号仅用于直接赋值中,而‘=e=’仅用于方程定义。
这两者是完全不同的。
直接赋值是在求解之前给参数赋值。
方程定义也描述一个关系式,但必须在求解的时候才能得到满足。
因此,方程定义必须包含变量,而直接赋值不能包含变量。
Ø变量可以出现在方程的左边或右边,或者在两边同时出现。
相同的变量可在一个方程中出现不止一次。
在被求解之前,GAMS处理器将自动将方程转化成与它等价的标准形式(变量在左边,不重复出现)。
Ø方程定义可以出现在GAMS输入的任何地方,给定方程以及方程所指的所有变量和参数都在前面定义过。
(值得注意的是方程中出现的变量在定义之后进行赋值或重新赋值都是允许的。
这在以一个GAMS输入执行多个模型的时候非常有用)。
方程不需要以与它们声明顺序相同的顺序进行定义。
2.7目标函数
这里仅作一种提示,说明GAMS中没有称为目标函数的明确实体。
为了设定被优化的函数,你必须创建一个变量,它是free类型的(没有符号限制),同时是标量值(没有定义域),它出现在将它设定为等于目标函数的方程定义中。
2.8模型和求解语句
单词model在GAMS中有明确的含义。
它只是方程的集合。
与其它GAMS实体相同,它必须在声明中给定一个名称。
声明的格式是关键词model后紧随模型的名称,而后出现的是包含在斜杠中一列方程名称。
如果所有前面定义的方程都被包括在模型中,你可输入/all/替代明确的列表。
在我们的例子中,只有一个model语句:
定义域被忽略,因为它们不是方程名称的一部分。
当现存方程的一个子集能够组成一个具体的模型(或子模型)时,列表选项才被使用。
一旦模型被声明并赋予方程,我们就能调用求解模块。
这可通过求解语句来实现,在我们的例子中写成:
求解语句的格式如下:
1.关键词solve
2.要求解的模型名称
3.关键词using
4.可用的求解程序。
完整的清单如下:
5.关键词‘minimizing’或‘maximizing’
6.用于优化的变量名称
2.9显示语句
Solve语句被执行的时候会发生几个事情。
我们感兴趣的具体程序将被生成,将这个问题输入给求解模块的适当的数据结构也将被创建,求解模块将被调用,求解的输出将被打印到一个文件中。
为了得到基本变量或双元变量的最优值,我们可以查看求解模块的输出,或者,如果我们愿意,也可以要求显示这些GAMS的输出。
我们的例子包含如下语句:
它要求打印输出运输变量x(i,j)最后的水平值x.l和边际值x.m。
GAMS将以适当标题的多维表格自动编排打印输出的格式。
2.10.lo,.l,.up,.m数据库
GAMS带有一个小型数据库系统,其中保留了变量和方程的记录。
每个记录中最重要的域是:
引用这些数字的格式是变量名或者方程名称后面跟域名,然后再跟必要的定义域(或者是定义域中的一个元素)。
GAMS允许用户读取或写入数据库。
现在,这对你来说可能看起来不寻常,但它对高级用户而言是一个非常好用特性。
下面将给出使用这个数据库的例子。
2.10.1变量边界和初始值的赋值
变量的下界和上界会根据变量类型自动设置(free,positive,negative,binary或integer),但这些边界可由GAMS用户重写。
以下是一些例子:
在第一个和第三个例子中,我们假设capacity(i,j)是前面声明和赋值过的参数。
这些语句必须出现在变量声明之后,solve语句之前。
所有直接赋值可用的数学表达式也可用于等式右边。
在非线性程序设计中,建模者给求解模块设定一个下界和上界之间尽可能狭小的范围是非常重要的。
同时,设定求解模块寻找最优解的初始解也是非常有帮助的。
例如,在有限制的存货模型中,变量是quantity(i),我们知道该问题的无限制最优解是参数eoq(i),作为对有限制的问题的最优解的猜测,我们输入:
(默认的初始水平是零,除非零不在边界范围内,这种情况下默认值是最接近于零的边界)
要理解的重要一点是:
.lo和.up域是完全由GAMS用户控制的,相反,.l和.m域能被用户初始化,然后由求解模块控制。
2.10.2最优值的转化和显示
(本节对初学者可跳过)
优化程序通过solve语句调用后,它为基本变量和二元变量计算的值就被储存在.l和.m域数据库中。
我们可以读取这些结果,采用GAMS语句进行转化和显示。
例如,在运输模型中,假设我们想要知道每个工厂所占的市场需求份额。
在求解语句之后,我们可以输入:
将这个命令附加到原先运输问题的输入中,得到如下输出:
对包含边际值的例子,我们简短地考虑经常出现在配料问题和精练问题中比例限制(ratioconstraints)。
这些线性规划模型关注的问题是:
如何决定几种可变原料中每种原料投入到每个最终产品的最优数量。
令变量y(i,j)是原材料i投入到最终产片j中吨数。
假设比例限制是最终产品中包含一种原料的最高比例是25%,也即:
对所有的i,j。
为了保证模型是线性的,限制式可以写成:
而不是直接写成比例形式。
这里的问题是ratio.m(i,j),也即与线性形式的限制式相连的边际值是没有内在含义的。
在最优点,它告诉我们放松下面的线性限制,最多能获利多少:
不幸的是,这个放松的限制式没有实际意义。
我们感兴趣的放松(或缩紧)的限制式是比例限制的非线性形式。
例如,我们想要知道可能是将比例限制改到如下形式时,能得到边际收益:
事实上,我们能够得到想要的边际值,通过输入如下转化:
应该注意的是amr的赋值语句从数据库中读取.m和.l记录。
转化背后的思想是注意到:
等价于:
2.11GAMS输出
GAMS运行的默认输出是非常全面的,信息容量很大。
全面的讨论可见第10章。
本指南仅讨论如下输出中的一部分:
一些没必要的担忧由教科书和用户手册引起,它们给读者错误的印象,认为高级软件的运用对每个用户来说应该绝对简单。
GAMS的设计中,理解到即使是最熟练的用户也会犯错,因此,GAMS试图尽可能的发现错误,最小化它们带来的后果。
2.11.1复写
不管错误是否让你的优化问题无法求解,GAMS运行输出的第一个部分是你输入文件的复写。
出于后面引用的缘故,GAMS在复写的左边写出了行数。
对于我们的运输例子,很幸运它没有包含错误,复写如下:
复写从第3行而不是从第1行开始的原因是输入文件包括dollar-print-control语句。
这类型的工具控制了输出打印,但因为它与优化模型的定义无关,在复写中它被忽略了。
Dollar打印控制必须开始于第1列。
$title语句引起其后的文本在输出的每页上被打印出来。
$offupper语句是必要的,以让复写包含混合大小写。
其它可用的工具可见附录D。
2.11.2错误信息
当GAMS编辑器在输出文件中碰到错误的时候,它会插入在程序复写中错误出现的行后面插入一个编码的错误信息。
这些信息通常以****开始,包含一个$符号于编辑器认为出现错误的地方的下面。
$后面是数字错误代码,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- GAMS 用户手册 中文翻译 215