R/structure_select2.R

Defines functions as.RVMKernel2 fasttau deleteEdges set_weight adjacencyMatrix findMaxTree2 makeFullGraph2 graphFromTauMatrix getEdgeInfo2 buildNextGraph2 graphFromTauMatrix2 initializeFirstGraph2 hoeffd est.TreeCopulas2 est.FirstTreeCopulas2 structure_select2

structure_select2 <- function(data, type, method, mult, struct.crit, test.level,
                              trunc.level, renorm.iter, cores, info, progress = FALSE) {
    if (type == 0) {
        type <- "RVine"
    } else if (type == 1) {
        type <- "CVine"
    }
    if (type != "RVine" & type != "CVine")
        stop("Vine model not implemented.")
    n <- nrow(data)
    d <- ncol(data)
    if (n < 2)
        stop("Number of observations has to be at least 2.")
    if (d < 2)
        stop("Dimension has to be at least 2.")
    if (any(data > 1) || any(data < 0))
        stop("Data has be in the interval [0,1].")
    if (is.na(test.level))
        test.level <- 1
    if (!(struct.crit %in% c("tau", "AIC", "cAIC", "hoeffd")))
        stop("'struct.crit' has to be one of 'tau', 'AIC', 'cAIC', or 'hoeffd'")

    # set names if not available
    if (is.null(colnames(data)))
        colnames(data) = paste("V", 1:d, sep = "")

    ## initialize objects
    RVine <- list(Tree = NULL, Graph = NULL)
    res <- as.list(numeric(d - 1))
    for (i in 1:(d - 1))
        res[[i]] <- as.list(numeric(d - i))
    llikv <- array(0, dim = c(d, d, n))
    llik <- matrix(0, d, d)
    effp <- matrix(0, d, d)
    AIC <- matrix(0, d, d)
    cAIC <- matrix(0, d, d)
    BIC <- matrix(0, d, d)

    ## register parallel backend
    if (cores != 1 | is.na(cores)) {
        if (is.na(cores))
            cores <- max(1, detectCores() - 1)
        if (cores > 1) {
            cl <- makeCluster(cores)
            registerDoParallel(cl)
            on.exit(try(stopCluster(), silent = TRUE))
        }
    }

    ## build first tree
    g <- initializeFirstGraph2(data, struct.crit = struct.crit, weights = NA)
    mst <- findMaxTree2(g, mode = type)

    ## estimate copulas in first tree and store results
    est <- est.FirstTreeCopulas2(mst,
                                 data,
                                 method = method,
                                 mult = mult,
                                 info = info,
                                 test.level = test.level,
                                 renorm.iter = renorm.iter,
                                 parallel = cores > 1)
    res[[1]] <- est$est
    VineTree <- est$mst
    RVine$Tree[[1]] <- VineTree
    RVine$Graph[[1]] <- g

    ## higher trees
    for (k in 2:(d - 1)) {
        g <- buildNextGraph2(VineTree,
                             weights = NA,
                             struct.crit = struct.crit,
                             parallel = cores > 1)
        mst <- findMaxTree2(g, mode = type)
        est <- est.TreeCopulas2(mst,
                                k = k,
                                d2 = d,
                                data = data,
                                oldVineGraph = VineTree,
                                method = method,
                                mult = mult,
                                info = info,
                                test.level = test.level,
                                renorm.iter = renorm.iter,
                                parallel = cores > 1,
                                truncate = trunc.level <= k)

        res[[k]] <- est$est
        VineTree <- est$tree
        RVine$Tree[[k]] <- VineTree
        RVine$Graph[[k]] <- g
    }

    ## finalize results
    res[[d]] <- data
    res[[d + 1]] <- M <- as.RVMKernel2(RVine)$Matrix
    for (i in 1:(d - 1)) {
        for (k in (i + 1):d) {
            hfit <- res[[i]][[k - i]]$h
            if (info) {
                pcfit <- res[[i]][[k - i]]$c
                llikv[k, i, ] <- log(pcfit$info$likvalues)
                llik[k, i] <- pcfit$info$loglik
                effp[k, i] <- pcfit$info$effp
                AIC[k, i] <- -2 * pcfit$info$loglik + 2 * effp[k, i]
                cAIC[k, i] <-
                    AIC[k, i] + (2 * effp[k, i] * (effp[k, i] + 1)) /
                    (n - effp[k, i] - 1)
                BIC[k, i] <- -2 * pcfit$info$loglik + log(n) * effp[k, i]
            }
        }
    }
    res[[d + 2]] <- if (info) {
        list(llikv       = apply(llikv, 3, sum),
             loglik      = sum(llik),
             pair.loglik = llik,
             effp        = sum(effp),
             pair.effp   = effp,
             AIC         = sum(AIC),
             pair.AIC    = AIC,
             cAIC        =
                 sum(AIC) +
                 (2 * sum(effp) * (sum(effp) + 1)) /
                 (n - sum(effp) - 1),
             pair.cAIC   = cAIC,
             BIC         = sum(BIC),
             pair.BIC    = BIC)
    } else list(NULL)

    names(res) <- vapply(1:(d - 1), function(x) paste("T", x, sep = ""), "")
    names(res)[d:(d + 2)] <- c("data", "matrix", "info")

    ## return results
    class(res) <- "kdevinecop"
    res
}

