我想计算积分,其中被积函数是ODE解的函数。
为了求解积分,R需要求解积分算法使用的每个值的ODE。这是我到目前为止所做的:
require(deSolve)
# Function to be passed to zvode in order to solve the ODE
ODESR <- function(t, state, parameters) {
with(as.list(c(state, parameters)),{
dPSI <- -kappa*PSI+0.5*sigma^2*PSI^2
dPHI <- kappa*theta*PSI
return(list(c(dPSI, dPHI)))
})
}
# For a given value of p this code should return the solution of the integral
pdfSRP <- function (p) {
integrand <- function (u) {
state <- c(PSI = u*1i, PHI = 0)
out <- as.complex(zvode(y = state, times = times, parms = parameters, fun = ODESR)[2, 2:3])
Re(exp(out[2] + out[1]*x)*exp(-u*1i*p))
}
integrate(f = integrand, lower = -Inf, upper = Inf)$value/(2*pi)
}
对于以下给定值:
parameters <- c(kappa = 1, theta = 0.035, sigma = 0.05)
times <- c(0,1)
x <- 0.1
运行:
pdfSRP(p = 2)
产生以下错误:
Error in eval(expr, envir, enclos) : object 'PSI' not found
我无法弄明白为什么。我很确定这是由于语法错误,因为运行:
integrand <- function (u) {
state <- c(PSI = u*1i, PHI = 0)
out <- as.complex(zvode(y = state, times = times, parms = parameters, fun = ODESR)[2, 2:3])
Re(exp(out[2] + out[1]*x)*exp(-u*1i*p))
}
p <- 2
和(例如)u <- 3
有效。
答案 0 :(得分:3)
这似乎是integrand
输入u
中的矢量化问题。如果我理解正确,PSI
应该是每个计算的数字而不是数字向量(这会在PSI
和PHI
之间产生尺寸问题。因此
integrand <- Vectorize(integrand)
应解决您的问题。来自?integrate
:
f必须接受输入向量并在这些点产生函数评估向量。
但是,这会导致不同的错误。
pdfSRP(p = 2)
## Error in integrate(f = integrand, lower = -Inf, upper = Inf) :
## the integral is probably divergent
如果我们绘制被积函数,我们可能会发现分歧问题
p <- 2
par(mfrow = c(1,2))
curve(integrand,-1e3,1e3,n = 100)
curve(integrand,-1e3,1e3,n = 1e3)
假设被积分在两个尾部中足够快地收敛到零,则积分的发散可能是数值不精确的结果。我们可以通过增加积分的子区间数来提高精度,这确实给出了结果 - 我想,正如通过启发式查看图表所预期的那样。
pdfSRP <- function (p) {
int <- integrate(f = integrand, lower = -Inf, upper = Inf,
subdivisions = 1e3)
int$value/(2*pi)
}
## [1] 2.482281e-06