ECLiPSe CLPで最大流問題を解く方法の説明をします。
最大流問題って自分は知らなかったのですが、グラフが与えられ、ノードからノードを結ぶそれぞれのエッジに転送量の上限(転送するのはデータでも物でも何でも良い)が決められているとき、あるノードからもう一つのノードへの最大の転送量を求めるという問題です。
電子回路のキルヒホッフの法則のように、各ノードに入る量とそのノードから出ていく量は一致している必要があります(始点と終点は除く)つまりあるノードに注目したとき、入ってくる量の許容量が6で出ていく量の許容量が4の場合は少ない方の4に合わされてしまうことになります(ボトルネックとなる)
自分の勝手な解釈ですが、いくつかのノードが接続された形の水道管ネットワークみたいのがあったとして、ノード同士をつなぐ水道管の最大流量が決まっているとき、入口Aから出口Bに流せる最大の水の量を求めるみたいな感じかなとイメージしました。
以下のようなグラフ(Problems and exercises in Operations Research 10ページ目 1.3 Maximum flow の図)が与えられたときにノード1からノード7への最大流を求めるプログラムを書きます。
エッジの数値はノード間の距離ではなくエッジの許容流量を表していることに注意です。
library(max_flow)を使用します。
またlibrary(graph_algorithms)も使用します。
グラフの作成はmake_graph/3を使用します(使い方は以前の記事参照)
最大流問題を解く述語はmax_flow/5やmax_flow/7ですが、今回は得られる情報が多いmax_flow/7を使用します。
max_flow(
+Graph,
+CapacityArg,
+SourceNode,
+SinkNode,
-MaxFlowValue,
-MaxFlowEdges,
-MaxFlowEdgesGraph)
引数の意味は以下となります。
1.Graph 生成したグラフ
2.CapacityArg エッジの許容量をどこに書いたか指定
(e(_,_,Capacity)のCapacityの部分に数値で記載した場合は0)
3.SourceNode 開始ノード番号
4.SinkNode 終了ノード番号
5.MaxFlowValue 最大流量(戻り値)
6.MaxFlowEdges 使用されたエッジとそのエッジに流される流量
(流量ゼロのエッジは出力されない) (戻り値)
7.MaxFlowEdgesGraph 使用されたエッジをグラフの形で出力
(流量ゼロのエッジは出力されない) (戻り値)
プログラム:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
:-lib(graph_algorithms). :-lib(max_flow). solve(MaxFlowValue,MaxFlowEdges,MaxFlowEdgesGraph):- make_graph( 7, [ e(1,2,6), e(1,3,6), e(2,3,1), e(2,4,3), e(2,5,3), e(3,5,7), e(4,5,1), e(4,7,1), e(5,7,4), e(5,6,5), e(6,7,4) ], Graph), max_flow(Graph, 0, 1, 7, MaxFlowValue,MaxFlowEdges,MaxFlowEdgesGraph). |
実行結果(見やすくなるよう手で改行入れてます):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
?- solve(MaxFlow, Edges, Graph). MaxFlow = 9 Edges = [ 4 - e(6, 7, 4), 4 - e(5, 7, 4), 4 - e(5, 6, 5), 1 - e(4, 7, 1), 1 - e(4, 5, 1), 4 - e(3, 5, 7), 3 - e(2, 5, 3), 2 - e(2, 4, 3), 4 - e(1, 3, 6), 5 - e(1, 2, 6) ] Graph = graph(7, []( [e(1, 2, 6), e(1, 3, 6)], [e(2, 4, 3), e(2, 5, 3)], [e(3, 5, 7)], [e(4, 5, 1), e(4, 7, 1)], [e(5, 6, 5), e(5, 7, 4)], [e(6, 7, 4)], []), _2193, _2194, _2195, _2196, _2197, _2198) Yes (0.00s cpu) |
最大9の量流せるようですね。
一応注意点ですがこのlibrary(max_flow)はステータスが「prototype」となっていることに気を付けてください。もしバグ見つかったらECLiPSeの開発者に報告すると喜ばれます。手間でしたら私(koyahataアットマークkoyahatataku.com)に報告くだされば私が報告します。
以上