【问题标题】:How can I vectorize (and speed up) this recursive graph search function in R?如何在 R 中对这个递归图搜索函数进行矢量化(并加速)?
【发布时间】: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 &lt;- 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


【解决方案1】:

igraph的开发版有一个get.all.simple.paths()函数,你可以从这里得到它:http://igraph.org/nightly

【讨论】:

  • 我使用了 Tamas 的建议,不调用 get.adjlist(),而是使用 neighbors(),这提供了不错的速度提升。然而,真正有助于提高性能的是并行搜索,方法是在每个 start 节点的子节点上调用 fastFindPaths() 并聚合结果。我目前在 Windows 机器上,所以使用了clusterApply() 函数。
【解决方案2】:

我使用了 Tamas 的建议,不调用 get.adjlist(),而是使用 neighbors(),这提供了不错的速度提升。然而,真正有助于提高性能的是并行搜索,方法是在每个起始节点的子节点上调用 fastFindPaths() 并聚合结果。我目前在一台 Windows 机器上,所以使用了 clusterApply() 函数。虽然我可能会概括代码来检查Sys.info()[1],如果不是Windows,则使用mclapply()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多