est.FirstTreeCopulas2 <- function(mst, data.univ, method, mult, test.level,
                                  renorm.iter, info, parallel) {
    d <- nrow(mst$E$nums)

    ## estimation
    pkgs <- c("kdevine", "kdecopula")

    ## For independence pair-copulas
    indepinfo <- list(effp = 0,
                      likvalues = rep(1, nrow(data.univ)),
                      loglik = 0,
                      effp = 0,
                      AIC = 0,
                      cAIC = 0,
                      BIC = 0)

    doEst <- function(i) {
        a <- rev(mst$E$nums[i, ])

        ## store samples
        Copula.Data.1 =  list(data.univ[, a[1]])
        Copula.Data.2 =  list(data.univ[, a[2]])

        ## set names for this edge
        if (is.null(mst$V$names[a[1]])) {
            Copula.CondName.1 <- a[1]
        } else {
            Copula.CondName.1 <- mst$V$names[a[1]]
        }
        if (is.null(mst$V$names[a[2]])) {
            Copula.CondName.2 <- a[2]
        } else {
            Copula.CondName.2 <- mst$V$names[a[2]]
        }
        if (is.null(mst$V$names[a[1]]) || is.null(mst$V$names[a[2]])) {
            Copula.Name <- paste(a[1],
                                 a[2],
                                 sep = " , ")
        } else {
            Copula.Name <- paste(mst$V$names[a[1]],
                                 mst$V$names[a[2]],
                                 sep = " , ")
        }

        ## identify with numbers
        nums <- paste(a[2], a[1], sep = ",")

        ## estimation
        s <- cbind(data.univ[,a[2]], data.univ[,a[1]])
        indep <- ifelse(test.level < 1,
                        BiCopIndTest(s[, 1], s[, 2])$p.value >= test.level,
                        FALSE)
        if (is.na(indep))
            browser()

        if (indep) {
            pcfit <- list()
            if (info)
                pcfit$info <- indepinfo
            class(pcfit) <- c("kdecopula", "indep.copula")
        } else {
            pcfit <- kdecop(s,
                            method = method,
                            mult = mult,
                            renorm.iter = renorm.iter,
                            info = info)
            # pcfit$udata <- NULL
        }

        ## get and store new pseudo-samples
        if (indep == TRUE) {
            Copula.CondData.1 <- s[,1]
            Copula.CondData.2 <- s[,2]
        } else {
            Copula.CondData.1 <- list(hkdecop(s,
                                              obj = pcfit,
                                              cond.var = 2L))
            Copula.CondData.2 <- list(hkdecop(s,
                                              obj = pcfit,
                                              cond.var = 1L))
        }

        ## store estimates
        resi <- list(c = pcfit, name = nums)

        ## return results
        list(Copula.Data.1 = Copula.Data.1,
             Copula.Data.2 = Copula.Data.2,
             Copula.CondName.1 = Copula.CondName.1,
             Copula.CondName.2 = Copula.CondName.2,
             Copula.Name = Copula.Name,
             Copula.CondData.1 = Copula.CondData.1,
             Copula.CondData.2 = Copula.CondData.2,
             resi = resi)
    }

    res <- if (parallel) {
        foreach(i = 1:d,
                .export = c("d"),
                .packages = pkgs) %dopar% doEst(i)
    } else {
        lapply(1:d, doEst)
    }

    ## clean and return results
    for (i in 1:d) {
        mst$E$Copula.Data.1[[i]] =  res[[i]]$Copula.Data.1
        mst$E$Copula.Data.2[[i]] =  res[[i]]$Copula.Data.2
        mst$E$Copula.CondName.1[[i]] = res[[i]]$Copula.CondName.1
        mst$E$Copula.CondName.2[[i]] = res[[i]]$Copula.CondName.2
        mst$E$Copula.Name[[i]] = res[[i]]$Copula.Name
        mst$E$Copula.CondData.1[[i]] = res[[i]]$Copula.CondData.1
        mst$E$Copula.CondData.2[[i]] = res[[i]]$Copula.CondData.2
        mst$E$Copula.Nums.1 = res[[i]]$resi$name
        res[[i]] <- res[[i]]$resi
    }

    list(mst = mst, est = res)
}



