如何构造for和if循环以构造拉丁方?

时间:2020-03-31 00:09:08

标签: r for-loop if-statement

我的目标是构造每个给定大小n的唯一https://www.researchgate.net/post/What_is_the_best_SAT-solver_with_option_to_find_all_solutions_satisfied_given_CNF。 R命令rlatin(n)使用马尔可夫链构造大小为n x n的随机拉丁方。但是,此命令不仅会构造其大小的所有拉丁方。

下面是我的代码:

library(magic)

L <- function(n){
  size <- factorial(n) * factorial(n-1)
  l <- list()
  l[[1]] <- rlatin(n)
  for(k in 2:size){
    new <- rlatin(n)
    for(j in 1:(k-1)){
      if(new == l[[j]]){
        new <- rlatin(n)
      }
    }
    l[[k]] <- new
  }
  l
} 

这不能正常工作,我不明白为什么。有人可以说明我的错误吗?另外,一旦所有拉丁广场都建成后,有没有一种我可以组织它们的方式,以便在拉丁广场中有一些清晰的地方?

1 个答案:

答案 0 :(得分:1)

您的代码无法防止重复,因为一旦相等性测试成功,您就会找到一个新的拉丁方,但是您就不会使用当前的拉丁方列表来测试该新方!您可能需要一个while循环,仅当当前拉丁方与之前所有拉丁方都不相同时才中断。可以使用sapply进行评估,尽管当n变大时可能会很慢。

L <- function(n) {
  size <- factorial(n) * factorial(n-1)
  l <- list()
  l[[1]] <- rlatin(n)
  for(k in 2:size) {
    new <- rlatin(n)
    while(sum(sapply(l, function(x) any(identical(x, new)))) > 0) {
      new <- rlatin(n)
    }
    l[[k]] <- new
  }
  l
} 

对于n = 4(大小= 144),代码仅需几秒钟。但是对于n = 5(大小= 2880),代码将花费一整天的时间。也许有一个更快的解决方案。


L4 <- L(4)  # About 10 seconds.

检查重复项:

x <- list()
for(i in 1:length(L4)) {
    x[[i]] <- sapply(L4[-i], function(x) any(identical(x, L4[[i]])))
}

sum(sapply(x, sum))
# [1] 0

L5 <- L(5) # Still waiting... or as grampa used to say: 
                                            "you'll be wait'n til the cows come home".

啊,终于。

   user  system elapsed 
 816.16    0.54  827.20