将 arma::mat 邻接矩阵转换为 C (Rcpp) 中的 igraph 图
Converting and an arma::mat adjacency matrix into an igraph graph in C (Rcpp)
我在处理矩阵的某些 (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_t
和 arma::matrix
必须是根本不同的数据类型。我该如何转换,即如何轻松解决这个问题?
如您所料,igraph_matrix_t
和arma::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));
根据@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;
}
我在处理矩阵的某些 (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_t
和 arma::matrix
必须是根本不同的数据类型。我该如何转换,即如何轻松解决这个问题?
如您所料,igraph_matrix_t
和arma::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));
根据@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;
}