【问题标题】:Extract the adjacency matrix from a BGL graph从 BGL 图中提取邻接矩阵
【发布时间】:2013-03-10 20:46:21
【问题描述】:

使用 Boost Graph Library 我正在寻找一种方法来boost::adjacency_listboost::adjacency_matrix 表示的基础图中提取邻接矩阵。我想将此矩阵与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?

}

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

【问题讨论】:

  • 我不确定,但我认为没有不涉及遍历图形的方法来完成此任务。希望有人能证明我错了,但与此同时,您可以看到 here 通过迭代真的很容易。

标签: c++ boost boost-graph


【解决方案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。继续之前的 sn-p 我们得到:

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 可以被视为矩阵行等的迭代器。

当然,图矩阵是不可变的,因此应谨慎使用。

【讨论】:

    【解决方案2】:

    只是一种简单的方法,我不知道它的效率如何。 这是我想出的:

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

    #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 
    

    【讨论】:

      【解决方案3】:

      adjacency_matrixcurrent revision 有一个无证公共成员 m_matrix(见第 640 行)。但是,它是元组 &lt;bool, bundled_properties&gt; 的平面向量(第 512 行)。由于底层存储看起来与 ublas 矩阵如此不同,因此除了迭代边之外,很可能无法将图转换为矩阵。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多