est.TreeCopulas2 <- function(mst, k, d2, data, oldVineGraph, method, mult, info,
                             test.level, renorm.iter, weights = NA, parallel,
                             truncate) {

    d <- nrow(mst$E$nums) # number of nodes in the tree

    ## For independence pair-copulas
    indepinfo <- list(effp = 0,
                      likvalues = rep(1, nrow(data)),
                      loglik = 0,
                      effp = 0,
                      AIC = 0,
                      cAIC = 0,
                      BIC = 0)

    ## estimation
    exp <- c("split_name", "split_num", "naming")
    pkgs <- c("kdecopula")
    doEst <- function(i, mst) {
        ## get edge and corresponding data
        con <- rev(mst$E$nums[i, ])
        temp <- oldVineGraph$E$nums[con, ]

        ## find conditional variable
        if ((temp[1, 1] == temp[2, 1]) || (temp[1, 2] == temp[2, 1])) {
            same <- temp[2, 1]
        } else {
            if((temp[1, 1] == temp[2, 2]) || (temp[1, 2] == temp[2, 2])) {
                same <- temp[2, 2]
            }
        }

        ## find conditioned variables
        other1 <- temp[1, temp[1, ] != same]
        other2 <- temp[2, temp[2, ] != same]

        ## extract observations and names
        if (temp[1, 1] == same) {
            zr1 <- oldVineGraph$E$Copula.CondData.2[[con[1]]]
            n1  <- oldVineGraph$E$Copula.CondName.2[[con[1]]]
        } else {
            zr1 <- oldVineGraph$E$Copula.CondData.1[[con[1]]]
            n1  <- oldVineGraph$E$Copula.CondName.1[[con[1]]]
        }
        if (temp[2, 1] == same) {
            zr2 <- oldVineGraph$E$Copula.CondData.2[[con[2]]]
            n2  <- oldVineGraph$E$Copula.CondName.2[[con[2]]]
        } else {
            zr2 <- oldVineGraph$E$Copula.CondData.1[[con[2]]]
            n2  <- oldVineGraph$E$Copula.CondName.1[[con[2]]]
        }

        zr1a <- if (is.list(zr1)) as.vector(zr1[[1]]) else zr1
        zr2a <- if (is.list(zr2)) as.vector(zr2[[1]]) else zr2
        n1a <- if (is.list(n1)) as.vector(n1[[1]]) else n1
        n2a <- if (is.list(n2)) as.vector(n2[[1]]) else n2

        ## store pseudo-samples
        Copula.Data.1 <- zr1a
        Copula.Data.2 <- zr2a

        ## store names
        Copula.CondName.2 <- n1a
        Copula.CondName.1 <- n2a

        ## estimations
        samples <- cbind(zr1a, zr2a)
        indep <- ifelse(test.level < 1,
                        BiCopIndTest(samples[, 1], samples[, 2])$p.value >= test.level,
                        FALSE)

        if (truncate)
            indep <- TRUE
        if (indep) {
            pcfit <- list()
            if (info)
                pcfit$info <- indepinfo
            class(pcfit) <- c("kdecopula", "indep.copula")
        } else {
            pcfit <- kdecop(samples,
                            mult = mult,
                            method = method,
                            renorm.iter = renorm.iter,
                            info = info)
            # pcfit$udata <- NULL
        }

        ## naming
        tmpname <- mst$E$names[i]
        namesplt <- split_name(tmpname)
        numsplt  <- sapply(namesplt, function(x) which(colnames(data) == x))
        nums <- naming(sprintf("%d", numsplt))

        ## get and store new pseudo-samples
        if (indep == TRUE) {
            Copula.CondData.1 <- samples[,2]
            Copula.CondData.2 <- samples[,1]
        } else {
            Copula.CondData.1 <- hkdecop(samples,
                                         obj = pcfit,
                                         cond.var = 1L)
            Copula.CondData.2 <- hkdecop(samples,
                                         obj = pcfit,
                                         cond.var = 2L)
        }


        ## store estimates
        resi <- list(c = pcfit, name = nums)

        ## return results
        list(Copula.Data.1 = Copula.Data.1,
             Copula.Data.2 = Copula.Data.2,
             Copula.CondName.1 = Copula.CondName.1,
             Copula.CondName.2 = Copula.CondName.2,
             Copula.CondData.1 = Copula.CondData.1,
             Copula.CondData.2 = Copula.CondData.2,
             resi = resi)
    }

    res.k <- if (parallel) {
        foreach(i = 1:d, .export = exp, .packages = pkgs) %dopar% doEst(i, mst)
    } else {
        lapply(1:d, doEst, mst = mst)
    }

    ## clean and return results
    for (i in 1:d) {
        mst$E$Copula.Data.1[[i]] =  res.k[[i]]$Copula.Data.1
        mst$E$Copula.Data.2[[i]] =  res.k[[i]]$Copula.Data.2
        mst$E$Copula.CondName.1[[i]] = res.k[[i]]$Copula.CondName.1
        mst$E$Copula.CondName.2[[i]] = res.k[[i]]$Copula.CondName.2
        mst$E$Copula.CondData.1[[i]] = res.k[[i]]$Copula.CondData.1
        mst$E$Copula.CondData.2[[i]] = res.k[[i]]$Copula.CondData.2
        res.k[[i]] <- res.k[[i]]$resi
    }
    list(tree = mst, est = res.k)
}

