Boost Graph

Boost のグラフ構造を扱うライブラリ.

てことで少しさわり中.確かに,頂点リスト,接続辺リスト,走査処理とか自前で実装するのもなんかな,とは思っていたのでちょいちょい使い方を見てる.


キモは, graph_traits と adjacency_list によって適度に抽象化されてる(きがする
あと property_map でいろいろ属性足せるのもすごいね.頂点の重みづけとか色とか,辺の距離とかもこれつかえばいけるっぽ.


まあまださわりしかみてないけど.

// directed_graph.cpp
//
// 有向グラフのサンプル
// boost の graph つかってみる

#include <iostream>                      // for std::cout
#include <utility>                       // for std::pair
#include <boost/utility.hpp>             // for boost::tie
#include <boost/graph/graph_traits.hpp>  // for boost::graph_traits
#include <boost/graph/adjacency_list.hpp>


using namespace std;
using namespace boost;

int main(int argc, char* argv[])
{
    typedef adjacency_list<vecS, vecS, bidirectionalS> Graph; // 隣接リストを使って有向グラフを定義
    // typedef adjacency_list<vecS, vecS, undirectedS> Graph; // 無向グラフは undirectedS
    typedef pair<int, int> Edge;

    enum {A, B, C, D, E, N};
    const char* name = "ABCDE";

    Edge edge_array[] = { Edge(A,B), Edge(A,D), Edge(C,A), Edge(D,C), Edge(C,E), Edge(B,D), Edge(D,E), };
    const int num_edges = sizeof(edge_array)/sizeof(edge_array[0]);
    const int num_vertices = N;

    // グラフオブジェクトを宣言
    // コンストラクタでエッジを与えてしまう
    // 引数は,エッジリストの開始ポインタと終点ポインタ,エッジ数
    Graph g(edge_array, edge_array + num_edges, num_vertices);

    // エッジイテレータのコンストラクタを使わずに,
    // オブジェクトを作成してから add_edge で辺を追加 する場合
    /*
    Graph g(num_vertices);
    for (int i = 0; i < num_edges; ++i)
      add_edge(edge_array[i].first, edge_array[i].second, g);
      */

    // 頂点インデックスのためのプロパティマップ
    typedef property_map<Graph, vertex_index_t>::type IndexMap;
    IndexMap index = get(vertex_index, g);

    typedef graph_traits<Graph>::vertex_iterator vertex_iter;
    pair<vertex_iter, vertex_iter> vp;

    // 頂点リストの出力
    cout << "vertices(g) = ";
    for (vp = vertices(g); vp.first != vp.second; ++vp.first)
      cout << name[index[*vp.first]] <<  " ";
    cout << endl;

    graph_traits<Graph>::edge_iterator ei, ei_end;
    // 辺リストの出力
    cout << "edges(g)    = ";
    for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
        cout << "(" << name[index[source(*ei, g)]]
             << "," << name[index[target(*ei, g)]] << ")";
    }
    cout << endl;

    return 0;
}
vertices(g) = A B C D E
edges(g)    = (A,B)(A,D)(C,A)(D,C)(C,E)(B,D)(D,E)

graphviz での出力

用のapiもあったりなどする. boost/graph/graphviz.hpp

これを使うと,上のを,こんなかんじで出力できる.

// directed_graph_graphviz.cpp

#include <iostream>                      // for std::cout
#include <utility>                       // for std::pair
#include <boost/utility.hpp>             // for boost::tie
#include <boost/graph/graph_traits.hpp>  // for boost::graph_traits
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>


using namespace std;
using namespace boost;

int main(int argc, char* argv[])
{
    typedef adjacency_list<vecS, vecS, bidirectionalS> Graph; // 隣接リストを使って有向グラフを定義
    typedef pair<int, int> Edge;

    enum {A, B, C, D, E, N};
    const char* name = "ABCDE";

    Edge edge_array[] = { Edge(A,B), Edge(A,D), Edge(C,A), Edge(D,C), 
        Edge(C,E), Edge(B,D), Edge(D,E), };
    const int num_edges = sizeof(edge_array)/sizeof(edge_array[0]);
    const int num_vertices = N;

    Graph g(edge_array, edge_array + num_edges, num_vertices);

    write_graphviz(
        cout,
        g,
        make_label_writer(name)
    );

    return 0;
}
digraph G {
0[label="A"];
1[label="B"];
2[label="C"];
3[label="D"];
4[label="E"];
0->1 ;
0->3 ;
2->0 ;
3->2 ;
2->4 ;
1->3 ;
3->4 ;
}


べんりすぐる.