mrca.R
## mrca.R (2009-05-10)
## Find Most Recent Common Ancestors Between Pairs
## Copyright 2005-2009 Emmanuel Paradis
## This file is part of the R-package `ape'.
## See the file ../COPYING for licensing issues.
mrca <- function(phy, full = FALSE)
{
if (!inherits(phy, "phylo")) stop('object "phy" is not of class "phylo"')
## if (!is.rooted(phy)) stop("the tree must be rooted.")
## Get all clades:
nb.tip <- length(phy$tip.label)
nb.node <- phy$Nnode
BP <- .Call("bipartition", phy$edge, nb.tip,
nb.node, PACKAGE = "ape")
N <- nb.tip + nb.node
ROOT <- nb.tip + 1
## In the following matrix, numeric indexing will be used:
M <- numeric(N * N)
dim(M) <- c(N, N)
## We start at the root:
next.node <- ROOT
while (length(next.node)) {
tmp <- numeric(0)
for (anc in next.node) {
## Find the branches which `anc' is the ancestor...:
id <- which(phy$edge[, 1] == anc)
## ... and get their descendants:
desc <- phy$edge[id, 2]
## `anc' is itself the MRCA of its direct descendants:
M[anc, desc] <- M[desc, anc] <- anc
## Find all 2-by-2 combinations of `desc': `anc'
## is their MRCA:
for (i in 1:length(desc))
M[cbind(desc[i], desc[-i])] <- anc
## If one element of `desc' is a node, then the tips it
## leads to and the other elements of `desc' have also
## `anc' as MRCA!
for (i in 1:length(desc)) {
if (desc[i] < ROOT) next
## (get the tips:)
tips <- BP[[desc[i] - nb.tip]]
## Same thing for the nodes...
node.desc <- numeric(0)
for (k in 1:nb.node) {
if (k == desc[i] - nb.tip) next
## If the clade of the current node is a
## subset of desc[i], then it is one of its
## descendants:
if (all(BP[[k]] %in% tips))
node.desc <- c(node.desc, k)
}
## all nodes and tips which are descendants of
## `desc[i]':
ALLDESC <- c(tips, node.desc + nb.tip)
M[ALLDESC, desc[-i]] <- M[desc[-i], ALLDESC] <- anc
for (j in 1:length(desc)) {
if (j == i || desc[j] < ROOT) next
tips2 <- BP[[desc[j] - nb.tip]]
node.desc <- numeric(0)
for (k in 1:nb.node) {
if (k == desc[j] - nb.tip) next
if (all(BP[[k]] %in% tips2))
node.desc <- c(node.desc, k)
}
ALLDESC2 <- c(tips2, node.desc + nb.tip)
M[ALLDESC, ALLDESC2] <- M[ALLDESC2, ALLDESC] <- anc
}
## `anc' is also the MRCA of itself and its descendants:
M[ALLDESC, anc] <- M[anc, ALLDESC] <- anc
}
## When it is done, `desc' i stored to become
## the new `next.node', if they are nodes:
tmp <- c(tmp, desc[desc > nb.tip])
}
next.node <- tmp
}
M[cbind(1:N, 1:N)] <- 1:N
if (full)
dimnames(M)[1:2] <- list(as.character(1:N))
else {
M <- M[1:nb.tip, 1:nb.tip]
dimnames(M)[1:2] <- list(phy$tip.label)
}
M
}