R:嵌套函数中的范围,第2部分:嵌套的do.call

时间:2018-03-15 06:30:47

标签: r scope nested iteration numerical-integration

在这里,我有一个真正的问题和一个大大简化的问题,可能会或可能不会包含我对第一个问题的困惑。

下面的函数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的值,因此我希望lbm_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

1 个答案:

答案 0 :(得分:0)

(1)对我来说,integrate最多可达到7.0e08。想想它是什么巨大的集成领域。您正在应用来自 pracma 的函数,这些函数更多的是作为方法演示,而不是用于自命不凡的测试。 quadgkintegrate类似,最高可达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) {...}。 行extra0extra1等对行有用的内容尚不清楚。

(3)添加以提供一些合理的积分值:

通过选择适当的参数,整数函数integralquadgk能够为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 |

这些函数使用类似的“自适应高斯求积法”规则,因此难怪它们会返回类似的结果。其他完全不同的集成例程可能会产生(稍微?)不同的结果。