Reputation: 43
Hi can I generate all possible binary matrices with fixed number of 1's in each matrix of given order in matlab.
For example, all 4x4 matrices with two 1's in each matrix, [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]
Upvotes: 2
Views: 131
Reputation: 112679
Here's a vectorized solution:
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;
Each matrix is a 3rd-dim slice of 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
Upvotes: 2
Reputation: 18838
You can find all subsets of indices with the length of 2, and then replace 1
s in that indices. First find subsets with specidfied length using the 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
Then, get all possible indices and replace 1
s:
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
UPDATE:
As a matter of efficiency, instead of get_subset
, you can use combnk
as a native function in matlab.
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
Upvotes: 0
Reputation: 2343
if you want to create every combination there should be (16x15)/2 combinations (Matsize*Matsize-1)/2), because you can choose the fist on anywhere, the second one anywhere but where the first is and devied by 2 because 1-2 is the same as 2-1. Be aware that if you want to have 3 '1' for example you would have to have 16x15x14/6 (as 3 facotrial). There is a MATLAB function for getting every combination and then you just have to create every matrix while using the combinations as indices (in a 4x4 matrix you can address Matrix(2,1) as 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
There is most certainly a way to get rid of the for loop, but as I dont know how performance critical this is I just went for the easy way.
Upvotes: 0