hoeffd <- function(x) {
    n <- nrow(x)
    R <- apply(x,2,rank)-1
    Q <- sapply(1:n, function(i) sum(x[,1] < x[i,1] & x[,2] < x[i,2]))
    A <- sum(apply(R*(R-1),1,prod))
    B <- sum(apply((R-1),1,prod)*Q)
    C <- sum(Q*(Q-1))
    return((A - 2*(n-2)*B + (n-2)*(n-3)*C)/(n*(n-1)*(n-2)*(n-3)*(n-4)))
}

initializeFirstGraph2 <- function(data.univ, weights, struct.crit = "tau") {

    # C = cor(data.univ,method='kendall')
    q <- dim(data.univ)[2]
    C <- matrix(rep(1, q * q), ncol = q)

    for (i in 1:(q - 1)) {
        for (j in (i + 1):q) {
            if (struct.crit == "tau") {
                crit <- fasttau(data.univ[, i],
                                data.univ[, j],
                                weights)
            } else if (struct.crit == "AIC") {
                crit <- kdecop(data.univ[, c(i, j)], info = TRUE)$info$AIC
            } else if (struct.crit == "cAIC") {
                crit <- kdecop(data.univ[, c(i, j)], info = TRUE)$info$cAIC
            } else if (struct.crit == "hoeffd") {
                crit <- abs(hoeffd(data.univ[, c(i, j)]))
            }
            C[i, j] <- crit
            C[j, i] <- crit
        }
    }
    rownames(C) <- colnames(C) <- colnames(data.univ)
    rownames(C) <- colnames(C) <- colnames(data.univ)

    graphFromTauMatrix(C)
}


## functions for handling the tree structure -------------------------
graphFromTauMatrix2 <- function(tau) {
    d <- ncol(tau)
    # get variable names
    nms <- colnames(tau)
    # construct edge set
    E <- cbind(do.call(c, sapply(1:(d-1), function(i) seq.int(i))),
               do.call(c, sapply(1:(d-1), function(i) rep(i+1, i))))
    # add edge names
    E.names <- apply(E, 1, function(x) paste(nms[x[1]],  nms[x[2]], sep = ","))
    # set weights
    w <- tau[upper.tri(tau)]

    ## return results
    list(V = list(names = nms,
                  conditionedSet = NULL,
                  conditioningSet = NULL),
         E = list(nums = E,
                  names = E.names,
                  weights = w,
                  conditionedSet = lapply(1:nrow(E), function(i) E[i, ]),
                  conditioningSet = NULL))
}


