Динамически увеличивать размер списка в Rcpp

Я пытаюсь реализовать алгоритм «связи с прошлым» в Rcpp. Для этого мне нужно сохранить матрицу случайных чисел, и если алгоритм не сошелся, создайте новую матрицу случайных чисел и сохраните ее. Возможно, это придется сделать более 10 раз или около того, пока не сойдется.

Я надеялся, что смогу использовать List и динамически обновлять его, как в R. На самом деле я был очень удивлен, что это немного сработало, но у меня возникали ошибки всякий раз, когда размер списка становился большим. Кажется, это имеет смысл, так как я не выделил необходимую память для дополнительных элементов списка, хотя я не очень хорошо знаком с C++ и не уверен, что проблема в этом.

Вот пример того, что я пробовал. однако имейте в виду, что это, вероятно, приведет к сбою сеанса R:

library("Rcpp")

cppFunction(
includes = ' 
NumericMatrix RandMat(int nrow, int ncol)
 {
  int N = nrow * ncol;
  NumericMatrix Res(nrow,ncol);
  NumericVector Rands  = runif(N);
   for (int i = 0; i < N; i++) 
  {
    Res[i] = Rands[i];
  }
  return(Res);
 }',

code = '
void foo()
{
  // This is the relevant part, I create a list then update it and print the results:
  List x;
  for (int i=0; i<10; i++)  
  {
   x[i] = RandMat(100,10);
   Rf_PrintValue(wrap(x[i]));
  }
}
')


foo()

Кто-нибудь знает способ сделать это без сбоя R? Думаю, здесь я мог бы инициировать список с фиксированным количеством элементов, но в моем приложении количество элементов является случайным.


person Sacha Epskamp    schedule 01.08.2013    source источник


Ответы (1)


Вы должны «выделить» достаточно места для своего списка. Возможно, вы можете использовать что-то вроде resizefunction:

List resize( const List& x, int n ){
    int oldsize = x.size() ;
    List y(n) ;
    for( int i=0; i<oldsize; i++) y[i] = x[i] ;
    return y ;
}

и всякий раз, когда вы хотите, чтобы ваш список был больше, чем сейчас, вы можете сделать:

x = resize( x, n ) ;

Ваш исходный список имеет размер 0, поэтому ожидалось, что вы получите непредсказуемое поведение на первой итерации вашего цикла.

person Romain Francois    schedule 01.08.2013
comment
Вы также можете делать такие вещи, как x.push_back(newElement) с обычной оговоркой, что внизу делается полная копия. Это действительно векторы внизу, и вы должны сначала зарезервировать место. В качестве альтернативы, растите типы данных STL (у них это получается лучше) и конвертируйте в типы R/Rcpp перед возвратом. - person Dirk Eddelbuettel; 01.08.2013
comment
Одно различие между использованием List или STL-коллекции заключается в том, что первая гарантирует защиту от сборки мусора своих элементов, а вторая — нет. Защита каждого элемента невозможна для больших коллекций (ограничения скорости и стека RecursiveRelease), поправьте меня, если я ошибаюсь. - person piccolbo; 29.01.2014