如何构造一个 128x32 的置乱矩阵?

Posted

技术标签:

【中文标题】如何构造一个 128x32 的置乱矩阵?【英文标题】:How to construct a 128x32 scrambled matrix? 【发布时间】:2014-01-26 14:46:08 【问题描述】:

如何在 vb.netMatlab 中构造一个 128 行 32 列的加扰矩阵?

矩阵的条目是 1 到 32 之间的数字,条件是每行不得包含重复的元素,并且行不得重复。

【问题讨论】:

【参考方案1】:

这类似于@thewaywewalk's answer,但通过测试是否存在重复行并在这种情况下生成一个新矩阵来确保矩阵没有重复行:

done = 0;
while ~done
    [~, matrix] = sort(rand(128,32),2);
    %// generate each row as a random permutation, independently of other rows.
    %// This line was inspired by randperm code
    done = size(unique(matrix,'rows'),1) == 128;
    %// in the event that there are repeated rows: generate matrix again 
end

如果我的计算是正确的,那么矩阵重复行(因此必须再次生成)的概率小于

>> 128*127/factorial(32)
ans =
  6.1779e-032

嘿,cosmic ray 更有可能破坏程序的给定运行!所以我猜你可以安全地删除while 循环:-)

【讨论】:

当然对于这种特殊情况,for 循环恰好有 128 次迭代和之后的验证测试会更好。但是,如果重复行的概率更高,您的解决方案不是效率很低吗?因为每次只重复一行时,您都会生成一个全新的矩阵。在我看来,生成更多的行作为缓冲区并没有什么坏处,但是多次生成一个完整的新矩阵确实有坏处。 @thewaywewalk 完全同意。我专注于 OP 中的数字所代表的特定情况。最好只重新生成检测为重复的行 看看我上次的编辑,我做了一些有趣的测试。 我想理论上可以通过不添加它作为现有集合成员的行来稍微改进,而不是重新开始。但出于实际目的,我认为这绝对是一个很好的解决方案。 @thewaywewalk 23/24 是第二行与第一行不同的概率。 22/24 是第三行与第一行和第二行不同的概率,依此类推。您将这些概率相乘,因为它们是独立事件。我在 (6,3) 的情况下测试了 100000 个矩阵,得到 0.0159,非常接近 prod((5:-1:1)/6) = 0.0154。所以我觉得是对的【参考方案2】:

使用randperm 可以生成一行:

row = randperm(32)

如果这个向量不会那么长,您可以使用perms 来查找所有排列

B = perms(randperm(32))

但它在内存方面太多了!(32!= 2.6313e+35 行


所以你可以使用一个小循环:

N = 200;    

A = zeros(N,32);
for ii = 1:N
    A(ii,:) = randperm(32);
end

B = unique(A, 'rows');
B = B(1:128,:);

对于我的测试,直接使用N = 128 并跳过最后两行就足够了,因为使用 2.6313e+35 可能的排列,第一次尝试得到正确矩阵的概率非常高。但要确保没有行重复,请选择更大的数字并最终选择前 128 行。如果输入向量相对较短并且所需的行数接近可能排列的总数,则使用建议的perms(randperm( n ))


小例子,用于从 14 的整数以及从 24 种可能的排列中选择 10 个:

N = 20;    
A = zeros(N,4);
for ii = 1:N
    A(ii,:) = randperm(4);
end
B = unique(A, 'rows');
B = B(1:10,:);

返回:

B =

     1     2     3     4
     1     2     4     3
     1     3     4     2
     2     3     1     4
     2     3     4     1
     2     4     1     3
     2     4     3     1
     3     1     2     4
     3     1     4     2
     3     2     1     4

选择N的一些补充说明:

我进行了一些测试运行,我使用上面的循环来查找 所有排列,就像 perms 所做的那样。对于n=4n=7N = factorial(n) 的向量长度:60-80% 的行是唯一的。 所以对于小的n我建议选择N如下绝对安全:

N = min( [Q factorial(n)] )*2;

其中Q 是您想要的排列数。对于更大的n,您要么在搜索所有排列时耗尽内存,要么与所有可能的排列数量相比,所需的子集太小以至于不太可能重复! (Luis Mendo 联系的宇宙射线理论)

【讨论】:

+1 用于考虑一般情况,而不仅仅是 128x32【参考方案3】:

您的要求非常宽松,并允许许多不同的可能性。我能想到的满足这些要求的最有效的解决方案如下:

p = perms(1:6);
[p(1:128,:) repmat(7:32,128,1)]

【讨论】:

perms(6) 没有真正的意义,可能你的意思是perms(1:6) - 而且你生成的矩阵是随机的,从所有 2.6313e+35 可能的排列中,你的子集是可能分布最差的。如果分配无关紧要,它的效率是正确的。 @thewaywewalk 我更正了对烫发的调用。但实际上,对于均匀随机分布的解决方案,Luis 的答案似乎是最好的选择。

以上是关于如何构造一个 128x32 的置乱矩阵?的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB中如何构造一个矩阵,该矩阵中每一列个数不等

主流的图像置乱方法

如何构造householder矩阵

如何在 C++ 中为矩阵类型构建构造函数

随机矩阵位置构造题——519. 随机翻转矩阵

在 python pandas 中构造一个共现矩阵