C++ 使用RcppArmadillo用向量填充上三角矩阵(包括对角线)

C++ 使用RcppArmadillo用向量填充上三角矩阵(包括对角线),c++,r,rcpp,armadillo,C++,R,Rcpp,Armadillo,我正在学习Rcpp软件包的功能,以前没有使用C++的经验。我试过: #include <RcppArmadillo.h> // [[Rcpp::depends("RcppArmadillo")]] // [[Rcpp::export]] arma::mat VtoMatCpp(int n, arma::vec x) { arma::mat V = arma::eye<arma::mat>(n,n) ; V.elem(fin

我正在学习
Rcpp
软件包的功能,以前没有使用
C++
的经验。我试过:

#include <RcppArmadillo.h>

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

arma::mat VtoMatCpp(int n, 
                    arma::vec x) {

arma::mat V = arma::eye<arma::mat>(n,n) ;

V.elem(find(trimatu(V))) = x;

return(V);

}
#包括
//[[Rcpp::depends(“RcppArmadillo”)]]
//[[Rcpp::导出]]
arma::mat VtoMatCpp(国际编号,
arma::vec x){
arma::mat V=arma::眼(n,n);
V.elem(find(trimatu(V)))=x;
返回(V);
}

当我在R
sourceCpp('fun.cpp')
中使用时,然后尝试
VtoMatCpp(2,1:3)
get
Error:Mat::elem():大小不匹配
。看来
trimatu
函数没有拾取对角线的索引。

您得到了错误,因为您的
find
调用实际上是在查找非零元素(在本例中是您的对角线元素)。这导致您的
VtoMatCpp(2,1:3)
调用只有2个元素,其中3个元素太大,无法容纳

这有点类似于我的问题,我实际上想排除对角线元素。不幸的是,我现在能想到的最好办法就是基本上复制R如何使用
upper.tri
。下面是一个使用
RcppArmadillo
的工作示例

library(inline)

src <- '
using namespace arma;
using namespace Rcpp;

vec x = as<vec>(x_);

int n = as<int>(n_);
mat V = eye<mat>(n,n);

// make empty matrices
mat Z(n,n,fill::zeros);
mat X(n,n,fill::zeros);

// fill matrices with integers
vec idx = linspace<mat>(1,n,n);
X.each_col() += idx;
Z.each_row() += trans(idx);

// assign upper triangular elements
// the >= allows inclusion of diagonal elements
V.elem(find(Z>=X)) = x;

return(wrap(V));
'

fun <- cxxfunction(signature(n_ = "integer", x_ = "vector"), 
                   body=src, plugin="RcppArmadillo")

fun(2,1:3)

     [,1] [,2]
[1,]    1    2
[2,]    0    3
运行快速基准测试确实表明此实现比
base
R更快。在这里,我将上面的
base
解决方案包装为
fun2

library(microbenchmark)
microbenchmark(fun(100, seq(5050)), fun2(100, seq(5050)))

Unit: microseconds
                 expr     min      lq     mean   median       uq      max neval
  fun(100, seq(5050)) 117.823 154.106 241.2361 188.2575 242.0360 3392.611   100
 fun2(100, seq(5050)) 545.042 592.988 736.6958 622.7405 650.7475 4057.011   100

本周我遇到了同样的问题,由于使用了
arma::trimatl\u ind
函数,我可以找到一个令人满意的解决方案。尽管@cdeterman的答案已经解决了这个问题,但我相信我的解决方案更容易理解,也更简洁。此外,我的判断是珍贵答案中实现的函数是错误的,因此我也重写了它

库(内联)
fun2[2,]03
最后,我还做了一个时间比较。我的实现比之前提出的
Rcpp
解决方案略快。然而,从时间比较中得到的最令人惊讶的信息是在R中实现的函数的性能是如何改进的

microbenchmark::microbenchmark(
“r”=fun2(100,seq(5050)),
“rcpp1”=乐趣(100,序号(5050)),
“rcpp2”=fun3(100,序号(5050))
)
#>单位:微秒
#>expr最小lq平均uq最大neval
#>r 74.902 84.1845 311.6322 89.2775 149.7765 20276.213 100
#>rcpp1 67.045 109.1470 141.0202 116.8895 191.0715 229.312 100
#>rcpp2 54.575 106.3015 136.6472 114.3975 182.0125 231.395 100
下面是我的会话信息

