簡體   English   中英

如何在 Boost 圖形庫中讀取圖形到鄰接矩陣?

[英]How Can I Read in a Graph to an Adjacency Matrix In the Boost Graph Library?

在 boost 圖形庫中,有兩個流行的函數可以從文件中讀取圖形: boost::read_graphviz()boost::read_graphml() ,分別用於GraphVizGraphML 格式

現在兩者都通用讀取任何類型的boost::adjacency_list<...> ,因為它們是可變圖概念的模型:

#include <string>
#include <fstream>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/graph/graph_traits.hpp>

template <typename GraphType>
GraphType load(std::string filename, std::string format) {

    GraphType g(0);

    std::ifstream t(filename.c_str());
    boost::dynamic_property dp(boost::ignore_other_properties);

    if (format == "graphml")
        boost::read_graphml(t, g, dp);
    else
        boost::read_graphviz(t, g, dp);

    return g;
}

如果你要測試

load<boost::adjacency_matrix<boost::undirectedS> >("my_file.gv", "graphviz");

你可能會得到類似的東西

Assertion failed: (false), function add_vertex, file /usr/local/include/boost/graph/adjacency_matrix.hpp, line 966.
Abort trap: 6

那么我怎樣才能包括讀取到boost::adjacency_matrix<...>的可能性,最好不必從中間鄰接列表中復制圖形,如this SO post中所述(圖形可能非常大)。

我不明白的是,對於復制,(復制目標)圖顯然必須是可變圖,那么我們如何才能復制到鄰接矩陣? 並沒有入一個?

謝謝你的幫助!

筆記

boost/graph/graphml.hpp庫不是僅標頭,需要鏈接,例如在直接從 CLI 編譯/鏈接時附加-lboost_graph ,如

g++ -lboost_graph my_file.cc

關於copy_graph

我不明白的是,對於復制,(復制目標)圖顯然也必須是可變圖,那么我們如何才能復制到鄰接矩陣? 並沒有讀入一個?

我同意。 那沒有意義。 盡管如此, copy_graph似乎不應該工作,或者記錄的概念要求已經過時。

也許它總是被過度約束,或者專門為adjacency_matrix添加了專業化。

粗略的一瞥表明它可能已經過度約束,因為很明顯不存在 adjacency_matrix 的特化/重載。

在我們測試之前,讓我們看一下斷言。

關於斷言

斷言源於這里:

template < typename D, typename VP, typename EP, typename GP, typename A >
inline typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor
add_vertex(adjacency_matrix< D, VP, EP, GP, A >& g)
{
    // UNDER CONSTRUCTION
    BOOST_ASSERT(false);
    return *vertices(g).first;
}

正如您所看到的,這已經是一個正在規划更多靈活性的領域。 如果您保留足夠的空間,您似乎可以閱讀圖表。

可能已經為copy_graph提供了動力(因為當容量已經足夠時才避免使用add_vertex ;即使在技術上(概念上)仍然需要add_vertex ,但可能並不總是如此。

檢驗假設

讓我們來測試一下。 看看我們是否真的可以從鄰接表復制到矩陣中:

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>
#include <boost/graph/copy.hpp>
using boost::vecS;
using D = boost::undirectedS¹;
using L = boost::adjacency_list<vecS, vecS, D>;
using M = boost::adjacency_matrix<D>;

int main() {
    { L list(0); M matrix(20); copy_graph(matrix, list);   } // okay
    { L list(0); M matrix(20); copy_graph(list,   matrix); } // okay
    { L list(1); M matrix(1);  copy_graph(list,   matrix); } // ASSERTS
    { L list(1); M matrix(20); copy_graph(list,   matrix); } // ASSERTS
}

¹方向性實際上並沒有什么不同,我測試過

這就是我們的謎語的答案。 我們實際上無法復制。

它確實可以編譯,但沒有斷言就無法運行。

現在,您可能認為您可以#define NDEBUG並使斷言保持沉默。 然而,看看上面的代碼,很明顯你不能指望它會起作用,因為它總是會返回頂點0

悲傷的長號

#define NDEBUG
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>
#include <boost/graph/copy.hpp>
#include <boost/graph/graph_utility.hpp>
using boost::vecS;
using D = boost::undirectedS;
using L = boost::adjacency_list<vecS, vecS, D>;
using M = boost::adjacency_matrix<D>;

int main() {
    L list(5);
    M matrix(10);

    add_edge(1, 4, list);
    add_edge(3, 1, list);

    copy_graph(list, matrix);

    print_graph(list, std::cout << "\nlist:");
    print_graph(matrix, std::cout << "\nmatrix:");
}

印刷

list:0 --> 
1 --> 4 
2 --> 
3 --> 1 
4 --> 

matrix:0 --> 0 
1 --> 
2 --> 
3 --> 
4 --> 

這顯然是不正確的,盡管這是您閱讀代碼所期望的。

結束語

手動編寫一些解析代碼可能更容易。 如果必須,您可以先閱讀經過高度優化的鄰接列表。 例如,您可以完全使用 memory map。

如果boost::adjacency_list不允許,您可以考慮提供自己的數據結構來建模可變圖概念。 這聽起來可能令人生畏,但實際上它的工作量比您預期的要少:

坦率地說,這些答案沒有我剛剛針對您的其他問題所做的獎勵部分復雜。 一定要給他們閱讀靈感(從第一個開始)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM