简体   繁体   中英

How to use boost make_label_writer to write edge properties?

I have a simple graph, I suceeded writing properties with the vertex, but when I use make_label_writer to write properties to the edges, the complier always complains. Could someone help with it?

My code is as following:

int main (int argc, char * argv[]) {
    typedef std::pair<int ,int> Edge;
    std::vector<Edge> used_by = {Edge(1, 0), Edge(2, 1),
            Edge(1,2), Edge(2, 0)};
    using namespace boost;
    typedef adjacency_list<vecS, vecS, directedS
             > Graph;
    Graph g(used_by.begin(), used_by.end(), 3);
    std::ofstream dmp;
    dmp.open("dmp.dot");
    //name for vertex
    std::vector<std::string> name{"one", "two", "three"};
    //name for edge
    std::vector<std::string> name1{"e1", "e2", "e3", "e4"};
    write_graphviz(std::cout, g, make_label_writer(&name[0]) 
                                   ,make_label_writer(&name1[0]));
}

The write_graphviz() will ofc called the template, which is perfectly fine :

  template <typename Graph, typename VertexWriter, typename 
  EdgeWriter>
  inline void
  write_graphviz(std::ostream& out, const Graph& g,
             VertexWriter vw, EdgeWriter ew
       BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
  {
    default_writer gw;
    write_graphviz(out, g, vw, ew, gw);
  }

So the problem is now: when I only write the vertex properties using make_label_writer(&name[0]]]) , the code runs perfectly. But when I add make_label_writer(&name1[0]) , there is error.

The default vertex index is integral, which is why you can use the address of the first vertex name as implied associative property map.

The edge descriptor is a different beast and requires you to either

  • create an explicit iterator property map (using an extra index property map to map from edge descriptor to the integral index into the name1 vector)
  • or use a model of the Associative PropertyMap concept.

In this case you should property do the later using a std::map<edge_descriptor, std::string> .

Please also consider making your life with properties a lot simpler by using Bundled Properties .

Associative Property Map

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>

typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS> Graph;

int main() {
    Graph g(3);
    auto e1 = add_edge(1, 0, g).first;
    auto e2 = add_edge(2, 1, g).first;
    auto e3 = add_edge(1, 2, g).first;
    auto e4 = add_edge(2, 0, g).first;

    std::vector<std::string>                      vname{ "one", "two", "three" };
    std::map<Graph::edge_descriptor, std::string> ename{ 
        { e1, "e1" },
        { e2, "e2" },
        { e3, "e3" },
        { e4, "e4" },
    };

    write_graphviz(std::cout, g,
            boost::make_label_writer(&vname[0]),
            make_label_writer(boost::make_assoc_property_map(ename)));
}

Prints

Bundled Properties Instead

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>

struct VertexProps { std::string name; };
struct EdgeProps   { std::string name; };
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProps, EdgeProps> Graph;

int main() {
    Graph g(3);
    g[0].name = "one";
    g[1].name = "two";
    g[2].name = "three";
    add_edge(1, 0, {"e1"}, g);
    add_edge(2, 1, {"e2"}, g);
    add_edge(1, 2, {"e3"}, g);
    add_edge(2, 0, {"e4"}, g);

    write_graphviz(std::cout, g,
            make_label_writer(get(&VertexProps::name, g)),
            make_label_writer(get(&EdgeProps::name, g)));
}

Prints the same

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM