如何使用R中的RCPP使用C ode求解器
How to use C++ ODE solver with Rcpp in R?
评估求解R和C 之间的速度的差异,我在R:
中构建以下ode系统modelsir_cpp =function(t,x){
S = x[1]
I1 = x[2]
I2 = x[3]
N=S+I1+I2
with(as.list(parm), {
dS=B*I1-mu*S-beta*(S*(I1+I2)/N)
dI1=beta*(S*(I1+I2)/N)-B*I1-lambda12*I1
dI2=lambda12*I1
res=c(dS,dI1,dI2)
return(res)
})
}
要解决它,我使用了desolde软件包。
times = seq(0, 10, by = 1/52)
parm=c(B=0.01,mu=0.008,beta=10,lambda12=1)
xstart=c(S=900,I1=100,I2=0)
out = as.data.frame(lsoda(xstart, times, modelsir, parm))
这有效。我尝试通过使用R中的RCPP库来求解相同的系统。这是我添加的:
#include <Rcpp.h>
#include <boost/array.hpp>
// include Boost's odeint
#include <boost/numeric/odeint.hpp>
// [[Rcpp::depends(BH)]]
using namespace Rcpp;
using namespace std;
using namespace boost::numeric::odeint;
typedef boost::array< double ,3 > state_type;
// [[Rcpp::export]]
Rcpp::NumericVector my_fun2(const Rcpp::NumericVector &x, const double t){
Function f("modelsir_cpp");
return f(_["t"]=t,_["x"]=x);
}
void eqsir(const state_type &x, state_type &dxdt, const double t){
Rcpp::NumericVector nvec=boost_array_to_nvec(x);
Rcpp::NumericVector nvec2(3);
nvec2=my_fun2(nvec,t);
dxdt=nvec_to_boost_array(nvec2);
}
void write_cout_2( const state_type &x , const double t ) {
// use Rcpp's stream
Rcpp::Rcout << t << 't' << x[0] << 't' << x[1] << 't' << x[2] << endl;
}
typedef runge_kutta_dopri5< state_type > stepper_type;
// [[Rcpp::export]]
bool my_fun10_solver() {
state_type x = { 900 , 100, 0 }; // initial conditions
integrate_adaptive(make_controlled( 1E-12 , 1E-12 , stepper_type () ) ,
eqsir , x , 1.0 , 2 , 1/52 , write_cout_2 );
return true;
}
但是出现了一条错误消息:
在函数'bool my_fun10_solver(('中: ex3.CPP:114:64:错误:呼叫'integnate_Adaptive(boost :: numeric :: odeint :: rescom_of :: make_controllled>>:type>:type type,void(&amp;((const state_type&amp; amp; amp; amp; ampe&ampe&amp&amp&amp&amp; amp; amp; amp;,double(,state_type&amp;,double,int,int,void(&amp;((const state_type&amp;,double(('' eqsir,x,1.0,2,1/52,write_cout_2(;
我的代码怎么了?
以下是我拿到的脚本,并适应了我的问题。此脚本运行良好。
#include <Rcpp.h>
#include <boost/array.hpp>
// include Boost's odeint
#include <boost/numeric/odeint.hpp>
// [[Rcpp::depends(BH)]]
using namespace Rcpp;
using namespace std;
using namespace boost::numeric::odeint;
typedef boost::array< double ,3 > state_type;
void rhs( const state_type &x , state_type &dxdt , const double t ) {
dxdt[0] = 3.0/(2.0*t*t) + x[0]/(2.0*t);
dxdt[1] = 3.0/(2.0*t*t) + x[1]/(2.0*t);
dxdt[2] = 3.0/(2.0*t*t) + x[1]/(2.0*t);
}
void write_cout( const state_type &x , const double t ) {
// use Rcpp's stream
Rcpp::Rcout << t << 't' << x[0] << 't' << x[1] << 't' << x[2] << endl;
}
typedef runge_kutta_dopri5< state_type > stepper_type;
// [[Rcpp::export]]
bool boostExample() {
state_type x = { 1.0 , 1.0, 1.0 }; // initial conditions
integrate_adaptive(make_controlled( 1E-12 , 1E-12 , stepper_type () ) ,
rhs , x , 1.0 , 10.0 , 0.1 , write_cout );
return true;
}
您可以尝试以下操作吗?
integrate_adaptive(make_controlled( 1E-12 , 1E-12 , stepper_type () ) ,
eqsir , x , 1.0 , 2.0 , 1.0/52.0 , write_cout_2 );
不过有几个优化建议。您正在解决一种颂歌,这表明您是物理学家或工程师,这太棒了,我也是物理学家,物理学家只是摇滚。
但是,计算机科学家也是如此,他们尽了最大的努力尽可能快地做事。他们建立了编译器,这些编译器消除了许多涉及的思想。尽可能地帮助他们。
我为什么告诉你这个?回到颂歌。Boost的自适应间介绍可能正在调用eqsir()
1e9
次。尝试使该功能尽可能地表现。考虑重写my_fun2
,以便x
被覆盖而不是创建新的并返回。x
是最后一个状态。除非您想绘制动态,否则您不会关心它。
void my_fun2(Rcpp::NumericVector &x, const double t);
也
Rcpp::NumericVector nvec=boost_array_to_nvec(x);
Rcpp::NumericVector nvec2(3);
必须在每个呼叫上分配新的内存。最后,考虑将2个转换器用于nvec
和state_type
与我写为第二个选项的参考文献。您的新eqsir
看起来像这样,并且运行速度可能会更快。
Rcpp::NumericVector nvec(3); // declared outside
void eqsir(const state_type &x, state_type &dxdt, const double t){
boost_array_to_nvec(x, nvec);
my_fun2(nvec,t);
nvec_to_boost_array(nvec, dxdt);
}
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- C++:TypeDef使用元组
- 使用std::multimap迭代器创建std::list
- 从不同线程使用int64的不同字节安全吗
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么在全局范围内使用"extern int a"似乎不行?
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用Google Mock来模拟gettimeofday()
- 如何使用默认参数等选择模板专业化
- 为什么使用 "this" 指针调用派生成员函数?
- 使用新行和不使用新行读取文件
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 如何确定我已使用非编码文件到达 EOF?
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 使用CMake创建QML插件
- 减少使用 GSL 用于 ODE 系统的编译资源
- 使用推力的 ODE 求解器的 CUDA 编程
- 如何使用R中的RCPP使用C ode求解器
- runge-kutta第四阶使用C 解决第二阶ode