1、目录第二章 GAMS指南22.1 引言22.2 GAMS模型的结构42.3 集合62.4 数据72.4.1 清单数据输入72.4.2 表格数据输入82.4.3 直接赋值数据输入82.5 变量92.6 方程102.6.1 方程声明102.6.2 GAMS的求和符号(乘积符号)112.6.3 方程定义112.7 目标函数132.8 模型和求解语句132.9 显示语句142.10 .lo,.l,.up,.m数据库142.10.1 变量边界和初始值的赋值142.10.2 最优值的转化和显示152.11 GAMS输出162.11.1 复写162.11.2 错误信息182.11.3 引用地图202.11.
2、4 方程清单212.11.5 模型统计数据222.11.6 状态报告222.11.7 解报告232.12 总结24第三章 GAMS 程序263.1 引言263.2 GAMS程序的结构263.2.1 GAMS输入的格式263.2.2 GAMS语句的分类273.2.3 GAMS程序的组织273.3 数据类型和定义283.4 语言项293.4.1 字符293.4.2 保留词293.4.3 标识符(Identifiers)303.4.4 标签303.4.5 文本313.4.6 数字313.4.7 分隔符323.4.8 注释323.5 小结33第四章 集合定义344.1 引言344.2 简单集合344.
3、2.1 语法344.2.2 集合名称344.2.3 集合元素354.2.4 相关文本364.2.5 作为集合元素的序列364.2.6多集合声明374.3 别名语句:一个集合多个名称374.4 子集合和定义域检查384.5 多维集合394.5.1 一对一映射394.5.2 多对多映射404.6 小结41第五章 数据输入:参数,标量和表格425.1 引言425.2 标量425.2.1 语法425.2.2 例子425.3 参数435.3.1 语法435.3.2 例子435.3.3 高维数据参数445.4 表格445.4.1 语法455.4.2 例子455.4.3 续表465.4.4 超过两维的表格4
4、65.4.5浓缩表格475.4.6 处理长行表格485.5 Acronyms485.5.1 语法485.5.2 示例495.6 小结49第六章参数的数据处理506.1 引言506.2 赋值语句506.2.1 标量赋值506.2.2 指数化赋值506.2.3 在赋值中直接采用标签516.2.4 子集上的赋值516.2.5 控制指数的相关问题516.2.6 赋值中扩展值域的标识符526.2.7 赋值中的Acronyms526.3 表达式526.3.1 标准算术运算526.3.2 指数化运算536.3.3 函数546.3.4 扩展值域算法和错误处理556.4 小结56第七章 变量577.1 引言57
5、7.2 变量声明577.2.1 语法577.2.2 变量类型587.2.3变量声明的方式587.3 变量属性597.3.1 变量的边界597.3.2 定值变量597.3.3 变量的活动水平607.4 显示语句和赋值语句中的变量607.4.1 对变量属性进行赋值607.4.2 赋值语句中的变量属性607.4.3 显示变量属性617.5 小结62第八章 方程638.1 引言638.2 方程声明638.2.1 语法638.2.2 例子638.3 方程定义648.3.1 语法648.3.2 例子648.3.3 标量方程658.3.4 指数化方程658.3.5 在方程中明确使用标签658.4 方程定义中
6、的表达式668.4.1 方程定义中的算术算子668.4.2 方程定义中的函数668.4.3 避免方程中的无定义操作678.5 方程的数据处理问题67第九章 模型和求解语句699.1 引言699.2 模型语句699.2.1 语法699.2.2 模型的分类709.2.3 模型属性709.3 求解语句719.3.1 语法729.3.2 合法求解语句的要求729.3.3 求解语句触发的行动729.4 多个求解语句的程序739.4.1 几个模型739.4.2 敏感性分析和场景分析739.4.3 非标准算法的迭代执行749.5 让GAMS获得新的求解模块75第十章 GAMS输出7610.1 引言7610.
7、2 示例模型7610.3 编辑输出7710.3.1 输入文件的复写7710.3.2 符号引用地图7910.3.3 符号清单地图8010.3.4 单元素清单地图8110.3.5 实用的dollar($)控制指令8210.4 执行输出8210.5 求解语句生成的输出8310.5.1 方程清单8310.5.2 列清单8410.5.3 模型统计数据8510.5.4 求解摘要8610.5.5 求解模块报告8910.5.6 解清单8910.5.7 报告摘要9110.5.8 文件概要9110.6 错误报告9110.6.1 编辑错误9210.6.2 编辑时间错误9310.6.3 执行错误9410.6.4 求解
8、错误9410.7 小结95第十一章 条件表达式,赋值和方程9611.1 引言9611.2 逻辑条件9611.2.1 作为逻辑条件的数值表达式9611.2.2 数值关系算子9611.2.3 逻辑算子9711.2.4 集合元素9711.2.5 包含Acronyms的逻辑条件9711.2.6 逻辑条件的数值9811.2.7 混合逻辑条件算子优先顺序9811.2.8 混合逻辑条件例子9911.3 Dollar条件9911.3.1 例子9911.3.2 嵌套dollar条件9911.4 条件赋值10011.4.1 dollar置于赋值语句左边10011.4.2 dollar置于赋值语句右边10111.4
9、.3 在指数化运算中过滤控制指数10111.4.4 过滤赋值语句中的集合10211.5 条件指数化运算10311.5.1 在指数化运算中过滤控制指数10411.6 条件方程10511.6.1 代数表达式中的dollar算子10511.6.2 定义域的dollar控制10511.6.3 过滤定义域106第十二章 动态集合10712.1 引言10711.2 动态集合的元素赋值10711.2.1 语法10711.2.2 例子10712.2.3 多指数动态集合10811.2.4 动态集合定义域上赋值语句10812.2.5 定义在动态集合定义域上的方程10812.3 使用带有动态集合的dollar控制1
10、0912.3.1 赋值10912.3.2 指数化运算10912.3.3 方程11012.3.4 通过动态集合过滤11012.4 集合运算11112.4.1 并集11112.4.2 交集11112.4.3 补集11112.4.4 差集11112.5 小结112第十三章 作为序列的集合:有序集合11313.1 引言11313.2 有序和无序集合11313.3 ord和card11413.3.1 ord算子11413.3.2 Card算子11513.4 lag和lead算子11513.5 赋值语句中的lags和leads11613.5.1 线性lag和lead算子引用11613.5.2 线性lag和
11、lead算子赋值11613.5.3 循环lag和lead算子11713.6 方程中的lags和leads11813.6.1 线性lag和lead算子定义域控制11813.6.2 线性lag和lead算子引用11913.6.3 循环lag和lead算子11913.7 小结120第十四章 显示语句12114.1 引言12114.2 语法12114.3 例子12114.4 显示语句中的标签顺序12214.4.1 例子12314.5 显示控制12414.5.1 全局显示控制12414.5.2 局部显示控制12414.5.3 生成列表格式数据的显示语句125第十五章 put书写工具12715.1 引言1
12、2715.2 语法12715.3 例子12715.4 输出文件12915.4.1 定义文件12915.4.2 赋值文件13015.4.3 关闭文件13015.4.4 添加内容到文件13015.5 页面格式13115.6 页面区域13215.6.1 访问不同的页面区域13215.5.2 分页13315.7 定位页面指针13315.8 系统后缀13315.9 输出项13415.9.1 文本项13415.9.2 数字项13515.9.3 集合值项13615.10 全局输出项格式13615.10.1 字段对齐13615.10.2 字段宽度13615.11 局部输出项格式13715.12 额外的数字显示
13、控制13715.12.1 例子13815.13 指针控制13915.13.1 当前指针列13915.13.2 当前指针行14015.13.3 末行控制14015.14 分页控制14115.15 例外处理14115.16 与put语句相关的错误来源14115.16.1 语法错误14115.16.2 put错误14215.17 简单的电子数据表/数据库应用14215.17.1 例子142第二章 GAMS指南2.1 引言本书的介绍部分将给出一个详细的例子,介绍如何使用GAMS来描述、求解和分析一个简单的小型优化问题。加利福尼亚州蒙特里海军研究院的Richard E.Rosenthal写了这个指南。这
14、个例子对GAMS及其特性给出了一个快速但全面的概述。许多内容可参考书本的其它部分,但它们仅仅是告诉你要去哪里寻找更详细的细节。这里的材料在不参考书本其余部分的情况下,单独阅读也能带来诸多益处。例子是一个线性规划的运输问题,在优化技术的发展历史中,它充当了“试验动物”的角色。(例如,见Dantzig,1963)。这是用来说明像GAMS这样的代数建模语言的强大功能的一个很好选择,因为运输问题,不管多复杂,它都拥有一个简单的,可利用的代数结构。你将看到如果要考虑一个更大的运输问题,我们要给出的GAMS输入文件中几乎所有的语句都将保持不便。在这个大家熟悉的运输问题中,我们给定几个厂商和几个市场对单一商
15、品的供给和需求,同时给定将商品从工厂运到市场的单位运输成本。经济问题是:应该从每个工厂向每个市场运输多少,才能最小化总的运输成本。这个问题的代数表达式通常以与下列相同的格式给出:指数: 工厂 市场给定数据: 工厂i的商品供给(cases) 市场j的商品需求 工厂i到市场j之间的单位运输成本($/case)决策变量: =从工厂i向市场j运输的商品数量(case) 其中,for all i,j约束条件:工厂i的供给限制: for all i (cases) 满足市场j的需求: for all j (cases)目标函数: ($K)值得注意的是这个简单的例子揭示了一些我们一般认为是好习惯的建模惯例,
16、它与GAMS的设计是一致的。首先,模型的所有实体是通过类型识别(和分组)的。其次,实体顺序的选择应该使得符号在被定义之前没有被引用到。第三,所有实体单位是详细设定的。第四,单位被选择为一定度量比例,它使得优化程序碰到的数字有相对小的绝对数量级。(这里,符号$K表示千美元)。实体类型的名称对不同建模者可能不同。例如,经济学家使用外生变量和内生变量这两个术语来分别表示给定的数据和决策变量。在GAMS中,采用的术语如下:指数被称为集合(sets),给定数据被称为参数(parameters),决策变量被称为变量(variables),限制条件和目标函数被称为方程(equations)。运输问题的GAM
17、S表达式几乎与上面的代数表达式相同。但是,最重要的不同之处在于GAMS版本能够由计算机阅读并执行。表2.1 运输问题的数据(改编自Dantzig,1963)作为运输问题的一个例子,假设有两个罐头厂和三个市场,数据在表2.1中给出。运输距离用千英里表示,运输成本假设为每case每千英里$90.00。这个问题的GAMS表达式如下:如果你将包含上述语句的文件作为GAMS程序的输入文件,那么这个运输模型将被读取并求解。细节将根据在不同计算机上如何调用GAMS而有所不同,但是,调用GAMS的最简单的(不带任何虚饰)方式是在输入文件名之前输入单词GAMS。你将看到许多简洁的行,它描述了GAMS的进展情况,
18、包括输出被写入的文件的名称。当GAMS完成之后,检查这个文件,如果运行良好,那么最优的运输量将显示在其底部,结果如下:你也将得到如下边际成本(单纯形乘子):这些结果表明,从Seattle到Topeka的最优运输量是零,但如果你坚持要运输一单位的话,最优成本将增加$0.036$K(也即$36.00)。(你能从最优运输量和给定数据证明这个数字是正确的吗?)2.2 GAMS模型的结构在这个指南的剩余部分中,我们将以上述的例子作为参考讨论GAMS模型的基本成分。基本成分列在表2.2中。表2.2 GAMS模型的基本成分.GAMS模型中存在可选的输入成分,如错误数据的编辑检查和结果的定制报告要求。其它可选
19、的高级特征包括存储和恢复旧模型,在一次运行中生成多个模型等,但该指南只讨论基本成分。在处理单个成分之前,我们给出几个综合的注释。1 GAMS模型是用GAMS语言书写的语句集合。控制语句顺序的唯一规则是模型实体不能在其被声明存在之前被引用;2 GAMS语句能够以用户喜好的几乎任何方式来进行编排。一个语句存在于多行,植入空白行以及一行存在多个语句都是可行的。你将从该指南的例子中得到什么是被允许的概念,但其准确的规则将在下一章给出。3 如果你是GAMS的初级用户,那么你应该用分号终止每个语句,如同本例一样。GAMS编辑器不区分大小写字母,因此你能够自由使用大小写中任一种。4 注释对数学模型的有效性是
20、至关重要的。如果注释被植入模型本身,而不是分开书写,那么它将更加有用(也更加精确)。至少存在两种方式在GAMS模型中插入注释。首先,任何在第一列以星号开始的行都被GAMS编辑器认为是注释行。第二,也许是更重要的一点,解释性文本能够插入到具体的GAMS语句之中。运输模型中所有的小写单词是第二种文件形式的例子。5 正如你从上面输入成分列表中看到的,GAMS实体的创建包含两个步骤:声明(declaration)和赋值(assignment)或定义(definition)。声明意味着宣布某些东西的存在,并给其一个名称。赋值或定义意味着给这些东西一个具体的值或具体的形式。在方程中,你必须在单独的GAMS
21、语句中进行声明和定义。然而,对于所有的GAMS实体,你可以选择在同一个语句中,或在不同的语句中进行声明和赋值。6 给模型实体的名称必须以字母开头,后面跟随最多为30个的字母或数字。2.3 集合集合(sets)是GAMS模型的基本建筑模块,它对应于模型算术表达式中的指数。上面的运输模型仅包含一个集合语句:语句是能够自我解释的。我们声明了两个集合,起名为i和j,同时对集合赋予如下元素:你必须注意GAMS格式和常用的数学格式之间在罗列集合元素上的差别。GAMS采用斜杠“/”,而不是大括号“”来描绘集合,这仅仅是因为并非所有的计算机键盘都有大括号键。应该注意的还有多单词名称,如New York是不允许
22、的,因此必须插入连字符号。上述集合语句中的小写单词称为文本(text)。文本是可选的。它仅为了内部说明而存在,在模型中没有正式的目的。GAMS编辑器并不试图解释这些文本,而是储存这些文本,并在你觉得方便的时候把它复制给你。并没有必要将集合i和集合j的创建放在同一个语句中。我们可将它们放到如下分开的语句中:空格和空行的布置(以及大小写的选择)取决于你的偏好。每个GAMS用户往往使用自己格式上的习惯。(单数set的使用也取决于你自己,在一个进行单一声明的语句中使用set,和在一个进行多个声明的语句中使用sets仅是英语好的表现,但单数和复数对GAMS而言是相同的。)当你对一个集合赋予元素的时候,可
23、采用一个方便的特性,即使用星号。这在元素是一个序列的情况下使用。例如,下列是GAMS中的合法set语句。这里结果是赋值:应该注意的是集合元素是作为字符串进行存储的,因为t的元素不是数字。另一个方便的特性是alias语句,它用于给前面声明的集合起另外一个名称。看下面例子:名称tp就像在数学符号中的t。在相同集合中的元素之间存在相互联系的模型中,这个语句是非常有用的。上述语句中集合i,j,t和m是静态集合的例子,也即,这些集合的元素直接由用户赋值,并且不再改变。GAMS有几种创建动态集合的功能,它要求集合的元素在集合理论和逻辑运算的执行中是可变的。动态集合将在第12章讨论。另一个有价值的高级特性是
24、多维集合,这将在4.5节讨论。2.4 数据这个运输问题的GAMS模型说明了所有三种允许用于输入数据的基本格式。这三种格式是:下面三个小节将依次讨论每种格式。2.4.1 清单数据输入第一种格式可由例子的第一个parameters语句说明,它表示如下:这个语句有多个结果。再次,它也是能自我解释的,但详细分析它们是值得的。这个语句声明两个参数的存在,并给定名称a和b,宣布它们的定义域分别为i和j(定义域是这样一个集合或一组集合:参数,变量或方程被定义在这个或这些集合上)。这个语句也给出了每个参数对应的解释性文本,并赋值给i和j中每个元素对应的参数a(i)和b(j)。如果你喜欢的话,也完全可以将这个语
25、句分成如下两个语句:在采用list格式时应该记住的几点:1 定义域元素及其各自参数值的罗列可采用任何你喜欢的形式。唯一的规则是整个列表必须在斜杠之中,元素值对必须由逗号分开,或在不同行输入。2 元素值列表之前的名称,定义域和文本与元素值列表之间不用分号分开。这是因为当你使用list格式的时候,相同的语句被用于声明和赋值。(元素值列表本身是无法被GAMS解释的,这将导致一个错误信息。)3 GAMS编辑器有一个非常有用的特性,称为定义域检查,它保证列表中的每个定义域元素在实际中是引用集合的元素。例如,如果你在声明集合i的语句中正确地拼写了Seattle,而在随后的元素值列表中拼错为Seatle,那
26、么GAMS编辑器将给出一个错误信息,说明元素Seatle并不属于集合i。4 零是所有参数的默认值。因此,你只要将非零的参数输入元素值列表中即可,而且可以以任何方式输入。5 常数被认为是没有定义域的参数,用Scalar语句进行声明和赋值,它包含只有一个值的退化的列表,参见如下运输模型中的语句:如果参数的定义域有两个或更多维度,它仍然可采用list格式输入数据。这在输入稀疏数组(几乎没有非零值)和超稀疏数组(几乎没有区别于零的非零值)的时候非常有用。2.4.2 表格数据输入在某些时候,大模型的许多输入数据可从相对较小的数字表中推导而得。这样,拥有表格形式的数据输入就非常有用。一个两维表格(矩阵)的
27、例子可由上述运输模型提供:这个语句的结果是声明参数d,并将其定义域设定为由i和j的笛卡儿积形成的有序对集合。在适当的标题下,这个语句也给出了d的值。如果在表格中有空格输入,那么它们被理解为零。与list格式相同,GAMS将进行定义域检查以确保表格的行和列的名称是所用集合的元素。输入无法在一行中实现的多列表格以及输入两维以上的表格的格式将在第5章讨论。2.4.3 直接赋值数据输入数据输入的直接赋值方式与列表(list)方式和表格(table)方式的不同之处在于,它将参数声明和参数赋值分开到不同语句中。运输模型包含了这种赋值方式:应该强调的是在第一行的末尾出现了分号。没有这个分号,GAMS编辑器将
28、试图将这两行视为一个相同的语句。(GAMS将无法识别一个正确的解释,因此它会给你一个简洁但非常有帮助的错误信息。)上面的第一个语句是要声明参数c,设定定义域(i,j),并给出一些解释性文本。第二个语句赋值给c(i,j),令其值为参数f和d(i,j)的乘积。很自然,在GAMS中,只有你已经在前面的语句中赋值给f和d(i,j),这个语句才是合法的。上面的直接赋值适用于定义域c中的所有(i,j)对。如果你要对定义域中的具体元素进行赋值,你可用引号将元素名称括起来。例如:这是一个合法的GAMS赋值语句。同一个参数可赋值多次。每个赋值语句马上生效,并覆盖任何前面的值。(相反,相同的参数不能声明超过一次。
29、这是GAMS的一个错误检查方式,以保证你不会对两个不同的事物使用相同的名称。)赋值语句的右边可以包含各种数学表达式以及内嵌的函数。如果你熟悉程序设计语言如FORTRAN或C语言,那么你将会很适应在GAMS中书写赋值语句。(但是,记住GAMS有很多FORTRAN和C语言所没有的高效率的地方,例如,我们可以在不构建do loops结构的情况下,对所有(i,j)赋值给c(i,j))。GAMS标准的运算函数将在后面介绍。这里是一些合法的赋值语句。所有情况下,我们都假设左边的参数已经被声明过,右边参数已经在前面的语句中赋值过。后面要介绍的求和算子和乘积算子也可用于直接赋值中。2.5 变量用GAMS表示的
30、模型的决策变量(或说是内生变量)必须采用Variables语句声明。每个变量给定一个名称,一个定义域(如果需要的话)和文本。运输模型包含了如下varialbles语句:这个语句声明了与每个(i,j)对应的运输变量。(你将在第8章看到GAMS是如何处理这种典型的现实情况的,也即只有(i,j)的一个子集在运输中是被允许的。)Z变量的声明不带定义域,因为这是一个标量。每个GAMS优化模型必须包含这样一个变量作为被最小化或最大化的量。一旦被声明,每个变量就必须赋予一个类型。允许的类型在表2.3中给出。表2.3 允许的变量类型作为优化目标的变量必须是标量,并且为free类型。在我们的运输模型中,z处于默
31、认的free类型下,但x(i,j)通过如下语句被限制为非负:应该注意的是x的定义域在类型赋值中不能重复。定义域中的所有输入自动有相同的变量类型。2.10节将描述如何给变量赋予下边界,上边界和初始值。2.6 方程GAMS代数建模语言的强大功能在方程以及包含在所构建模型中限制不等式的构建中体现的淋漓尽致。这是因为只要一组方程或不等式有相同的代数结构,这个组中的所有方程或限制式都能同时构建,而不用单独构建。2.6.1 方程声明方程必须在分开的语句中进行声明和定义。声明的格式与GAMS其它实体一样。首先是关键字Equations,而后是要声明的一组或多组方程或不等式的名称,定义域和文本。我们的运输模型
32、中包含下列方程声明:记住单词Equation在GAMS中有非常广阔的意思。它包含等式和不等式关系,单一名称的GAMS方程能指向一个或多个这些关系。例如,cost没有定义域,因此它是单个方程。但supply却指向定义在定义域i上的一组不等式。2.6.2 GAMS的求和符号(乘积符号)在说明方程定义之前,我们描述GAMS中的求和符号。记住GAMS是为标准键盘和逐行输入阅读设计的,因此不可能(它对用户来说,也不方便)使用标准的数学符号来进行求和。GAMS中的求和符号可用于单一或复合表达式。这个格式是基于通常的概念建立的,也即求和是对两个变量的算子:sum(index of summation, su
33、mmand)。一个逗号格开了两个变量,如果第一个变量需要有一个逗号,那么它必须用括号括起来。第二个变量可以是任何数学表达式,甚至可以包含另一个求和算子。作为一个例子,运输问题包含了如下表达式:这等价于。一个稍微复杂一点的求和用于如下例子:这等价于。最后一个表达式也能够写成如下一个嵌套式的求和:11.3节中,我们将描述如何使用dollar算子对求和算子施加限制,使得满足具体条件的i和j中的元素包含在求和中。GAMS中乘积的定义使用的是与求和完全相同的格式,将sum换成prod即可。例如:这等价于:求和算子和乘积算子可用于参数的直接赋值语句中。例如:2.6.3 方程定义由于其多样性,方程定义是GA
34、MS中最复杂的语句。方程定义的成分,按顺序包括:1 被定义方程的名称2 定义域3 定义域限制条件(可选的)4 符号.5 左边表达式6 关系算子:=l=,=e=,=g=7 右边表达式运输例子包含三个语句:以下是要记住的几点: 采用一个GAMS语句创建多个方程的能力是由定义域控制的。例如,demand限制式的定义将导致对定义域上每个元素创建一个限制式,如下从GAMS输出中的摘录所示: 这里的主要思想是:不论我们是在求解上面的小型例子,还是在求解有20000个节点的实际问题,GAMS所需的限制式是完全相同的。每种情况下,用户只要输入一个普通的代数方程表达式,然后GAMS就创建了适用于手上例子的具体方
35、程(使用一些其它的优化包,上面的摘录将成为输入的一部分,而不是输出的一部分。) 许多实际问题中,由于存在某种例外,一些方程定义域中的元素必须被忽略,或者必须区别于其它方程。GAMS能够方便地调节这种结构上的缺失,通过使用一个称为dollar或“such-that”算子的强大特征来实现,这个特征在这里不进行讨论。定义域限制特征是绝对必要的,它用于将实际模型的大小保持在可解的范围内。 关系算子有如下含义: 理解=和=e=之间的区别是非常重要的。=符号仅用于直接赋值中,而=e=仅用于方程定义。这两者是完全不同的。直接赋值是在求解之前给参数赋值。方程定义也描述一个关系式,但必须在求解的时候才能得到满足
36、。因此,方程定义必须包含变量,而直接赋值不能包含变量。 变量可以出现在方程的左边或右边,或者在两边同时出现。相同的变量可在一个方程中出现不止一次。在被求解之前,GAMS处理器将自动将方程转化成与它等价的标准形式(变量在左边,不重复出现)。 方程定义可以出现在GAMS输入的任何地方,给定方程以及方程所指的所有变量和参数都在前面定义过。(值得注意的是方程中出现的变量在定义之后进行赋值或重新赋值都是允许的。这在以一个GAMS输入执行多个模型的时候非常有用)。方程不需要以与它们声明顺序相同的顺序进行定义。2.7 目标函数这里仅作一种提示,说明GAMS中没有称为目标函数的明确实体。为了设定被优化的函数,
37、你必须创建一个变量,它是free类型的(没有符号限制),同时是标量值(没有定义域),它出现在将它设定为等于目标函数的方程定义中。2.8 模型和求解语句单词model在GAMS中有明确的含义。它只是方程的集合。与其它GAMS实体相同,它必须在声明中给定一个名称。声明的格式是关键词model后紧随模型的名称,而后出现的是包含在斜杠中一列方程名称。如果所有前面定义的方程都被包括在模型中,你可输入/all/替代明确的列表。在我们的例子中,只有一个model语句:定义域被忽略,因为它们不是方程名称的一部分。当现存方程的一个子集能够组成一个具体的模型(或子模型)时,列表选项才被使用。一旦模型被声明并赋予方
38、程,我们就能调用求解模块。这可通过求解语句来实现,在我们的例子中写成:求解语句的格式如下:1 关键词solve2 要求解的模型名称3 关键词using4 可用的求解程序。完整的清单如下:5 关键词minimizing或maximizing6 用于优化的变量名称2.9 显示语句Solve语句被执行的时候会发生几个事情。我们感兴趣的具体程序将被生成,将这个问题输入给求解模块的适当的数据结构也将被创建,求解模块将被调用,求解的输出将被打印到一个文件中。为了得到基本变量或双元变量的最优值,我们可以查看求解模块的输出,或者,如果我们愿意,也可以要求显示这些GAMS的输出。我们的例子包含如下语句:它要求打
39、印输出运输变量x(i,j)最后的水平值x.l和边际值x.m。GAMS将以适当标题的多维表格自动编排打印输出的格式。2.10 .lo,.l,.up,.m数据库GAMS带有一个小型数据库系统,其中保留了变量和方程的记录。每个记录中最重要的域是:引用这些数字的格式是变量名或者方程名称后面跟域名,然后再跟必要的定义域(或者是定义域中的一个元素)。GAMS允许用户读取或写入数据库。现在,这对你来说可能看起来不寻常,但它对高级用户而言是一个非常好用特性。下面将给出使用这个数据库的例子。2.10.1 变量边界和初始值的赋值变量的下界和上界会根据变量类型自动设置(free,positive,negative,
40、binary或integer),但这些边界可由GAMS用户重写。以下是一些例子:在第一个和第三个例子中,我们假设capacity(i,j)是前面声明和赋值过的参数。这些语句必须出现在变量声明之后,solve语句之前。所有直接赋值可用的数学表达式也可用于等式右边。在非线性程序设计中,建模者给求解模块设定一个下界和上界之间尽可能狭小的范围是非常重要的。同时,设定求解模块寻找最优解的初始解也是非常有帮助的。例如,在有限制的存货模型中,变量是quantity(i),我们知道该问题的无限制最优解是参数eoq(i),作为对有限制的问题的最优解的猜测,我们输入:(默认的初始水平是零,除非零不在边界范围内,这
41、种情况下默认值是最接近于零的边界)要理解的重要一点是:.lo和.up域是完全由GAMS用户控制的,相反,.l和.m域能被用户初始化,然后由求解模块控制。2.10.2 最优值的转化和显示(本节对初学者可跳过)优化程序通过solve语句调用后,它为基本变量和二元变量计算的值就被储存在.l和.m域数据库中。我们可以读取这些结果,采用GAMS语句进行转化和显示。例如,在运输模型中,假设我们想要知道每个工厂所占的市场需求份额。在求解语句之后,我们可以输入:将这个命令附加到原先运输问题的输入中,得到如下输出:对包含边际值的例子,我们简短地考虑经常出现在配料问题和精练问题中比例限制(ratio constr
42、aints)。这些线性规划模型关注的问题是:如何决定几种可变原料中每种原料投入到每个最终产品的最优数量。令变量y(i,j)是原材料i投入到最终产片j中吨数。假设比例限制是最终产品中包含一种原料的最高比例是25%,也即:对所有的i,j。为了保证模型是线性的,限制式可以写成:而不是直接写成比例形式。这里的问题是ratio.m(i,j),也即与线性形式的限制式相连的边际值是没有内在含义的。在最优点,它告诉我们放松下面的线性限制,最多能获利多少:不幸的是,这个放松的限制式没有实际意义。我们感兴趣的放松(或缩紧)的限制式是比例限制的非线性形式。例如,我们想要知道可能是将比例限制改到如下形式时,能得到边际
43、收益:事实上,我们能够得到想要的边际值,通过输入如下转化:应该注意的是amr的赋值语句从数据库中读取.m和.l记录。转化背后的思想是注意到:等价于:2.11 GAMS输出GAMS运行的默认输出是非常全面的,信息容量很大。全面的讨论可见第10章。本指南仅讨论如下输出中的一部分:一些没必要的担忧由教科书和用户手册引起,它们给读者错误的印象,认为高级软件的运用对每个用户来说应该绝对简单。GAMS的设计中,理解到即使是最熟练的用户也会犯错,因此,GAMS试图尽可能的发现错误,最小化它们带来的后果。2.11.1 复写不管错误是否让你的优化问题无法求解,GAMS运行输出的第一个部分是你输入文件的复写。出于
44、后面引用的缘故,GAMS在复写的左边写出了行数。对于我们的运输例子,很幸运它没有包含错误,复写如下:复写从第3行而不是从第1行开始的原因是输入文件包括dollar-print-control语句。这类型的工具控制了输出打印,但因为它与优化模型的定义无关,在复写中它被忽略了。Dollar打印控制必须开始于第1列。$title语句引起其后的文本在输出的每页上被打印出来。$offupper语句是必要的,以让复写包含混合大小写。其它可用的工具可见附录D。2.11.2 错误信息当GAMS编辑器在输出文件中碰到错误的时候,它会插入在程序复写中错误出现的行后面插入一个编码的错误信息。这些信息通常以*开始,包含一个$符号于编辑器认为出现错误的地方的下面。$后面是数字错误代码,它在复写之后被解释。几个例子如下:例1:输入如下语句得到如下复写结果:在这个例子中,GAMS编辑器指出集合元素sum出错了。在复写的下面,我们可以看到对错误代码160的解释:这里的问题是sum是表示求和的保留词,因此我们的集合元素必须有一个唯一的名称如“summer”。这是初学者常见的错误。下一章会给出保留词的完整列表。例2:另一个常见的错误是在直接赋值或方程定义之前忽略分号。在我们的运输例子中,假设我们忽略了c(i,j)赋值语句前面的分号,如下:结果如下:像忽略分号这样一个小错误生成五个错误信息的情况并不寻常。这里