RcppArmadillo:带有 each_slice 的 Lambda 表达式
RcppArmadillo: Lambda expression with each_slice
我有一个正定矩阵的三维数组,我想获得一个大小与所有矩阵的 Cholesky 因子相同的数组。我正在使用 Armadillo 库和 cube
类型,为此我正在尝试使用方便的函数 each_slice
。但是我没有让 lambda 表达式正常工作,所以希望有人能帮助我并指出我的错误。
这是一个最小的例子:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
arma::cube chol_array(arma::cube Sigma) {
arma::cube Sigma_chol = Sigma;
Sigma_chol.each_slice([](arma::mat X) {return arma::chol(X);});
return Sigma_chol;
}
// [[Rcpp::export]]
arma::cube chol_array2(arma::cube Sigma) {
arma::cube Sigma_chol(size(Sigma));
for (arma::uword i = 0; i < Sigma.n_slices; i++) {
Sigma_chol.slice(i) = arma::chol(Sigma.slice(i));
}
return Sigma_chol;
}
/*** R
Sigma <- array(crossprod(matrix(rnorm(9), 3, 3)), dim = c(3, 3, 2))
chol_array(Sigma)
chol_array2(Sigma)
*/
函数 chol_array2
完成这项工作,但 chol_array
只是 returns 原始矩阵。我错过了什么?
这里的问题是 .each_slice()
调用中缺少引用。 Armadillo 对 lambda 表达式的使用需要引用来更新对象并且 而不是 return 语句。特别是,我们有:
For form 3:
apply the given lambda_function to each slice; the function must accept a reference to a Mat object with the same element type as the underlying cube
所以,改变:
Sigma_chol.each_slice([](arma::mat X) {return arma::chol(X);});
至:
Sigma_chol.each_slice([](arma::mat& X) {X = arma::chol(X);});
固定代码
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// Enable lambda expressions....
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
arma::cube chol_array(arma::cube Sigma) {
arma::cube Sigma_chol = Sigma;
// NOTE: the '&' and saving _back_ into the object are crucial
Sigma_chol.each_slice( [](arma::mat& X) { X = arma::chol(X); } );
return Sigma_chol;
}
测试代码
set.seed(1113)
Sigma = array(crossprod(matrix(rnorm(9), 3, 3)), dim = c(3, 3, 2))
all.equal(chol_array(Sigma), chol_array2(Sigma))
# [1] TRUE
我有一个正定矩阵的三维数组,我想获得一个大小与所有矩阵的 Cholesky 因子相同的数组。我正在使用 Armadillo 库和 cube
类型,为此我正在尝试使用方便的函数 each_slice
。但是我没有让 lambda 表达式正常工作,所以希望有人能帮助我并指出我的错误。
这是一个最小的例子:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
arma::cube chol_array(arma::cube Sigma) {
arma::cube Sigma_chol = Sigma;
Sigma_chol.each_slice([](arma::mat X) {return arma::chol(X);});
return Sigma_chol;
}
// [[Rcpp::export]]
arma::cube chol_array2(arma::cube Sigma) {
arma::cube Sigma_chol(size(Sigma));
for (arma::uword i = 0; i < Sigma.n_slices; i++) {
Sigma_chol.slice(i) = arma::chol(Sigma.slice(i));
}
return Sigma_chol;
}
/*** R
Sigma <- array(crossprod(matrix(rnorm(9), 3, 3)), dim = c(3, 3, 2))
chol_array(Sigma)
chol_array2(Sigma)
*/
函数 chol_array2
完成这项工作,但 chol_array
只是 returns 原始矩阵。我错过了什么?
这里的问题是 .each_slice()
调用中缺少引用。 Armadillo 对 lambda 表达式的使用需要引用来更新对象并且 而不是 return 语句。特别是,我们有:
For form 3:
apply the given lambda_function to each slice; the function must accept a reference to a Mat object with the same element type as the underlying cube
所以,改变:
Sigma_chol.each_slice([](arma::mat X) {return arma::chol(X);});
至:
Sigma_chol.each_slice([](arma::mat& X) {X = arma::chol(X);});
固定代码
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// Enable lambda expressions....
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
arma::cube chol_array(arma::cube Sigma) {
arma::cube Sigma_chol = Sigma;
// NOTE: the '&' and saving _back_ into the object are crucial
Sigma_chol.each_slice( [](arma::mat& X) { X = arma::chol(X); } );
return Sigma_chol;
}
测试代码
set.seed(1113)
Sigma = array(crossprod(matrix(rnorm(9), 3, 3)), dim = c(3, 3, 2))
all.equal(chol_array(Sigma), chol_array2(Sigma))
# [1] TRUE