c++ - 如何将图表读入 Boost 图表库中的邻接矩阵?

标签 c++ boost graph adjacency-matrix boost-graph

在 boost 图形库中,有两个流行的函数可以从文件中读取图形: boost::read_graphviz() , 和 boost::read_graphml() , 对于 GraphVizGraphML format , 分别。

现在两者都可以读取任何类型的 boost::adjacency_list<...> ,因为它们是 Mutable Graph 的模型理念:

#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<...> 的可能性呢? ,最好不必从中间邻接列表复制图形,如解释的那样in this SO post (图表可能真的很大)。

我不明白的是,对于复制,(复制目标)图 apparently 必须是可变图,那么我们如何才能复制到邻接矩阵?而不是成一个?

感谢您的帮助!

注意事项

boost/graph/graphml.hpp库不是仅 header ,需要链接,例如通过附加 -lboost_graph直接从 CLI 编译/链接时,如

g++ -lboost_graph my_file.cc

最佳答案

关于copy_graph

What I don't understand is, that for copying, the (copy target) graph apparently also has to be a Mutable Graph, so how can we then copy to an adjacency matrix? And not read into one?

我同意。那没有意义。看起来 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;
}

如您所见,这已经是一个正在规划更多灵 active 的领域。如果您保留足够的空间,您似乎确实可以阅读图表。

这可能是已经为 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:

Sad Trombone :

#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 --> 

这显然是不正确的,尽管这是您阅读代码时所期望的。

结束语

手动编写一些解析代码可能会更容易。如果必须的话,您可能会先读入经过高度优化的邻接列表。例如,您可以将其完全内存映射。

如果 boost::adjacency_list 不允许,您可以考虑提供自己的数据结构,对可变图概念进行建模。这听起来可能令人生畏,但实际上比您预期的要少:

坦率地说,这些答案没有 bonus section 复杂。我刚刚回答了你的另一个问题。一定要给他们阅读以获取灵感(从第一本开始)

关于c++ - 如何将图表读入 Boost 图表库中的邻接矩阵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66977885/

相关文章:

algorithm - 用于在图中查找最小切割的随机收缩算法

python - 存储和检索大量小型非结构化消息的最快方法

c++ - 将原始鼠标/指针数据转换为有意义的东西?

c++ - 如何将 boost::object_pool<>::construct 与非 const 引用一起用作 ctor 参数?

c++ - boost::crc_32_type 会产生任何异常吗?

PostgreSQL 将数据从递归 CTE 传递到函数

c++ - 模拟不存在的 3D 驱动程序

c++ - short(expression) 是什么意思?

boost - 如何通过 Gloa 使用来自多个文件的 boost 日志

c - 为什么我的输出不正确?