Определить функцию в другой функции в C ++ - PullRequest
0 голосов
/ 18 мая 2018

Для решения дифференциальных уравнений я использую пакет Rcpp в R и пакет boost в C ++.Я создал функцию eq в C ++, которая преобразовывает функцию R mod_cpp в «функцию C ++» (см. Ниже).Затем функция eq помещается в качестве аргумента в функцию integrate_const.Наконец, я могу скомпилировать его в R с помощью Rcpp и получить функцию R с именем my_fun, которая зависит только от вектора против. Все работает хорошо.

// [[Rcpp::export]]
void my_fun22(Rcpp::NumericVector &x, const double t){
  Function f("mod_cpp");
  x=f(_["t"]=t,_["x"]=x);
}     

Rcpp::NumericVector nvec(130);
void eq(const state_type &x, state_type &dxdt, const double t){
  boost_array_to_nvec2(x, nvec);
  my_fun22(nvec,t);
  nvec_to_boost_array2(nvec, dxdt);
}

Rcpp::NumericMatrix my_fun(const Rcpp::NumericVector vs) {
  state_type x = nvec_to_boost_array(vs); // initial conditions
  integrate_const(make_dense_output( 1E-4 , 1E-4 , stepper_type () ) ,
                eq , x , 0.0 , 120.0 , 1.0 , write_cout);
  return data;
}

Проблема в том, что все параметры моей моделисодержащиеся в функции mod_cpp исправлены.Теперь я хочу создать другую функцию, которая выполняет ту же работу, что и my_fun, но зависит от некоторых параметров модели.Точнее, создайте функцию my_fun2 (vs, theta), которая зависит от vs и theta.Я уже пытался это сделать, но боролся с повторным уточнением функции eq в функции my_fun, так как ей не разрешалось определять функцию внутри другой функции в R. Я что-то пропустил?

1 Ответ

0 голосов
/ 18 мая 2018

Для достижения того, что вы хотите, я бы использовал лямбда-функции c ++ 11 и вместо создания eq в качестве функции я определил бы ее как функцию второго порядка: функцию, которая возвращает другую функцию, аргумент которой может быть thetaты упомянул.Например:

...
Rcpp::NumericMatrix my_fun(const Rcpp::NumericVector vs, const float theta) {
  state_type x = nvec_to_boost_array(vs); // initial conditions
  integrate_const(make_dense_output( 1E-4 , 1E-4 , stepper_type () ) ,
            eq(theta) , x , 0.0 , 120.0 , 1.0 , write_cout);
...
}

, а затем измененный eq будет выглядеть примерно так:

std::function<void(const state_type, state_type, const double)> eq(const float theta) {
   return [&theta](const state_type &x, state_type &dxdt, const double t) {
     // do something with theta here
     // for instance, modify nvec
     ...
     // then your old function body
     boost_array_to_nvec2(x, nvec);
     my_fun22(nvec,t);
     nvec_to_boost_array2(nvec, dxdt);
   }
}

Таким образом, вы можете передавать параметры во время выполнения.Я не проверял это, но идея должна быть хорошей, я думаю.

Чтобы использовать функции c ++ 11, вам нужно убедиться, что вы установили компилятор c ++ в системный путь, который может компилировать код c ++ 11 иотредактируйте файл Makevars в вашем R-проекте и добавьте сверху:

PKG_CXXFLAGS = -g -O3 -std=c++11

Подробнее об этом здесь , например.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...