繁体   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