您的位置:首页 > 编程语言 > Go语言

(转)强大的数学优化建模语言Lingo

2009-02-01 09:32 106 查看
转载点lingo的文章,学习并且收藏,原文中有几处打字错误,这里改正

从本部分介绍lingo的强大的数学优化建模语言。这是他专门为大规模优化建模提供的一套
规范语言,下面介绍简单的例子来说明他的基本组成。
一、原始问题(运输问题):
现在WW(Wireless Widgets)公司拥有6个仓库,向其8个销售商供应它的产品。要求每个
仓库供应不能超量,每个销售商的需求必须得到满足。WW公司需要决策具体的从每个仓库
运输多少产品到每个销售商。以使得所花的运输费用最少?
二、问题的已知数据:
1、产品仓库数据:
仓库编号 产品库存量
1 60
2 55
3 51
4 43
5 41
6 52
2、销售商产品需求:
销售商编号 产品需求量
1 35
2 37
3 22
4 32
5 41
6 32
7 43
8 38
3、每件产品运输费用($):
销售商[右] V1 V2 V3 V4 V5 V6 V7 V8
仓库[下]
Wh1 6 2 6 7 4 2 5 9
Wh2 4 9 5 3 8 5 8 2
Wh3 5 2 1 9 7 4 3 3
Wh4 7 6 7 3 9 2 7 1
Wh5 2 3 9 5 7 2 6 5
Wh6 5 5 2 2 8 1 4 3

