Nothing
#' Adaptive multivariate integration over hypercubes (hcubature and pcubature)
#'
#' The function performs adaptive multidimensional integration (cubature) of
#' (possibly) vector-valued integrands over hypercubes. The function includes
#' a vector interface where the integrand may be evaluated at several hundred
#' points in a single call.
#'
#' The function merely calls Johnson's C code and returns the results.
#'
#' One can specify a maximum number of function evaluations (default is 0 for
#' no limit). Otherwise, the integration stops when the estimated error is
#' less than the absolute error requested, or when the estimated error is less
#' than tol times the integral, in absolute value, or the maximum number of
#' iterations is reached (see parameter info below), whichever is earlier.
#'
#' For compatibility with earlier versions, the `adaptIntegrate` function
#' is an alias for the underlying `hcubature` function which uses h-adaptive
#' integration. Otherwise, the calling conventions are the same.
#'
#' We highly recommend referring to the vignette to achieve the best results!
#'
#' @importFrom Rcpp evalCpp
#' @aliases adaptIntegrate pcubature
#'
#' @param f The function (integrand) to be integrated
#' @param lowerLimit The lower limit of integration, a vector for
#' hypercubes
#' @param upperLimit The upper limit of integration, a vector for
#' hypercubes
#' @param ... All other arguments passed to the function f
#' @param tol The maximum tolerance, default 1e-5.
#' @param fDim The dimension of the integrand, default 1, bears no
#' relation to the dimension of the hypercube
#' @param maxEval The maximum number of function evaluations needed,
#' default 0 implying no limit. Note that the actual number of
#' function evaluations performed is only approximately guaranteed
#' not to exceed this number.
#' @param absError The maximum absolute error tolerated, default `.Machine$double_eps * 10^2`.
#' @param doChecking As of version 2.0, this flag is ignored and will
#' be dropped in forthcoming versions
#' @param vectorInterface A flag that indicates whether to use the
#' vector interface and is by default FALSE. See details below
#' @param norm For vector-valued integrands, `norm` specifies the
#' norm that is used to measure the error and determine
#' convergence properties. See below.
#' @return The returned value is a list of four items:
#' \item{integral}{the value of the integral} \item{error}{the
#' estimated absolute error} \item{functionEvaluations}{the number
#' of times the function was evaluated} \item{returnCode}{the
#' actual integer return code of the C routine}
#'
#' @details
#'
#' The `hcubature` function is the h-adaptive version that recursively partitions
#' the integration domain into smaller subdomains, applying the same integration
#' rule to each, until convergence is achieved.
#'
#' The p-adaptive version, `pcubature`, repeatedly doubles the degree
#' of the quadrature rules until convergence is achieved, and is based on a tensor
#' product of Clenshaw-Curtis quadrature rules. This algorithm is often superior
#' to h-adaptive integration for smooth integrands in a few (<=3) dimensions,
#' but is a poor choice in higher dimensions or for non-smooth integrands.
#' Compare with `hcubature` which also takes the same arguments.
#'
#' The vector interface requires the integrand to take a matrix as its argument.
#' The return value should also be a matrix. The number of points at which the
#' integrand may be evaluated is not under user control: the integration routine
#' takes care of that and this number may run to several hundreds. We strongly
#' advise vectorization; see vignette.
#'
#' The `norm` argument is irrelevant for scalar integrands and is ignored.
#' Given vectors \eqn{v} and \eqn{e} of estimated integrals and errors therein,
#' respectively, the `norm` argument takes on one of the following values:
#' \describe{
#' \item{`INDIVIDUAL`}{Convergence is achieved only when each integrand
#' (each component of \eqn{v} and \eqn{e}) individually satisfies the requested
#' error tolerances}
#' \item{`L1`, `L2`, `LINF`}{The absolute error is measured as
#' \eqn{|e|} and the relative error as \eqn{|e|/|v|}, where \eqn{|...|} is the
#' \eqn{L_1}, \eqn{L_2}, or \eqn{L_{\infty}} norm, respectively}
#' \item{`PAIRED`}{Like `INDIVIDUAL`, except that the integrands are
#' grouped into consecutive pairs, with the error tolerance applied in an
#' \eqn{L_2} sense to each pair. This option is mainly useful for integrating
#' vectors of complex numbers, where each consecutive pair of real integrands
#' is the real and imaginary parts of a single complex integrand, and the concern
#' is only the error in the complex plane rather than the error in the real and
#' imaginary parts separately}
#' }
#'
#' @author Balasubramanian Narasimhan
#' @keywords math
#' @examples
#'
#' \dontrun{
#' ## Test function 0
#' ## Compare with original cubature result of
#' ## ./cubature_test 2 1e-4 0 0
#' ## 2-dim integral, tolerance = 0.0001
#' ## integrand 0: integral = 0.708073, est err = 1.70943e-05, true err = 7.69005e-09
#' ## #evals = 17
#'
#' testFn0 <- function(x) {
#' prod(cos(x))
#' }
#'
#' hcubature(testFn0, rep(0,2), rep(1,2), tol=1e-4)
#'
#' pcubature(testFn0, rep(0,2), rep(1,2), tol=1e-4)
#'
#' M_2_SQRTPI <- 2/sqrt(pi)
#'
#' ## Test function 1
#' ## Compare with original cubature result of
#' ## ./cubature_test 3 1e-4 1 0
#' ## 3-dim integral, tolerance = 0.0001
#' ## integrand 1: integral = 1.00001, est err = 9.67798e-05, true err = 9.76919e-06
#' ## #evals = 5115
#'
#' testFn1 <- function(x) {
#' val <- sum (((1-x) / x)^2)
#' scale <- prod(M_2_SQRTPI/x^2)
#' exp(-val) * scale
#' }
#'
#' hcubature(testFn1, rep(0, 3), rep(1, 3), tol=1e-4)
#' pcubature(testFn1, rep(0, 3), rep(1, 3), tol=1e-4)
#'
#' ##
#' ## Test function 2
#' ## Compare with original cubature result of
#' ## ./cubature_test 2 1e-4 2 0
#' ## 2-dim integral, tolerance = 0.0001
#' ## integrand 2: integral = 0.19728, est err = 1.97261e-05, true err = 4.58316e-05
#' ## #evals = 166141
#'
#' testFn2 <- function(x) {
#' ## discontinuous objective: volume of hypersphere
#' radius <- as.double(0.50124145262344534123412)
#' ifelse(sum(x*x) < radius*radius, 1, 0)
#' }
#'
#' hcubature(testFn2, rep(0, 2), rep(1, 2), tol=1e-4)
#' pcubature(testFn2, rep(0, 2), rep(1, 2), tol=1e-4)
#'
#' ##
#' ## Test function 3
#' ## Compare with original cubature result of
#' ## ./cubature_test 3 1e-4 3 0
#' ## 3-dim integral, tolerance = 0.0001
#' ## integrand 3: integral = 1, est err = 0, true err = 2.22045e-16
#' ## #evals = 33
#'
#' testFn3 <- function(x) {
#' prod(2*x)
#' }
#'
#' hcubature(testFn3, rep(0,3), rep(1,3), tol=1e-4)
#' pcubature(testFn3, rep(0,3), rep(1,3), tol=1e-4)
#'
#' ##
#' ## Test function 4 (Gaussian centered at 1/2)
#' ## Compare with original cubature result of
#' ## ./cubature_test 2 1e-4 4 0
#' ## 2-dim integral, tolerance = 0.0001
#' ## integrand 4: integral = 1, est err = 9.84399e-05, true err = 2.78894e-06
#' ## #evals = 1853
#'
#' testFn4 <- function(x) {
#' a <- 0.1
#' s <- sum((x - 0.5)^2)
#' (M_2_SQRTPI / (2. * a))^length(x) * exp (-s / (a * a))
#' }
#'
#' hcubature(testFn4, rep(0,2), rep(1,2), tol=1e-4)
#' pcubature(testFn4, rep(0,2), rep(1,2), tol=1e-4)
#'
#' ##
#' ## Test function 5 (double Gaussian)
#' ## Compare with original cubature result of
#' ## ./cubature_test 3 1e-4 5 0
#' ## 3-dim integral, tolerance = 0.0001
#' ## integrand 5: integral = 0.999994, est err = 9.98015e-05, true err = 6.33407e-06
#' ## #evals = 59631
#'
#' testFn5 <- function(x) {
#' a <- 0.1
#' s1 <- sum((x - 1/3)^2)
#' s2 <- sum((x - 2/3)^2)
#' 0.5 * (M_2_SQRTPI / (2. * a))^length(x) * (exp(-s1 / (a * a)) + exp(-s2 / (a * a)))
#' }
#'
#' hcubature(testFn5, rep(0,3), rep(1,3), tol=1e-4)
#' pcubature(testFn5, rep(0,3), rep(1,3), tol=1e-4)
#'
#' ##
#' ## Test function 6 (Tsuda's example)
#' ## Compare with original cubature result of
#' ## ./cubature_test 4 1e-4 6 0
#' ## 4-dim integral, tolerance = 0.0001
#' ## integrand 6: integral = 0.999998, est err = 9.99685e-05, true err = 1.5717e-06
#' ## #evals = 18753
#'
#' testFn6 <- function(x) {
#' a <- (1 + sqrt(10.0)) / 9.0
#' prod(a / (a + 1) * ((a + 1) / (a + x))^2)
#' }
#'
#' hcubature(testFn6, rep(0,4), rep(1,4), tol=1e-4)
#' pcubature(testFn6, rep(0,4), rep(1,4), tol=1e-4)
#'
#'
#' ##
#' ## Test function 7
#' ## test integrand from W. J. Morokoff and R. E. Caflisch, "Quasi=
#' ## Monte Carlo integration," J. Comput. Phys 122, 218-230 (1995).
#' ## Designed for integration on [0,1]^dim, integral = 1. */
#' ## Compare with original cubature result of
#' ## ./cubature_test 3 1e-4 7 0
#' ## 3-dim integral, tolerance = 0.0001
#' ## integrand 7: integral = 1.00001, est err = 9.96657e-05, true err = 1.15994e-05
#' ## #evals = 7887
#'
#' testFn7 <- function(x) {
#' n <- length(x)
#' p <- 1/n
#' (1 + p)^n * prod(x^p)
#' }
#'
#' hcubature(testFn7, rep(0,3), rep(1,3), tol=1e-4)
#' pcubature(testFn7, rep(0,3), rep(1,3), tol=1e-4)
#'
#'
#' ## Example from web page
#' ## http://ab-initio.mit.edu/wiki/index.php/Cubature
#' ##
#' ## f(x) = exp(-0.5(euclidean_norm(x)^2)) over the three-dimensional
#' ## hyperbcube [-2, 2]^3
#' ## Compare with original cubature result
#' testFnWeb <- function(x) {
#' exp(-0.5 * sum(x^2))
#' }
#'
#' hcubature(testFnWeb, rep(-2,3), rep(2,3), tol=1e-4)
#' pcubature(testFnWeb, rep(-2,3), rep(2,3), tol=1e-4)
#'
#' ## Test function I.1d from
#' ## Numerical integration using Wang-Landau sampling
#' ## Y. W. Li, T. Wust, D. P. Landau, H. Q. Lin
#' ## Computer Physics Communications, 2007, 524-529
#' ## Compare with exact answer: 1.63564436296
#' ##
#' I.1d <- function(x) {
#' sin(4*x) *
#' x * ((x * ( x * (x*x-4) + 1) - 1))
#' }
#'
#' hcubature(I.1d, -2, 2, tol=1e-7)
#' pcubature(I.1d, -2, 2, tol=1e-7)
#'
#' ## Test function I.2d from
#' ## Numerical integration using Wang-Landau sampling
#' ## Y. W. Li, T. Wust, D. P. Landau, H. Q. Lin
#' ## Computer Physics Communications, 2007, 524-529
#' ## Compare with exact answer: -0.01797992646
#' ##
#' ##
#' I.2d <- function(x) {
#' x1 = x[1]
#' x2 = x[2]
#' sin(4*x1+1) * cos(4*x2) * x1 * (x1*(x1*x1)^2 - x2*(x2*x2 - x1) +2)
#' }
#'
#' hcubature(I.2d, rep(-1, 2), rep(1, 2), maxEval=10000)
#' pcubature(I.2d, rep(-1, 2), rep(1, 2), maxEval=10000)
#'
#' ##
#' ## Example of multivariate normal integration borrowed from
#' ## package mvtnorm (on CRAN) to check ... argument
#' ## Compare with output of
#' ## pmvnorm(lower=rep(-0.5, m), upper=c(1,4,2), mean=rep(0, m), corr=sigma, alg=Miwa())
#' ## 0.3341125. Blazing quick as well! Ours is, not unexpectedly, much slower.
#' ##
#' dmvnorm <- function (x, mean, sigma, log = FALSE) {
#' if (is.vector(x)) {
#' x <- matrix(x, ncol = length(x))
#' }
#' if (missing(mean)) {
#' mean <- rep(0, length = ncol(x))
#' }
#' if (missing(sigma)) {
#' sigma <- diag(ncol(x))
#' }
#' if (NCOL(x) != NCOL(sigma)) {
#' stop("x and sigma have non-conforming size")
#' }
#' if (!isSymmetric(sigma, tol = sqrt(.Machine$double.eps),
#' check.attributes = FALSE)) {
#' stop("sigma must be a symmetric matrix")
#' }
#' if (length(mean) != NROW(sigma)) {
#' stop("mean and sigma have non-conforming size")
#' }
#' distval <- mahalanobis(x, center = mean, cov = sigma)
#' logdet <- sum(log(eigen(sigma, symmetric = TRUE, only.values = TRUE)$values))
#' logretval <- -(ncol(x) * log(2 * pi) + logdet + distval)/2
#' if (log)
#' return(logretval)
#' exp(logretval)
#' }
#'
#' m <- 3
#' sigma <- diag(3)
#' sigma[2,1] <- sigma[1, 2] <- 3/5 ; sigma[3,1] <- sigma[1, 3] <- 1/3
#' sigma[3,2] <- sigma[2, 3] <- 11/15
#' hcubature(dmvnorm, lower=rep(-0.5, m), upper=c(1,4,2),
#' mean=rep(0, m), sigma=sigma, log=FALSE,
#' maxEval=10000)
#' pcubature(dmvnorm, lower=rep(-0.5, m), upper=c(1,4,2),
#' mean=rep(0, m), sigma=sigma, log=FALSE,
#' maxEval=10000)
#' }
#'
#' @export hcubature adaptIntegrate pcubature
#'
hcubature <- adaptIntegrate <- function(f, lowerLimit, upperLimit, ..., tol = 1e-5,
fDim = 1, maxEval = 0, absError = .Machine$double.eps * 10^2 / 2.0, doChecking = FALSE,
vectorInterface = FALSE,
norm = c("INDIVIDUAL",
"PAIRED",
"L2",
"L1",
"LINF")) {
NORM_CODES <- c(INDIVIDUAL = 0L, PAIRED = 1L, L2 = 2L, L1 = 3L, LINF = 4L)
norm <- as.integer(NORM_CODES[match.arg(norm)])
nL = length(lowerLimit); nU = length(upperLimit)
if (fDim <= 0 || nL <= 0 || nU <= 0) {
stop("Both f and x must have dimension >= 1")
}
if (nL != nU) {
stop("lowerLimit and upperLimit must have same length")
}
if (tol <= 0) {
stop("tol should be positive!")
}
f <- match.fun(f)
if (all(is.finite(c(lowerLimit, upperLimit)))) {
fnF <- function(x) {
f(x, ...)
}
} else {
lowerLimit <- atan(lowerLimit)
upperLimit <- atan(upperLimit)
fnF <- if (!vectorInterface)
function(x) f(tan(x), ...) / prod(cos(x))^2
else
function(x) f(tan(x), ...) / rep(apply(cos(x), 2, prod)^2, each = fDim)
}
.Call("_cubature_doHCubature", as.integer(fDim), fnF, as.double(lowerLimit),
as.double(upperLimit), as.integer(maxEval), as.double(absError),
as.double(tol), as.integer(vectorInterface), norm, PACKAGE="cubature")
}
#' @rdname hcubature
pcubature <- function(f, lowerLimit, upperLimit, ..., tol = 1e-5,
fDim = 1, maxEval = 0, absError = .Machine$double.eps * 10^2, doChecking = FALSE,
vectorInterface = FALSE,
norm = c("INDIVIDUAL",
"PAIRED",
"L2",
"L1",
"LINF")) {
NORM_CODES <- c(INDIVIDUAL = 0L, PAIRED = 1L, L2 = 2L, L1 = 3L, LINF = 4L)
norm <- as.integer(NORM_CODES[match.arg(norm)])
nL = length(lowerLimit); nU = length(upperLimit)
if (fDim <= 0 || nL <= 0 || nU <= 0) {
stop("Both f and x must have dimension >= 1")
}
if (nL != nU) {
stop("lowerLimit and upperLimit must have same length")
}
if (nL > 3) {
warning("pcubature not recommended for dimensions > 3!")
}
if (tol <= 0) {
stop("tol should be positive!")
}
f <- match.fun(f)
if (all(is.finite(c(lowerLimit, upperLimit)))) {
fnF <- function(x) {
f(x, ...)
}
} else {
lowerLimit <- atan(lowerLimit)
upperLimit <- atan(upperLimit)
fnF <- if (vectorInterface)
function(x) f(tan(x), ...) / rep(apply(cos(x), 2, prod)^2, each = fDim)
else
function(x) f(tan(x), ...) / prod(cos(x))^2
}
.Call("_cubature_doPCubature", as.integer(fDim), fnF, as.double(lowerLimit),
as.double(upperLimit), as.integer(maxEval), as.double(absError),
as.double(tol), as.integer(vectorInterface), norm, PACKAGE="cubature")
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.