由(v0.3.0)于2020年12月9日创建

devtools::session_info()
#> ─ 会话信息───────────────────────────────────────────────────────────────
#>设定值
#>R版4.0.3版(2020-10-10)
#>操作系统Ubuntu 20.04.1 LTS
#>系统x86_64,linux gnu
#>ui X11
#>语言(英文)
#>核对en_US.UTF-8
#>ctype en_US.UTF-8
#>tz美国/纽约
#>日期2020-12-09
#> 
#> ─ 包装───────────────────────────────────────────────────────────────────
#>包*版本日期库源
#>资产负债表0.2.1 2019-03-21[2]起重机(R 4.0.2)
#>callr 3.5.1 2020-10-13[2]起重机(R 4.0.3)
#>cli 2.2.0 2020-11-20[2]起重机(R 4.0.3)
#>蜡笔1.3.4 2017-09-16[2]克兰(R4.0.2)
#>描述1.2.0 2018-05-01[2]起重机(R 4.0.2)
#>开发工具2.3.2 2020-09-18[2]起重机(R 4.0.3)
#>文摘0.6.27 2020-10-24[2]CRAN(R 4.0.3)
#>省略号0.3.1 2020-05-15[2]CRAN(R 4.0.2)
#>评估0.14 2019-05-28[2]起重机(R 4.0.2)
#>fansi 0.4.1 2020-01-08[2]起重机(R 4.0.2)
#>fs 1.5.0 2020-07-31[2]起重机(R4.0.3)
#>胶水1.4.2 2020-08-27[2]起重机(R 4.0.2)
#>高0.8 2019-03-20[2]克朗(R4.0.2)
#>htmltools 0.5.0 2020-06-16[2]起重机(R4.0.2)
#>内联*0.3.16 2020-09-06[2]起重机(R4.0.3)
#>克尼特1.30 2020-09-22[2]克兰(R 4.0.3)
#>magrittr 2.0.1 2020-11-17[2]起重机(R 4.0.3)
#>备忘录1.1.0 2017-04-21[2]克兰(R 4.0.2)
#>微型基准1.4-7 2019-09-24[2]起重机(R 4.0.2)
#>pkgbuild 1.1.0 2020-07-13[2]起重机(R 4.0.2)
#>pkgload 1.1.0 2020-05-29[2]起重机(R4.0.2)
#>prettyunits 1.1.1 2020-01-24[2]起重机(R 4.0.2)
#>processx 3.4.5 2020-11-30[2]起重机(R 4.0.3)
#>ps 1.4.0 2020-10-07[2]起重机(R 4.0.3)
#>R6 2.5.0 2020-10-28[2]起重机(R4.0.3)
#>Rcpp 1.0.5 2020-07-06[2]起重机(R 4.0.2)
#>RcppArmadillo 0.9.900.3.0 2020-09-03[2]起重机(R 4.0.2)
#>遥控器2.2.0 2020-07-21[2]起重机(R4.0.3)
#>rlang 0.4.9 2020-11-26[2]起重机(R 4.0.3)
#>R标记2.4 2020-09-30[2]起重机(R 4.0.3)
#>rprojroot 2.0.2 2020-11-15[2]起重机(R 4.0.3)
#>会议信息1.1.1 2018-11-05[2]CRAN(R 4.0.2)
#>stringi 1.5.3 2020-09-09[2]起重机(R 4.0.3)
#>纵梁1.4.0 2019-02-10[2]起重机(R4.0.2)
#>测试3.0.0 2020-10-31[2]起重机(R4.0.3)
#>使用本1.6.3 2020-09-17[2]起重机(R 4.0.3)
#>带R 2.3.0 2020-09-22[2]起重机
library(microbenchmark)
microbenchmark(fun(100, seq(5050)), fun2(100, seq(5050)))

Unit: microseconds
                 expr     min      lq     mean   median       uq      max neval
  fun(100, seq(5050)) 117.823 154.106 241.2361 188.2575 242.0360 3392.611   100
 fun2(100, seq(5050)) 545.042 592.988 736.6958 622.7405 650.7475 4057.011   100