【问题标题】:Random binary matrix with two non-trivial constraints具有两个非平凡约束的随机二进制矩阵
【发布时间】:2013-06-22 17:34:23
【问题描述】:

我需要生成一个包含 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)来解决问题?

【问题讨论】:

    标签: matlab sparse-matrix


    【解决方案1】:

    首先,生成 N 个位置的唯一 k 长排列:

    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
    

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

    【讨论】:

    • 这在 Matlab 中仍然成立吗?从the docs 看来,randperm(K,N) 将创建一个 1×N 向量,而不是我认为这个答案所依赖的 N×K 矩阵。 The Mathworks 是否改变了 randperm 的行为?
    • 似乎在 matlab2013b 中不起作用,因为在复制您的示例时出现错误:“使用稀疏向量的错误必须是相同的长度。”
    • @Dan 好问题。我写这个答案已经一年了:)但我会想出一些更“便携”的东西:)
    • @EitanT 这与这个问题非常相似:stackoverflow.com/questions/25547072/… 但我主要是想知道 Mathworks 是否改变了 randperm 的行为?
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      如果您有足够的内存用于 nchoosek(K,k) 整数,则构建一个数组,使用部分 Fisher-Yates 洗牌来获得其中 N 个适当的均匀随机子集。现在,给定 N 个整数数组,将每个整数解释为代表最终数组每一行的组合的等级。如果您使用按字典顺序排列的组合,则根据排名计算组合非常简单(尽管它使用了许多二项式组合函数,因此使用快速组合函数是值得的)。

      我不是 Matlab 人,但我在 C 中做过类似的事情。这段代码,例如:

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

      将使用从0n-1 的索引填充数组buf[],用于kk 的第n 元素的colex 顺序组合。您会将这些解释为您所在行中1s 的位置。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-08
        • 2018-04-11
        • 2015-11-26
        • 1970-01-01
        • 1970-01-01
        • 2011-12-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多