Хорошее место.Связанный ответ на самом деле имеет UB, как объясняет ваш собственный ответ.Карта, передаваемая в функцию write_graphviz
, на самом деле не должна иметь node_id для вывода graphviz.Вместо этого предполагалось, что эта карта является 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;
}
Что отображается как