Manually colouring of boost's graphs

2020-04-21 07:33发布

问题:

I'm struggling trying to manually colouring graph's vertices using boost. I wrote the code below but I can't figure it out why the generated file does not have any colour.

int main(int,char*[]) {
    typedef property<edge_name_t, string> EdgeProperties;
    typedef property<vertex_name_t, string, property<vertex_color_t, default_color_type>> VertexProperties;
    typedef adjacency_list<vecS, vecS, directedS, VertexProperties, EdgeProperties> Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    typedef graph_traits<Graph>::edge_descriptor Edge;

    Graph g;
    property_map<Graph, vertex_name_t>::type vertex_label = get(vertex_name, g);
    property_map<Graph, vertex_color_t>::type color_map = get(vertex_color, g);
    property_map<Graph, edge_name_t>::type edge_label = get(edge_name, g);

    Vertex v1 = add_vertex(g);
    vertex_label[v1] = "v1";

    put(color_map, v1, boost::red_color);

    std::ofstream outf("example.gv");
    write_graphviz(outf, g,
                   make_label_writer(vertex_label),
                   make_label_writer(edge_label)
                   );
    return 0;
}

回答1:

Vertex colourings are really an algorithmic detail. There is no "automatic" provision to translate it to graphviz, as far as I know.

You can add custom attributes though.

I'd usually change it around to use dynamic properties:

std::ofstream outf("example.gv");

dynamic_properties dp;
dp.property("node_id", get(vertex_index, g));
dp.property("label", vertex_label);
dp.property("label", edge_label);

write_graphviz_dp(outf, g, dp);

Now it's as simple as adding a new vertex attribute to the dynamic set:

dp.property("color", make_transform_value_property_map(&color_to_string, color_map));

The only complication is that you need to supply the conversion from default_color_type to text. This is another symptom of the fact that the color maps aren't usually used for representational purposes. Here's a fully working sample:

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include <iostream>
using namespace boost;

inline char const* color_to_string(default_color_type c) {
    switch(c) {
        case default_color_type::red_color:   return "red";
        case default_color_type::green_color: return "green";
        case default_color_type::gray_color:  return "gray";
        case default_color_type::white_color: return "white";
        case default_color_type::black_color: return "black";
    }
    return ""; // not known
}


int main() {
    typedef property<edge_name_t, std::string> EdgeProperties;
    typedef property<vertex_name_t, std::string, property<vertex_color_t, default_color_type>> VertexProperties;
    typedef adjacency_list<vecS, vecS, directedS, VertexProperties, EdgeProperties> Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;

    Graph g;
    property_map<Graph, vertex_name_t>::type vertex_label = get(vertex_name, g);
    property_map<Graph, vertex_color_t>::type color_map = get(vertex_color, g);
    property_map<Graph, edge_name_t>::type edge_label = get(edge_name, g);

    Vertex v1 = add_vertex(g);
    vertex_label[v1] = "v1";

    put(color_map, v1, boost::red_color);

    dynamic_properties dp;
    dp.property("node_id", get(vertex_index, g));
    dp.property("label", vertex_label);
    dp.property("label", edge_label);
    dp.property("color", make_transform_value_property_map(&color_to_string, color_map));

    write_graphviz_dp(std::cout, g, dp);
}

Prints:

digraph G {
0 [color=red, label=v1];
}


标签: c++ boost graph