用lapply向量化嵌套循环

时间:2014-08-28 22:55:31

标签: r vectorization graph-theory

我正在尝试对拓扑排序进行矢量化以便更快地运行 其中一部分是带有嵌套while的{​​{1}}。我在矢量化方面遇到了麻烦。 这个功能的想法是托管相互依赖的任务

这是我到目前为止的代码:

for

这是一个相互依赖的任务列表,可以使用函数进行排序:

tsort <- function(deps) {
  nm <- names(deps)
  libs <- union(as.vector(unlist(deps)), nm)
  s <- c()
  s <- unlist(lapply(libs,function(x){
    if(!(x %in% nm)) {
      s <- c(s, x)
    }
  }))
  k <- 1
  while(k > 0) {
    k <- 0
    for(x in setdiff(nm, s)) {
      r <- c(s, x)
      if(length(setdiff(deps[[x]], r)) == 0) {
        s <- r
        k <- 1
      }
    }
  }
  if(length(s) < length(libs)) {
    v <- setdiff(libs, s)
    stop(sprintf("Unorderable items :\n%s", paste("", v, sep="", collapse="\n")))
  }
  s
}

我想要矢量化的部分是:

tasks <- list(
"seven" = c("eight", "nine", "ten", "seven", "five", "one", "eleven", "two"),
"one" = c("two", "one", "three", "four"),
"five" = c("two", "five", "three"),
"six" = c("eight", "nine", "three", "six", "five", "one", "two", "four"),
"twelve" = c("twelve", "two", "one", "three", "four"),
"thirteen" = c("thirteen", "two", "three"),
"fourteen" = c("fourteen", "two", "three"),
"fifteen" = c("two", "three"),
"three" = c("two", "three"),
"four" = c("two", "four"),
"eleven" = c("eight", "two"),
"ten" = c("two", "ten"),
"nine" = c())

我发现很难将函数的主要部分向量化,其中我有一个k <- 1 while(k > 0) { k <- 0 for(x in setdiff(nm, s)) { r <- c(s, x) if(length(setdiff(deps[[x]], r)) == 0) { s <- r k <- 1 } } } 和一个for

1 个答案:

答案 0 :(得分:1)

首先,请查看包含函数igraph的包topological.sort()。它提供了更多功能来处理图形,并且每个需要进行拓扑排序的问题通常都可以用图表重新表示。

我不完全确定您的代码是否正确排序。你有两个循环级别:内部循环遍历所有x,这些x是以nm为单位但不是s。外部循环是一个while循环,并再次启动该过程。

每次通过内部循环时,都会考虑先前传递的结果。这导致了一个有趣的结果:而#13;十三&#34;,&#34;十四&#34;和&#34;十五&#34;不包含与&#34;五&#34;的连接或者&#34;一个&#34;和&#34;六&#34;是的,&#34;六&#34;仍然在拓扑之前排序在另一个之前。这是因为&#34;六&#34;在&#34; one&#34;之后添加和&#34;五&#34;,但在同一个循环中。

此行为 - 如果正确 - 无法以任何方式进行矢量化。但是,据我所知,&#34;十三&#34;,&#34; forteen&#34;和&#34;十五&#34;应该在&#34; six&#34;之前而不是之后排序。

这就是说,你对你感兴趣的部分有一个非常简单的矢量化:

   s <- unlist(lapply(libs,function(x){
     if(!(x %in% nm)) {
       s <- c(s, x)
     }
  }))

实际上只是s <- setdiff(libs,nm)。此外,您在那里执行的任务没有意义,因为来自s的{​​{1}}是在s <- c(s,x)的本地环境中创建的,并且对外部{lapply没有任何影响1}}。它所做的全部与s完全相同。

如果您想以这样的方式进行矢量化,请执行以下操作:

  • 遍历尚未在解决方案中的所有名称,并检查他们的集合是否涵盖解决方案中的所有内容
  • 将此为TRUE的名称添加到解决方案
  • 重复,直到所有名称都在解决方案中

您可以使用以下代码。请注意我如何预先分配内存空间来保存解决方案。这种预分配可以节省大量的内存操作。 R中的对象越来越多,就像在代码中一样,正在浪费资源。

另请注意,我的代码会根据您的代码提供不同的顺序,原因如上所述。

invisible(x)