在这里,我有一个真正的问题和一个大大简化的问题,可能会或可能不会包含我对第一个问题的困惑。
下面的函数multi_quad
应该整合来自GB2包的dfun
dgb2
,超过从下限lb
到上限{{1}的限制}。 base-R ub
函数成功地对此处给出的参数值和限制执行此积分,但对于ub = 4.55e8或更高版本失败。我发布了有关此问题的问题,here: R: Convergence problems with numerical integration
我努力解决收敛问题,我在下面有函数integrate
,它应该尝试与pracma包中的各种替代正交方法集成。我正在使用purrr包中的multi_quad
来尝试所有方法,如果它们收敛则返回值,否则返回错误消息。
对于safely( )
的每次迭代,我得到一个参数map
的错误。这里外部do.call的封闭和调用环境都是m_quad的执行环境,m_quad的封闭和调用环境都是multi_quad的执行环境。由于我为"lb" is missing, with no default
提供了multi_quad
的值,因此我希望lb
和m_quad
能够找到它,无论外部的do.call
如何.call是作用域。这是不正确的,我不知道为什么。
lb
下面是一个极其简化的例子,我认为我对内部函数何时以及如何找到提供给调用函数的值的期望以类似的方式受挫。名称以“extra”开头的变量是为了防止位置匹配。
在此示例中,library(GB2)
library(pracma)
library(purr)
multi_quad <- function(dfun, params, lb, ub){
m_quad <- function(q_method, dfun, params, lb, ub){
do.call(what=q_method,
args=list(f=function(X){do.call(what=dfun, args=params)}, a=lb, b=ub))
}
safe_m_quad <- safely(m_quad)
q_methods<- list("quadgk", "quadcc", "simpadpt", "renshaw", "quadgr") %>%
map(safe_m_quad) -> out
out
}
GB2_params <- list(shape1 = 3.652, scale = 65797, shape2 = 0.3, shape3 = 0.8356)
results <- multi_quad(dfun=dgb2, params=GB2_params, lb=1, ub=3e8)
results
的执行环境既是fa
的调用环境,也是封闭环境。为什么fb
的{{1}}在arg1
fa
arg1
范围内的价值不是fb
的价值? fb
的{{1}}是否在其调用环境中查找arg1
,或者它是封闭环境,还是在arg1
的执行环境中,从那里开始,在每种情况下应该到达fb
的执行环境。但事实并非如此。为什么是这样?它在哪里寻找呢?
fa
答案 0 :(得分:0)
(1)对我来说,integrate
最多可达到7.0e08。想想它是什么巨大的集成领域。您正在应用来自 pracma 的函数,这些函数更多的是作为方法演示,而不是用于自命不凡的测试。 quadgk
与integrate
类似,最高可达1.0e09,实践中的integral
功能最高可达1.0e10!
如果要在无限区间[0. Inf]
上进行整合,则integrate
将无法再次运行。但integral
认识到无限,并回归到其他方法:
fun = function(x) dgb2(x, shape1 = 3.652, scale = 65797,
shape2 = 0.3, shape3 = 0.8356)
pracma::integral(fun, 0, Inf)
## For infinite domains Gauss integration is applied!
## [1] 1
它实际上使用pracma::quadinf
在应用高斯求积法则之前将无限域转换为有限域。
(2)在简化文本示例中,第一个错误是在定义之前调用fb(arg1)
。如果您将fb(arg1)
放在函数定义之后,arg1
将被分配给extra3
,参数arg1
仍未定义。
可能的纠正可能是:
fa <- function(extra0=0, arg1, extra2=2){
fb <- function(extra3=3, arg1){
print(arg1)
}
fb(arg1 = arg1)
}
fa(arg1=1)
## [1] 1
或将fb
更改为fb <- function(arg1, extra3=3) {...}
。
行extra0
,extra1
等对行有用的内容尚不清楚。
(3)添加以提供一些合理的积分值:
通过选择适当的参数,整数函数integral
和quadgk
能够为5e08及更大的区间返回合理的值。
I1 = integrate(fun, 0, 5.0e08, rel.tol=1e-14, subdivisions=1000)$value; I1 - 1
## [1] -4.792833e-13
I2 = integral(fun, 0, 5.0e08, reltol=1e-14); I2 -1
## [1] -4.775069e-13
I3 = quadgk(fun, 0, 5.0e08, tol=1e-14); I3 - 1
## [1] -4.773959e-13
这样我们得到以下积分值:
| Function | Value |
|-------------------|-------------------|
| stats::integrate | 0.999999999999521 |
| pracma::integral | 0.999999999999522 |
| pracma::quadgk | 0.999999999999523 |
这些函数使用类似的“自适应高斯求积法”规则,因此难怪它们会返回类似的结果。其他完全不同的集成例程可能会产生(稍微?)不同的结果。