将 arma::mat 邻接矩阵转换为 C 中的 igraph 图 (Rcpp)

Posted

技术标签:

【中文标题】将 arma::mat 邻接矩阵转换为 C 中的 igraph 图 (Rcpp)【英文标题】:Converting and an arma::mat adjacency matrix into an igraph graph in C (Rcpp) 【发布时间】:2019-09-06 11:03:04 【问题描述】:

我在一些处理矩阵的 (Rcpp) 代码中使用 Armadillo 对象。

矩阵是邻接矩阵,我需要快速计算底层网络的组件,尽管我可以通过 igraph 来完成。

但是我已经无法将邻接矩阵转换为可以与igraph 一起使用的东西。

#include <RcppArmadillo.h>
#include <iostream>
#include <igraph-0.7.1\include\igraph.h>

using namespace arma;

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
vec component_membership(const mat& adjacencymatrix) 
  igraph_t  g;
  igraph_adjacency(&g,&adjacencymatrix,IGRAPH_ADJ_DIRECTED);
  // here is more code that is immaterial to my problem

编译时会报错

 cannot convert 'const mat* aka const arma::Mat<double>*' to  
  'igraph_matrix_t*' for argument '2' to 
  'int igraph_adjacency(igraph_t*, igraph_matrix_t*, igraph_adjacency_t)'

我理解为什么会这样:我相信 igraph_matrix_tarma::matrix 必须是根本不同的数据类型。我如何转换,即,但我如何轻松解决这个问题?

【问题讨论】:

不确定adjacencymatrix 的类型是什么,但看起来该函数需要一个指向矩阵的指针并且您传递了一个矩阵。 adjacencymatrix 是如何声明的? 例如喜欢arma::mat adjacencymatrix=arma::zeros&lt;mat&gt;(10,10); 我认为指针不是问题,当我将调用更改为igraph_adjacency(&amp;g,&amp;adjacencymatrix,IGRAPH_ADJ_DIRECTED); 时,我得到` cannot convert const mat* aka const arma::Mat* to igraph_matrix_t * 用于参数 2 ....` 这肯定不像 C。它似乎是纯 C++。 【参考方案1】:

正如您所怀疑的,igraph_matrix_tarma::matrix 是完全不同的类型。 igraph documentation 没有列出可以使用 C 数组构造 igraph_matrix_t 的方法,所以我认为必须手动完成。像这样的东西可能会起作用(完全未经测试!):

igraph_matrix_t *m;
int rc = igraph_matrix_init(m, mat.n_rows, mat.n_cols);
for (unsigned long j = 0; j < mat.n_cols; ++j)
    for (unsigned long i = 0; i < mat.n_rows; ++i)
        igraph_matrix_set(m, i, j, mat(i, j));              

【讨论】:

【参考方案2】:

按照@Ralf_Stubner 的建议,我最终使用了以下代码。不确定它是否聪明,我想我还是会分享它

void armamat_to_igraph_matrix(const mat &x_in, igraph_matrix_t *x_out) 
  igraph_matrix_init(x_out, x_in.n_rows, x_in.n_cols);
  for (unsigned long j = 0; j < x_in.n_cols; ++j)
    for (unsigned long i = 0; i < x_in.n_rows; ++i)
      igraph_matrix_set(x_out, i, j, x_in(i, j));        
  return;

void igraph_vector_to_armauvec(const igraph_vector_t *x_in, uvec  &x_out) 
  x_out = uvec(igraph_vector_size(x_in));
  for (unsigned long j = 0; j < igraph_vector_size(x_in); ++j)
    x_out(j) = igraph_vector_e(x_in,j);        
  return;

void igraph_vector_to_armavec(const igraph_vector_t *x_in, vec  &x_out) 
  x_out = vec(igraph_vector_size(x_in));
  for (unsigned long j = 0; j < igraph_vector_size(x_in); ++j)
    x_out(j) = igraph_vector_e(x_in,j);        
  return;

【讨论】:

以上是关于将 arma::mat 邻接矩阵转换为 C 中的 igraph 图 (Rcpp)的主要内容,如果未能解决你的问题,请参考以下文章

使用 List 将 R 矩阵转换为 arma::mat

(Rcpp, armadillo) 将 arma::vec 转换为 arma::mat

将 arma::cx_mat 转换为数组数组

在 for 循环中获取 arma::mat 矩阵的每一行作为 arma::vec

使用 Rcpp 代码访问和修改 arma::sp_mat 类稀疏矩阵的非零元素

Armadillo - 从列向量中的值填充矩阵