## Copyright (C) 2012 Marius Hofert, Ivan Kojadinovic, Martin Maechler, and Jun Yan
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 3 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, see .
### pdf = dCopula() --- but then also pCopula()
### === ~~~~~~~~~ ~~~~~~~~~
require(copula)
## library(fCopulae)
source(system.file("Rsource", "utils.R", package="copula", mustWork=TRUE))
## tryCatch.W.E() etc
## All non-virtual copula classes: ../inst/Rsource/cops.R
source(system.file("Rsource", "cops.R", package="copula", mustWork=TRUE))
## --> copcl, copObs, copBnds, excl.2 , copO.2, copBnd.2
(doExtras <- copula:::doExtras())
### preparation for a grid
n1 <- 17
n2 <- 21
eps <- .001 ## <- not going to very extremes
u1 <- seq(0, 1, length=n1); u1[1] <- eps; u1[n1] <- 1-eps
u2 <- seq(0, 1, length=n2); u2[1] <- eps; u2[n2] <- 1-eps
### d=2 ########################################################################
Exp.grid <- function(...)
as.matrix(expand.grid(..., KEEP.OUT.ATTRS = FALSE))
umat <- Exp.grid(u1=u1, u2=u2)
## all copulas give the same tau except amh (TODO: *range* of tau's ??)
tau <- 0.5
if(!dev.interactive(orNone=TRUE)) pdf("densCop_2d.pdf")
fCols <- colorRampPalette(c("red", "white", "blue"), space = "Lab")
options(width = 137)# -> nicer table printing
showProc.time()
## frankCopula
theta.fr <- iTau(frankCopula(), tau)
dcop <- matrix(dCopula(umat, frankCopula(param=theta.fr, dim = 2)),
n1, n2)
filled.contour(u1, u2, dcop, color.palette = fCols,
main=sprintf("Density( frankCopula(%.4g) )", theta.fr))
round(dcop, 3)
## claytonCopula
(theta.cl <- iTau(claytonCopula(), tau))
stopifnot(all.equal(theta.cl, copClayton@iTau(tau), tolerance = 1e-13))
dcop <- matrix(dCopula(umat, claytonCopula(param=theta.cl, dim = 2)),
n1, n2)
filled.contour(u1, u2, dcop, color.palette = fCols,
main=sprintf(" Density( claytonCopula(%.4g) )", theta.cl))
filled.contour(u1, u2, log(dcop), color.palette = fCols,
main=sprintf("log Density( claytonCopula(%.4g) )", theta.cl))
round(dcop, 3)
## gumbelCopula
theta.gu <- iTau(gumbelCopula(), tau)
stopifnot(all.equal(theta.gu, copGumbel@iTau(tau), tolerance = 1e-13))
dcop <- matrix(dCopula(umat, gumbelCopula(param=theta.gu, dim = 2)),
n1, n2)
filled.contour(u1, u2, dcop, color.palette = fCols,
main=sprintf("Density( gumbelCopula(%.4g) )", theta.gu))
filled.contour(u1, u2, log(dcop), color.palette = fCols,
main=sprintf("log Density( gumbelCopula(%.4g) )", theta.gu))
round(dcop, 3)
## normalCopula
uB <- cbind(c(0:1, .5), (1:9)/10) # values at boundaries
fC <- dCopula(uB, normalCopula(0.55))
stopifnot(is.finite(fC), length(fC)==nrow(uB), fC[-3*(1:3)] == 0)
theta.n <- iTau(normalCopula(), tau)
dcop <- matrix(dCopula(umat, normalCopula(param=theta.n, dim = 2)),
n1, n2)
filled.contour(u1, u2, log(dcop), color.palette = fCols,
main=sprintf("log Density( normalCopula(%.4g) )", theta.n))
filled.contour(u1, u2, dcop, color.palette = fCols,
main=sprintf("Density( normalCopula(%.4g) )", theta.n))
round(dcop, 3)
## tCopula
fC <- dCopula(uB, tCopula(0.55))
stopifnot(is.finite(fC), length(fC)==nrow(uB), fC[-3*(1:3)] == 0)
(theta.t. <- iTau(tCopula(df=10), tau))
dcop <- matrix(dCopula(umat, tCopula(param=theta.t., dim = 2, df=10)),
n1, n2)
filled.contour(u1, u2, log(dcop), color.palette = fCols,
main=sprintf("log Density( tCopula(%.4g, df = 10) )", theta.t.))
filled.contour(u1, u2, dcop, color.palette = fCols,
main=sprintf("Density( tCopula(%.4g, df = 10) )", theta.t.))
round(dcop, 3)
## tCopula -- df=4
(theta <- iTau(tCopula(df=4), tau))
dcop <- matrix(dCopula(umat, tCopula(param=theta, dim = 2, df=4)),
n1, n2)
filled.contour(u1, u2, log(dcop), color.palette = fCols,
main=sprintf("log Density( tCopula(%.4g, df = 4) )", theta))
filled.contour(u1, u2, dcop, color.palette = fCols,
main=sprintf("Density( tCopula(%.4g, df = 4) )", theta))
round(dcop, 3)
## galambosCopula
#
(theta <- iTau(galambosCopula(), tau))
stopifnot(all.equal(tau, tau(galambosCopula(theta)), tolerance = 1e-5))
dcop <- matrix(dCopula(umat, galambosCopula(param=theta)),
n1, n2)
filled.contour(u1, u2, log(dcop), color.palette = fCols,
main=sprintf("log Density( galambosCopula(%.4g) )", theta))
filled.contour(u1, u2, dcop, color.palette = fCols,
main=sprintf("Density( galambosCopula(%.4g) )", theta))
round(dcop, 3)
## plackettCopula
#
(theta <- iTau(plackettCopula(), tau))
stopifnot(all.equal(tau, tau(plackettCopula(theta)), tolerance = 1e-5))
dcop <- matrix(dCopula(umat, plackettCopula(param=theta)),
n1, n2)
filled.contour(u1, u2, log(dcop), color.palette = fCols,
main=sprintf("log Density( plackettCopula(%.4g) )", theta))
filled.contour(u1, u2, dcop, color.palette = fCols,
main=sprintf("Density( plackettCopula(%.4g) )", theta))
round(dcop, 3)
## amhCopula
tau <- 0.3 ## -- to be in range for AMH
(theta <- iTau(amhCopula(), tau))
stopifnot(all.equal(tau, tau(amhCopula(theta)), tolerance = 1e-5))
dcop <- matrix(dCopula(umat, amhCopula(param=theta)),
n1, n2)
filled.contour(u1, u2, dcop, color.palette = fCols,
main=sprintf("Density( amhCopula(%.4g) )", theta))
round(dcop, 3)
showProc.time()
if(!dev.interactive()) dev.off()
### d > 2 ######################################################################
### for package fCopulae
## dcop.f <- darchmCopula(umat, alpha=2, type=1, alternative=T)
## round(matrix(dcop.f, n1, n2), 3)
## dcop.fCopulae <- darchmCopula(umat, alpha=theta.fr, type = 5, alternative = TRUE)
## round (matrix(dcop.fCopulae, n1, n2), 3)
## dim = 3, frankCopula
um3 <- Exp.grid(u1=u1, u2=u2, u3=u1)
dcE <- tryCatch(dcopula(um3), error=identity)
dcop <- dCopula(um3, frankCopula(param=theta.fr, dim = 3))
stopifnot(dcop >= 0, # no NA here
inherits(dcE, "error"),
grepl("defunct", conditionMessage(dcE), ignore.case=TRUE))
round(array(dcop, c(n1,n2,n1)), 3)
## dim = 4 --- fine as long we are "out of corners"
um4 <- Exp.grid(u1=u1, u2=u2, u3=u1, u4=rev(u2))
dcop <- dCopula(um4, frankCopula(param=theta.fr, dim = 4))
stopifnot(dcop >= 0,# no NA here
all.equal(dcop, copFrank@dacopula(um4, theta = theta.fr)))
## round(array(dcop, c(n1,n2,n1,n2)), 3)
showProc.time()
### --- now look at dCopula() and pCopula() for *all* copulas:
##' u "mostly" in [0,1] .. with exceptions that are even NA, NaN
mku <- function(n, fr = 1/20, sd = 1/10) {
r <- runif(n) + rnorm(n, sd=sd)
r[sample(n, ceiling(fr*n))] <- c(NA,NaN)
r
}
## This is from ./moments.R --- keep in sync! ---
tau.s <- c( -.1, 0, 0.05805, (1:2)/9, 0.3)
names(tau.s) <- paste0("tau=", sub("0[.]", ".", formatC(tau.s)))
suppressWarnings( # warnings about ... "tau must be >= 0.
tTau <- sapply(tau.s, function(tau) vapply(copObs, iTau, numeric(1), tau = tau))
) # tTau is printed in moments.R
suppressWarnings(RNGversion("3.5.0")) ; set.seed(12)
u <- matrix(mku(1000), ncol= 2)# d = 2 required in the copula objects
##' == function(u) copula:::outside.01(u, strictly = FALSE) --- used in dCopula()
u.outside.01 <- function(u) apply(u, 1, function(x) any(x <= 0, 1 <= x))
u.out <- u.outside.01(u) # has NAs
u.ina <- apply(u, 1, anyNA)
u.iNA <- is.na(u.out)
(tuna <- table(u.ina, u.out, exclude={}))
## u.out
## u.ina FALSE TRUE
## FALSE 384 67 0
## TRUE 0 7 42
stopifnot(identical(c(384L, 0L, 67L, 7L, 0L, 42L), c(tuna)))
u.OUT <- u.out & !u.ina # no NAs
## NB: f(u) = 0 if some u_j is outside (0,1) - even when another u_k is NA
copsT <- lapply(setNames(,names(copObs)), # so have *named* list
function(cN)
lapply(unique(tTau[cN,]), function(th) setPar(copObs[[cN]], th)))
copsTh <- unlist(copsT, recursive=FALSE)
## --> a list of 72 parametrized copulas
## ... currently one of them not being "valid":
okC <- lapply(copsTh, validObject, test=TRUE)
(inOk <- which(notOk <- !sapply(okC, isTRUE)))
## joeCopula2
## 43
if(length(inOk)) { # maybe no longer in future
stopifnot(identical(inOk, c(joeCopula2 = 43L)))
jp <- copsTh[[inOk]]@parameters
print(jp - 1) # -3.41e-10
stopifnot(all.equal(jp, 1))
## now fix it up:
copsTh[[inOk]]@parameters <- 1
validObject(copsTh[[inOk]])
}
## Now, *all* are validObject :
stopifnot( vapply(copsTh, validObject, logical(1), test=TRUE) )
## now using ( u[], u.ina, u.OUT ):
op <- options(warn = 1) # immediate
## ==> *all* Huessler-Reiss produce warnings such as << FIXME eventually
## Warning in log(u1p/u2p) : NaNs produced
## all other copulas give no warning !
errH <- if(getRversion() < "3.5.0") identity else function(e) {e$call <- NULL ; e}
copChk <- lapply(copsTh, function(cop) {
show(cop)
fu <- dCopula(u, cop)
Fu <- pCopula(u, cop)
lfu <- dCopula(u, cop, log=TRUE)
## lfu. <- lfu[!u.ina]
cat("-----------\n")
tryCatch(
stopifnot(fu[u.OUT] == 0,
all.equal(fu, exp(lfu), tolerance = 1e-15),
0 <= fu[!u.ina],
0 <= Fu[!u.ina], Fu[!u.ina] <= 1,
is.finite(lfu[!u.ina]) | lfu[!u.ina] == -Inf,
is.na(fu[u.iNA]), is.na(Fu[u.ina]), is.na(lfu[u.iNA]))
, error = errH)
})
options(op)
### FIXME: Should see nothing below ( <==> length(ccc) == 0) ! ------------------------------
ccc <- unlist(copChk) # ==> drop all those that have NULL, i.e. *no* error above :
names(ccc) <- sub(".message$", "", names(ccc))
structure(as.list(ccc), class="simple.list")
stopifnot(length(ccc) <= 17)
## claytonCopula2 is.na(Fu[u.ina]) are not all TRUE ((indepCopula case; progress already))
## frankCopula2 0 <= Fu[!u.ina] are not all TRUE ((indepCopula case; fix?
## galambosCopula1 is.na(fu[u.iNA]) are not all TRUE ((indepCopula case; progress already))
## galambosCopula2 0 <= Fu[!u.ina] are not all TRUE
## galambosCopula3 0 <= Fu[!u.ina] are not all TRUE
## galambosCopula4 0 <= Fu[!u.ina] are not all TRUE
## galambosCopula5 0 <= Fu[!u.ina] are not all TRUE
## huslerReissCopula1 0 <= Fu[!u.ina] are not all TRUE
## huslerReissCopula2 0 <= Fu[!u.ina] are not all TRUE
## huslerReissCopula3 0 <= Fu[!u.ina] are not all TRUE
## huslerReissCopula4 0 <= Fu[!u.ina] are not all TRUE
## huslerReissCopula5 0 <= Fu[!u.ina] are not all TRUE
## tawnCopula1 is.na(Fu[u.ina]) are not all TRUE
## tawnCopula2 is.na(Fu[u.ina]) are not all TRUE
## tawnCopula3 is.na(Fu[u.ina]) are not all TRUE
## tawnCopula4 is.na(Fu[u.ina]) are not all TRUE
## tawnCopula5 is.na(Fu[u.ina]) are not all TRUE
###-------------- "Unit" Tests for specific cases: ------------------------------
n.c <- as.integer(if(doExtras) 1001 else 101)
##== plackettCopula: density log(dCopula()) vs "better" dCopula(*, log=TRUE) ----- _UNFINISHED_ TODO
##' difference log(c(..)) - c(.., log=TRUE)
mkDfn <- function(u) {
stopifnot(is.numeric(u), length(u) == 2 || (is.matrix(u) && ncol(u) == 2))
Vectorize(function(alp) { C <- plackettCopula(alp); log(dCopula(u,C)) - dCopula(u,C,log=TRUE) })
}
Df <- mkDfn(u = c(.01,.99))
curve(Df, 0.99, 1.01, n=n.c) # alpha ~= 1 -- log=TRUE should be better -- but difference seem random!
curve(Df, 0, 2, n=n.c) # to my surprise, alpha ~= 0 makes big difference
curve(Df, 1e-9, .01, log="x")
curve(abs(Df(x)), 1e-14, .1, log="xy")# and which one is more accurate ??
# another u[]
Df <- mkDfn(u = c(.1,.2))
curve(Df, 0.99, 1.01, n=n.c) # alpha ~= 1 -- log=TRUE: diff. larger for 1+eps than 1-eps
curve(Df, 0, 2, n=n.c) # all very small
# and another
curve(mkDfn(u = c(.01,.02 ))(x), 0, 2, n=n.c) # all very small
curve(mkDfn(u = c(.98,.999))(x), 0, 2, n=n.c) # growing with alpha
curve(mkDfn(u = c(.98,.999))(x), .1, 1e4, n=n.c, log="x") # growing with alpha, still |.| < 6e-12
curve(mkDfn(u = c(.01,.001))(x), .01,1e8, n=n.c, log="x") # (growing) still small: |.| < 6e-15
##' 2-dim u[] in the low-density corner
mku <- function(n, one. = 0.999, eps = c(4^-(2:n2), b.n^-((n-n2):n))) {
## find basis for eps for very small eps
stopifnot(n >= 2)
n2 <- n %/% 2
R.n <- - .Machine$double.min.exp / n
b.n <- trunc(100*(2^R.n + 0.05))/100
stopifnot(.5 > eps, eps > 0, 0.9 <= one., one. <= 1)
cbind(one., eps, deparse.level = 0L)
}
if(doExtras) withAutoprint({
alpha <- 1e6 ## <- large alpha
(cop <- plackettCopula(alpha))
summary(u <- mku(64))
d1 <- dCopula(u, cop, log=TRUE)
d2 <- log(dCopula(u, cop))
summary(d1-d2)
all.equal(d1,d2, tol=0)
})