あめだまふぁくとりー

Boost.Graphとかできますん

Boost.Graph property to Boost.Fusion

Boost.Graph のグラフ構造体で使用される property を fusion::for_each で使用できるようにしてみました. ソースは こちら にあげています.

property に bundle (ユーザが定義した構造体)が含まれる場合, bundle は fusion::for_each 上には現れないので注意です.

以下は使用例で, グラフを graphviz の dot 言語に書き出す際に node attributes を fusion::for_each で出力しています(attribute の名前は面倒なので typeinfo::name に使用しています).

使用例:

#include <iostream>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/container/map.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include "canard/property_sequence.hpp"

// 長い property のリスト
using vertex_property
    = boost::property<
        boost::vertex_index_t, std::size_t
    , boost::property<
        boost::vertex_color_t, std::string
    , boost::property<
        boost::vertex_name_t, std::string
    , boost::property<
        boost::vertex_rank_t, std::size_t
    >>>>;
using graph = boost::adjacency_list<boost::listS, boost::listS, boost::directedS, vertex_property>;

struct print_property
{
    explicit print_property(std::ostream& out)
        : out{out}
    {
    }

    template <class Tag, class T, class Base>
    void operator()(boost::property<Tag, T, Base>& p) const
    {
        (is_first ? out : (out << ", ")) << typeid(Tag).name() << "=" << p.m_value;
        is_first = false;
    }

    std::ostream& out;
    mutable bool is_first = true;
};

struct vertex_property_writer
{
    using all_property_map = boost::property_map<graph, boost::vertex_all_t>::type;

    template <class Vertex>
    void operator()(std::ostream& out, Vertex const v) const
    {
        // node attirbutes を出力
        out << "[";
        boost::fusion::for_each(get(all_map, v), print_property{out});
        out << "]";
    }

    all_property_map all_map;
};

int main()
{
    auto g = graph{};
    add_vertex(vertex_property{0, {"blue", {"tokyo", {2}}}}, g);
    add_vertex(vertex_property{1, {"red", {"sapporo", {1}}}}, g);
    boost::write_graphviz(std::cout, g, vertex_property_writer{get(boost::vertex_all, g)});
}

実行結果:

digraph G {
0[N5boost14vertex_index_tE=0, N5boost14vertex_color_tE=blue, N5boost13vertex_name_tE=tokyo, N5boost13vertex_rank_tE=2];
1[N5boost14vertex_index_tE=1, N5boost14vertex_color_tE=red, N5boost13vertex_name_tE=sapporo, N5boost13vertex_rank_tE=1];
}