BGL: модуль записи пользовательских свойств для связанных свойств и списков как VertexList / EdgeList - PullRequest
1 голос
/ 27 марта 2019

Я взял следующий код из этой записи и изменил VertexList и EdgeList на listS вместо vecS.

Я обнаружил, что из-за отсутствия индекса make_label_writer(get(&VertexProps::name, g)) не работает.Может кто-нибудь сказать мне, как я должен изменить код, чтобы заставить его работать.Я бы предпочел решение с автором пользовательских свойств.

Большое спасибо.

#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::listS, boost::listS, 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)));

}


Ради полноты приведем модификацию решения sehe савтор пользовательских свойств.Пожалуйста, не забудьте подтвердить первоначальный ответ.

Wandbox

#include <boost/graph/adjacency_list.hpp>
#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::listS, boost::listS, boost::directedS, VertexProps, EdgeProps> Graph;

template <class Name>
class my_label_writer {
public:
    my_label_writer(Name _name) : name(_name) {}
    template <class VertexOrEdge>
    void operator()(std::ostream& out, const VertexOrEdge& v) const {
        out << "[label=\"" << name[v].name << "\"]";
    }
private:
    Name name;
};


int main() {
    Graph g;
    Graph::vertex_descriptor v0 = add_vertex({"one"}, g);
    Graph::vertex_descriptor v1 = add_vertex({"two"}, g);
    Graph::vertex_descriptor v2 = add_vertex({"three"}, g);
    add_edge(v1, v0, {"e1"}, g);
    add_edge(v2, v1, {"e2"}, g);
    add_edge(v1, v2, {"e3"}, g);
    add_edge(v2, v0, {"e4"}, g);

    std::map<Graph::vertex_descriptor, int> vertex_index;
    for (auto vd : boost::make_iterator_range(vertices(g)))
        vertex_index[vd] = vertex_index.size();

    my_label_writer<Graph> w(g);

    write_graphviz(std::cout, g,
        w,
        make_label_writer(get(&EdgeProps::name, g)),
        boost::default_writer{}, // graph_property_writer
        boost::make_assoc_property_map(vertex_index));
}

1 Ответ

2 голосов
/ 28 марта 2019

При listS тип дескриптора вершины не является целочисленным и поэтому не подходит в качестве индекса вершины.

Вам нужно использовать фактические дескрипторы сейчас:

Graph g;
Graph::vertex_descriptor v0 = add_vertex({"one"}, g);
Graph::vertex_descriptor v1 = add_vertex({"two"}, g);
Graph::vertex_descriptor v2 = add_vertex({"three"}, g);
add_edge(v1, v0, {"e1"}, g);
add_edge(v2, v1, {"e2"}, g);
add_edge(v1, v2, {"e3"}, g);
add_edge(v2, v0, {"e4"}, g);

Кроме того, при написании вы должны будете предоставить vertex_index карту свойств. Это, кстати, требует от вас про graph_property_writer проформы:

std::map<Graph::vertex_descriptor, int> vertex_index;
for (auto vd : boost::make_iterator_range(vertices(g)))
    vertex_index[vd] = vertex_index.size();

write_graphviz(std::cout, g,
    make_label_writer(get(&VertexProps::name, g)),
    make_label_writer(get(&EdgeProps::name, g)),
    boost::default_writer{}, // graph_property_writer
    boost::make_assoc_property_map(vertex_index));

DEMO

Live On Wandbox

#include <boost/graph/adjacency_list.hpp>
#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::listS, boost::listS, boost::directedS, VertexProps, EdgeProps> Graph;

int main() {
    Graph g;
    Graph::vertex_descriptor v0 = add_vertex({"one"}, g);
    Graph::vertex_descriptor v1 = add_vertex({"two"}, g);
    Graph::vertex_descriptor v2 = add_vertex({"three"}, g);
    add_edge(v1, v0, {"e1"}, g);
    add_edge(v2, v1, {"e2"}, g);
    add_edge(v1, v2, {"e3"}, g);
    add_edge(v2, v0, {"e4"}, g);

    std::map<Graph::vertex_descriptor, int> vertex_index;
    for (auto vd : boost::make_iterator_range(vertices(g)))
        vertex_index[vd] = vertex_index.size();

    write_graphviz(std::cout, g,
        make_label_writer(get(&VertexProps::name, g)),
        make_label_writer(get(&EdgeProps::name, g)),
        boost::default_writer{}, // graph_property_writer
        boost::make_assoc_property_map(vertex_index));
}

печать

digraph G {
0[label=one];
1[label=two];
2[label=three];
1->0 [label=e1];
1->2 [label=e3];
2->1 [label=e2];
2->0 [label=e4];
}
...