使用 Boost图库我正在寻找一种方法从boost::adjacency_list
或{{1}代表的基础图中提取邻接矩阵 }。我想结合boost::adjacency_matrix
使用这个矩阵来求解一个联立线性方程组。
这是一个让你前进的最小例子:
boost::numeric::ublas
如果有人能想出一种有效的方法来获得邻接矩阵,我将非常感激。理想情况下,该解决方案与uBLAS兼容。我想知道是否有办法避免遍历整个图表。
答案 0 :(得分:1)
将adjacency_list转换为adjacency_matrix的最简单方法是使用boost::copy_graph
MatrixGraph mg
的代码应修改如下
#include <boost/graph/copy.hpp>
#include <cassert>
using namespace boost;
typedef boost::adjacency_list< listS, vecS, directedS > ListGraph;
typedef boost::adjacency_matrix< directedS > MatrixGraph;
int main(){
ListGraph lg;
add_edge(0, 1, lg);
add_edge(0, 3, lg);
add_edge(1, 2, lg);
add_edge(2, 3, lg);
//How do I get the adjacency matrix underlying lg?
//How do I get the adjacency matrix underlying mg?
MatrixGraph mg( num_vertices(lg));
boost::copy_graph(lg, mg);
}
现在,要使用与ublas或类似的邻接矩阵,您可以编写一个简单的“访问”类,以使语法更符合ublas。继续前面的代码片段,我们得到:
template <class Graph>
class MatrixAccessor
{
public:
typedef typename Graph::Matrix Matrix; //actually a vector<
typedef typename Matrix::const_reference const_reference;
MatrixAccessor(const Graph* g)
: m_g(g)
{
static_assert(boost::is_same<size_t, typename Graph::vertex_descriptor>::value, "Vertex descriptor should be of integer type");
}
const_reference operator()(size_t u, size_t v) const
{
return m_g->get_edge(u, v);
}
const Graph* m_g;
};
void use_matrix(const MatrixGraph & mg)
{
MatrixAccessor<MatrixGraph> matr(&mg);
assert(matr(0, 1) == 1);
assert(matr(0, 2) == 0);
}
如果您的adjacency_matrix具有一些边缘捆绑属性,您可能需要修改MatrixAccessor中的operator()。
根据您使用的uBLAS数量,您可以进一步优化MatrixAccessor。例如,对于MatrixGraph的给定顶点,out_edge_iterator
实际上是矩阵列上的迭代器; vertex_iterator可以被视为矩阵行等的迭代器。
当然,图表矩阵是不可变的,因此应谨慎使用。
答案 1 :(得分:1)
这是一个简单的方法,我不知道它有多高效。 这就是我想出的:
我使用了一个小世界图并打印了邻接矩阵。
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/small_world_generator.hpp>
#include <boost/random/linear_congruential.hpp>
using namespace std;
using namespace boost;
typedef adjacency_list<vecS, vecS, undirectedS> Graph;
typedef small_world_iterator<boost::minstd_rand, Graph> SWGen;
int main()
{
boost::minstd_rand gen;
int N = 20;
int degree = 4;
double rewiring = 0.;
Graph g(SWGen(gen, N, degree, rewiring), SWGen(), 20);
cout << num_edges(g)<< '\n';
typedef graph_traits<Graph>::edge_iterator edge_iterator;
pair<edge_iterator, edge_iterator> ei = edges(g);
for(edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter) {
cout << "(" << source(*edge_iter, g) << ", " << target(*edge_iter, g) << ")\n";
}
vector<vector<int> > mat(N,vector<int>(N));
for (edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter){
int a = source(*edge_iter, g);
int b = target(*edge_iter, g);
mat[a][b] = 1;
mat[b][a] = 1;
}
for (int i=0; i<N; i++){
for (int j=0; j<N; j++){
cout << mat[i][j]<<" ";
}
cout <<endl;
}
return 0;
}
<强>输出:强>
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
答案 2 :(得分:0)
adjacency_matrix
的{{3}}有一个无证件的公共成员m_matrix
(参见第640行)。但是,它是元组<bool, bundled_properties>
的平面向量(第512行)。由于底层存储看起来与ublas矩阵有很大不同,因此除了迭代边缘之外,很可能无法将图形转换为矩阵。