## 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) })