## initialize graph for next vine tree (possible edges)
buildNextGraph2 <- function(oldVineGraph, weights = NA, struct.crit = "tau", parallel) {
    d <- nrow(oldVineGraph$E$nums)

    ## initialize with full graph
    g <- makeFullGraph2(d)
    g$V$names <- oldVineGraph$E$names
    g$V$conditionedSet <- oldVineGraph$E$conditionedSet
    g$V$conditioningSet <- oldVineGraph$E$conditioningSet
    ## get info for all edges
    if (parallel) {
        i <- NULL  # dummy for CRAN check
        out <- foreach(i = 1:nrow(g$E$nums)) %dopar% getEdgeInfo2(i,
                                                                  g = g,
                                                                  oldVineGraph = oldVineGraph,
                                                                  weights = weights,
                                                                  struct.crit = struct.crit)
    } else {
        out <- lapply(1:nrow(g$E$nums),
                      getEdgeInfo2,
                      g = g,
                      oldVineGraph = oldVineGraph,
                      weights = weights,
                      struct.crit = struct.crit)
    }

    ## annotate graph (same order as in old version of this function)
    g$E$weights         <- sapply(out, function(x) x$w)
    g$E$names           <- sapply(out, function(x) x$name)
    g$E$conditionedSet  <- lapply(out, function(x) x$nedSet)
    g$E$conditioningSet <- lapply(out, function(x) x$ningSet)
    g$E$todel           <- sapply(out, function(x) x$todel)

    ## delete edges that are prohibited by the proximity condition
    deleteEdges(g)
}

## function for obtaining edge information
getEdgeInfo2 <- function(i, g, oldVineGraph, weights, struct.crit = "tau") {

    ## get edge
    con <- g$E$nums[i, ]
    temp <- oldVineGraph$E$nums[con, ]

    ## check for proximity condition
    ok <- FALSE
    if ((temp[1, 1] == temp[2, 1]) || (temp[1, 2] == temp[2, 1])) {
        ok <- TRUE
        same <- temp[2, 1]
    } else {
        if ((temp[1, 1] == temp[2, 2]) || (temp[1, 2] == temp[2, 2])) {
            ok <- TRUE
            same <- temp[2, 2]
        }
    }

    ## dummy output
    w <- nedSet <- ningSet <- name <- NA
    todel <- TRUE

    # info if proximity condition is fulfilled ...
    if (ok) {
        ## get data
        if (temp[1, 1] == same) {
            zr1 <- oldVineGraph$E$Copula.CondData.2[[con[1]]]
        } else {
            zr1 <- oldVineGraph$E$Copula.CondData.1[[con[1]]]
        }
        if (temp[2, 1] == same) {
            zr2 <- oldVineGraph$E$Copula.CondData.2[[con[2]]]
        } else {
            zr2 <- oldVineGraph$E$Copula.CondData.1[[con[2]]]
        }
        zr1a <- if (is.list(zr1)) as.vector(zr1[[1]]) else zr1
        zr2a <- if (is.list(zr2)) as.vector(zr2[[1]]) else zr2

        ## calculate Kendall's tau
        keine_nas <- !(is.na(zr1a) | is.na(zr2a))
        if (struct.crit == "tau") {
            w <- fasttau(zr1a[keine_nas],
                                      zr2a[keine_nas],
                                      weights)
        } else if (struct.crit == "AIC") {
            w <- kdecop(cbind(zr1a[keine_nas], zr2a[keine_nas]),
                                     info = TRUE)$info$AIC
        } else if (struct.crit == "cAIC") {
            w <- kdecop(cbind(zr1a[keine_nas], zr2a[keine_nas]),
                                     info = TRUE)$info$cAIC
        }  else if (struct.crit == "hoeffd") {
            w <- abs(hoeffd(cbind(zr1a[keine_nas], zr2a[keine_nas])))
        }

        ## get names
        name.node1 <- strsplit(g$V$names[con[1]], split = " *[,;] *")[[1]]
        name.node2 <- strsplit(g$V$names[con[2]], split = " *[,;] *")[[1]]

        ## infer conditioned set and conditioning set
        l1 <- c(g$V$conditionedSet[[con[1]]],
                g$V$conditioningSet[[con[1]]])
        l2 <- c(g$V$conditionedSet[[con[2]]],
                g$V$conditioningSet[[con[2]]])
        nedSet <- c(setdiff(l1, l2), setdiff(l2, l1))
        ningSet <- intersect(l1, l2)

        ## set edge name
        nmdiff <- c(setdiff(name.node1, name.node2),
                    setdiff(name.node2, name.node1))
        nmsect <- intersect(name.node1, name.node2)
        name <- paste(paste(nmdiff, collapse = ","),
                      paste(nmsect, collapse = ","),
                      sep = " ; ")

        ## mark as ok
        todel <- FALSE
    }

    ## return edge information
    list(w = w,
         nedSet = nedSet,
         ningSet = ningSet,
         name = name,
         todel = todel)
}

