【发布时间】:2018-01-09 05:54:01
【问题描述】:
您好,我可以在 matlab 中生成所有可能的二进制矩阵,在每个给定顺序的矩阵中具有固定数量的 1。
例如,所有 4x4 矩阵,每个矩阵中都有两个 1, [1 1 0 0;0 0 0 0;0 0 0 0;0 0 0 0],[1 0 0 0;0 1 0 0;0 0 0 0;0 0 0 0],[1 0 0 0; 0 0 0 0;1 0 0 0;0 0 0 0]
【问题讨论】:
您好,我可以在 matlab 中生成所有可能的二进制矩阵,在每个给定顺序的矩阵中具有固定数量的 1。
例如,所有 4x4 矩阵,每个矩阵中都有两个 1, [1 1 0 0;0 0 0 0;0 0 0 0;0 0 0 0],[1 0 0 0;0 1 0 0;0 0 0 0;0 0 0 0],[1 0 0 0; 0 0 0 0;1 0 0 0;0 0 0 0]
【问题讨论】:
这是一个矢量化的解决方案:
N = 4; % matrix size
M = 2; % number of ones
ind = nchoosek(1:N^2, M);
result = zeros(N,N,size(ind,1));
result(bsxfun(@plus, ind, (0:size(ind,1)-1).'*N^2)) = 1;
每个矩阵都是result 的第三维切片:
>> result
result(:,:,1) =
1 0 0 0
1 0 0 0
0 0 0 0
0 0 0 0
result(:,:,2) =
1 0 0 0
0 0 0 0
1 0 0 0
0 0 0 0
···
result(:,:,120) =
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 1
【讨论】:
如果您想创建每个组合,则应该有 (16x15)/2 个组合 (Matsize*Matsize-1)/2),因为您可以在任何地方选择拳头,在任何地方选择第二个,但第一个在哪里并且偏离乘以 2,因为 1-2 与 2-1 相同。请注意,例如,如果您想拥有 3 个“1”,则必须拥有 16x15x14/6(作为 3 个 facotrial)。有一个 MATLAB 函数可以获取每个组合,然后您只需创建每个矩阵,同时使用组合作为索引(在 4x4 矩阵中,您可以将 Matrix(2,1) 寻址为 Matrix(5) )。
C = combnk(1:16,2); %16 elements and 2 '1'
Matrizes = zeros(length(C),4,4);
for i=1:size(Matrizes,1)
Matrizes(i,C(i,:))=1;
end
肯定有一种方法可以摆脱 for 循环,但由于我不知道这对性能有多重要,所以我选择了简单的方法。
【讨论】:
您可以找到所有长度为 2 的索引子集,然后在该索引中替换 1s。首先使用following code 找到具有指定长度的子集:
function subsets = get_subset(N, c)
indices = dec2bin(1:(2 ^ N - 1)) - '0'; % indices of all subsets
counter = sum(indices, 2); % number of elements in subsets
subsets = indices(find(counter == c), :); % select appropriate subsets
end
然后,获取所有可能的索引并替换1s:
n = 10; k = 2;
A = zeros(n);
all = cell(1,nchoosek(n,k));
subsets = get_subset(numel(A), k);
len = size(subsets,1);
for i = 1:len
temp = A;
temp(find(subsets(i,:) == 1)) = 1;
all{i} = temp;
end
更新:
出于效率考虑,您可以在 matlab 中使用 combnk 作为本机函数,而不是 get_subset。
n = 10; k = 2;
A = zeros(n);
all = cell(1,nchoosek(n,k));
subsets = combnk(numel(A), k);
len = size(subsets,1);
for i = 1:len
temp = A;
temp(find(subsets(i,:) == 1)) = 1;
all{i} = temp;
end
【讨论】: