R语言 如何得到一个6列12行的二进矩阵的所有唯一置换?

bvuwiixz  于 2023-02-06  发布在  其他
关注(0)|答案(1)|浏览(110)

我试图生成所有可能的12 x6阶二元矩阵,其中只包含元素-1和+1。有2^72个唯一矩阵(2^16),使得没有两个矩阵在相同坐标中包含相同的元素。
我尝试使用下面的代码:

binary3.2 <- function(m, n) {
mn <- m*n
  perm <- RcppAlgos::permuteGeneral(c(-1,1), mn, TRUE)
  asplit(array(t(perm), c(m, n, 2^(m*n))), 3)
}

但是它给了我错误,提到m*n不能大于31,在我的例子中,它是72,有没有其他的方法来做到这一点?

vsdwdz23

vsdwdz231#

首先,我是RcppAlgos的作者。有几种方法可以解决您当前的问题。
在我们开始讨论您的主要问题之前,让我们先稍微简化一下您的代码。

使用FUN

不用生成所有的排列,然后调用asplit,我们可以利用FUN参数,动态地将向量转换为矩阵,就像combn一样:

library(RcppAlgos)
m <- 3L
n <- 2L

perms <- permuteGeneral(c(1L, -1L), m * n, TRUE, FUN = \(x) {
    matrix(x, m, n)
})

perms[1:2]
#> [[1]]
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1    1
#> [3,]    1    1
#> 
#> [[2]]
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1    1
#> [3,]    1   -1

perms[63:64]
#> [[1]]
#>      [,1] [,2]
#> [1,]   -1   -1
#> [2,]   -1   -1
#> [3,]   -1    1
#> 
#> [[2]]
#>      [,1] [,2]
#> [1,]   -1   -1
#> [2,]   -1   -1
#> [3,]   -1   -1

解决内存问题

使用lowerupper

我们可以使用lowerupper参数,以便生成块中的排列:

## Generate the first 2 results
permuteGeneral(c(1L, -1L), m * n, TRUE, FUN = \(x) {
    matrix(x, m, n)
}, upper = 2)
#> [[1]]
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1    1
#> [3,]    1    1
#> 
#> [[2]]
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1    1
#> [3,]    1   -1

## Get the next 2 results
permuteGeneral(c(1L, -1L), m * n, TRUE, FUN = \(x) {
    matrix(x, m, n)
}, lower = 3, upper = 4)
#> [[1]]
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1   -1
#> [3,]    1    1
#> 
#> [[2]]
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1   -1
#> [3,]    1   -1

这可以完成工作,但有点麻烦。
有没有更好的解决办法?

更好的方式

RcppAlgos提供了组合迭代器,因此可以一次生成 n 个结果,从而保持低内存。

使用迭代器

iter <- permuteIter(c(1L, -1L), m * n, TRUE, FUN = \(x) {
    matrix(x, m, n)
})

## See the first result
iter@nextIter()
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1    1
#> [3,]    1    1

## Get the next 2 results (Note we are using nextNIter instead of nextIter)
iter@nextNIter(2)
#> [[1]]
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1    1
#> [3,]    1   -1
#> 
#> [[2]]
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1   -1
#> [3,]    1    1

这些迭代器真正的优点是它们是双向的,而且还提供随机访问:

## See the previous result
iter@prevIter()
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1    1
#> [3,]    1   -1

## Get a quick summary
iter@summary()
#> $description
#> [1] "Permutations with repetition of 2 choose 6"
#> 
#> $currentIndex
#> [1] 2
#> 
#> $totalResults
#> [1] 64
#> 
#> $totalRemaining
#> [1] 62

## Go to the middle
middle <- permuteCount(2, m * n, TRUE) %/% 2L
middle
#> [1] 32
iter[[middle]]
#>      [,1] [,2]
#> [1,]    1   -1
#> [2,]   -1   -1
#> [3,]   -1   -1

## See the last result
iter@back()
#>      [,1] [,2]
#> [1,]   -1   -1
#> [2,]   -1   -1
#> [3,]   -1   -1

## Go back to the front
iter@front()
#>      [,1] [,2]
#> [1,]    1    1
#> [2,]    1    1
#> [3,]    1    1

而至于眼前的问题,记忆力将是没有问题的!

m_big <- 12L
n_big <- 6L