## functions for handling the tree structure -------------------------
graphFromTauMatrix <- function(tau) {
    d <- ncol(tau)
    # get variable names
    nms <- colnames(tau)
    # construct edge set
    E <- cbind(do.call(c, sapply(1:(d-1), function(i) seq.int(i))),
               do.call(c, sapply(1:(d-1), function(i) rep(i+1, i))))
    # add edge names
    E.names <- apply(E, 1, function(x) paste(nms[x[1]],  nms[x[2]], sep = ","))
    # set weights
    w <- tau[upper.tri(tau)]

    ## return results
    list(V = list(names = nms,
                  conditionedSet = NULL,
                  conditioningSet = NULL),
         E = list(nums = E,
                  names = E.names,
                  weights = w,
                  conditionedSet = lapply(1:nrow(E), function(i) E[i, ]),
                  conditioningSet = NULL))
}



makeFullGraph2 <- function(d) {
    ## create matrix of all combinations
    E <- cbind(do.call(c, lapply(1:(d-1), function(i) rep(i, d-i))),
               do.call(c, lapply(1:(d-1), function(i) (i+1):d)))
    E <- matrix(E, ncol = 2)

    ## output dummy list with edges set
    list(V = list(names = NULL,
                  conditionedSet = NULL,
                  conditioningSet = NULL),
         E = list(nums = E,
                  names = NULL,
                  weights = NULL,
                  conditionedSet = E,
                  conditioningSet = NULL))
}

findMaxTree2 <- function(g, mode = "RVine") {
    ## construct adjency matrix
    A <- adjacencyMatrix(g)
    d <- ncol(A)

    if (mode == "RVine") {
        ## initialize
        tree <- NULL
        edges <- matrix(NA, d - 1, 2)
        w <- numeric(d - 1)
        i <- 1

        ## construct minimum spanning tree
        for (k in 1:(d - 1)) {
            # add selected edge to tree
            tree <- c(tree, i)

            # find edge with minimal weight
            m <- apply(as.matrix(A[, tree]), 2, min)
            a <- apply(as.matrix(A[, tree]), 2, function(x) order(rank(x)))[1, ]
            b <- order(rank(m))[1]
            j <- tree[b]
            i <- a[b]

            # store edge and weight
            edges[k, ] <- c(j, i)
            w[k] <- A[i, j]

            ## adjust adjecency matrix to prevent loops
            for (t in tree)
                A[i, t] <- A[t, i] <- Inf
        }

        ## reorder edges for backwads compatibility with igraph output
        edges <- t(apply(edges, 1, function(x) sort(x)))
        edges <- edges[order(edges[, 2], edges[, 1]), ]

        ## delete unused edges from graph
        E <- g$E$nums
        in.tree <- apply(matrix(edges, ncol = 2), 1,
                         function(x) which((x[1] == E[, 1]) & (x[2] == E[, 2])))
        if (is.list(in.tree))
            in.tree <- unlist(in.tree)
        MST <- g
        g$E$todel <- rep(TRUE, nrow(E))
        if (any(g$E$todel)) {
            g$E$todel[in.tree] <- FALSE
            MST <- deleteEdges(g)
        }
    } else if (mode  == "CVine") {
        ## set root as vertex with minimal sum of weights
        A <- adjacencyMatrix(g)
        diag(A) <- 0
        sumtaus <- rowSums(A)
        root <- which.min(sumtaus)

        ## delete unused edges
        g$E$todel <- !((g$E$nums[, 2] == root) | (g$E$nums[, 1] == root))
        MST <- g
        if (any(g$E$todel ))
            MST <- deleteEdges(g)
    } else {
        stop("vine not implemented")
    }

    ## return result
    MST
}

