简体   繁体   English

如何在 Boost 图形库中读取图形到邻接矩阵?

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

In the boost graph library, there are two popular functions to read in graphs from a file: boost::read_graphviz() , and boost::read_graphml() , for the GraphViz and the GraphML format , respectively.在 boost 图形库中,有两个流行的函数可以从文件中读取图形: boost::read_graphviz()boost::read_graphml() ,分别用于GraphVizGraphML 格式

Now both read generically to any type of boost::adjacency_list<...> , as they are models of the Mutable Graph concept:现在两者都通用读取任何类型的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;
}

If you were to test如果你要测试

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

you might get something like你可能会得到类似的东西

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

So how can I include the possibility to read to a boost::adjacency_matrix<...> , preferably without having to copy the graph from an intermediate adjacency list, as explained in this SO post (the graph may be really large).那么我怎样才能包括读取到boost::adjacency_matrix<...>的可能性,最好不必从中间邻接列表中复制图形,如this SO post中所述(图形可能非常大)。

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?并没有入一个?

Thanks for any help!谢谢你的帮助!

Note笔记

The boost/graph/graphml.hpp library is not header-only and needs to be linked against, for example by appending -lboost_graph when compiling/linking directly from the CLI, as in boost/graph/graphml.hpp库不是仅标头,需要链接,例如在直接从 CLI 编译/链接时附加-lboost_graph ,如

g++ -lboost_graph my_file.cc

Regarding copy_graph关于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?并没有读入一个?

I agree.我同意。 That doesn't make sense.那没有意义。 For all it appears the copy_graph should not work or the documented concept requirement is out-of-date.尽管如此, copy_graph似乎不应该工作,或者记录的概念要求已经过时。

Perhaps it was always over-constrained, or specializations have been added specifically for adjacency_matrix .也许它总是被过度约束,或者专门为adjacency_matrix添加了专业化。

A cursory glance tells that it might have been over-constrained since clearly no specializations/overloads exist for adjacency_matrix.粗略的一瞥表明它可能已经过度约束,因为很明显不存在 adjacency_matrix 的特化/重载。

Before we test, let's look at the assertion.在我们测试之前,让我们看一下断言。

Regarding the Assertion关于断言

The assert stems here:断言源于这里:

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

As you can see this was already an area where more flexibility was being planned.正如您所看到的,这已经是一个正在规划更多灵活性的领域。 It does seem likely that if you reserve enough space, you might be able to read the graph.如果您保留足够的空间,您似乎可以阅读图表。

The same might be what already powers copy_graph (in that add_vertex is just avoided when the capacity already suffices; even though add_vertex is still technically ( conceptually ) required, it may not always be.可能已经为copy_graph提供了动力(因为当容量已经足够时才避免使用add_vertex ;即使在技术上(概念上)仍然需要add_vertex ,但可能并不总是如此。

Testing The Hypotheses检验假设

Let's put it to the test.让我们来测试一下。 See whether we can actually copy from adjacency list into a matrix:看看我们是否真的可以从邻接表复制到矩阵中:

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

( ¹ The directionality doesn't actually make a difference, I tested ) ¹方向性实际上并没有什么不同,我测试过

There's the answer to our riddle.这就是我们的谜语的答案。 We can't actually copy.我们实际上无法复制。

It does compile but it doesn't run without assertion.它确实可以编译,但没有断言就无法运行。

Now, you are probably thinking you can #define NDEBUG and silence the assertion.现在,您可能认为您可以#define NDEBUG并使断言保持沉默。 However, looking at the code above it's clear that you cannot expect this to work, because it will always return vertex 0 :然而,看看上面的代码,很明显你不能指望它会起作用,因为它总是会返回顶点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:");
}

Prints印刷

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

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

That's cleary not correct, though it is what you'd expect from reading the code.这显然是不正确的,尽管这是您阅读代码所期望的。

Closing Words结束语

It could be easier to just write some parsing code manually.手动编写一些解析代码可能更容易。 If you must you might read into a heavily optimized adjacency list first.如果必须,您可以先阅读经过高度优化的邻接列表。 For example you could memory map it completely.例如,您可以完全使用 memory map。

If boost::adjacency_list doesn't let you, you can consider providing your own datastructures modeling the Mutable Graph concept.如果boost::adjacency_list不允许,您可以考虑提供自己的数据结构来建模可变图概念。 That may sound daunting, but it's actually less work than you might expect:这听起来可能令人生畏,但实际上它的工作量比您预期的要少:

To be frank, those answers are less complex than the bonus section I just made on your other question.坦率地说,这些答案没有我刚刚针对您的其他问题所做的奖励部分复杂。 Do give them a read for inspiration (starting with the first one)一定要给他们阅读灵感(从第一个开始)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM