我正在尝试使用Monte Carlo积分来集成以下功能。我要积分的间隔是x <- seq(0, 1, by = 0.01)
和y <- seq(0, 1, by = 0.01)
。
my.f <- function(x, y){
result = x^2 + sin(x) + exp(cos(y))
return(result)
}
我使用cubature
包计算了积分。
library(cubature)
library(plotly)
# Rewriting the function, so it can be integrated
cub.function <- function(x){
result = x[1]^2 + sin(x[1]) + exp(cos(x[2]))
return(result)
}
cub.integral <- adaptIntegrate(f = cub.function, lowerLimit = c(0,0), upperLimit = c(1,1))
结果为3.134606。但是,当我使用蒙特卡洛集成代码时,请参见下文,结果约为1.396652。我的代码有2倍以上的错误!
我做了什么:
由于我需要一个体积来进行蒙特卡洛积分,因此我按上述间隔计算了函数值。这样可以估算出该函数的最大值和最小值。
# My data range
x <- seq(0, 1, by = 0.01)
y <- seq(0, 1, by = 0.01)
# The matrix, where I save the results
my.f.values <- matrix(0, nrow = length(x), ncol = length(y))
# Calculation of the function values
for(i in 1:length(x)){
for(j in 1:length(y)){
my.f.values[i,j] <- my.f(x = x[i], y = y[j])
}
}
# The maximum and minimum of the function values
max(my.f.values)
min(my.f.values)
# Plotting the surface, but this is not necessary
plot_ly(y = x, x = y, z = my.f.values) %>% add_surface()
因此,我们需要的容量仅仅是函数值的最大值,因为1 * 1 * 4.559753
就是4.559753
。
# Now, the Monte Carlo Integration
# I found the code online and modified it a bit.
monte = function(x){
tests = rep(0,x)
hits = 0
for(i in 1:x){
y = c(runif(2, min = 0, max = 1), # y[1] is y; y[2] is y
runif(1, min = 0, max = max(my.f.values))) # y[3] is z
if(y[3] < y[1]**2+sin(y[1])*exp(cos(y[2]))){
hits = hits + 1
}
prop = hits / i
est = prop * max(my.f.values)
tests[i] = est
}
return(tests)
}
size = 10000
res = monte(size)
plot(res, type = "l")
lines(x = 1:size, y = rep(cub.integral$integral, size), col = "red")
因此,结果是完全错误的。但是,如果我稍微改变一下功能,突然可以了。
monte = function(x){
tests = rep(0,x)
hits = 0
for(i in 1:x){
x = runif(1)
y = runif(1)
z = runif(1, min = 0, max = max(my.f.values))
if(z < my.f(x = x, y = y)){
hits = hits + 1
}
prop = hits / i
est = prop * max(my.f.values)
tests[i] = est
}
return(tests)
}
size = 10000
res = monte(size)
plot(res, type = "l")
lines(x = 1:size, y = rep(cub.integral$integral, size), col = "red")
有人可以解释为什么结果突然改变吗?在我看来,这两个功能似乎完全一样。
答案 0 :(得分:4)
在您的monte
的(第一个)代码中,此行有误:
y[3] < y[1]**2+sin(y[1])*exp(cos(y[2]))
鉴于您对my.f
的定义,肯定是
y[3] < y[1]**2 + sin(y[1]) + exp(cos(y[2]))
或者...,鉴于您不应该不必要地重复自己的话:
y[3] < my.f(y[1], y[2])