C++ 从BGL图中提取邻接矩阵

C++ 从BGL图中提取邻接矩阵,c++,boost,boost-graph,C++,Boost,Boost Graph,使用Boost图形库我正在寻找一种方法来从由Boost::adjacence_列表或Boost::adjacence_矩阵表示的基础图中提取邻接矩阵。我想将此矩阵与boost::numeric::ublas结合使用,以求解联立线性方程组 下面是一个简单的示例,可以帮助您继续: #include <boost/graph/adjacency_list.hpp> #include <boost/graph/adjacency_matrix.hpp> using namesp

使用Boost图形库我正在寻找一种方法来从由
Boost::adjacence_列表
Boost::adjacence_矩阵
表示的基础图中提取邻接矩阵。我想将此矩阵与
boost::numeric::ublas
结合使用,以求解联立线性方程组

下面是一个简单的示例,可以帮助您继续:

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>

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?

  MatrixGraph mg(3); 
  add_edge (0, 1, mg); 
  add_edge (0, 3, mg); 
  add_edge (1, 2, mg); 
  add_edge (2, 3, mg); 

  //How do I get the adjacency matrix underlying mg?

}
#包括
#包括
使用名称空间boost;
typedef boost::邻接列表<列表、向量、方向>列表图;
typedef boost::邻接矩阵矩阵图;
int main(){
列表图lg;
添加_边(0,1,lg);
添加_边(0,3,lg);
添加_边(1,2,lg);
添加_边(2,3,lg);
//如何获得lg下的邻接矩阵?
矩阵图mg(3);
添加_边缘(0,1,mg);
添加_边缘(0,3,mg);
添加_边缘(1,2,mg);
添加_边缘(2,3,mg);
//如何获得mg下的邻接矩阵?
}

如果有人能想出一个有效的方法来获得邻接矩阵,我将不胜感激。理想情况下,该解决方案与uBLAS兼容。我想知道是否有一种方法可以避免整个图中的迭代。

邻接矩阵的
有一个未记录的公共成员
m\u矩阵(参见第640行)。但是,它是元组的平面向量
(第512行)。由于底层存储看起来与ublas矩阵非常不同,因此除了在边上迭代外,很可能无法将图形转换为矩阵。

将邻接列表转换为邻接矩阵的最简单方法是使用
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);
}
#包括
#包括
使用名称空间boost;
typedef boost::邻接列表<列表、向量、方向>列表图;
typedef boost::邻接矩阵矩阵图;
int main(){
列表图lg;
添加_边(0,1,lg);
添加_边(0,3,lg);
添加_边(1,2,lg);
添加_边(2,3,lg);
//如何获得lg下的邻接矩阵?
//如何获得mg下的邻接矩阵?
矩阵图mg(num_顶点(lg));
boost::复制图(lg,mg);
}
现在,若要将邻接矩阵与ublas或类似工具结合使用,可以编写一个简单的“access”类,使语法更符合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);
}
模板
类矩阵接受器
{
公众:
typedef typename图形::矩阵矩阵;//实际上是一个向量<
typedef typename矩阵::常量引用常量引用;
矩阵接受器(常数图*g)
:m_g(g)
{
静态_断言(boost::is_same::value,“顶点描述符应为整数类型”);
}
常量引用运算符()(大小,大小)常量
{
返回m_g->获取边(u,v);
}
常数图*m_g;
};
无效使用矩阵(常数矩阵图和mg)
{
MatrixAccessor matr(&mg);
断言(matr(0,1)==1);
断言(matr(0,2)==0);
}
如果您的邻接矩阵具有一些边绑定属性,则可能需要修改MatrixAccessor中的运算符()

根据您使用的uBLAS数量,您可以进一步优化MatrixAccessor。例如,矩阵图的给定顶点的
out\u edge\u迭代器实际上是矩阵列上的迭代器;顶点迭代器可以视为矩阵行上的迭代器等


当然,图形矩阵是不可变的,因此应该小心使用。

这是一种简单的方法,我不知道它的效率有多高。 这就是我想到的:

我使用了一个小世界图并打印了邻接矩阵

#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