如何在1乘41的1矢量中产生定位20个-1值的每个排列



我编写了不同的代码来产生不同的1和减号排列。它们适用于小尺寸的矩阵:

例如:

S=[-1 -1 1 1 1 1 1 1];
P=unique(perms(S),'rows');

生产:

-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   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   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   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   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  -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   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  -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
1   1   1   1   1  -1  -1   1
1   1   1   1   1  -1   1  -1
1   1   1   1   1   1  -1  -1

indices = nchoosek(1:41, 6);
N = size(indices, 1);
S = ones(N, 41);
S(sub2ind([N 41], [1:N 1:N 1:N 1:N 1:N 1:N].', indices(:))) = -1;

可以生产所有6减1(-1(和35一(1(的排列的4496388_by_ 41的矩阵。

这些代码适用于较小的维度,但不适用于较大维度的矩阵。

我的目标是生成20减去1和21的所有排列,这个矩阵有269128937220行和41列。但以下代码不起作用:

indices = nchoosek(1:41, 20);
N = size(indices, 1);
S = ones(N, 41);
S(sub2ind([N 41], [1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N 1:N].', indices(:))) = -1;

S=[-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 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1];
P=unique(perms(S),'rows');

我对每个排列(这个矩阵的每一行(做一个简单的计算。如果我能用for循环写下矩阵的每一行,然后对这一行进行计算,我就能保持最佳结果,在这种情况下,我不必把所有这些数据都保存在内存中,也不会从matlab中得到内存外错误。

如果你知道如何用for循环或任何其他方式在我的计算机中存储20减1(-1(和21 1(1(的所有排列的矩阵,请帮忙。

提前感谢

我不是Matlab的专家,所以我不能代表所有可用的资源,但是,我知道您的任务在标准笔记本电脑上是可行的,没有任何花哨的高性能服务,例如https://aws.amazon.com/hpc/.

我用R编写了一个名为RcppAlgos的软件包,它能够在几个小时内轻松完成这项任务。这是代码:

options(scipen = 999)
library(parallel)
library(RcppAlgos)
## WARNING Don't run this unless you have a few hours on your hand
## break up into even intervals of one million
firstPart <- mclapply(seq(1, 269128000000, 10^6), function(x) {
temp <- permuteGeneral(c(1L,-1L), freqs = c(21,20), lower = x, upper = x + 999999)
## your analysis here
x
}, mc.cores = 8)
## get the last few results and complete analysis
lastPart <- permuteGeneral(c(1L, -1L), freqs = c(21, 20), 
lower = 269128000000, upper = 269128937220)
## analysis for last part goes here

为了向您展示这种设置的效率,我们将展示前10亿个结果完成的速度。

system.time(mclapply(seq(1, 10^9, 10^6), function(x) {
temp <- permuteGeneral(c(1L, -1L), freqs = c(21, 20), lower = x, upper = x + 999999)
## your analysis here
x
}, mc.cores = 8))
user  system elapsed 
121.158  64.057  27.182

在30秒内获得1000000000个结果!!!!!!!

因此,这不会像@CrisLuengo计算的那样需要3000多天,而是保守估计的十亿分之30秒:

(269128937220 / 1000000000 / 60) * 30 ~= 134.5645 minutes

我还应该注意,使用上面的设置,您一次只使用1251.2 Mb,所以您的内存不会爆炸。

testSize <- object.size(permuteGeneral(c(1L,-1L), freqs = c(21,20), upper = 1e6))
print(testSize, units = "Mb")
156.4 Mb ## per core

所有结果都是在MacBook Pro 2.8GHz四核(有4个虚拟核。共8个(上获得的。

编辑:

正如@CrisLuengo所指出的,上述仅测量产生那么多排列,而没有考虑分析每次计算所需的时间。经过更多的澄清和一个新的问题,我们现在有了答案。。。大约2.5天!!!

最新更新