Rcpp::rmultinom с указателем на матричное подпредставление

Для выборки из полиномиального распределения в Rcpp мы можем сделать:

int n = 100;
int k = 3;
arma::vec probs = {0.4,0.2,0.4}
arma::irowvec c(k);
Rcpp::rmultinom(n, probs.begin(), k, c.begin());

Я хотел бы знать, можем ли мы сделать то же самое, когда C — матрица. я попробую

int n = 100;
int k = 3;
arma::vec probs = {0.4,0.2,0.4}
# C (arma::mat C) passed by reference to the function
Rcpp::rmultinom(n, probs.begin(), k, C.row(1).begin());

но выдает ошибку. Есть ли простой способ сделать это?

Я хочу попробовать второй подход, потому что у меня есть большая матрица C, которую я передаю по ссылке в свою функцию, а затем я хочу обновить ее строки после многочлена.

MWE:

#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::plugins(cpp11)]]

using namespace Rcpp;
using namespace arma;

void subfunction(const arma::imat& C) {

  int n = 100;
  int k = 3;
  arma::vec probs = {0.4,0.2,0.4};

  rmultinom(n, probs.begin(), k, C.col(1).begin());
}

// [[Rcpp::export]]
arma::imat myfunction(){

  arma::imat C = { {1, 2}, 
                  {3, 4},
                  {5, 6}};
  subfunction(C);
  Rcpp::Rcout << "C: " <<  C << std::endl;

}

Ошибка:

test_multim.cpp:18:44: error: ‘class arma::subview_col<int>’ 
has no member named ‘begin’
rmultinom(n, probs.begin(), k, Ct.col(1).begin());

person alberto    schedule 20.11.2017    source источник


Ответы (1)


Эта проблема имеет две проблемы:

  1. Типы, требуемые определением функции rmultinom.
  2. Доступ к указателю памяти для матрицы armadillo.

Для начала обратите внимание, что одна из ошибок:

mondayso.cpp:16:3: error: no matching function for call to 'Rf_rmultinom'
  rmultinom(1, probs.begin(), k, C.colptr(1));
  ^~~~~~~~~
/Library/Frameworks/R.framework/Resources/include/Rmath.h:468:6: note: candidate function not viable: no known conversion from 'double *' to 'int *' for 4th argument
void    rmultinom(int, double*, int, int*);
        ^
1 error generated.

По сути, функция rmultinorm должна иметь целое число, передаваемое в качестве 4-го аргумента. Из-за конструкции arma::mat, равной double по умолчанию, тип матрицы< /em> неуместно. В этом случае матрица C должна быть arma::imat, так как она использует arma::sword или подписанный int компонент.

Затем данные для armadillo матриц сохраняются в постолбцовом порядке ( Подробнее см. в Википедии). Это означает, что указатели могут быть легко установлены только column через .colptr. Это устраняет вторую возникшую ошибку:

error: no member named 'begin' in 'arma::subview_row<int>'
  rmultinom(n, probs.begin(), k, C.row(1).begin());
                                 ~~~~~~~~ ^
1 error generated.

Сказав это, я построил пример, который облегчает преобразование.

#include <RcppArmadillo.h>

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

// [[Rcpp::plugins(cpp11)]]

// [[Rcpp::export]]
arma::imat test() {

  int n = 100;
  int k = 3;
  arma::vec probs = {0.4,0.2,0.4};

  arma::imat C = { {1, 3, 5},
                  {2, 4, 6} };

  arma::imat Ct = C.t();

  // C++ indices start at 0 (thus, this is the second column!)
  rmultinom(n, probs.begin(), k, Ct.colptr(1));

  return Ct;
}

Тест

set.seed(111)
test()
#      [,1] [,2]
# [1,]    1   43
# [2,]    3   18
# [3,]    5   39
person coatless    schedule 20.11.2017
comment
Спасибо без пальто и @Dirk. Теперь это работает благодаря C.colptr (я добавил недостающий MWE) - person alberto; 20.11.2017