将犰狳矩阵转换为特征MatriXd,反之亦然

时间:2017-10-12 02:40:31

标签: eigen rcpp armadillo

如何从Armadillo矩阵转换为Eigen MatrixXd,反之亦然?

我的nuarma::vec,尺寸为Nz为尺寸arma::mat的{​​{1}}。我想计算矩阵N x 3,例如条目P

P_ij

因此我使用了这段代码

Pij=exp(nu(i) + nu(j) + z.row(j)*z.row(j)))

但是计算时间太长了。特别是,对于int N=z.n_rows; mat P= exp(nu*ones(1,N) + one(N,1)*(nu.t()) + z*(z.t())); ,运行时间要高得多。

似乎使用Eigen可以更快。但我的矩阵是犰狳。我如何使用Eigen操作?或者我怎样才能更快地完成这项操作。

2 个答案:

答案 0 :(得分:4)

使用armadillo.memptr()类成员函数,我们可以提取内存指针。在这里,我们可以使用EigenMap<T>()构造函数来创建Eigen矩阵。

现在,我们可以使用Eigen成员函数从.data()矩阵中提取点到Eigen的内存结构。然后,使用advanced constructor options of arma::mat我们可以创建armadillo matrix

例如:

#include <RcppArmadillo.h>
#include <RcppEigen.h>

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

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

// [[Rcpp::export]]
Eigen::MatrixXd example_cast_eigen(arma::mat arma_A) {

  Eigen::MatrixXd eigen_B = Eigen::Map<Eigen::MatrixXd>(arma_A.memptr(),
                                                        arma_A.n_rows,
                                                        arma_A.n_cols);

  return eigen_B;
}

// [[Rcpp::export]]
arma::mat example_cast_arma(Eigen::MatrixXd eigen_A) {

  arma::mat arma_B = arma::mat(eigen_A.data(), eigen_A.rows(), eigen_A.cols(),
                               false, false);

  return arma_B;
}

/***R
(x = matrix(1:4, ncol = 2))
example_cast_eigen(x)
example_cast_arma(x)
*/

结果:

(x = matrix(1:4, ncol = 2))
#      [,1] [,2]
# [1,]    1    3
# [2,]    2    4

example_cast_eigen(x)
#      [,1] [,2]
# [1,]    1    3
# [2,]    2    4

example_cast_arma(x)
#      [,1] [,2]
# [1,]    1    3
# [2,]    2    4

一个快速评论:如果你使用的是Eigen的映射函数,那么你应该自动对Armadillo矩阵进行更改(反之亦然),例如

#include <RcppArmadillo.h>
#include <RcppEigen.h>

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

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

// [[Rcpp::export]]
void map_update(Eigen::MatrixXd eigen_A) {

  Rcpp::Rcout << "Eigen Matrix on Entry: " << std::endl << eigen_A << std::endl;

  arma::mat arma_B = arma::mat(eigen_A.data(), eigen_A.rows(), eigen_A.cols(),
                               false, false);

  arma_B(0, 0) = 10;
  arma_B(1, 1) = 20;

  Rcpp::Rcout << "Armadill Matrix after modification: " << std::endl << arma_B << std::endl;

  Rcpp::Rcout << "Eigen Matrix after modification: " << std::endl << eigen_A << std::endl;
}

执行命令

map_update(x)

输出:

Eigen Matrix on Entry: 
1 3
2 4

Armadill Matrix after modification: 
   10.0000    3.0000
    2.0000   20.0000

Eigen Matrix after modification: 
10  3
 2 20

答案 1 :(得分:1)

我只花了几个小时试图将Eigen稀疏矩阵转换为Armadillo稀疏矩阵,如果其他人发现需要这样做,我会在这里发布代码。

我这样做是因为我找不到稀疏复杂矩阵的本征解析器,而Armadillo是唯一拥有它的人,但我的其余代码已经在Eigen完成了所以我不得不进行转换。 / p>

#include <Eigen/Sparse>
#include <armadillo>
using namespace std;
using namespace arma;
int main() {
    auto matrixA = new SparseMatrix<complex<double>>(numCols, numRows); //your Eigen matrix

    /*
    SOME CODE TO FILL THE Eeigen MATRIX

    */
    //  now create a separate vectors for row indeces, first non-zero column element indeces and non-zero values
    //  why long long unsigned int, because armadilo will expect that type when constructing sparse matrix
    vector<long long unsigned int> rowind_vect((*matrixA).innerIndexPtr(),
                                               (*matrixA).innerIndexPtr() + (*matrixA).nonZeros());
    vector<long long unsigned int> colptr_vect((*matrixA).outerIndexPtr(),
                                               (*matrixA).outerIndexPtr() + (*matrixA).outerSize() + 1);
    vector<complex<double>> values_vect((*matrixA).valuePtr(),
                                        (*matrixA).valuePtr() + (*matrixA).nonZeros());

    //  you can delete the original matrixA to free up space
    delete matrixA;

    //new Armadillo vectors from std::vector, we set the flag copy_aux_mem=false, so we don't copy the values again
    cx_dvec values(values_vect.data(), values_vect.size(), false);
    uvec rowind(rowind_vect.data(), rowind_vect.size(), false);
    uvec colptr(colptr_vect.data(), colptr_vect.size(), false);

    //  now create Armadillo matrix from these vectors
    sp_cx_dmat arma_hamiltonian(rowind, colptr, values, numCols, numRows);

    //  you can delete the vectors here if you like to free up the space

    return 0; 

}