简体   繁体   English

求解R中的微分方程组

[英]Solving a system of differential equations in R

I have a simple flux model in R. It boils down to two differential equations that model two state variables within the model, we'll call them A and B . 我在R中有一个简单的通量模型。它归结为两个微分方程,模拟模型中的两个状态变量,我们称之为AB They are calculated as simple difference equations of four component fluxes flux1-flux4 , 5 parameters p1-p5 , and a 6th parameter, of_interest , that can take on values between 0-1. 它们被计算为四分量通量flux1-flux4个参数p1-p5和第六个参数of_interest简单差分方程,其可以取0-1之间的值。

parameters<- c(p1=0.028, p2=0.3, p3=0.5, p4=0.0002, p5=0.001, of_interest=0.1) 
state     <- c(A=28, B=1.4)

model<-function(t,state,parameters){
  with(as.list(c(state,parameters)),{
  #fluxes
  flux1  = (1-of_interest) * p1*(B / (p2 + B))*p3
  flux2  = p4* A          #microbial death
  flux3  = of_interest * p1*(B / (p2 + B))*p3 
  flux4  = p5* B      

  #differential equations of component fluxes
  dAdt<- flux1 - flux2
  dBdt<- flux3 - flux4
  list(c(dAdt,dBdt))
  })

I would like to write a function to take the derivative of dAdt with respect to of_interest , set the derived equation to 0, then rearrange and solve for the value of of_interest . 我想写一个函数来获取关于of_interestdAdt的导数,将导出的方程设置为0,然后重新排列并求解of_interest的值。 This will be the value of the parameter of_interest that maximizes the function dAdt . 这将是最大化函数dAdt的参数of_interest的值。

So far I have been able to solve the model at steady state, across the possible values of of_interest to demonstrate there should be a maximum. 到目前为止,我已经能够在稳定状态下解决模型,跨越of_interest的可能值来证明应该有一个最大值。

require(rootSolve)
range<- seq(0,1,by=0.01)
for(i in range){
of_interest=i
parameters<- c(p1=0.028, p2=0.3, p3=0.5, p4=0.0002, p5=0.001, of_interest=of_interest) 
state     <- c(A=28, B=1.4)
ST<- stode(y=y,func=model,parms=parameters,pos=T)
out<- c(out,ST$y[1])

Then plotting: 然后绘图:

plot(out~range, pch=16,col='purple')
lines(smooth.spline(out~range,spar=0.35), lwd=3,lty=1)

在此输入图像描述

How can I analytically solve for the value of of_interest that maximizes dAdt in R? 我该如何分析解决的价值of_interest最大化dAdt R中? If an analytical solution is not possible, how can I know, and how can I go about solving this numerically? 如果无法获得分析解决方案,我怎么知道,如何以数字方式解决这个问题呢?

Update: I think this problem can be solved with the deSolve package in R, linked here , however I am having trouble implementing it using my particular example. 更新:我认为这个问题可以通过R中的deSolve包解决,在这里链接,但是我在使用我的特定示例实现它时遇到了麻烦。

Your equation in B(t) is just-about separable since you can divide out B(t) , from which you can get that 你在B(t)等式只是可分离的,因为你可以除去B(t) ,从中可以得到它

B(t) = C * exp{-p5 * t} * (p2 + B(t)) ^ {of_interest * p1 * p3}

This is an implicit solution for B(t) which we'll solve point-wise. 这是B(t)的隐式解,我们将逐点解决。

You can solve for C given your initial value of B . 您可以根据B的初始值求解C I suppose t = 0 initially? 我想最初t = 0 In which case 在这种情况下

C = B_0 / (p2 + B_0) ^ {of_interest * p1 * p3}

This also gives a somewhat nicer-looking expression for A(t) : 这也为A(t)提供了一个更好看的表达式:

dA(t) / dt = B_0 / (p2 + B_0) * p1 * p3 * (1 - of_interest) *
   exp{-p5 * t} * ((p2 + B(t) / (p2 + B_0)) ^ 
   {of_interest * p1 * p3 - 1} - p4 * A(t)

This can be solved by integrating factor (= exp{p4 * t} ), via numerical integration of the term involving B(t) . 这可以通过积分因子(= exp{p4 * t} ),通过涉及B(t)的项的数值积分来解决。 We specify the lower limit of the integral as 0 so that we never have to evaluate B outside the range [0, t] , which means the integrating constant is simply A_0 and thus: 我们将积分的下限指定为0,这样我们就不必在范围[0, t]之外评估B,这意味着积分常数只是A_0 ,因此:

A(t) = (A_0 + integral_0^t { f(tau; parameters) d tau}) * exp{-p4 * t}

The basic gist is B(t) is driving everything in this system -- the approach will be: solve for the behavior of B(t) , then use this to figure out what's going on with A(t) , then maximize. 基本要点是B(t)正在驱动这个系统中的所有东西 - 方法将是:解决B(t)的行为,然后用它来弄清楚A(t)发生了什么,然后最大化。

First, the "outer" parameters; 一,“外”参数; we also need nleqslv to get B : 我们还需要nleqslv才能获得B

library(nleqslv)

t_min <- 0
t_max <- 10000
t_N <- 10

#we'll only solve the behavior of A & B over t_rng
t_rng <- seq(t_min, t_max, length.out = t_N)

#I'm calling of_interest ttheta
ttheta_min <- 0
ttheta_max <- 1
ttheta_N <- 5

tthetas <- seq(ttheta_min, ttheta_max, length.out = ttheta_N)

B_0 <- 1.4
A_0 <- 28

#No sense storing this as a vector when we'll only ever use it as a list
parameters <- list(p1 = 0.028, p2 = 0.3, p3 = 0.5, 
                   p4 = 0.0002, p5 = 0.001)

From here, the basic outline is: 从这里开始,基本概要是:

  1. Given the parameter values (in particular ttheta ), solve for BB over t_rng via non-linear equation solving 给定参数值(特别是ttheta ),通过非线性方程求解求解BB超过t_rng
  2. Given BB and the parameter values, solve for AA over t_rng by numerical integration 给定BB和参数值,通过数值积分求解AA超过t_rng
  3. Given AA and your expression for dAdt, plug & maximize. 鉴于AA和dAdt的表达式,插入和最大化。

derivs <- sapply(tthetas, function(th){ #append current ttheta params <- c(parameters, ttheta = th) deris < - sapply(tthetas,function(th){#append current ttheta params < - c(parameters,ttheta = th)

#declare a function we'll use to solve for B (see above)
b_slv <- function(b, t) 
  with(params, b - B_0 * ((p2 + b)/(p2 + B_0)) ^ 
         (ttheta * p1 * p3) * exp(-p5 * t))

#solving point-wise (this is pretty fast)
#  **See below for a note**
BB <- sapply(t_rng, function(t) nleqslv(B_0, function(b) b_slv(b, t))$x)

#this is f(tau; params) that I mentioned above;
#  we have to do linear interpolation since the
#  numerical integrator isn't constrained to the grid.
#  **See below for note**
a_int <- function(t){
  #approximate t to the grid (t_rng)
  #  (assumes B is monotonic, which seems to be true)
  #  (also, if t ends up negative, just assign t_rng[1])
  t_n <- max(1L, which.max(t_rng - t >= 0) - 1L)
  idx <- t_n:(t_n+1)
  ts <- t_rng[idx]

  #distance-weighted average of the local B values
  B_app <- sum((-1) ^ (0:1) * (t - ts) / diff(ts) * BB[idx])
  #finally, f(tau; params)
  with(params, (1 - ttheta) * p1 * p3 * B_0 / (p2 + B_0) *
         ((p2 + B_app)/(p2 + B_0)) ^ (ttheta * p1 * p3 - 1) *
         exp((p4 - p5) * t))
}

#a_int only works on scalars; the numeric integrator
#  requires a version that works on vectors
a_int_v <- function(t) sapply(t, a_int)

AA <- exp(-params$p4 * t_rng) * 
  sapply(t_rng, function(tt)
    #I found the subdivisions constraint binding in some cases
    #  at the default value; no trouble at 1000.
    A_0 + integrate(a_int_v, 0, tt, subdivisions = 1000L)$value)

#using the explicit version of dAdt given as flux1 - flux2
max(with(params, (1 - ttheta) * p1 * p3 * BB / (p2 + BB) - p4 * AA))})

Finally, simply run `tthetas[which.max(derivs)]` to get the maximizer.

Note: 注意:

This code is not optimized for efficiency. 此代码未针对效率进行优化。 There are a few places where there are some potential speed-ups: 有几个地方有一些潜在的加速:

  • probably faster to run the equation solver recursively, as it'll converge faster with better initial guesses -- using the previous value instead of the initial value is surely better 可能更快地递归运行方程求解器,因为它会以更好的初始猜测更快地收敛 - 使用先前的值而不是初始值肯定更好
  • Will be faster to simply use Riemann sums to integrate; 简单地使用黎曼总和进行整合会更快; the tradeoff is in accuracy, but should be fine if you have a dense enough grid. 权衡是准确的,但如果你有足够密集的网格应该没问题。 One beauty of Riemann is you won't have to interpolate at all, and numerically they're simple linear algebra. 黎曼的一个美妙之处在于你根本不需要插值,而在数值上它们是简单的线性代数。 I ran this with t_N == ttheta_N == 1000L and it ran within a few minutes. 我用t_N == ttheta_N == 1000L运行它,它在几分钟内运行。
  • Probably possible to vectorize a_int directly instead of just sapply ing on it, which concomitant speed-up by more direct appeal to BLAS. 可能直接向a_int进行矢量化而不是仅仅sapply ,这可以通过更直接地吸引BLAS来加速。
  • Loads of other small stuff. 其他小东西的负荷。 Pre-compute ttheta * p1 * p3 since it's re-used so much, etc. 预先计算ttheta * p1 * p3因为它被重复使用了很多,等等。

I didn't bother including any of that stuff, though, because you're honestly probably better off porting this to a faster language -- Julia is my own pet favorite, but of course R speaks well with C++, C, Fortran, etc. 我没有打扰包括任何这些东西,但是,因为你真的可能更好地将它移植到更快的语言 - Julia是我自己的宠物最喜欢的,但当然R与C ++,C,Fortran等说得很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM