Boost.Graph和Graphviz嵌套子图

时间:2019-02-08 19:38:40

标签: c++ boost graphviz boost-graph

我希望输入代码

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

using namespace boost;

using attrs_t = std::map<std::string, std::string>;

using graph_t = adjacency_list<
    vecS, vecS, directedS,
    property<vertex_attribute_t, attrs_t>,
    property<edge_index_t, int, property<edge_attribute_t, attrs_t>>,
    property<graph_name_t, std::string,
        property<graph_graph_attribute_t, attrs_t,
            property<graph_vertex_attribute_t, attrs_t,
                property<graph_edge_attribute_t, attrs_t>>>>>;

int main()
{
    char names[] = {"AB"};
    enum {A, B, N};

    subgraph<graph_t> main(N);
    subgraph<graph_t>& sub1 = main.create_subgraph();
    subgraph<graph_t>& sub2 = sub1.create_subgraph();

    add_vertex(A, sub1);
    add_vertex(B, sub2);
    add_edge(A, B, main);

    get_property(main, graph_name) = "G0";
    get_property(sub1, graph_name) = "clusterG1";
    get_property(sub2, graph_name) = "clusterG2";

    write_graphviz(std::cout, main, make_iterator_vertex_map(names));
}

生成左侧的图形,而我得到右侧的图形:

enter image description here

输出为:

digraph G0 {
subgraph clusterG1 {
subgraph clusterG2 {
//B;
}
//A;
}
A -> B;
}

注释的节点语句是层次结构信息丢失的地方(这些行在我的输出中没有)。我该如何避免呢?


如果我将两个顶点都添加到同一子图中:

add_vertex(A, sub1);
add_vertex(B, sub1);
add_edge(A, B, main);

连接A -> B出现在clusterG1的范围内,据我所知,在那儿也将隐式声明所提到的顶点。

我正在使用Boost 1.68.0

2 个答案:

答案 0 :(得分:1)

问题是由提供make_iterator_vertex_map(names)引起的,该charnames'A''B')返回vertex_index。这与预期的(和默认的)0属性(1digraph G0 { subgraph clusterG1 { subgraph clusterG2 { 1; } 0; } 0 -> 1; } )不兼容。修复后,我得到:

vertex_marker

std::vector<bool>,在我的情况下是2个元素中的67个,而不是if ( vertex_marker[pos] )个元素,并且期望通过顶点索引来索引更多个元素。我遇到了不确定的行为,
并且boost::detail::write_graphviz_subgraph从未实现。

// Print out vertices and edges not in the subgraphs. typename graph_traits<Graph>::vertex_iterator i, end; typename graph_traits<Graph>::edge_iterator ei, edge_end; for(boost::tie(i,end) = vertices(g); i != end; ++i) { Vertex v = g.local_to_global(*i); int pos = get(vertex_id, v); // 66, 65, should be 1, 0 if ( vertex_marker[pos] ) { // out-of-bounds access vertex_marker[pos] = false; out << escape_dot_string(pos); make_vertex_attributes_writer(g.root())(out, v); out << ";" << std::endl; } } 的负责部分:

static_assert

相对于vertex_id的{​​{1}}类型(可以在Graph中完成),vertex_id参数类型的boost::write_graphviz / SFINAE欢迎。附带一提,硬编码的int pos = ...看起来不太专业...

如果要保留自定义名称,则必须通过label属性提供它们。

答案 1 :(得分:1)

好地方。 linked answer实际上具有UB,如您自己的答案所述。传递给write_graphviz函数的映射实际上不应该具有graphviz输出的node_id。相反,该映射被假定为vertex_index_t属性映射。

这是我可能从boost::print_graph(graph_utility.hpp)得出的一个假设,即确实这种属性映射。

为使其安全运行,我将修改示例以使用write_graphviz_dp-使用动态属性:

int main() {
    boost::dynamic_properties dp;
    dp.property("node_id", boost::make_transform_value_property_map<std::string>(&name_for_index, boost::identity_property_map{}));
    write_graphviz_dp(std::cout, create_data<subgraph<Graph> >(), dp);
}

我选择使用转换函数来获取任何顶点描述符的名称,也不想再假设任何关于顶点数目的东西,我编写了更通用的函数来生成诸如“ A”的名称,..., “ Z”,“ AA”,...,“ ZZ”等:

static std::string name_for_index(intmax_t index) {
    std::string name;

    do {
        name += 'A' + (index%26);
        index /= 26;
    } while (index);

    return name;
}

Live On Coliru

保留子图信息

以上重载不支持子图。因此,让我们修复vertex_attribute映射以具有预期的顶点标签:

int main() {
    auto g = create_data<subgraph<Graph> >();

    for (auto vd : make_iterator_range(vertices(g))) {
        put(get(vertex_attribute, g), vd, 
                GraphvizAttributes{
                    {"label", name_for_index(vd)}
                });
    }

    write_graphviz(std::cout, g);
}

现在它可以打印:

Live On Coliru

digraph G0 {
subgraph clusterG1 {
graph [
label=G1];
node [
color=red, shape=Mrecord];
0[label="Vertex A"];
1[label="Vertex B"];
0 -> 1;
}
subgraph clusterG2 {
graph [
fillcolor=lightgray, label=G2, style=filled];
node [
shape=circle];
4[label="Vertex E"];
2[label="Vertex C"];
5[label="Vertex F"];
4 -> 5;
2 -> 5;
}
3[label="Vertex D"];
1 -> 2;
1 -> 3;
4 -> 1;
5 -> 3;
}

哪个呈现为

enter image description here