Можно ли использовать объекты R (NumericVector, NumericMatrix) в std ::pair?

#c #r #rcpp

#c #r #rcpp

Вопрос:

Я новичок в Rcpp (и, следовательно, cpp), и я застрял на том, как правильно использовать std::pair .

Я работаю с графами, и структура данных для графика: std::vector<std::vector<std::pair<int, double> > >

Мне нужно расширить концепцию единого веса. Я написал пару минималистичных примеров. Все это принимает матрицу и возвращает ту же самую матрицу (после выполнения необходимых операций она будет проходить в реальном коде. Поэтому важно, чтобы структура данных графа была std::vector<std::vector<std::pair<int, ?> > > такой, чтобы holding вектор выполнял обратные действия и чтобы a Rcpp::NumericMatrix возвращался с использованием элементов holding в конце):

1.

 Rcpp::cppFunction('
  NumericMatrix test_stdvector(Rcpp::NumericMatrix x) {
  
    std::vector<std::pair<int, std::vector<double> > > holding(x.nrow());
    
    for (int i=0; i < x.nrow(); i  ) {
      NumericVector nv_x = x.row(i);
      std::vector<double> b =  Rcpp::as<std::vector<double> >(nv_x);
      holding.push_back(std::make_pair(i, b));
    }
  
    Rcpp::NumericMatrix y(x.nrow(), x.ncol());
    for (int i=0; i < x.nrow(); i  ) {
    
      NumericVector b = wrap(holding[i].second);
      y(i, _) = b;
    }
    
    return y;
  }
') 
  
 Rcpp::cppFunction('
  NumericMatrix test_numericvector(Rcpp::NumericMatrix x) {
  
    std::vector<std::pair<int, Rcpp::NumericVector> > holding(x.nrow());
    
    for (int i=0; i < x.nrow(); i  ) {
      holding.push_back(std::make_pair(i, x(i, _)));
    }
  
    Rcpp::NumericMatrix y(x.nrow(), x.ncol());
    for (int i=0; i < x.nrow(); i  ) {
    
      y(i, _) = holding[i].second;
    }
    
    return y;
  }
')
  

Обе функции компилируются нормально, однако для ввода x = matrix(1:100, nrow=10) вывод получается странным:

                [,1]          [,2]          [,3]          [,4]          [,5]          [,6]          [,7]          [,8]          [,9]
 [1,] 1.356944e-311 2.121996e-314 1.356944e-311 1.355961e-311 1.355961e-311 1.355967e-311 1.356944e-311 1.356944e-311 2.121996e-314
 [2,] 1.356944e-311 9.881313e-324 1.356944e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.356944e-311 2.121996e-314
 [3,] 1.356944e-311 9.881313e-324 1.356944e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.356944e-311 2.121996e-314
 [4,] 1.356944e-311 9.881313e-324 1.356944e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.356944e-311 2.121996e-314
 [5,] 1.356944e-311 9.881313e-324 1.356944e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.356944e-311 2.121996e-314
 [6,] 1.356944e-311 9.881313e-324 1.356944e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.356944e-311 2.121996e-314
 [7,] 1.356944e-311 9.881313e-324 1.356944e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.356944e-311 2.262910e-314
 [8,] 1.356944e-311 9.881313e-324 1.356944e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.356944e-311 2.121996e-314
 [9,] 1.356944e-311 9.881313e-324 1.356944e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.356944e-311 2.121996e-314
[10,] 1.356944e-311 9.881313e-324 1.356944e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.355961e-311 1.356944e-311 2.121996e-314
              [,10]
 [1,] 1.356944e-311
 [2,] 1.356944e-311
 [3,] 1.356944e-311
 [4,] 1.356944e-311
 [5,] 1.356944e-311
 [6,] 1.356944e-311
 [7,] 1.356944e-311
 [8,] 1.356944e-311
 [9,] 1.356944e-311
[10,] 1.356944e-311
  

Может кто-нибудь, пожалуйста, объяснить, что происходит?

Заранее спасибо

Ответ №1:

Я бы рекомендовал тщательную отладку и проверку индекса, возможно, с меньшими примерами.

Вы также можете распечатать матрицу по пути, чтобы проверить, что вы получаете данные в начале, достаточно простого print(x); на уровне C . То же самое для y before return .

Я бы начал, возможно, с примеров 3×3 и попытался бы сделать это правильно. И я не думаю, что у нас есть конвертеры для std::pair .

Наконец, иногда это мелочи: на y(i, _) = holding[i].second; самом деле вы делаете несколько вещей одновременно, когда вы извлекаете и переназначаете. Иногда это помогает извлечь временную переменную, а затем назначить эту временную переменную.

Комментарии:

1. Спасибо, Дирк, похоже, что при вызове push_back удерживающего вектора вектор добавляется за пределы его диапазона, поскольку он был инициализирован holding(x.nrow()) .