Create random matrix (MATLAB)
2 views (last 30 days)
Show older comments
Dear,
I have these initial parameters :
numRows = 216;
numCols = 432;
A = zeros(numRows,numCols);
numOnesPerCol = randi(([2,3]),[1,numCols]);
numOnesPerRow = randi(([5,6]),[numRows,1]);
and I want to create a binary matrix with dimensions (numRows*numCols) that has numOnesPerCol and numOnesPerRow.
How can I do that please
4 Comments
Accepted Answer
Torsten
on 15 Jan 2022
Edited: Torsten
on 20 Jan 2022
Use intlinprog for the program
min: sum_{i=1}^{numRows} (e1_i+ + e1_i-) + sum_{j=1}^{numCols} (e2_j+ + e2_j-)
under the constraints
e1_j+ - e1_j- - sum_{i=1}^{numRows} A(i,j) = -numOnesPerCol(j) (j=1,...,numCols)
e2_i+ - e2_i- - sum_{j=1}^{numCols} A(i,j) = -numOnesPerRow(i) (i=1,...,numRows)
e1_j+, e1_j- >= 0 (j=1,...,numCols)
e2_i+, e2_i- >= 0 (i=1,...,numRows)
A(i,j) in {0,1} for all i,j
6 Comments
Torsten
on 20 Jan 2022
Edited: Torsten
on 20 Jan 2022
Test whether this code works for your purpose.
If fopt as output from intlinprog is equal to zero, a matrix with the desired properties exists and is written to console.
If you want to run the program for larger values of numRows and numCols, you should construct Aeq as a sparse matrix.
numRows = 5;
numCols = 10;
%numOnesPerCol = randi(([2,3]),[1,numCols]); % Number of ones in each column
%numOnesPerRow = randi(([5,6]),[numRows,1]); % Number of ones in each Row
numOnesPerCol = [3 2 3 3 2 3 2 3 3 2];
numOnesPerRow = [5;6;5;5;5];
%Usually, nothing needs to be changed after this line
f = [ones(2*numCols,1);ones(2*numRows,1);zeros(numRows*numCols,1)];
intcon = 2*numCols+2*numRows+1:2*numRows+2*numCols+numRows*numCols;
Aeq11 = [eye(numCols,numCols),-eye(numCols,numCols),zeros(numCols,numRows),zeros(numCols,numRows)];
Aeq12 = -repmat(eye(numCols,numCols),1,numRows);
Aeq21 = [zeros(numRows,numCols),zeros(numRows,numCols),eye(numRows,numRows),-eye(numRows,numRows)];
Aeq22 = [];
for i=1:numRows
Aeq22 = [Aeq22;zeros(1,(i-1)*numCols),ones(1,numCols),zeros(1,(numRows-i)*numCols)];
end
Aeq22 = -Aeq22;
Aeq = [Aeq11,Aeq12;Aeq21,Aeq22];
beq = [-numOnesPerCol.';-numOnesPerRow];
Aineq = [];
bineq = [];
lb = [zeros(2*numCols,1);zeros(2*numRows,1);zeros(numCols*numRows,1)];
ub = [Inf(2*numCols,1);Inf(2*numRows,1);ones(numCols*numRows,1)];
[xopt,fopt,status,output] = intlinprog(f,intcon,Aineq,bineq,Aeq,beq,lb,ub);
disp(xopt)
disp(fopt)
disp(status)
disp(output)
if abs(fopt) < eps
for i = 1:numRows
for j = 1:numCols
A(i,j) = xopt(2*numRows+2*numCols+(i-1)*numCols+j);
end
end
disp(A)
end
More Answers (1)
Image Analyst
on 15 Jan 2022
Then mask it with two numbers like
output = latinRectangle == 1 | latinRectangle == 2;
Sorry I don't have Latin Rectangle code but there is Latin Square, and maybe Latin Rectangle, code in the File Exchange.
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!