0
votes

I have got the following function for spreading out the number of 1's in a matrix and if there are rows with all 0's or all 1's then that particular row has to be deleted

function ReducedMatrix = ReduceMatrix(result)
D1 = sum(result(:));
NumberOfOnes = floor(D1*0.3);
NewMatrix = zeros(size(result));
NewMatrix(randi(numel(NewMatrix),1,NumberOfOnes)) = 1;
ReducedMatrix = NewMatrix;
while numel(ReducedMatrix)/numel(NewMatrix) > 0.2
IndexOfFullRows = find(all(ReducedMatrix));
if isempty(IndexOfFullRows)

    break
end
ReducedMatrix(:,IndexOfFullRows(1)) = [];

end
end

The input of the function and output are as follows

 result =

 0     1     1     1     1     1     1     1     1     1
 1     1     1     1     1     0     1     0     1     1
 1     1     0     1     1     1     1     1     1     1
 1     1     1     1     1     1     1     1     1     0
 1     1     1     1     1     1     0     1     0     1
 1     0     1     1     1     1     1     0     1     1
 1     1     1     1     0     1     1     1     0     1
 1     0     1     1     1     0     1     1     1     1
 1     1     1     1     0     1     0     1     1     1
 1     1     1     0     1     1     1     1     1     1


 ReducedMatrix =

 0     1     1     0     0     0     0     0     1     0
 0     1     0     0     0     0     0     1     0     0
 1     1     1     0     0     0     0     0     0     0
 0     0     0     1     0     0     1     0     0     0
 0     0     0     0     0     0     1     0     0     0
 0     1     0     0     0     0     1     0     1     1
 1     0     1     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     1     0     1
 0     0     0     0     0     0     0     0     0     0
 1     0     1     0     0     0     0     0     0     1


row_sum =

 3
 2
 3
 2
 1
 4
 2
 2
 0
 3


col_sum =

 3     4     4     1     0     0     3     2     2     3

Now if there exists a row or column with the row_sum/col_sum equal to either 0 or 1 then then the corresponding row has to be deleted. For Example. Row-R4,R9 and Col-C4,C5,C6 have row_sum and col_sum as either 1,0. So adding them up R4,R9,C4,C5,C6 = 5 rows have to be eliminated from the matrix so my reduced matrix should be of the size 5x5. Please note column should not be eliminated and instead of removing columns having 0 and 1, the corresponding rows can be removed. Similarly this function has to run for larger matrices with the same constraints. I tried doing the above function however i do not possess enough skills to achieve my desired results, Any help is much appreciated

1
So what happens if removing a row now changes the column sums and makes it so you now have to delete another column?Suever
i have made a constrained in the function that not more than 30% of the rows can be reducedCJs

1 Answers

0
votes

I see a number of potential problems and possible simplifications to your code.

For one thing, the way you construct the original matrix, NewMatrix(randi(numel(NewMatrix),1,NumberOfOnes)) = 1; may not behave the way you would expect. randi does not guarantee that the same index will not appear multiple times in the output, so your new matrix may have fewer ones than the original. To solve this, shuffle the elements using randperm:

ReducedMatrix = [ones(1, NumberOfOnes), zeros(1, numel(result) - NumberOfOnes)];
ReducedMatrix = ReducedMatrix(randperm(numel(ReducedMatrix)));
ReducedMatrix = reshape(ReducedMatrix, size(result));

Secondly, you do not need to construct the new matrix as NewMatrix and then reassign it with ReducedMatrix = NewMatrix;. Just do ReducedMatrix = zeros(size(result)); and skip the reassignment. For the while loop condition, where NewMatrix appears to be "used", remember that numel(NewMatrix) == numel(result).

If you are not removing homogeneous columns, only rows, you do not need a loop to do the removal:

rowSum = sum(ReducedMatrix, 2);
rowMask = (rowSum == size(ReducedMatrix, 2) | rowSum == 0);
ReducedMatrix(rowMask, :) = [];

Your original code seems to swap the row and column indices when removing the rows. It also did not handle the case of all zeros. If you want to remove not more than 30% of rows, you can do something like this before the removal:

rowMask = find(rowMask); % Convert to indices
rowMask = rowMask(1:min(numel(rowMask), round(0.3 * size(ReducedMatrix, 2))));