步骤:
三、目标函数描述:
线性优化建模的重要一步就是构造目标函数,正如上面提到的,在此问题中,WW 公司欲使总的运输费用最小。
现在令:变量VOLUME_I_J 表示从仓库I到销售商J运送的产品数目。这样我们就可以写出如下的目标函数:
MIN = 6 * VOLUME_1_1 + 2 * VOLUME_1_2 + 6 * VOLUME_1_3 + 7 * VOLUME_1_4 +4 * VOLUME_1_5 +...8 * VOLUME_6_5 + VOLUME_6_6 + 4 * VOLUME_6_7 +3 * VOLUME_6_8;
当然上面是个简写形式。很明显的上面的目标函数如此的冗长,很容易导致输入错误。现实中的情况往往是销售商成千上万个,如果还是使用上述的方法就难以想象了。熟悉规划数学定义的人可以很轻易的用下面的方式表达上述的目标函数:
Minimize SUM(ij)(COST_ij*VOLUME_ij)
LINGO就是采用这种类似的方式来描述规划模型的,比如这个例子的等价的LINGO语句就是:
MIN = @SUM( LINKS(I,J): COST(I,J) * VOLUME(I,J));
总之:LINGO的规划语言很适合熟悉数学的人使用,很自然。上面的@SUM是系统函数,后面会介绍常见系统函数
四、变量约束:
这里有两种约束,第一种是供货约束,第二种是接货约束。例如:对于第一个销售商而言
VOLUME_1_1 + VOLUME_2_1 + VOLUME_3_1 + VOLUME_4_1 + VOLUME_5_1 + VOLUME_6_1 = 35;
如果使用原始的规划语句,要建如类似上面的语句8次呢: (有了建模语言就方便了:
@FOR( VENDORS( J ) : @SUM( WAREHOUSES( I ) : VOLUME( I, J)) = DEMAND( J));
类似的:
@FOR( WAREHOUSES( I ) : @SUM( VENDORS( J ) : VOLUME( I, J))<= CAPACITY( I));
好了,到此为止我们的模型就建起来了:
MODEL:
MIN = @SUM( LINKS( I, J):
COST( I, J) * VOLUME( I, J));
@FOR( VENDORS( J):
@SUM( WAREHOUSES( I): VOLUME( I, J)) =
DEMAND( J));
@FOR( WAREHOUSES( I):
@SUM( VENDORS( J): VOLUME( I, J)) <=
CAPACITY( I));
END
注释:从上面可以看出一个LINGO模型必须包含在MODEL/END中间,然后在中间依次给出目标函数,约束条件等。
但是我们的数据该如何给出呢?也就是解决LINGO建模语言中的赋值问题

五、定义变量集合:
我们要处理的实际建模问题中经常会遇到一类同样的问题:若干相关的对象集合。比如:工厂集合、客户集合、车辆集合和雇员集合等等。通常我们希望:约束某个集合中的特定对象的条件也同样适用于同一集合内其他的对象。这恰好是LINGO建模语言的最基本的概念。LINGO允许在SETS段定义某些相关对象于同一个集合内。集合段以关键字SETS开始;以关键字ENDSETS结束。一旦你定义了集合,LINGO可以提供大量的集合循环函数(例如:@FOR), 通过简单的调用他们的语句就可以操作集合内的所有元素。我们回到最初的例子:Wireless Widget 模型,定义如下的三个集合:
仓库集,销售商集,运输路线集。
具体的定义如下:
SETS:
WAREHOUSES / WH1 WH2 WH3 WH4 WH5 WH6/: CAPACITY;
VENDORS / V1 V2 V3 V4 V5 V6 V7 V8/ : DEMAND;
LINKS( WAREHOUSES, VENDORS): COST, VOLUME;
ENDSETS
注解:普通集合定义格式如下:集合名/成员列表/:成员共有属性。最后的LINKS集合,代表着48条运输路线。每条路线分别有两个属性COST和VOLUME。定义这种集合的语法和前面不同:
LINKS( WAREHOUSES, VENDORS)
上面前面两个集合称为“基本集合(Primarity Sets)”,第三个集合LINKS是“派生集合(Derived Sets)”;顾名思义他是由基本集合WAREHOUSES和VENDORS派生出来的。在这个例子中, LINGO生成每个可能的(warehouse, vendor)序对,这48个有序对组成了集合LINKS。 下面从LINKS集合中调出的部分成员可以帮助我们认识着些序对的生成方式:
索引 运输线路
1 WH1-->V1
2 WH1-->V2
3 WH1-->V3
......
47 WH6-->V7
48 WH6-->V8
我们当然可以自己键入这些成员,但是LINGO在后台为我们节省了时间和劳动,我们只需搞明白他的工作原理即可。
六、集合变量赋值:
LINGO允许用户在数据段中单独的给模型中变量赋值;比如下面是我们的这个例子的数据段:
DATA:
CAPACITY = 60 55 51 43 41 52;
DEMAND = 35 37 22 32 41 32 43 38;
COST = 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;
ENDDATA
注解:
[1]、数据段以关键字DATA开始;以关键字ENDDATA结尾。派生集合的赋值有个顺序问题,在这里它先初始化COST( WH1, V1), 接下来是从COST( WH1, V2)到COST (WH1, V8);然后是COST(WH2, V1), 依此类推。
[2]、LINGO还支持从外部文件中导入数据,更一般化地,他甚至支持通过OLE连接到Excel, 或者创建到流行数据库的ODBC链接,这对于数据经常改变的模型非常重要的。

七、总结:
直到现在,我们使用LINGO建模语言建立的运输模型已经初具规模,全部模型是这样的:
MODEL:
!示例:6仓库/8销售商运输模型;
SETS:
WAREHOUSES/ WH1 WH2 WH3 WH4 WH5 WH6/: CAPACITY;
VENDORS/ V1 V2 V3 V4 V5 V6 V7 V8/: DEMAND;
LINKS (Warehouses, Vendors): COST, VOLUME;
ENDSETS
!目标函数;
MIN = @SUM( LINKS( I, J):
COST( I, J) * VOLUME( I, J));
!需求约束;
@FOR( VENDORS( J):
@SUM( WAREHOUSES( I): VOLUME( I, J)) =
DEMAND( J));
!供应约束;
@FOR( WAREHOUSES( I):
@SUM( VENDORS( J): VOLUME( I, J)) <=
CAPACITY( I));
!数据段;
DATA:
CAPACITY = 60 55 51 43 41 52;
DEMAND = 35 37 22 32 41 32 43 38;
COST = 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
ENDDATA
END
注解:在LINGO中使用!和;构造注释语句。另外提醒大家:不要忘了这里的VOLUME(I,J)是要求的具体每条运输线路的运货量。
上面将LINGO8.0分成三部分大致的介绍完了,这其实也是我的学习过程。我每天只能拿出半个小时左右看看LINGO,今天比较幸运,比较闲,就写些感受吧
一、上面三篇后的小尾巴:
上面讲了这么多,最后为啥嘎然而止?实际上,上面的最后已经给出了运输模型的完整的LINGO建模语言描述的程序,只需点击一下运行就可。
二、体会:
为什么LINGO这个软件到现在为止还越来越有活力了呢?现在像Matlab/Maple?MathCAD这样的软件功能强大的很!这几天的使用让我稍有体会了:
1、线性规划这一块的欠缺:在matlab的最初的发展中,线性规划这一块就没考虑多大,当然,如果你非常熟悉单纯形法或分支定界法这样的算法的话,完全可以使用C或者matlab来解决一个具体的规划问题。但是LINDO公司有着独特的眼光,发现了将这些成熟的算法批量机械化的好处,形成了现在的LINDO系列优化软件。
2、线性规划的巨大使用价值:现实的金融/经济/社会等等方面非常多的出现线性规划问题,只要看一下现在的MBA/MPA的教材就知道这是多么基本的一项技术!正如此,LINDO系列软件的使用领域现在主要在这些社会领域,当然教育上也有相当的应用。
3、LINGO建模语言的统一性:熟悉数学优化的人就是知道LINDO公司实际上没做什么,只是将相应数学理论概念对应到面向对象编程中而已,但是这是具有创造性地!Matlab没做这些
,尤其是线性/整数规划!当然对于非线性优化,Matlab的优化工具箱绝对是超级工具。
4、统一性:使用LINDO的语言,特别是建模语言,你能够比较清醒地认识你现在所处理的问题到底是哪一类规划问题?有助于更深刻地认识你所面临的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: