对于我的C ++程序,我需要使用Boost Graph读取DOT文件,然后输出另一个DOT文件。但是,我在读入阶段遇到了一个奇怪的错误,这真的搞砸了我的程序。
我的读入代码(图形类型是双向Boost图的typedef)
void readGraph(Graph& graph, string filename) {
boost::dynamic_properties dp(boost::ignore_other_properties);
ifstream fin(filename.c_str());
boost::read_graphviz(fin, graph, dp);
}
好的,问题是.DOT文件中的节点是以错误的顺序在中读取的!我用一个简单的例子尝试了它.DOT文件:
digraph G {
0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10;
0->1; 1->0;
1->2; 2->1;
2->3; 3->2;
3->4; 4->3;
4->5; 5->4;
5->6; 6->5;
6->7; 7->6;
7->8; 8->7;
8->9; 9->8;
9->10; 10->9;
}
这是从节点0到节点10的双向链。但是,如果我使用Boost Graph读取此文件并立即输出而不进行更改,则会变为:
digraph G {
0;
1;
2;
3;
4;
5;
6;
7;
8;
9;
10;
0->1 ;
1->3 ;
3->4 ;
4->5 ;
5->6 ;
6->7 ;
7->8 ;
8->9 ;
9->10 ;
10->2 ;
1->0 ;
3->1 ;
4->3 ;
5->4 ;
6->5 ;
7->6 ;
8->7 ;
9->8 ;
10->9 ;
2->10 ;
}
注意,节点2现在莫名其妙地连接到节点10,并且位于链的末尾。我在阅读和输出图表之间完成了 nothing 。
注意:
当我尝试使用更复杂的.DOT文件时,图表的拓扑结构保持不变,只是因为某些奇怪的原因而对节点进行了置换。
我知道这是一个读,而不是写错误,因为当我在程序中输出顶点和边时,它们已经被搞砸了。
任何人都可以帮助我理解和解决这个问题吗?感谢。
答案 0 :(得分:2)
如果您阅读图表并再次打印结果(以graphviz格式),您会发现图表是等效的(或同构):
<强> Live On Coliru 强>
#include <boost/graph/graphviz.hpp>
#include "/Archive2/45/a4410ef1bd3024/main.cpp" // alias <libs/graph/src/read_graphviz_new.
using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS>;
void readGraph(Graph &graph, std::string filename) {
boost::dynamic_properties dp(boost::ignore_other_properties);
std::ifstream fin(filename.c_str());
boost::read_graphviz(fin, graph, dp);
}
int main() {
Graph g;
readGraph(g, "input.dot");
boost::write_graphviz(std::cout, g);
}
输入您的信息:
输出显然是等形的:
注意您自己问题中显示的输出也就是这样!
您真正想要的是保留顶点ID。
为了做到这一点,你必须明确地将顶点ID(从点文件中读取)存储到属性中。这是一个例子:
<强> Live On Coliru 强>
#include <boost/graph/graphviz.hpp>
#include "/Archive2/45/a4410ef1bd3024/main.cpp" // alias <libs/graph/src/read_graphviz_new.
using namespace boost;
struct MyVertex {
int id;
};
using Graph = adjacency_list<
vecS, vecS, directedS,
MyVertex
>;
void readGraph(Graph &graph, std::string filename) {
boost::dynamic_properties dp(boost::ignore_other_properties);
dp.property("node_id", boost::get(&MyVertex::id, graph));
std::ifstream fin(filename.c_str());
boost::read_graphviz(fin, graph, dp);
}
int main() {
Graph g;
readGraph(g, "input.dot");
boost::dynamic_properties dp(boost::ignore_other_properties);
dp.property("node_id", boost::get(&MyVertex::id, g));
boost::write_graphviz_dp(std::cout, g, dp);
}
生成:
答案 1 :(得分:1)
好的,所以我做了更多调查。我修改了我的读入函数:
void readGraph(Graph& graph, string filename) {
boost::dynamic_properties dp(boost::ignore_other_properties);
ifstream fin(filename.c_str());
dp.property("node_id", boost::get(&vert::id, graph));
boost::read_graphviz(fin, graph, dp, "node_id");
}
我在哪里创建了结构
vert {
int id;
}
作为我的图表中顶点的捆绑属性:
typedef boost::adjacency_list<boost::listS, boost::vecS, boost::bidirectionalS, vert, edge> Graph;
如果我现在使用.id包打印出读入图的所有顶点和边缘:
Graph h;
readGraph(h, "InputGraph.dot");
for(pair<vertexIt, vertexIt> it = boost::vertices(h); it.first != it.second; ++it.first) {
cout << h[*it.first].id << endl;
}
for(pair<edgeIt, edgeIt> it = boost::edges(h); it.first != it.second; ++it.first) {
cout << h[source(*it.first,h)].id << " -> " << h[target(*it.first,h)].id << endl;
}
我明白了:
0
1
10
2
3
4
5
6
7
8
9
0 -> 1
1 -> 0
1 -> 2
2 -> 1
2 -> 3
3 -> 2
3 -> 4
4 -> 3
4 -> 5
5 -> 4
5 -> 6
6 -> 5
6 -> 7
7 -> 6
7 -> 8
8 -> 7
8 -> 9
9 -> 8
9 -> 10
10 -> 9
所以我们看到一个潜在的问题 - 节点已按字母顺序读取。我不知道这是如何解释我之前看到的奇怪的2-> 10连接。值得庆幸的是,.id包存储了节点的真实信息,因此我们只使用它来访问图。 我仍然认为read_graphviz解析点文件是多么愚蠢和不直观。