У меня есть имитационная модель, написанная как класс C ++.Я написал простую оболочку Rcpp
, которая позволяет запускать ее из R
.Я задаюсь вопросом о том, как наилучшим образом получить и установить свойства модели (двойники, векторы двойников и векторы векторов двойников) из R
.Я использую три std::unordered_map
как способ предоставления пользователю доступа к свойствам модели:
class molly_class {
...
public:
// unordered_map gives user efficient access to variables by name
std::unordered_map< std::string , double > variable;
std::unordered_map< std::string , std::vector< double >* > vector; // pointers to vectors
std::unordered_map< std::string , std::vector< std::vector< double > >* > array; // pointers to arrays
...
}
В моей оболочке Rcpp
я предоставил методы для доступа к "переменным" (скалярам) "векторы "и" массивы "из R
.Это работает, но я не уверен, что это правильный путь.Я хочу избежать ненужного копирования информации, и, возможно, есть более эффективные / более безопасные способы передачи данных назад и вперед?Я заглянул в документацию Rcpp
о разоблачении классов C ++ и RCCP_MODULE
, но на самом деле я этого не понимаю.Заранее спасибо.Оболочка Rcpp
содержит следующее:
molly_class molly;
// return molly scalar variables and their values as a named vector
// [[Rcpp::export]]
Rcpp::NumericVector get_molly_variables(){
Rcpp::NumericVector var_vector;
molly.pull_variables_from_model();
var_vector = molly.variable; // coerces unordered_map to named vector
return var_vector;
}
// set values of molly variables from the supplied named vector
// [[Rcpp::export]]
void set_molly_variables(Rcpp::NumericVector var_vector){
Rcpp::CharacterVector names = var_vector.names(); // types are a bit tricky
std::string name_i;
molly.pull_variables_from_model();
for (int i=0; i<var_vector.size(); ++i){
name_i = Rcpp::as<std::string>(names[i]); // types are a bit tricky
if (molly.variable.find(name_i) != molly.variable.end()){
molly.variable[name_i] = var_vector[i];
} else {
Rcpp::Rcout << "molly error : unknown variable " << name_i << std::endl;
}
}
molly.push_variables_to_model();
}
// return names of molly vectors
// [[Rcpp::export]]
Rcpp::StringVector get_molly_vectors(){
Rcpp::StringVector key_vector;
// /7699214/poluchenie-spiska-klychei-i-znachenii-iz-unorderedmap
for (auto mvi : molly.vector){
key_vector.push_back(mvi.first);
}
return key_vector;
}
// return a molly vector
// [[Rcpp::export]]
Rcpp::NumericVector get_molly_vector(Rcpp::String vec_name){
Rcpp::NumericVector vec_values;
vec_values = *molly.vector[vec_name];
return vec_values;
}
// set a molly vector using the supplied vector
// [[Rcpp::export]]
void set_molly_vector(Rcpp::String vec_name, Rcpp::NumericVector vec_values){
int ncols = (*molly.vector[vec_name]).size();
if (vec_values.size() == ncols){
for (int col=0; col<ncols; col++){
(*molly.vector[vec_name]).at(col) = vec_values.at(col);
}
} else {
Rcpp::Rcout << "molly error : supplied vector does not match length of " << vec_name << std::endl;
}
}
// return names of molly arrays
// [[Rcpp::export]]
Rcpp::StringVector get_molly_arrays(){
Rcpp::StringVector key_vector;
// /7699214/poluchenie-spiska-klychei-i-znachenii-iz-unorderedmap
// key_vector.reserve(molly.vector.size());
for (auto mvi : molly.array){
key_vector.push_back(mvi.first);
}
return key_vector;
}
// return a molly array as a matrix
// [[Rcpp::export]]
Rcpp::NumericMatrix get_molly_array(Rcpp::String arr_name){
int nrows = (*molly.array[arr_name]).size();
int ncols = (*molly.array[arr_name]).at(0).size();
Rcpp::NumericMatrix arr_values(nrows, ncols);
for (int row=0; row<nrows; row++){
for (int col=0; col<ncols; col++){
arr_values(row, col) = (*molly.array[arr_name]).at(row).at(col);
}
}
return arr_values;
}
// set a molly array using the supplied matrix
// [[Rcpp::export]]
void set_molly_array(Rcpp::String arr_name, Rcpp::NumericMatrix arr_values){
int nrows = (*molly.array[arr_name]).size();
int ncols = (*molly.array[arr_name]).at(0).size();
if (arr_values.nrow() == nrows && arr_values.ncol() == ncols){
for (int row=0; row<nrows; row++){
for (int col=0; col<ncols; col++){
(*molly.array[arr_name]).at(row).at(col) = arr_values(row, col);
}
}
} else {
Rcpp::Rcout << "molly error : supplied matrix does not match dimensions of " << arr_name << std::endl;
}
Обратите внимание, что pull_variables_from_model()
заполняет unordered_map
variable
, а push_variables_to_model()
использует unordered_map
variable
для установки внутренних переменных модели,которые являются частными членами molly_class
.unordered_map
variable
используется только как интерфейс, позволяющий пользователям получать доступ к внутренним переменным модели по имени.