From what I’ve analyzed of your code, your suspicion is correct: the function perm
is what is slowing down the code. I came to this conclusion by testing the function execution time topswops
:
library(rbenchmark)
benchmark(topswops(sample(1:i, 10)), replications = 100000)
test replications elapsed relative user.self sys.self user.child sys.child
1 topswops(sample(1:i, 10)) 100000 2.388 1 2.253 0.107 0 0
Repeat topswops
100,000 times in random vectors of size 10, with elements 1 to 10, took 2,388 seconds. That is, the bottleneck is not here.
That said, I looked for other ways to generate all possible permutations for a sequence of numbers. In addition to the Deducer
, the packages combinat
and gtools
can also generate all permutations of a sequence of numbers. My test results were as follows::
library(Deducer)
inicio <- Sys.time()
resultado.Deducer <- NULL
for(i in 1:10){
A <- perm(1:i)
A <- data.frame(A)
A$flips <- apply(A, 1, topswops)
resultado.Deducer <- rbind(resultado.Deducer, c(i, max(A$flips)))
}
fim <- Sys.time()
fim - inicio
Time difference of 4.131159 mins
library(combinat)
inicio <- Sys.time()
resultado.combinat <- NULL
for(i in 1:10){
A <- as.data.frame(matrix(unlist(permn(1:i)), ncol=i, byrow=TRUE))
A$flips <- apply(A, 1, topswops)
resultado.combinat <- rbind(resultado.combinat, c(i, max(A$flips)))
}
fim <- Sys.time()
fim - inicio
Time difference of 2.371664 mins
library(gtools)
inicio <- Sys.time()
resultado.gtools <- NULL
for(i in 1:10){
A <- permutations(i, i, 1:i)
A$flips <- apply(A, 1, topswops)
resultado.gtools <- rbind(resultado.gtools, c(i, max(A$flips)))
}
Warning messages:
1: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
2: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
3: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
4: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
5: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
6: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
7: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
8: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
9: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
10: In A$flips <- apply(A, 1, topswops) : Coercing LHS to a list
fim <- Sys.time()
fim - inicio
Time difference of 1.849558 mins
Therefore, one way to optimize the code is precisely by improving the generation of permutations. In my test, the function that best came out was gtools::permutations
, taking 1.849558 minutes to run. This is equivalent to 44% of the time used by the original function.
It may be possible to further improve this performance by optimizing the generation of permutations. Since there are millions of replications, I believe that any improvement in permutation generation is something that counts very much in the end.
If the search is for the shortest execution time and not necessarily the best algorithm, it is also possible to decrease the execution time by parallelizing the code. But then I leave this exercise to the reader : )
The idea of parallelization is good, but since it was a joke code, I’m not gonna worry about it that much. I was able to find another package that reduced the runtime to 1.58 minutes -
iterpc
. I ran my initial code again and the time spent was 3.25 minutes. So the gain, it was over 50%.– Rafael Cunha