【发布时间】:2014-06-02 23:59:39
【问题描述】:
我在 R 中编写了一个递归函数,用于查找有向图的所有路径 s-t 路径(无循环)。我将此页面用作我的模型:All possible paths from one node to another in a directed tree (igraph) 并输出正确的结果,但速度很慢。用小图,没什么大不了的。对于大图表,这是一个问题。
我是 R 新手,但读到它在避免循环和使用矢量化时表现得更好。我正在努力解决它,并希望您能提供帮助。我的代码:
findAllPaths <- function(graph,start,end) {
return(fastFindPaths(graph, start, end))
}
fastFindPaths <- function(graph, from, to, path) {
if(missing(path)) path <- c()
path <- cbind(path, from)
if (from == to) return(path)
paths <- c()
adjList <- get.adjlist(graph, mode="out")[[from]]
for (child in adjList) {
if (!child %in% path) {
childPaths <- fastFindPaths(graph, child, to, path)
for (childPath in childPaths) paths <- c(paths, childPath)
}
}
return(paths)
}
那么,这是矢量化的候选者吗?我怎样才能加快速度?您会给学习 R 的人提供任何其他提示吗?
谢谢!
【问题讨论】:
-
你见过
igraph包中的get.shortest.paths()函数吗?这看起来就像你所追求的那样,所以你可以使用它或查看它的源代码以获得灵感。对我来说,您的问题看起来并不容易矢量化。 -
一个可能的瓶颈是
get.adjlist()调用。基本上,对于fastFindPaths的每次调用,您构建图的整个 邻接列表只是为了获取单个节点的邻居(即from的邻居)。这可以使用neighbors函数更有效地完成。 -
另一个瓶颈是
paths <- c(paths, childPath)调用;我对 R 不是很熟悉,但我强烈怀疑这将是二次的,因为它分配了paths的新副本,将childPath附加到它,然后丢弃旧的paths向量。你能简单地预先分配一个带有 NA 值的大向量,然后开始填充它(如果它变满了就增加向量)? -
@Miff,
get.shortest.paths()函数只返回最短路径。我需要 all 路径。get.all.shortest.paths()也一样。 -
@Tamás 你的第一个建议很好。我从
get.adjlist()更改为neighborhood()并看到了很好的速度提升。对于具有 22 个节点和 107 条边的图,所有路径的时间从 ~26s 下降到 ~16s。我会试试你的第二个建议。
标签: r optimization recursion vectorization igraph