如何得到二元矩阵的所有唯一置换及其在R中的秩

如何得到二元矩阵的所有唯一置换及其在R中的秩,r,R,我正在尝试创建一个循环,以获得所有唯一的矩阵。唯一的参数范围为0:1,矩阵的尺寸为4x4。这意味着将有65536个唯一矩阵(2^16)。我将唯一定义为在相同坐标中没有两个矩阵共享相同的元素。以下是我到目前为止的情况: binary <- function(m, n) matrix(sample(0:1, m * n, replace = TRUE), m, n) binary这里有一些非常慢的代码 # Create options option <- replicate(16, c

我正在尝试创建一个循环,以获得所有唯一的矩阵。唯一的参数范围为0:1,矩阵的尺寸为4x4。这意味着将有65536个唯一矩阵(2^16)。我将唯一定义为在相同坐标中没有两个矩阵共享相同的元素。以下是我到目前为止的情况:

binary <- function(m, n)
matrix(sample(0:1, m * n, replace = TRUE), m, n)

binary这里有一些非常慢的代码

# Create options
option <- replicate(16, c(0, 1), simplify = FALSE)
vector_possibilities <- expand.grid(option)



matrixes <- list()

for (i in seq_len(nrow(vector_possibilities)))  {
  matrixes[[i]] <- matrix(vector_possibilities[i,],4)
}


matrixes[1]
#创建选项
选项中代码的更简单(更快)版本。算法是相同的,创建一个包含16个向量的列表
0:1
,将其扩展到所有可能的二进制字符串,并将此数据集的每一行强制转换为4x4矩阵

x <- replicate(4*4, 0:1, simplify = FALSE)
apply(expand.grid(x, KEEP.OUT.ATTRS = FALSE), 1, function(x) list(matrix(x, nrow = 4, ncol = 4)))
编辑 感谢用户

甚至


使用
RcppAlgos::permuteGeneral
的非常快速的解决方案

binary2 <- function(m, n) {
  mn <- m*n
  perm <- RcppAlgos::permuteGeneral(v=0:1, m=mn, repetition=TRUE)
  lapply(1:nrow(perm), function(i) matrix(perm[i, ], nrow=m, ncol=n))
}
使用2x2矩阵的示例 …现在是
微基准
注:使用
mb.asplit.array b.rcpp.arr b.rcpp.asp.arr微基准::微基准(b.array(4,4),b.asplit.array(4,4),
+b.rcpp.arr(4,4),b.rcpp.asp.arr(4,4),
+时间=100L,控制=列表(预热=100L))
单位:毫秒
expr最小lq平均uq最大neval cld
b、 阵列(4,4)22.69801 27.03368 41.87245 33.35203 37.11160 213.8378 100 a
b、 asplit.数组(4,4)231.28149251.42609 302.35571 295.42282 331.09442 492.8092 100 b
b、 rcpp.arr(4,4)32.03322 35.92215 55.64920 50.98276 56.55712 220.2534 100 a
b、 rcpp.asp.arr(4,4)245.92865272.14143316.28854307.01918335.84227 493.5027 100 b
>

您可以通过执行以下操作获得三维数组:

 x <- array(t(expand.grid(rep(list(c(0, 1)), 16))), c(4, 4, 2^16))
要将其作为矩阵列表,请执行以下操作:

 asplit(x, 3) # in R version >=4.0.0
或者你可以:

 purrr::array_tree(x, 3) 

