使用Armadillo访问较低三角形元素的更有效方式



是否有更有效的方法来创建包含矩阵下三角元素的向量?对于某些算法,在向量中只包含这些元素是有用的。

然而,下面的代码显然会创建副本,而我更喜欢指针。考虑到元素位置的非连续性,这可能是不可能的。

我想过的一个替代方案是通过find(trimatu(inmat)!=0)左右创建一个索引矩阵,但我无法想象这会更有效。在二重矩阵中找到精确的零通常不是很快,而且在我试图提取的三角形中可能有实际的0。这里已经讨论了一些类似的内容(C++Armadillo Access Triangular Matrix Elements(,然而,这个问题已经存在5年了,从那时起Armadillo已经改进了很多。

vec trimat2vec(mat const& inmat){
int K = inmat.n_rows;
int p = K*(K-1)/2;
vec out(p);
int counter=0;
for(int i=0; i<K; i++){
for(int j=1; j<K; j++){
if(i<j){
out(counter)=inmat(j,i);
counter+=1;
}
}
}
return(out);
}

好吧,有了新版本的Armadillo 9.870,现在有了更好的方法。速度的提高很小,尤其是在小矩阵上,但似乎是一致的。更重要的是,代码要短得多。

我调用新函数trimat2vec_new

vec trimat2vec_new(mat const& inmat){
return(inmat.elem(trimatl_ind(size(inmat),-1)));
}

R:中的简单基准

a=matrix(1:900,30,30)
all(trimat2vec_new(a) == trimat2vec(a))
library(microbenchmark)
microbenchmark(trimat2vec_new(a),
trimat2vec(a),
times = 1000)

收益率:

Unit: microseconds
expr   min     lq     mean median    uq    max neval cld
trimat2vec_new(a) 3.026 3.4060 3.633960  3.557 3.727 20.549  1000  a 
trimat2vec(a) 3.116 3.6515 3.955116  3.787 3.958 42.981  1000   b

我特别喜欢新的trimatl_ind功能的便利性。以及速度的小幅提升。

最新更新