Более эффективный способ доступа к элементам с более низким уровнем три angular с использованием Armadillo - PullRequest
0 голосов
/ 09 апреля 2020

Есть ли более эффективный способ создания вектора, содержащего нижние элементы tri angular матрицы? Для некоторых алгоритмов полезно иметь эти элементы в векторе.

Однако приведенный ниже код явно создает копии, когда я предпочитаю указатели. Это, вероятно, невозможно, учитывая неконкурентный характер позиций элементов.

Одна альтернатива, о которой я подумал, - это создать индексную матрицу с помощью find(trimatu(inmat)!=0) или около того, но я не могу представить, что это больше эффективный. Поиск точных нулей в матрице парных чисел обычно не очень быстрый, а также могут быть фактические 0 в пределах tri angular, который я пытаюсь извлечь. Нечто в этом направлении обсуждалось здесь ( C ++ Armadillo Access Tri angular Matrix Elements ), однако этому вопросу уже 5 лет, и с тех пор броненосец значительно улучшился.

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);
}

1 Ответ

0 голосов
/ 28 апреля 2020

Хорошо, с новой версией 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. И небольшое улучшение скорости.

...