R/incremental-association.R

Defines functions ia.markov.blanket incremental.association

incremental.association = function(x, cluster = NULL, whitelist, blacklist,
  test, alpha, B, max.sx = ncol(x), complete, debug = FALSE) {

  nodes = names(x)

  # 1. [Compute Markov Blankets]
  mb = smartSapply(cluster, as.list(nodes), ia.markov.blanket, data = x,
         nodes = nodes, alpha = alpha, B = B, whitelist = whitelist,
         blacklist = blacklist, test = test, max.sx = max.sx,
         complete = complete, debug = debug)
  names(mb) = nodes

  # check markov blankets for consistency.
  mb = bn.recovery(mb, nodes = nodes, mb = TRUE, debug = debug)

  # 2. [Compute Graph Structure]
  mb = smartSapply(cluster, as.list(nodes), neighbour, mb = mb, data = x,
         alpha = alpha, B = B, whitelist = whitelist, blacklist = blacklist,
         test = test, max.sx = max.sx, complete = complete, debug = debug)
  names(mb) = nodes

  # check neighbourhood sets for consistency.
  mb = bn.recovery(mb, nodes = nodes, debug = debug)

  return(mb)

}#INCREMENTAL.ASSOCIATION

ia.markov.blanket = function(x, data, nodes, alpha, B, whitelist, blacklist,
  start = character(0), test, max.sx = ncol(x), complete, debug = FALSE) {

  nodes = nodes[nodes != x]
  whitelisted = nodes[sapply(nodes,
          function(y) { is.whitelisted(whitelist, c(x, y), either = TRUE) })]
  mb = start
  to.add = ""

  # growing phase
  if (debug) {

    cat("----------------------------------------------------------------\n")
    cat("* learning the markov blanket of", x, ".\n")

    if (length(start) > 0)
      cat("* initial set includes '", mb, "'.\n")

  }#THEN

  # whitelisted nodes are included by default (if there's a direct arc
  # between them of course they are in each other's markov blanket).
  # arc direction is irrelevant here.
  mb = unique(c(mb, whitelisted))
  nodes = nodes[nodes %!in% mb]
  # blacklist is not checked, not all nodes in a markov blanket must be
  # neighbours.

  # phase I (stepwise forward selection)
  repeat {

    # stop if there are no nodes left, or if we cannot add any more nodes
    # because the conditioning set has grown too large.
    if (length(nodes) == 0 || is.null(nodes))
      break

    if (length(mb) > max.sx) {

       if (debug)
         cat("  @ limiting conditioning sets to", max.sx, "nodes.\n")

      break

    }#THEN

    # get an association measure for each of the available nodes.
    association = indep.test(nodes, x, sx = mb, test = test, data = data,
                    B = B, alpha = alpha, complete = complete)

    if (debug) {

      cat("  * checking nodes for association.\n")
      sapply(names(association),
        function(x) {  cat("    >", x, "has p-value", association[x], ".\n")})

    }#THEN

    # stop if there are no candidates for inclusion.
    if (all(association > alpha))
      break
    # get the one which maximizes the association measure.
    to.add = names(which.min(association))

    if (debug) {

      cat("    @", to.add, "included in the markov blanket ( p-value:",
        association[to.add], ").\n")
      cat("    > markov blanket (", length(mb) + 1, "nodes ) now is '", c(mb, to.add), "'.\n")

    }#THEN

    if (association[to.add] <= alpha) {

      mb = c(mb, to.add)
      nodes = nodes[nodes != to.add]

    }#THEN

  }#REPEAT

  # phase II (backward selection)
  if (debug)
    cat("  * checking nodes for exclusion.\n")

  # whitelisted nodes are neighbours, they cannot be removed from the markov
  # blanket; the last node added in phase I will never be removed, because
  # the tests for inclusion and removal are identical.
  fixed = c(to.add, whitelisted)
  fixed = fixed[fixed != ""]

  pv = roundrobin.test(x = x, z = mb, fixed = fixed, data = data, test = test,
         B = B, alpha = alpha, complete = complete, debug = debug)

  return(intersect(mb, c(names(pv[pv < alpha]), fixed)))

}#IA.MARKOV.BLANKET

Try the bnlearn package in your browser

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

bnlearn documentation built on Sept. 7, 2021, 1:07 a.m.