# Graph Coloring

隣接頂点が別個の色を持っているようにグラフ中の頂点に色を割り当てる事を含む グラフ (もしくは頂点) の着色の問題は、スケジューリング、 レジスタの割り当て、最適化、そして並列数値計算のような科学や技術の応用 の多くで発生する。

数学的に、無向グラフ G=(V,E) の適切な頂点の彩色は、G 中に 辺 (u,v) が存在する時はいつでも c(u) != c(v) となるような マップ c: V -> S である。集合 S の要素は利用可能色 (available colors) と呼ばれる。 問題は多くの場合、与えられたグラフ G のための最小濃度 (色数) を 決定する事か、またはいくつかの色でもってグラフを着色できるかどうか尋ねる事で ある。例えば隣接した州が異なる色になるような方法で地図上でアメリカを着色する のにどれだけの色が必要であろうか。 コンパイラはある点において決まった数のレジスタに変数と一時値を割り当てる 事ができるかどうか決定する必要がある。 もし目的のマシンが K 個のレジスタを持っているなら、個々の衝突グラフ は K 個の色で着色できるだろうか。(衝突グラフの各頂点は一時値を 表し、各辺は同じレジスタに割り当てられない一時値のペアを示す。)

他の例は最適化の際の大規模な非線形問題と微分方程式の差分による疎な ヤコビ行列の評価中にある。非線形関数 F が与えられると、 ヤコビ行列の評価は都合がよいベクトル d の選択によって Jd を評価する事によって得られる。Curtis、Powell そして Reid [9] は J の列グループは このグループ中の二つの列が同じ行の位置に 0 でない値を持っていなければ Jd を一回評価する事によって決定できる事に気づいた。 それゆえ質問が出てきた。近似のヤコビ行列を計算するのに必要な関数の 評価数はいくつだろうか。 実を言うともし次の要素でグラフを構築するならこの質問はグラフを着色するための 最小色数を計算するのと同じである。それは、頂点が J の列を表し、二つの 列が同じ行の位置に 0 でない値を持つなら、そしてもってさえいれば、辺が存在 するようにする。

しかしながら、一般のグラフを最小数の色 (集合 S の濃度) で 彩色する事は NP 完全問題 [30] として知られている。人は解答を発見するために発見的手法にしばしば頼る。 広く用いられている一般的などん欲を基本としたアプローチは、G の 順序づけられた頂点の列挙 v1, ..., vn から始めて、vi に i のために 1 から n のできるだけ小さな色を割り当てる。 章 Constructing graph algorithms with BGL 中でこのアルゴリズムを汎用プログラミングの 物の考え方でいかに書くかについて示した。しかしながら、頂点の順序付け は劇的に色づけに影響を及ぼす。任意の順序は非常に下手に遂行されるかもしれない のに対し他の順序付けは最も望ましい色づけを生じさせるかもしれない。 どん欲な色づけの発見的手法を助けるために最大先頭 (largest-first) 順序付け、 最小後尾 (smallest-last) 順序付け、接続次数 (incidence degree) による順序付け を含むいくつかの順序付けアルゴリズムが研究されてきた。

BGL の枠組みの中では、そのような順序付けを書くことはアルゴリズムの記述に 密接に従うので、そのような順序付けを構築/原型作りをする事はかなり容易 である。例として、最小後尾 (smallest-last) 順序付けのアルゴリズムを示す。

最小後尾 (smallest-last) 順序付け [29] の基本的な 着想は次の通りである。頂点 vk+1, ..., vn が 選択されたと仮定すると、V - {vk+1, ..., vn} によって誘導された副グラフ中の vk の次数が最小となる ように vk を選びなさい。

アルゴリズムはバケットが次数である場合に、グラフ中の頂点のためにバケット・ ソートを使う。二つの頂点プロパティ・マップ、`degree` と `marker` がアルゴリズム中で使われる。前者は各頂点の次数を格納するための物に対して 後者は隣接頂点の巡回の間頂点が順序付けられたか処理されているかを記録するため の物である。順序付けは `order` 中にしまわれる。アルゴリズムは次の 通りである。

- すべての頂点をバケット・ソータに置く。
- バケット・ソータ中の最小の次数を持つ頂点 `node` を見つける。
- `node` に番号を付けその次数とバケット・ソータ中の位置を更新 するためにその隣接頂点を通して巡回する。
- 全ての頂点が番号付けられるまで段階 2 に行く。

    namespace boost {
      template <class VertexListGraph, class Order, class Degree,
                class Marker, class BucketSorter>
      void
      smallest_last_ordering(const VertexListGraph& G, Order order,
                             Degree degree, Marker marker,
                             BucketSorter& bucket_sorter) {
        typedef typename graph_traits<VertexListGraph> GraphTraits;

        typedef typename GraphTraits::vertex_descriptor Vertex;
        //typedef typename GraphTraits::size_type size_type;
        typedef size_t size_type;

        const size_type num = num_vertices(G);

        typename GraphTraits::vertex_iterator v, vend;
        for (tie(v, vend) = vertices(G); v != vend; ++v) {
          put(marker, *v, num);
          put(degree, *v, out_degree(*v, G));
          degree_buckets.push(*v);
        }

        size_type minimum_degree = 1;
        size_type current_order = num - 1;

        while ( 1 ) {
          typedef typename BucketSorter::stack MDStack;
          MDStack minimum_degree_stack = degree_buckets[minimum_degree];
          while (minimum_degree_stack.empty())
            minimum_degree_stack = degree_buckets[++minimum_degree];

          Vertex node = minimum_degree_stack.top();
          put(order, current_order, node);

          if ( current_order == 0 ) //全ての頂点を見つける
            break;

          minimum_degree_stack.pop();
          put(marker, node, 0); //node は順序付けられた

          typename GraphTraits::adjacency_iterator v, vend;
          for (tie(v,vend) = adjacent_vertices(node, G); v != vend; ++v)

            if ( get(marker, *v) > current_order ) { //*v は順序付けられていない頂点
              put(marker, *v, current_order);   //node に隣接する列を記録する

              //最小次数が減る可能性がある
              //ここでその跡を付け続ける
              put(degree, *v, get(degree, *v) - 1);
              minimum_degree = std::min(minimum_degree, get(degree, *v));

              //バケット・ソータ中の *v の位置を更新する
              degree_buckets.update(*v);
            }

          current_order--;
        }
        //この点で get(order, i) == vertex(i, g) である
      }
    } // namespace boost

Copyright © 2000-2001 | Jeremy Siek, Indiana University (jsiek@osl.iu.edu) Lie-Quan Lee, Indiana University (llee@cs.indiana.edu) Andrew Lumsdaine, Indiana University (lums@osl.iu.edu)

Japanese Translation Copyright © 2003 Takashi Itou
オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」に提供されており、いかなる明示的、暗黙的保証も行わない。また、いかなる目的に対しても、その利用が適していることを関知しない。

このドキュメントの対象: Boost Version 1.30.0
最新版ドキュメント (英語)