具有两个非平凡约束的随机二进制矩阵

时间:2013-06-22 17:34:24

标签: matlab sparse-matrix

我需要生成包含1和0的K列和N行的随机矩阵,以便:

a)每行包含k个。{ b)每一行都与另一行不同(组合学强加如果N> nchoosek(K, k)将有nchoosek(K,k)行。

假设我想要N = 10000(在所有可能的nchoosek(K, k) = 27405组合中),不同的1×K向量(K = 30)包含k(含k = 4)个并且K - k零。

此代码:

clear all; close
N=10000; K=30; k=4;
M=randi([0 1],N,K);
plot(sum(M,2)) % condition a) not satisfied

既不满足a)也不满足b)。

此代码:

clear all; close;
N=10000;
NN=N;  K=30; k=4;
tempM=zeros(NN,K);   
for ii=1:NN
ttmodel=tempM(ii,:);
ttmodel(randsample(K,k,false))=1;  %satisfies condition a)
tempM(ii,:)=ttmodel;
end
Check=bi2de(tempM);                    %from binary to decimal
[tresh1,ind,tresh2] = unique(Check);%drop the vectors that appear more than once in the   matrix
M=tempM(ind,:);                             %and satisfies condition b)
plot(sum(M,2))                                  %verify that condition a) is satisfied
%Effective draws, Wanted draws, Number of possible combinations to draw from
[sum(sum(M,2)==k) N nchoosek(K,k) ]  

满足条件a)和部分条件b)。我部分说,因为除非NN>> N,否则最终矩阵将包含少于N个行,每个行彼此不同。

是否有更好更快的方法(可能避免使用for循环以及需要使用NN>> N)来解决问题?

3 个答案:

答案 0 :(得分:2)

首先,生成 N 唯一的k-long位置的排列:

cols = randperm(K, N);
cols = cols(:, 1:k);

然后生成匹配的行索引:

rows = meshgrid(1:N, 1:k)';

最后用:

创建稀疏矩阵
A = sparse(rows, cols, 1, N, K);

要获得矩阵的完整形式,请使用full(A)

实施例

K = 10;
k = 4;
N = 5;

cols = randperm(K, N);
cols = cols(:, 1:k);
rows = meshgrid(1:N, 1:k)';
A = sparse(rows, cols , 1, N, K);
full(A)

我得到的结果是:

ans = 
    1   1   0   0   0   0   0   1   0   1
    0   0   1   1   0   1   0   0   0   1
    0   0   0   1   1   0   1   0   1   0
    0   1   0   0   0   0   1   0   1   1
    1   1   1   0   0   1   0   0   0   0

即使对于 K N 的大值,此计算也应该非常快。对于 K = 30, k = 4, N = 10000,结果在不到0.01秒内获得。

答案 1 :(得分:0)

你可以使用randperm(n)生成从1到n的整数的随机序列,并将非重复序列作为行存储在矩阵M中直到大小(唯一(M,'行'),1)== size(男,1)。然后,您可以使用M来索引逻辑矩阵,并在每行中使用适当数量的真值。

答案 2 :(得分:0)

如果你有足够的内存用于nchoosek(K,k)整数,建立一个这样的数组,使用部分Fisher-Yates shuffle来获得N个合适的均匀随机子集。现在,给定N个整数数组,将每个整数解释为表示最终数组的每一行的组合的等级。如果你使用组合的colexicographical排序,从排名计算组合是非常简单的(虽然它使用了大量的二项式组合函数,所以有一个快速的组合是值得的。)

我不是一个Matlab人,但我在C中做过类似的事情。例如:

for (i = k; i >= 1; --i) {
    while ((b = binomial(n, i)) > r) --n;
    buf[i-1] = n;
    r -= b;
}

将使用buf[]0的索引填充数组n-1,以获取r kn1元素的组合colex order。您可以将这些解释为行中{{1}}的位置。