如何定义唯一的矩阵?所有元素都应该不同?每个矩阵不应该相同。我将“相同”定义为在同一坐标中没有两个矩阵共享相同的元素。你的意思是做
expand.grid(rep(list(c(0,1)),16))
另一个选项-
选项哦,这更干净了,我已经很久没有使用base了…也许你应该做
array(t(expand.grid(rep(list(0:1),16)),c(4,4,2^16))
如果你想要一个列表,那么在base R中你可以使用
asplit
:ie
asplit(数组(t)(展开网格(rep(list(0:1),16)),c(4,4,2^16)),3)
或者用
purr::array_tree
@Onyambu替换
asplit(展开网格(代表(列表(0:1),16)),c(4,4,2^16))
@onyanbu支持将其作为答案发布的建议。我已经更新了我的答案,并获得了相应的积分,但你真的应该将其作为你的答案发布。请注意,我已将微基准添加到我的答案中。
asplit
产生了相当大的开销,但仍然是最快的。只需在屏幕上键入
asplit
,你就不会发现它使用了循环的基础
是否可以尝试使用
数组树
?同样对于
rcpp
是否可以在其上使用
array
而不是
lappy
?我相信这种组合将非常有用fast@Onyambu我添加了
array\u tree
,但它比
asplit
慢。@onyanbu做到了。
array
vs
rcpp.array
似乎有点矛盾(可能是因为“小”矩阵大小),但是,
rcpp.array.asplit
似乎明显更快!刚刚做了基准测试。
rcpp+array
expand.grid+array
快。所以你需要再次检查你的基准测试。有趣的是,rcpp要比base R慢。嗯。我必须把这一点放在心上
binary3.2 <- function(m, n) {
  mn <- m*n
  perm <- RcppAlgos::permuteGeneral(0:1, mn, TRUE)
  asplit(array(t(perm), c(m, n, 2^(m*n))), 3)
}
binary3.2(2, 2)
# [[1]]
#      [,1] [,2]
# [1,]    0    0
# [2,]    0    0
# 
# [[2]]
#      [,1] [,2]
# [1,]    0    0
# [2,]    0    1
# 
# [[3]]
#      [,1] [,2]
# [1,]    0    1
# [2,]    0    0
# 
# [[4]]
#      [,1] [,2]
# [1,]    0    1
# [2,]    0    1
# 
# [[5]]
#      [,1] [,2]
# [1,]    0    0
# [2,]    1    0
# 
# [[6]]
#      [,1] [,2]
# [1,]    0    0
# [2,]    1    1
# 
# [[7]]
#      [,1] [,2]
# [1,]    0    1
# [2,]    1    0
# 
# [[8]]
#      [,1] [,2]
# [1,]    0    1
# [2,]    1    1
# 
# [[9]]
#      [,1] [,2]
# [1,]    1    0
# [2,]    0    0
# 
# [[10]]
#      [,1] [,2]
# [1,]    1    0
# [2,]    0    1
# 
# [[11]]
#      [,1] [,2]
# [1,]    1    1
# [2,]    0    0
# 
# [[12]]
#      [,1] [,2]
# [1,]    1    1
# [2,]    0    1
# 
# [[13]]
#      [,1] [,2]
# [1,]    1    0
# [2,]    1    0
# 
# [[14]]
#      [,1] [,2]
# [1,]    1    0
# [2,]    1    1
# 
# [[15]]
#      [,1] [,2]
# [1,]    1    1
# [2,]    1    0
# 
# [[16]]
#      [,1] [,2]
# [1,]    1    1
# [2,]    1    1
microbenchmark::microbenchmark(b.rcpp(), b.apply.exp(), b.apply.simp(), 
                               b.asplit.array(), b.array(), b.array_tree(),
                               b.rcpp.array(), b.rcpp.arr.aspl(),
                               times=5L, control=list(warmup=5L))

# Unit: milliseconds
#              expr       min        lq      mean    median        uq      max neval   cld
#          b.rcpp() 388.82227 389.27565 419.43537 408.99157 448.78494 461.3024     5   cd 
#     b.apply.exp() 446.85891 484.10602 502.78558 488.01344 518.98317 575.9664     5    de
#    b.apply.simp() 512.89587 553.52379 588.59234 569.65709 577.65281 729.2322     5     e
#  b.asplit.array() 273.01535 325.13691 320.53399 328.99840 335.36864 340.1507     5  bc  
#         b.array()  27.37996  29.33839  84.25181  39.65228  44.44757 280.4408     5 a    
#    b.array_tree() 322.98764 364.64733 424.07656 391.41701 439.77709 601.5537     5   cd 
#    b.rcpp.array()  51.87000  52.19530  66.88202  53.49471  61.88716 114.9629     5 a    
# b.rcpp.arr.aspl() 261.10201 263.29439 272.21605 278.05505 278.37984 280.2490     5  b   
> b.array <- function(m, n) {
+   array(t(expand.grid(rep(list(0:1),m*n))),c(m,n,2^(m*n)))
+ }
> 
> b.asplit.array <- function(m, n) {
+   asplit(array(t(expand.grid(rep(list(0:1),m*n))),c(m,n,2^(m*n))), 3)
+ }
> b.rcpp.arr <- function(m, n) {
+   perm <- RcppAlgos::permuteGeneral(0:1, m*n, TRUE)
+   array(t(perm), c(m, n, 2^(m*n)))
+ }
> 
> b.rcpp.asp.arr <- function(m, n) {
+   perm <- RcppAlgos::permuteGeneral(0:1, m*n, TRUE)
+   asplit(array(t(perm), c(m, n, 2^(m*n))), 3)
+ }
> 
> microbenchmark::microbenchmark(b.array(4, 4), b.asplit.array(4, 4),
+                                b.rcpp.arr(4, 4), b.rcpp.asp.arr(4, 4),
+                                times=100L, control=list(warmup=100L))
Unit: milliseconds
                 expr       min        lq      mean    median        uq      max neval cld
        b.array(4, 4)  22.69801  27.03368  41.87245  33.35203  37.11160 213.8378   100  a 
 b.asplit.array(4, 4) 231.28149 251.42609 302.35571 295.42282 331.09442 492.8092   100   b
     b.rcpp.arr(4, 4)  32.03322  35.92215  55.64920  50.98276  56.55712 220.2534   100  a 
 b.rcpp.asp.arr(4, 4) 245.92865 272.14143 316.28854 307.01918 335.84227 493.5027   100   b
>
 x <- array(t(expand.grid(rep(list(c(0, 1)), 16))), c(4, 4, 2^16))
x[,,1:2]
, , 1

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

, , 2

     [,1] [,2] [,3] [,4]
[1,]    1    0    0    0
[2,]    0    0    0    0
[3,]    0    0    0    0
[4,]    0    0    0    0
 asplit(x, 3) # in R version >=4.0.0
 purrr::array_tree(x, 3)