最小費用流アルゴリズム
最小費用流問題は、ネットワークフロー理論における中心的な最適化問題の一つであり、与えられたフロー量を最小のコストで流すことを目的とする。この問題は最大流問題の自然な拡張として位置づけられ、各辺に容量制約だけでなくコストが付与されたネットワークにおいて、指定された量のフローを送るための最小総コストを求める。実世界における輸送問題、割当問題、スケジューリング問題など、多くの組合せ最適化問題が最小費用流問題として定式化できることから、理論的にも実践的にも極めて重要な問題クラスである。
問題の定式化
有向グラフ
数学的に厳密に定式化すると、以下の線形計画問題として表現される:
ここで、
双対性理論と最適性条件
最小費用流問題の深い理解には、線形計画法における双対理論が不可欠である。各頂点
相補性条件により、最適解においては以下の条件が成立する:
ならば (タイトな辺) ならば
これらの条件は、被約コスト
残余ネットワークと負閉路
最小費用流アルゴリズムの多くは、残余ネットワーク(residual network)の概念を利用する。フロー
ならば、容量 、コスト の順方向辺 ならば、容量 、コスト の逆方向辺
フローの最適性と残余ネットワークにおける負閉路の存在には密接な関係がある。実際、フロー
連続最短路法
連続最短路法(successive shortest path algorithm)は、最小費用流問題を解く最も直感的なアルゴリズムの一つである。このアルゴリズムは、供給頂点から需要頂点への最短路を繰り返し見つけ、その経路に沿ってフローを流すという基本的なアイデアに基づいている。
アルゴリズムの動作原理は以下の通りである。まず、すべてのフローを0に初期化し、供給量
重要な点は、各反復においてポテンシャルを適切に更新することで、被約コストの非負性を保つことである。Dijkstra法を用いて最短路を求めた場合、最短距離
連続最短路法の計算量は、フロー値を
プライマル・デュアル法
プライマル・デュアル法は、線形計画法の一般的な解法技術を最小費用流問題に特化させたものである。このアルゴリズムは、主問題(フロー)と双対問題(ポテンシャル)を同時に改善していくことで、効率的に最適解を求める。
アルゴリズムの核心は、現在のポテンシャルに対して被約コストが0となる辺(タイトな辺)のみからなる補助グラフを構築し、この上で最大流を求めることである。得られた最大流に従ってフローを更新し、その後ポテンシャルを調整して新たなタイトな辺を追加する。この過程を、すべての供給・需要が満たされるまで繰り返す。
プライマル・デュアル法の各反復では、以下の手順を実行する:
- 現在のポテンシャル
に対して、被約コスト となる辺からなる補助グラフ を構築 上で供給頂点から需要頂点への最大流を計算 - 残余ネットワーク上で到達可能な頂点集合を求め、ポテンシャルを更新
計算量は
コストスケーリング法
コストスケーリング法は、最小費用流問題に対する強多項式時間アルゴリズムの一つであり、理論的にも実践的にも優れた性能を持つ[3]。このアルゴリズムは、コストを段階的に精密化していくことで、効率的に最適解に到達する。
アルゴリズムの基本的なアイデアは、コストを
各スケーリング段階では、以下の操作を繰り返す:
- 被約コストが負の辺を見つける
- その辺を含む最小平均コスト閉路を探索
- 閉路に沿ってフローを流す
Goldberg-Tarjanのコストスケーリング法では、計算量
容量スケーリング法
容量スケーリング法は、コストスケーリング法とは異なるアプローチで、容量を段階的に考慮することで効率化を図る。このアルゴリズムは、大きな容量の辺から順に処理していくことで、フローの増加操作の回数を削減する。
各スケーリング段階
容量スケーリング法は、連続最短路法と組み合わせることで特に効果的である。各スケーリング段階で連続最短路法を適用することで、全体の計算量を
ネットワーク単体法
ネットワーク単体法は、線形計画法の単体法を最小費用流問題に特化させたものである。このアルゴリズムは、実用的な問題において極めて高速に動作することが知られており、商用ソルバーでも広く採用されている[4]。
ネットワーク単体法の基本的な考え方は、フローを全域木(spanning tree)で表現することである。各反復において、現在の全域木に含まれない辺の中から被約コストが負のものを選び、それを全域木に追加する。同時に、閉路を解消するために別の辺を全域木から除去する。この操作をピボット操作と呼ぶ。
実装上の工夫として、以下の技術が重要である:
- 全域木の効率的な表現(親ポインタ、深さ、部分木サイズなど)
- 候補リストによる入る辺の選択の高速化
- 摂動法による退化の回避
ネットワーク単体法は最悪計算量が指数的になる可能性があるが、実用的な問題では線形時間に近い性能を示すことが多い。特に、疎なネットワークや特殊な構造を持つ問題において優れた性能を発揮する。
実装上の詳細と最適化技術
最小費用流アルゴリズムの実装において、理論的な正しさだけでなく、実用的な効率性を達成するためには多くの工夫が必要である。以下に主要な実装技術を詳述する。
データ構造の選択
グラフの表現方法は性能に大きく影響する。隣接リスト表現が一般的だが、辺の追加・削除が頻繁な場合は動的な構造を検討する必要がある。残余ネットワークの表現では、順方向辺と逆方向辺を対にして管理することで、相互参照を効率化できる:
struct Edge {
int to, rev;
long long cap, cost;
};
vector<vector<Edge>> graph;
数値精度と整数性
最小費用流問題では、整数容量・整数コストの場合、最適フローも整数となることが保証される(整数性定理)。しかし、計算過程でのオーバーフローに注意が必要である。特に、コストの累積値は容量とコストの積に比例して大きくなるため、適切な型選択が重要である。
負閉路の検出と処理
負閉路消去法を実装する場合、効率的な負閉路検出が鍵となる。Bellman-Ford法の高速化版として、SPFA(Shortest Path Faster Algorithm)がよく用いられる。ただし、最悪計算量は改善されないため、問題の特性に応じて使い分ける必要がある。
ポテンシャルの初期化
多くのアルゴリズムで、初期ポテンシャルの設定が性能に影響する。すべてのコストが非負の場合は0初期化で十分だが、負のコストが存在する場合は、Bellman-Ford法などで適切な初期値を計算する必要がある。
// ポテンシャルの初期化(負コスト対応)
vector<long long> h(n, INF);
h[s] = 0;
for (int i = 0; i < n - 1; ++i) {
for (int v = 0; v < n; ++v) {
if (h[v] == INF) continue;
for (auto& e : graph[v]) {
if (e.cap > 0) {
h[e.to] = min(h[e.to], h[v] + e.cost);
}
}
}
}
メモリ効率とキャッシュ性能
大規模なグラフを扱う場合、メモリアクセスパターンが性能のボトルネックとなることがある。辺の情報をStructure of Arrays(SoA)形式で管理することで、キャッシュ効率を改善できる場合がある。また、頻繁にアクセスされるデータ(ポテンシャル、距離ラベルなど)は連続したメモリ領域に配置することが望ましい。
応用問題と定式化技法
最小費用流問題の真の力は、様々な組合せ最適化問題を統一的に扱える汎用性にある。以下、代表的な応用例とその定式化技法を詳しく見ていく。
二部マッチング問題
重み付き二部マッチング問題は、最小費用流問題の特殊ケースとして定式化できる。二部グラフ
輸送問題
最小費用循環フロー
すべての頂点で供給量が0の場合、循環フローを求める問題となる。この問題は、任意の頂点対間に大容量・大コストの辺を追加し、適切な供給・需要を設定することで、通常の最小費用流問題に帰着できる。
プロジェクトスケジューリング
リソース制約付きプロジェクトスケジューリング問題も、時間展開グラフを用いて最小費用流として定式化できる。各時刻・各リソースを頂点とし、タスクの実行を辺で表現する。リソース容量は辺容量、遅延ペナルティはコストとして組み込む。
高度な実装技術
動的最小費用流
グラフの構造が動的に変化する場合の最小費用流問題は、実用上重要だが理論的にも挑戦的である。完全な再計算を避けるため、以下の技術が研究されている:
- 感度分析による局所的な更新
- 永続データ構造を用いた差分管理
- 並列化による高速化
近似アルゴリズム
厳密解が不要な場合、
GPUを用いた並列化
最小費用流アルゴリズムの並列化は、逐次的な性質のため困難だが、以下のアプローチが研究されている:
- 複数の最短路探索の並列実行
- ブロック単位でのフロー更新
- 投機的実行による並列化
実装例:連続最短路法
理論的な説明を補完するため、連続最短路法の基本的な実装を示す。この実装は教育的な目的のためのものであり、実用的な最適化は省略している:
struct MinCostFlow {
struct Edge {
int to, rev;
long long cap, cost;
};
vector<vector<Edge>> graph;
vector<long long> h, dist;
vector<int> parent, parent_edge;
int n;
MinCostFlow(int n) : n(n), graph(n), h(n), dist(n), parent(n), parent_edge(n) {}
void add_edge(int from, int to, long long cap, long long cost) {
graph[from].push_back({to, (int)graph[to].size(), cap, cost});
graph[to].push_back({from, (int)graph[from].size() - 1, 0, -cost});
}
pair<long long, long long> min_cost_flow(int s, int t, long long f) {
long long res = 0;
fill(h.begin(), h.end(), 0);
while (f > 0) {
priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;
fill(dist.begin(), dist.end(), LLONG_MAX);
dist[s] = 0;
pq.push({0, s});
while (!pq.empty()) {
auto [d, v] = pq.top();
pq.pop();
if (dist[v] < d) continue;
for (int i = 0; i < graph[v].size(); ++i) {
Edge& e = graph[v][i];
if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
parent[e.to] = v;
parent_edge[e.to] = i;
pq.push({dist[e.to], e.to});
}
}
}
if (dist[t] == LLONG_MAX) return {-1, -1};
for (int v = 0; v < n; ++v) h[v] += dist[v];
long long d = f;
for (int v = t; v != s; v = parent[v]) {
d = min(d, graph[parent[v]][parent_edge[v]].cap);
}
f -= d;
res += d * h[t];
for (int v = t; v != s; v = parent[v]) {
Edge& e = graph[parent[v]][parent_edge[v]];
e.cap -= d;
graph[v][e.rev].cap += d;
}
}
return {f, res};
}
};
理論的発展と未解決問題
最小費用流問題は、アルゴリズム理論において成熟した分野であるが、依然として多くの興味深い研究課題が残されている。
強多項式時間アルゴリズムの改善は継続的な研究テーマである。現在知られている最良の強多項式時間計算量は
動的最小費用流問題に対する効率的なアルゴリズムの開発も重要な課題である。現在のアプローチでは、最悪の場合、更新ごとに静的アルゴリズムと同等の時間がかかる。グラフの変更を効率的に処理し、償却的に高速な更新を実現するデータ構造の開発が求められている。
分散・並列アルゴリズムの観点からも、最小費用流問題は興味深い。MapReduceモデルやMPCモデルにおける効率的なアルゴリズムの設計は、大規模データ処理の文脈で重要性を増している。特に、通信量を削減しながら高速に収束するアルゴリズムの開発が課題となっている。
量子アルゴリズムの文脈でも、最小費用流問題は注目されている。古典的なアルゴリズムに対する量子スピードアップの可能性や、量子近似最適化アルゴリズム(QAOA)の適用可能性などが研究されている。
実用的な観点からは、機械学習との融合も興味深い方向性である。問題インスタンスの特性を学習し、適切なアルゴリズムやパラメータを選択する手法や、ニューラルネットワークを用いた高速な近似解法の開発などが進められている。
最小費用流問題は、理論的な美しさと実用的な重要性を兼ね備えた、組合せ最適化における中心的な問題である。本稿で述べた各アルゴリズムは、それぞれ異なる強みを持ち、問題の特性に応じて使い分けることが重要である。連続最短路法の実装の単純さ、プライマル・デュアル法の理論的優雅さ、コストスケーリング法の最悪計算量保証、ネットワーク単体法の実用的効率性など、各手法の特徴を理解し、適切に選択・実装することが、効率的な問題解決の鍵となる。
Ahuja, R. K., Magnanti, T. L., & Orlin, J. B. (1993). Network flows: theory, algorithms, and applications. Prentice Hall. ↩︎
Klein, M. (1967). A primal method for minimal cost flows with applications to the assignment and transportation problems. Management Science, 14(3), 205-220. ↩︎
Goldberg, A. V., & Tarjan, R. E. (1990). Finding minimum-cost circulations by successive approximation. Mathematics of Operations Research, 15(3), 430-466. ↩︎
Orlin, J. B. (1997). A polynomial time primal network simplex algorithm for minimum cost flows. Mathematical Programming, 78(2), 109-129. ↩︎
Fleischer, L. K., & Wayne, K. D. (2002). Fast and simple approximation schemes for generalized flow. Mathematical Programming, 91(2), 215-238. ↩︎