【问题标题】:Compute N random permutations of a vector of 36 elements计算 36 个元素的向量的 N 个随机排列
【发布时间】:2019-02-20 10:52:09
【问题描述】:

我有一个包含 36 个元素的向量 V,18 个是“0”,18 个是“1”。 我想计算这个向量的 N 个随机(不是第一个 N)排列。

我可以这样做:

library(combinat)
N <- 100 # or 200, 300, 500... max 1000
V <- c(rep(0, 18), rep(1, 18))
n <- factorial(36) # total number of unique possible permutations
p <- unique(permn(V))[sample(1:n, N)]

但我很快遇到了组合爆炸问题,因为 sample(1:n, N) 返回Error in 1:n : result would be too long a vector

permn(V) 返回Error in vector("list", gamma(n + 1)) : vector size specified is too large

还有其他(更好的)方法可以做到这一点吗?

【问题讨论】:

  • 如果你想做N01的随机组合,你为什么要从1:n采样?
  • 排列必须是唯一的吗?或者你可以做replicate(N, sample(V))吗?
  • 没有 factorial(36) 可能的排列,因为您正在处理多重集的排列(所有 0 和所有 1 都相同) - 请参阅 link。您可以使用multicool 包及其函数allPerm。但是,仍然有 485200708 变种,并且需要一些时间来生成它们。
  • @pisistrato 请查看link。您无法将一个 0 与另一个 0 区分开来,因此您可以多次计算一些排列。
  • @JosephWood 是的,我注意到你和我的号码不同。我使用了multicool 包和以下代码:x &lt;- rep(0:1, each=18); multinom(x)。这给了我485200708 排列。现在,我注意到multinom 函数中的参数useDouble 可以防止整数溢出。所以multinom(x, useDouble=TRUE) 给出了正确的数字。

标签: r permutation


【解决方案1】:

首先,没有factorial(36) 结果,因为您有重复的元素。如果我们这样做了,要获取总数,我们可以使用gmp 包来获取:

gmp::factorialZ(36)
Big Integer ('bigz') :
[1] 371993326789901217467999448150835200000000

我们实际处理的称为 multisets 的排列(正如 @JakubBucek 在 cmets 中指出的那样)。使用包RcppAlgos(我编写的)或包arrangements,我们可以轻松正确地计算结果总数,更重要的是生成所需的结果。

首先,实际结果数:

arrangements::npermutations(0:1, freq = c(18, 18), bigz = TRUE)
Big Integer ('bigz') :
[1] 9075135300

RcppAlgos::permuteCount(0:1, freqs = c(18, 18))
[1] 9075135300

这是组合学的结果。也就是说,我们必须除以相似元素的排列数的乘积:

gmp::factorialZ(36) / gmp::pow.bigz(gmp::factorialZ(18), 2)
Big Rational ('bigq') :
[1] 9075135300

现在,生成随机排列。对于包arrangements,我们使用nsample 参数。此外,我们可以设置可重复性的种子:

set.seed(123)
r1 <- arrangements::permutations(0:1, freq = c(18, 18), nsample = 10)

set.seed(123)
r2 <- arrangements::permutations(0:1, freq = c(18, 18), nsample = 10)

dim(r1)
[1] 10 36

identical(r1, r2)
[1] TRUE

## only showing 10 columns
head(r1[,1:10])
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    0    0    0    0    1    1    0    1    1     1
[2,]    1    0    1    1    1    1    1    1    1     0
[3,]    0    0    0    0    0    1    1    0    0     0
[4,]    1    1    1    0    0    1    0    1    0     0
[5,]    0    1    1    0    0    1    1    1    0     1
[6,]    0    0    0    1    1    1    0    1    1     1

对于RcppAlgos,我们使用类似的参数nseed 调用permuteSample

r3 <- RcppAlgos::permuteSample(0:1, freqs = c(18, 18), n = 10, seed = 42)
r4 <- RcppAlgos::permuteSample(0:1, freqs = c(18, 18), n = 10, seed = 42)

identical(r3, r4)
[1] TRUE

dim(r3)
[1] 10 36

这两个软件包也非常有效。生成 1000 个随机排列只需不到一秒的时间:

system.time(RcppAlgos::permuteSample(0:1, freqs = c(18, 18), n = 1000))
 user  system elapsed 
0.051   0.000   0.052 

system.time(arrangements::permutations(0:1, freq = c(18, 18), nsample = 1000))
 user  system elapsed 
0.249   0.000   0.249

【讨论】:

    【解决方案2】:

    @Joseph Wood 得到了完美的答案。以防万一您需要使用这些采样排列的列表:

    r <- RcppAlgos::permuteSample(0:1, freqs = c(18, 18), n = 100)
    r <- lapply(1:dim(r)[1], function(x) {r[x,]})
    

    【讨论】:

    • 不错的补充。另请注意,包arrangements 有一个名为type 的参数(我认为),它允许您返回一个列表,所以它更简洁一些。
    • 为了清楚起见,type 参数已重命名为 layout
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    • 2012-03-09
    • 2017-11-02
    • 1970-01-01
    • 2016-05-22
    • 2020-11-05
    • 1970-01-01
    相关资源
    最近更新 更多