iter_big <- permuteIter(c(1L, -1L), m_big * n_big, TRUE, FUN = \(x) {
    matrix(x, m_big, n_big)
})

iter_big@nextIter()
#>       [,1] [,2] [,3] [,4] [,5] [,6]
#>  [1,]    1    1    1    1    1    1
#>  [2,]    1    1    1    1    1    1
#>  [3,]    1    1    1    1    1    1
#>  [4,]    1    1    1    1    1    1
#>  [5,]    1    1    1    1    1    1
#>  [6,]    1    1    1    1    1    1
#>  [7,]    1    1    1    1    1    1
#>  [8,]    1    1    1    1    1    1
#>  [9,]    1    1    1    1    1    1
#> [10,]    1    1    1    1    1    1
#> [11,]    1    1    1    1    1    1
#> [12,]    1    1    1    1    1    1

iter_big@summary()
#> $description
#> [1] "Permutations with repetition of 2 choose 72"
#> 
#> $currentIndex
#> Big Integer ('bigz') :
#> [1] 1
#> 
#> $totalResults
#> Big Integer ('bigz') :
#> [1] 4722366482869645213696
#> 
#> $totalRemaining
#> Big Integer ('bigz') :
#> [1] 4722366482869645213695

iter_big@back()
#>       [,1] [,2] [,3] [,4] [,5] [,6]
#>  [1,]   -1   -1   -1   -1   -1   -1
#>  [2,]   -1   -1   -1   -1   -1   -1
#>  [3,]   -1   -1   -1   -1   -1   -1
#>  [4,]   -1   -1   -1   -1   -1   -1
#>  [5,]   -1   -1   -1   -1   -1   -1
#>  [6,]   -1   -1   -1   -1   -1   -1
#>  [7,]   -1   -1   -1   -1   -1   -1
#>  [8,]   -1   -1   -1   -1   -1   -1
#>  [9,]   -1   -1   -1   -1   -1   -1
#> [10,]   -1   -1   -1   -1   -1   -1
#> [11,]   -1   -1   -1   -1   -1   -1
#> [12,]   -1   -1   -1   -1   -1   -1

iter_big[["100"]]
#>       [,1] [,2] [,3] [,4] [,5] [,6]
#>  [1,]    1    1    1    1    1    1
#>  [2,]    1    1    1    1    1    1
#>  [3,]    1    1    1    1    1    1
#>  [4,]    1    1    1    1    1    1
#>  [5,]    1    1    1    1    1    1
#>  [6,]    1    1    1    1    1   -1
#>  [7,]    1    1    1    1    1   -1
#>  [8,]    1    1    1    1    1    1
#>  [9,]    1    1    1    1    1    1
#> [10,]    1    1    1    1    1    1
#> [11,]    1    1    1    1    1   -1
#> [12,]    1    1    1    1    1   -1

iter_big@prevNIter(2)
#> [[1]]
#>       [,1] [,2] [,3] [,4] [,5] [,6]
#>  [1,]    1    1    1    1    1    1
#>  [2,]    1    1    1    1    1    1
#>  [3,]    1    1    1    1    1    1
#>  [4,]    1    1    1    1    1    1
#>  [5,]    1    1    1    1    1    1
#>  [6,]    1    1    1    1    1   -1
#>  [7,]    1    1    1    1    1   -1
#>  [8,]    1    1    1    1    1    1
#>  [9,]    1    1    1    1    1    1
#> [10,]    1    1    1    1    1    1
#> [11,]    1    1    1    1    1   -1
#> [12,]    1    1    1    1    1    1
#> 
#> [[2]]
#>       [,1] [,2] [,3] [,4] [,5] [,6]
#>  [1,]    1    1    1    1    1    1
#>  [2,]    1    1    1    1    1    1
#>  [3,]    1    1    1    1    1    1
#>  [4,]    1    1    1    1    1    1
#>  [5,]    1    1    1    1    1    1
#>  [6,]    1    1    1    1    1   -1
#>  [7,]    1    1    1    1    1   -1
#>  [8,]    1    1    1    1    1    1
#>  [9,]    1    1    1    1    1    1
#> [10,]    1    1    1    1    1    1
#> [11,]    1    1    1    1    1    1
#> [12,]    1    1    1    1    1   -1

相关问题