Reputation: 544
I would like to generate a binary matrix A
of dimension m * n
with a unique number J
of 1
s on each column of the matrix and a unique number K
of 1
s on each row of the matrix.
For example, for a binary matrix A
of dimension m * n = 5 * 10
with J = 3
and K = 6
we may obtain the following matrix:
1 0 1 1 1 0 1 1 0 0
0 1 1 0 0 1 1 0 1 1
1 1 0 1 1 1 0 1 0 0
0 1 1 0 1 0 1 0 1 1
1 0 0 1 0 1 0 1 1 1
This answer by Luis Mendo, gives just the specific number of 1
s on each column. In my case I'm trying to add the option of the specific factor of 1
s on each column and on each row, which can be a different number.
How can I construct this matrix?
Upvotes: 0
Views: 392
Reputation: 337
I made this just for fun. It can get stuck, so it doesn't work all the time. For the values in your example, the function found a matrix in about 40 % of the runs. You might want to tinker a bit with max_iterations. If it's too small, the probability of finding a matrix goes down, but if it's too large it's really time consuming.
Note: I wrote this in python and haven't run it in matlab, so there might be typos.
function A = generate_matrix(m,n,J,K, max_iterations)
if nargin < 5
max_iterations = m*K*4;
end
% Check if it's possible to create matrix:
if (m*K ~= n*J)
error('Matrix not possible')
end
A = falses(m,n);
allowed_rows = 1:m;
allowed_cols = 1:n;
too_many_iterations = false;
counter = 0;
while ~isempty(allowed_rows) && ~too_many_iterations
% pick random row and column from the ones that don't have enough ones
row_index = allowed_rows(randi(length(allowed_rows)));
col_index = allowed_cols(randi(length(allowed_cols)));
A(row_index, col_index) = true;
% Update allowed_rows and allowed_cols
allowed_rows = find(sum(A,2) < K);
allowed_cols = find(sum(A,1) < J);
% Keep track of number of iterations
counter = counter + 1;
too_many_iterations = counter > max_iterations;
end
if ~isempty(allowed_rows)
warning('Matrix not found!')
A = [];
end
end
The function will start with a matrix of zeros and randomly pick a row and column that doesn't have enough ones and place a one at that location, then pick a new row and column and so on until there are no rows left. The reason it doesn't work all the time, is that it can reach a dead end. For example, with m=3, n=6, J=2 and K=4, the following matrix is a dead end, since the only row without four ones is row 1, the only column without two ones is column 3, but A[1,3] already is one.
[1, 0, 1, 1, 0, 0;
1, 1, 0, 0, 1, 1;
0, 1, 0, 1, 1, 1]
Upvotes: 2