updateDM <- function(DM, d, CL, j) {
l <- length(CL)
for (i in 1:l) {
DM[i, j] <- DM[j, i] <- mean.default(d[CL[[i]], CL[[j]]])
}
DM[j, j] <- 0
DM
}
Rx <- function(d, x, CL) {
lx <- length(x)
res <- numeric(lx)
lC <- length(CL)
for (i in 1:lx) {
xi <- x[i]
tmp <- 0
for (j in 1:lx) {
if (j != i) tmp <- tmp + d[xi, x[j]]
}
if (lC > 0) {
for (j in 1:lC) {
tmp <- tmp + mean.default(d[xi, CL[[j]]])
}
}
res[i] <- tmp
}
res
}
# Formula 1
reduc <- function(d, x, y, z) {
u <- 2 / 3 * d[x, ] + d[y, ] / 3
v <- 2 / 3 * d[z, ] + d[y, ] / 3
uv <- (d[x, y] + d[x, z] + d[y, z]) / 3
d[x, ] <- u
d[, x] <- u
d[z, ] <- v
d[, z] <- v
d[y, ] <- 0
d[, y] <- 0
d[x, z] <- d[z, x] <- uv
d[x, x] <- d[z, z] <- 0
# diag(d) <- 0
d
}
# computes ordering O(n^2) statt O(n^3) !!!
# needs debugging
getOrderingNN <- function(x) {
x <- as.matrix(x)
labels <- attr(x, "Labels")
if (is.null(labels))
labels <- colnames(x)
d <- x # as.matrix(x)
l <- dim(d)[1]
CL <- vector("list", l)
CL[] <- seq_len(l)
lCL <- length(CL)
ord <- CL
# DM_C connected components, DM_V vertices
DM_C <- DM_V <- DM <- d
z <- 0
while (lCL > 1) {
z <- z + 1
l <- nrow(DM)
# compute Q_D from D_C
if (l > 2) {
r <- rowSums(DM) / (l - 2)
tmp <- out_cpp(DM, r, l)
e1 <- tmp[1]
e2 <- tmp[2]
}
else {
e1 <- 1
e2 <- 2
}
n1 <- length(CL[[e1]])
n2 <- length(CL[[e2]])
if (n1 == 1 & n2 == 1) {
# add edge
newCL <- c(CL[[e1]], CL[[e2]])
newOrd <- newCL
CL[[e1]] <- newCL
# update DM_C
DM <- updateDM(DM, d, CL, e1)
DM <- DM[-e2, -e2, drop = FALSE]
CL <- CL[-e2]
ord[[e1]] <- newCL
ord <- ord[-e2]
lCL <- lCL - 1L
}
else {
CLtmp <- c(as.list(CL[[e1]]), as.list(CL[[e2]]), CL[-c(e1, e2)])
ltmp <- length(CLtmp)
CLtmp2 <- c(CL[[e1]], CL[[e2]])
rtmp2 <- Rx(d, CLtmp2, CL[-c(e1, e2)])
if (ltmp > 2) rtmp2 <- rtmp2 / (ltmp - 2)
DM3 <- d[CLtmp2, CLtmp2] - outer(rtmp2, rtmp2, "+")
# DM3 formula 3 in Spillner et al.
TMP2 <- DM3[1:n1, (n1 + 1):(n1 + n2)]
blub <- which.min(TMP2)
if (n1 == 2 & n2 == 1) {
if (blub == 2) {
newCL <- c(CL[[e1]][1], CL[[e2]])
newOrd <- c(ord[[e1]], ord[[e2]])
d <- reduc(d, CL[[e1]][1], CL[[e1]][2], CL[[e2]])
}
else {
newCL <- c(CL[[e2]], CL[[e1]][2])
newOrd <- c(ord[[e2]], ord[[e1]])
d <- reduc(d, CL[[e2]], CL[[e1]][1], CL[[e1]][2])
}
}
if (n1 == 1 & n2 == 2) {
if (blub == 1) {
newCL <- c(CL[[e1]], CL[[e2]][2])
newOrd <- c(ord[[e1]], ord[[e2]])
d <- reduc(d, CL[[e1]], CL[[e2]][1], CL[[e2]][2])
}
else {
newCL <- c(CL[[e2]][1], CL[[e1]])
newOrd <- c(ord[[e2]], ord[[e1]])
d <- reduc(d, CL[[e2]][1], CL[[e2]][2], CL[[e1]])
}
}
if (n1 == 2 & n2 == 2) {
if (blub == 1) {
newCL <- c(CL[[e1]][2], CL[[e2]][2])
newOrd <- c(rev(ord[[e1]]), ord[[e2]])
d <- reduc(d, CL[[e1]][2], CL[[e1]][1], CL[[e2]][1])
d <- reduc(d, CL[[e1]][2], CL[[e2]][1], CL[[e2]][2])
}
if (blub == 2) {
newCL <- c(CL[[e1]][1], CL[[e2]][2])
newOrd <- c(ord[[e1]], ord[[e2]])
d <- reduc(d, CL[[e1]][1], CL[[e1]][2], CL[[e2]][1])
d <- reduc(d, CL[[e1]][1], CL[[e2]][1], CL[[e2]][2])
}
if (blub == 3) {
newCL <- c(CL[[e1]][2], CL[[e2]][1])
newOrd <- c(rev(ord[[e1]]), rev(ord[[e2]]))
d <- reduc(d, CL[[e1]][2], CL[[e1]][1], CL[[e2]][2])
d <- reduc(d, CL[[e1]][2], CL[[e2]][2], CL[[e2]][1])
}
if (blub == 4) {
newCL <- c(CL[[e1]][1], CL[[e2]][1])
newOrd <- c(ord[[e1]], rev(ord[[e2]]))
d <- reduc(d, CL[[e1]][1], CL[[e1]][2], CL[[e2]][2])
d <- reduc(d, CL[[e1]][1], CL[[e2]][2], CL[[e2]][1])
}
}
ord[[e1]] <- newOrd
ord <- ord[-e2]
CL[[e1]] <- newCL
DM <- updateDM(DM, d, CL, e1)
DM <- DM[-e2, -e2, drop = FALSE]
CL <- CL[-e2]
lCL <- lCL - 1L
}
}
newOrd
}
#' Computes a neighborNet from a distance matrix
#'
#' Computes a neighborNet, i.e. an object of class \code{networx} from a
#' distance matrix.
#'
#' \code{neighborNet} is still experimental. The cyclic ordering sometimes
#' differ from the SplitsTree implementation, the \emph{ord} argument can be
#' used to enforce a certain circular ordering.
#'
#' @param x a distance matrix.
#' @param ord a circular ordering.
#' @return \code{neighborNet} returns an object of class networx.
#' @author Klaus Schliep \email{klaus.schliep@@gmail.com}
#' @seealso \code{\link{splitsNetwork}}, \code{\link{consensusNet}},
#' \code{\link{plot.networx}}, \code{\link{lento}},
#' \code{\link{cophenetic.networx}}, \code{\link{distanceHadamard}}
#' @references Bryant, D. & Moulton, V. (2004) Neighbor-Net: An Agglomerative
#' Method for the Construction of Phylogenetic Networks. \emph{Molecular
#' Biology and Evolution}, 2004, \bold{21}, 255-265
#' @keywords hplot
#' @examples
#'
#' data(yeast)
#' dm <- dist.ml(yeast)
#' nnet <- neighborNet(dm)
#' plot(nnet)
#'
#' @export neighborNet
neighborNet <- function(x, ord = NULL) {
x <- as.matrix(x)
labels <- attr(x, "Labels")[[1]]
if (is.null(labels))
labels <- colnames(x)
l <- length(labels)
if (is.null(ord)) ord <- getOrderingNN(x)
spl <- allCircularSplits(l, labels[ord])
spl <- nnls.splits(spl, x)
# nnls.split mit nnls statt quadprog
attr(spl, "cycle") <- 1:l
as.networx(spl)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.