adjacencyMatrix <- function(g) {
    ## create matrix of all combinations
    d <- length(g$V$names)
    v.all <- cbind(do.call(c, lapply(1:(d-1), function(i) seq.int(i))),
                   do.call(c, lapply(1:(d-1), function(i) rep(i+1, i))))

    ## fnd weight
    vals <- apply(v.all, 1, set_weight, E = g$E)

    ## create symmetric matrix of weights
    M <- matrix(0, d, d)
    M[upper.tri(M)] <- vals
    M <- M + t(M)
    diag(M) <- Inf

    ## return final matrix
    M
}

set_weight <- function(x, E) {
    is.edge <- (x[1] == E$nums[, 1]) & (x[2] == E$nums[, 2])
    w <- if (!any(is.edge)) Inf else (1 - abs(E$weights[which(is.edge)]))
    w
}


deleteEdges <- function(g) {
    ## reduce edge list
    keep <- which(!g$E$todel)
    E <- list(nums            = matrix(g$E$nums[keep, ], ncol = 2),
              names           = g$E$names[keep],
              weights         = g$E$weights[keep],
              conditionedSet  = g$E$conditionedSet[keep],
              conditioningSet = g$E$conditioningSet[keep])

    ## return reduced graph
    list(V = g$V, E = E)
}

# findMaximumAICTree <- function(g, mode = "RVine") {
#     if (mode == "RVine") {
#         return(minimum.spanning.tree(g, weights = -E(g)$weight))
#     } else if (mode == "CVine") {
#         stop("'struct.crit = AIC' is not yet available for C-Vines")
#     }
# }


# findMaxTree <- function(g, mode = "RVine", struct.crit = "tau") {
#     switch(struct.crit,
#            "tau"  = findMaximumTauTree(g, mode = mode),
#            "AIC"  = findMaximumAICTree(g, mode = mode),
#            "cAIC" = findMaximumAICTree(g, mode = mode))
# }

fasttau <- function(x, y, weights = NA) {
    TauMatrix(cbind(x, y))[1, 2]
}


as.RVMKernel2 <- function(RVine) {

    n <- length(RVine$Tree) + 1
    nam <- RVine$Tree[[1]]$V$names
    nedSets <- list()

    ## get selected pairs
    for (k in 1:(n - 2)) {
        nedSets[[k]]    <- RVine$Tree[[k]]$E$conditionedSet
    }
    if (is.list(RVine$Tree[[n - 1]]$E$conditionedSet)) {
        nedSets[[n - 1]] <- list(RVine$Tree[[n - 1]]$E$conditionedSet[[1]])
    } else {
        nedSets[[n - 1]] <- list(RVine$Tree[[n - 1]]$E$conditionedSet)
    }

    M <- matrix(NA,n,n)

    for (k in 1:(n-1)) {
        w <- nedSets[[n-k]][[1]][1]

        M[k, k] <- w
        M[k+1, k] <- nedSets[[n-k]][[1]][2]

        if (k == (n-1)) {
            M[(k+1),(k+1)] <- nedSets[[n-k]][[1]][2]
        } else {
            for (i in (k+2):n) {
                for (j in 1:length(nedSets[[n-i+1]])) {
                    cs <- nedSets[[n-i+1]][[j]]
                    if (cs[1] == w) {
                        M[i, k] <- cs[2]
                        break
                    } else if (cs[2] == w) {
                        M[i, k] <- cs[1]
                        break
                    }
                }
                nedSets[[n-i+1]][[j]] <- NULL
            }
        }
    }

    M[is.na(M)] <- 0
    zrs <- matrix(0, n, n)

    RVineMatrix(M, family = zrs, par = zrs, par2 = zrs, names = nam)
}

Try the kdevine package in your browser

Any scripts or data that you put into this service are public.

kdevine documentation built on Oct. 18, 2022, 5:05 p.m.