随机唯一二元矩阵

时间:2017-06-08 14:08:34

标签: r matrix combinations permutation

我想要尺寸为n * n的随机BUT唯一二进制矩阵。

例如,如果n = 5,则存在2 ^(5 * 5)= 33554432个唯一组合(矩阵),这是一个巨大的数字。我只需要1000.这是我目前的方法,但需要很多时间(我买不起,因为我需要在将来增加尺寸)。而且我觉得它是多余的,因为最后我只选择了全数中的1000个随机组合。还有其他方法来处理这个吗?这就是我目前正在做的事情:

我从n * n个变量的数据帧开始,第一行全1,第二行全0:

 Length = 25
 m <- as.data.frame(matrix(c(rep(0, connections), rep(1, 
      connections)),ncol=25, byrow = TRUE))

m看起来像这样:

#V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 
#V22 V23 V24 V25
#1  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   
#0   0   0   0   0
#2  1  1  1  1  1  1  1  1  1   1   1   1   1   1   1   1   1   1   1   1   
#1   1   1   1   1

接下来,我使用expand.grid

获得所有独特的组合
mFull = expand.grid(m) # This takes forever

然后我选择1000个随机行:

mRand = mFull[sample(1:nrow(mFull), 1000,)]

然后我将每一行转换为n * n矩阵,例如,第一行:

mRand[1,]
#     V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 
#V21 V22 V23 V24 V25
#21788869  1  1  0  1  1  1  0  0  1   1   1   0   0   0   0   1   1   1   0   
#0   1   1   0   1   0    

将其转换为矩阵:

> matrix(mRand[1,], nrow = 5, byrow = TRUE)
 [,1] [,2] [,3] [,4] [,5]
 [1,] 1    1    0    1    1   
 [2,] 1    0    0    1    1   
 [3,] 1    0    0    0    0   
 [4,] 1    1    1    0    0   
 [5,] 1    1    0    1    0   

是否有人建议采用更有效的解决方案?

2 个答案:

答案 0 :(得分:0)

我建议您完全随机生成矩阵,并检查每个新矩阵是否已经创建。如果没有,丢弃它。

只要可能的矩阵数量远大于所需矩阵的数量,这种方法效果很好,否则可能会很慢。

示例代码:

randomMatrix <- function(n) matrix(as.numeric(runif(n^2) > 0.5), ncol = n)  # generates random binary square matrix of size n x n

m <- 1000  # number of matrices needed

res <- vector("list", m)  # stores the result
i <- 1  # index of next matrix

while (i <= m) {

  cand <- randomMatrix(5)
  ## check if the candidate is distinct from all matrices in res
  if (!any(sapply(res, function(x) identical(x, cand)))) {  
    res[[i]] <- cand
    i <- i + 1
  }

}

如果你真的遇到速度问题(我怀疑),你可以使用一些哈希来加速比较。例如,您可以存储每个矩阵的行和列总和,并且只有在总和重合时才测试相等性。

答案 1 :(得分:0)

只要可能的矩阵数适合整数,就可以将每个矩阵编码为整数的二进制表示。因此,如果您在没有替换的情况下对整数进行采样,然后将这些整数转换为二进制矩阵,那么您就完成了。

这里有几个功能:

binmat <- function(dec,n){
    matrix(as.integer(intToBits(dec)[1:(n*n)]),n,n)

}
rbinmats <- function(n,m){
    max = 2^(m*m)
    stopifnot(max < .Machine$integer.max)

    m_decimal = sample(max,n)-1

    lapply(m_decimal, binmat, n=m)

}

binmat的工作原理如下:

> binmat(123,3)
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    1    1    0
[3,]    0    1    0

这只是123(001111011)的9位二进制表示,写成矩阵(向后)。

rbinmats只是采样并创建此形式的随机矩阵:

> rbinmats(4,3)
[[1]]
     [,1] [,2] [,3]
[1,]    1    0    1
[2,]    0    1    0
[3,]    0    1    0

[[2]]
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    1    1    0
[3,]    1    1    1

[[3]]
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    0    1    0
[3,]    0    1    0

[[4]]
     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    0    1
[3,]    1    0    1

这里它从0到(2 ^ 9)-1采样4个整数,没有替换,并对它们进行编码,因此它们将是唯一的。

5x5似乎是你可以用整数做的最大值,因为2 ^(5 * 5)小于max int,但是2 ^(6 * 6)isn&t; t。除非有64位数字的方法。