# inputs a graph adjacency matrix, and outputs a 2-column links matrix
# listing the edges emanating from each vertex, each row of the form
# (fvert,tvert), i.e. "from vertex" and "to vertex"

# Snow version, i.e. version for the portion of the 'parallel' package
# that was adapted from 'snow'

# arguments:
#    cls:  a snow cluster
#    adj:  adjacency matrix, n x n for n vertices

# value: the 2-column link matrix

library(parallel)

# convert a single row (with index rownum) of an adjacency matrix to a
# 2-column links matrix
processonerow <- function(onerow) {
   rownum <- onerow[1]
   ones <- which(onerow[-1] == 1)
   if (is.null(ones)) return(NULL)
   cbind(rownum,ones)
}

chunkfindlinks <- function(adj) {
   outm <- apply(adj,1,processonerow)
   Reduce(rbind,outm)
}

# serial version
serfindlinks <- function(adj) {
   adj <- cbind(1:nrow(adj),adj)
   chunkfindlinks(adj)
}

findlinks <- function(cls,adj) { 
   require(partools)  # on CRAN
   # append a column of row numbers
   adj <- cbind(1:nrow(adj),adj)
   formrowchunks(cls,adj,"adjchunk")
   clusterExport(cls,c("chunkfindlinks","processonerow"))
   outchunks <- clusterEvalQ(cls,chunkfindlinks(adjchunk))
   Reduce(rbind,outchunks)
}

test <- function(cls,n) {
   m <- matrix(sample(0:1,n^2,replace=T),ncol=n)
   findlinks(cls,m)
}
