第 1 行到第 5 行都是注释。# 在一行中不管从什么地方开始,都表示本行到末尾全部是注释。C 风格的注释全都可以使用,如第 7 行所示。它们甚至可以在声明中间使用。
第一个 MathProg 步骤是声明决策变量。第 8 行和第 9 行声明了 x1 和 x2。决策变量的声明以关键字 var 开头。为了简化符号约束(检查不等式 9),MathProg 允许在决策变量声明中使用 >= 0 约束,正如我们在第 8 行和第 9 行中看到的一样。GNU MathProg 中的每条语句都必须以分号(;)结束。记住 x1 表示 soldier 的数量,x2 表示 train 的数量。这些变量应该分别称为 soldiers 和 trains,但是这可能会把读者中的数学界人士搞得混乱不堪。
第 12 行声明了目标函数。线性问题可以是最大化问题,也可以是最小化问题。记住,Giapetto 的数学模型是一个最大化问题,因此我们应该使用 maximize 作为关键字,而不是相反的 minimize 关键字。目标函数称为 z,它等于 3x1 + 2x2。请注意:
:)字符分隔开了目标函数及其定义。 *)字符表示乘法,类似地,加号(+)、减号(-)和斜线(/)字符分别表示加法、减法和除法。 第 15、16、17 行定义了约束。尽管 s.t. 对于声明一个约束来说并不需要在行首,但是这样可以提高代码的可读性。
这三个 Giapetto 约束分别被标记成 Finishing、Carpentry 和 Demand。每个都是作为一个数学模型来声明的。符号 <= 和 >= 表示不等式。不要忘记每个声明末尾的 ;。
每个 GNU MathProg 文件必须要以 end; 结束,正如我们在 19 行看到的一样。
现在,glpsol 可以使用这个文件作为输入。但是请等一下,这个问题的数据部分在什么地方呢?噢,这个问题是如此简单,问题数据都作为声明中决策变量的系数直接包含在了目标函数和约束声明中。举例来说,在目标函数中,系数 3 和 1 就是问题数据集的一部分。当我使用数据集重写这个问题时,大家就可以非常清楚这到底是怎么样工作的。现在,我们不用关心这个问题。
使用 .mod 作为 MathProg 输入文件的扩展名并将答案重定向到一个扩展名为 .sol 的文件中是一个好习惯。不过这并不是必需的要求,您可以使用任何自己喜欢的文件名和扩展名。这个例子中 Giapetto 的 MathProg 文件是 giapetto.mod,输出结果在 giapetto.sol 中。现在,请在自己喜欢的终端中运行 glpsol:
glpsol -m giapetto.mod -o giapetto.sol
这个命令使用了两个 glpsol 选项:
-m 选项告诉 glpsol 输入是使用 GNU MathProg 编写的。 -o 选项告诉 glpsol 将自己的输出结果发送到 giapetto.sol 中。 解答报告现在就在 giapetto.sol 中了,但是有关 GLPK 所消耗的时间和内存信息会显示在标准输出上:
ceron@curly ~ $ glpsol -m giapetto.mod -o giapetto.sol Reading model section from giapetto.real.mod... 19 lines were read Generating z... Generating Finishing... Generating Carpentry... Generating Demand... Model has been successfully generated lpx_simplex: original LP has 4 rows, 2 columns, 7 non-zeros lpx_simplex: presolved LP has 2 rows, 2 columns, 4 non-zeros lpx_adv_basis: size of triangular part = 2 * 0: objval = 0.000000000e+00 infeas = 0.000000000e+00 (0) * 2: objval = 1.400000000e+02 infeas = 0.000000000e+00 (0) OPTIMAL SOLUTION FOUND Time used: 0.0 secs Memory used: 0.1M (151326 bytes) lpx_print_sol: writing LP problem solution to `giapetto.sol'... |
所生成的报告显示 glpsol 会读取这个模型,调用一个 GLPK API 函数来生成目标函数,然后调用另外一个 API 函数来生成约束。在生成模型之后,glpsol 简要地解释了 GLPK 在内部是怎么样对这个问题进行处理的。最后是有关解答和 GLPK 为解答这个问题所消耗的资源的信息,这个解答被明确说明是优化的。
这非常棒,但是决策变量的实际优化值是什么呢?它们都保存在 giapetto.sol 文件中:
清单 3. Giapetto 问题的解答:giapetto.sol
Problem: giapetto
Rows: 4
Columns: 2
Non-zeros: 7
Status: OPTIMAL
Objective: z = 180 (MAXimum)
No. Row name St Activity Lower bound Upper bound Marginal
------ ------------ -- ------------- ------------- ------------- -------------
1 z B 180
2 Finishing NU 100 100 1
3 Carpentry NU 80 80 1
4 Demand B 20 40
No. Column name St Activity Lower bound Upper bound Marginal
------ ------------ -- ------------- ------------- ------------- -------------
1 x1 B 20 0
2 x2 B 60 0
Karush-Kuhn-Tucker optimality conditions:
KKT.PE: max.abs.err. = 0.00e+00 on row 0
max.rel.err. = 0.00e+00 on row 0
High quality
KKT.PB: max.abs.err. = 0.00e+00 on row 0
max.rel.err. = 0.00e+00 on row 0
High quality
KKT.DE: max.abs.err. = 0.00e+00 on column 0
max.rel.err. = 0.00e+00 on column 0
High quality
KKT.DB: max.abs.err. = 0.00e+00 on row 0
max.rel.err. = 0.00e+00 on row 0
High quality
End of output
上一篇:程序员眼中的qmail(qmail源代码分析) 下一篇:用新的PHP插件实现MySQL为基础的事务 更多相关文章
|
推荐文章
精彩文章
|