将犰狳矩阵转换为特征矩阵,反之亦然
Converting an Armadillo Matrix to an Eigen MatriXd and vice versa
如何将 Armadillo 矩阵转换为 Eigen MatrixXd,反之亦然?
我有 nu
作为尺寸 N
的 arma::vec
,z
作为尺寸 N x 3
的 arma::mat
。我想计算一个矩阵 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()));
但是计算时间太长。特别是,对于 N = 50,000
,运行 时间太长了。
看来使用Eigen可以更快一些。但我的矩阵是犰狳。如何使用 Eigen 操作?或者我怎样才能更快地完成这个操作。
使用 armadillo's .memptr()
class member function, we are able to extract the memory pointer. From here, we can use Eigen's Map<T>()
constructor to create an Eigen 矩阵。
现在,我们可以从 Eigen matrix using the .data()
member function to extract a point to Eigen's memory structure. Then, using the advanced constructor options of arma::mat
we can create an 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 的映射功能,那么您应该自动在犰狳矩阵中进行更改(反之亦然),例如
#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
我只是花了几个小时尝试将 Eigen 稀疏矩阵转换为 Armadillo 稀疏矩阵,如果其他人发现需要这样做,我将 post 代码放在这里。
我这样做是因为我找不到稀疏复数矩阵的特征求解器,Armadillo 是唯一拥有它的,但我的其余代码已经在 Eigen 中完成,所以我必须进行转换.
#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;
}
如何将 Armadillo 矩阵转换为 Eigen MatrixXd,反之亦然?
我有 nu
作为尺寸 N
的 arma::vec
,z
作为尺寸 N x 3
的 arma::mat
。我想计算一个矩阵 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()));
但是计算时间太长。特别是,对于 N = 50,000
,运行 时间太长了。
看来使用Eigen可以更快一些。但我的矩阵是犰狳。如何使用 Eigen 操作?或者我怎样才能更快地完成这个操作。
使用 armadillo's .memptr()
class member function, we are able to extract the memory pointer. From here, we can use Eigen's Map<T>()
constructor to create an Eigen 矩阵。
现在,我们可以从 Eigen matrix using the .data()
member function to extract a point to Eigen's memory structure. Then, using the advanced constructor options of arma::mat
we can create an 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 的映射功能,那么您应该自动在犰狳矩阵中进行更改(反之亦然),例如
#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
我只是花了几个小时尝试将 Eigen 稀疏矩阵转换为 Armadillo 稀疏矩阵,如果其他人发现需要这样做,我将 post 代码放在这里。
我这样做是因为我找不到稀疏复数矩阵的特征求解器,Armadillo 是唯一拥有它的,但我的其余代码已经在 Eigen 中完成,所以我必须进行转换.
#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;
}