2015-09-27 70 views
2

對於我的C++程序,我需要使用Boost Graph讀取DOT文件,並稍後輸出另一個DOT文件。不過,我在讀入階段遇到了一個奇怪的錯誤,這真的搞砸了我的程序。奇數錯誤導入DOT文件

我的讀入的代碼(圖形類型是雙向升壓曲線圖的一個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的雙向鏈然而,如果我讀取使用升壓圖形,並將其輸出該文件沒有立即改變,變得:

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,並且在鏈的末端。我已經完成了沒有什麼在讀取和輸出圖之間。

注:

  • 當我嘗試這種更復雜的.DOT文件,圖的拓撲結構是一樣的,它只是節點已經被交換一些奇怪的原因。

  • 我知道這是一個讀,而不是寫錯誤,因爲當我在程序期間輸出頂點和邊時,它們已經搞砸了。

任何人都可以幫助我理解和解決這個問題嗎?謝謝。

回答

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); 
} 

隨你輸入:

enter image description here

輸出顯然是異的Morphic:

enter image description here

注意在你自己的問題顯示的輸出很簡單,太!

你真正想要的是頂點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); 
} 

生成:

enter image description here

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如何解析點文件。

+0

請稍候帶自受理這裏。我會在稍後時間找到完整的問題。我可能會發現潛在的問題。同時,你可以[搜索我現有的答案](http://stackoverflow.com/search?tab=relevance&q=user%3a85371%20read_graphviz)萬一你發現你在做什麼不同的事情 – sehe

+0

有沒有什麼可怕的事情發生畢竟(「虛假的」連接(_node 2現在無法解釋地連接到節點10_)在我的答案 – sehe

+0

+ 1-ed中解釋,因爲我看到你幾乎擁有了所有的組件,我只是不同意「這真的很愚蠢,不直觀「 - 在閱讀的時候,解析器無法知道節點id的類型順便說一下,如果你有能力改變節點id的格式(例如'02'和'03'),那麼就有另一種選擇:https://vimeo.com/channels/761265 – sehe