我估计物种在网格景观中分散的概率,给定具有最大扩散距离的扩散核(距离函数)。我正在尝试计算面积与面积的分散概率,如公式1所述。 this (open access) paper中的8个。这涉及四重积分,分别评估源和目标细胞中源点和目标点的每种可能组合的扩散函数的值。
我用adaptIntegrate
包中的cubature
实现了这个,如下所示,源单元格A,目标单元格B和简化的扩散内核,当点间距离为1时,分散为1 >否则为1.25和0。这在下面以图形方式显示,其中单元格B的红色区域是不可达的,因为单元格A中的任何点都不在1.25的距离内。
library(cubature)
f <- function(xmin, xmax, ymin, ymax) {
adaptIntegrate(function(x) {
r <- sqrt((x[3] - x[1])^2 + (x[4] - x[2])^2)
ifelse(r > 1.25, 0, 1)
},
lowerLimit=c(-0.5, -0.5, xmin, ymin),
upperLimit=c(0.5, 0.5, xmax, ymax),
maxEval=1e5)
}
f(xmin=1.5, xmax=2.5, ymin=-0.5, ymax=0.5)
# $integral
# [1] 0.01949567
#
# $error
# [1] 0.001225998
#
# $functionEvaluations
# [1] 100035
#
# $returnCode
# [1] 0
在考虑目标单元格C时,我得到了一个不同的积分,它位于相同的距离,但在上方而不是在单元格A的右侧。
f(xmin=-0.5, xmax=0.5, ymin=1.5, ymax=2.5)
# $integral
# [1] 0.01016105
#
# $error
# [1] 0.0241325
#
# $functionEvaluations
# [1] 100035
#
# $returnCode
# [1] 0
为什么这些积分如此不同(0.01949567
vs 0.01016105
)?我编码不正确吗?更改公差和最大评估数似乎没有太大区别。或者,是否有更好的方法来编写解决此类问题的解决方案?
我意识到关于一般方法的问题可能更适合stats.stackexchange.com,但我发布在这里,因为我怀疑可能有一些我用编码本身忽略的东西。
<小时/> 修改 对于
A -> B
案例,嵌套integrate
会返回类似于第一个adaptIntegrate
解决方案的解决方案。对于A -> C
案例,它会返回Error in integrate(function(ky) { : the integral is probably divergent
。
g <- function(Bx, By, Ax, Ay) {
r <- sqrt((Ax - Bx)^2 + (Ay - By)^2)
ifelse(r > 1.25, 0, 1)
}
integrate(function(Ay) {
sapply(Ay, function(Ay) {
integrate(function(Ax) {
sapply(Ax, function(Ax) {
integrate(function(By) {
sapply(By, function(By) {
integrate(function(Bx) g(Bx, By, Ax, Ay), 1.5, 2.5)$value # Bx
})
}, -0.5, 0.5)$value # By
})
}, -0.5, 0.5)$value # Ax
})
}, -0.5, 0.5)$value # Ay
# [1] 0.019593
答案 0 :(得分:3)
这样做的原因似乎是adaptIntegrate
的工作方式,因为很明显,你改变的唯一方法就是整合的顺序。不相同的结果很可能是因为单独的近似整合(参见第一个回复here),但这似乎更像是一个错误。
以下是计算r
f(xmin=1.5, xmax=2.5, ymin=-0.5, ymax=0.5)
的值
和f(xmin=-0.5, xmax=0.5, ymin=1.5, ymax=2.5)
因此,函数内部必定存在某些内容,因为值的范围会有很大差异。
另一个替代方案是蒙特卡洛积分,在这种情况下很好,因为你的点是均匀分布的。
MCI <- function(Ax, Ay, Bx, By, N, r) {
d <- sapply(list(Ax, Ay, Bx, By), function(l) runif(N, l[1], l[2]))
sum(sqrt((d[, 1] - d[, 3])^2 + (d[, 2] - d[, 4])^2) <= r) / N
}
set.seed(123)
MCI(c(-0.5, 0.5), c(-0.5, 0.5), c(1.5, 2.5), c(-0.5, 0.5), 100000, 1.25)
# [1] 0.0194
MCI(c(-0.5, 0.5), c(-0.5, 0.5), c(-0.5, 0.5), c(1.5, 2.5), 100000, 1.25)
# [1] 0.01929
答案 1 :(得分:2)
通常距离测量值为(x1-x2)^2+(y1-y2)^2
。你能解释为什么你在构造r时从y中减去x?考虑备用版本:
f <- function(xmin, xmax, ymin, ymax) {
adaptIntegrate(function(x) {
r <- sqrt((x[4] - x[3])^2 + (x[2] - x[1])^2)
ifelse(r > 1.25, 0, 1)
},
lowerLimit=c(-0.5, -0.5, xmin, ymin),
upperLimit=c(0.5, 0.5, xmax, ymax),
maxEval=1e5)
}
f(xmin=1.5, xmax=2.5, ymin=-0.5, ymax=0.5)
#-------------
$integral
[1] 0.01016105
$error
[1] 0.0241325
$functionEvaluations
[1] 100035
$returnCode
[1] 0
#---------
f(xmin=-0.5, xmax=0.5, ymin=1.5, ymax=2.5)
#---------
$integral
[1] 0.01016105
$error
[1] 0.0241325
$functionEvaluations
[1] 100035
$returnCode
[1] 0
答案 2 :(得分:1)
R cubature
软件包(Naras)的维护者告诉我,Cubature C库提供的结果与我在上面的问题中报告的结果相同,并且这不太可能是一个bug;相反,h-自适应立方体例程(R包是一个接口)在某些情况下不如Cubature的p-自适应例程准确,doubles the number of sampling points在适当的区域。
Naras还提供了以下julia代码,用于演示我的问题中提到的两种情况的一致pcubature
解决方案(返回值的元素是估计的积分,后跟估计的绝对误差)。 / p>
using Cubature
# integrand
f = x -> ifelse(sqrt((x[3] - x[1])^2 + (x[4] - x[2])^2) > 1.25, 0, 1)
# A to B case
pcubature(f, [-0.5, -0.5, 1.5, -0.5], [0.5, 0.5, 2.5, 0.5], abstol=1e-5)
# (0.019593408732917292,3.5592555263398717e-6)
# A to C case
pcubature(f, [-0.5, -0.5, -0.5, 1.5], [0.5, 0.5, 0.5, 2.5], abstol=1e-5)
# (0.019593408732918302,3.559255527241928e-6)