Logical operations on matrices columns. - matlab

Let say that I have 1 matrix with numbers (0,1). How can i create new matrix that is the result of a logical operation among the columns?
eg. A =
0 0 0 1 0
1 1 1 1 1
0 1 1 0 0
0 0 0 0 1
1 0 0 1 0
1 1 1 1 1
If all elements of **rows** are equal to 1 - 1, if not - 0.
(like AND operation)
Ans= 0
1
0
0
0
1
Thanks!

To solve your problem this would work -
all(A,2)
If you were looking to set elements based on the columnwise data in A, you would do this -
all(A,1)
More info on all, must serve you well.

Related

Matrix row/column manipulation in matlab

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
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))));

Finding the position of repeated values in a logical array

If I have a vector such as:
0 0 1 0 1 0 0 0 1 1 1 1 1 1 1 1 0 1 1 0 0 1 0 1 1 1 1 1 1 0 0 0
How do I find the position of the first time there are two consecutive 1s. I.e. the answer to the above would be 9.
Thanks!
Can't comment, so will give you a hint here: "Finite State Machines"

generating combinations in Matlab

I have a column vector x made up of 4 elements, how can i generate all the possible combinations of the values that x can take such that x*x' is less than or equal to a certain value?
note that the values of x are positive and integers.
To be more clear:
the input is the number of elements of the column vector x and the threshold, the output are the different possible combinations of the values of x respecting the fact that x*x' <=threshold
Example: threshold is 4 and x is a 4*1 column vector.....the output is x=[0 0 0 0].[0 0 0 1],[1 1 1 1]......
See if this works for you -
threshold = 4;
A = 0:threshold
A1 = allcomb(A,A,A,A)
%// Or use: A1 = combvec(A,A,A,A).' from Neural Network Toolbox
combs = A1(sum(A1.^2,2)<=threshold,:)
Please note that the code listed above uses allcomb from MATLAB File-exchange.
Output -
combs =
0 0 0 0
0 0 0 1
0 0 0 2
0 0 1 0
0 0 1 1
0 0 2 0
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
0 2 0 0
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1
2 0 0 0

MATLAB Add 1's to matrix elements around a specific element

Using MATLAB, I have a matrix such as:
1 1 0
1 0 1
1 1 1
The aim is to represent the zero's as a mine in a minesweeper program and the values around the 0's should reflect how many mines are adjacent to it.
Therefore creating a vector like this:
1 2 0
1 0 2
1 1 1
I have thought to take elements around the zero as a sub matrix and then add 1, but then it will turn 0's into 1's.
How would I program such a task?
I think this can be achieved by simple convolution plus some post-processing on the resultant matrix as follows:
% Defining a 6x6 matrix of zeros and ones
mineMat=randi(2,6,6)-1;
numberOfMines=conv2(double(~mineMat),ones(3,3),'same').*mineMat;
% Result:
mineMat=
1 0 1 1 0 0
0 0 0 1 0 0
1 1 1 1 1 0
1 1 1 1 0 1
0 1 0 0 0 0
0 1 1 0 0 0
numberOfMines=
3 0 3 3 0 0
0 0 0 3 0 0
2 3 2 3 4 0
1 2 2 4 0 4
0 3 0 0 0 0
0 3 3 0 0 0
Parag's answer would be my first option. Another approach is to use blockproc (Image Processing Toolbox):
blockproc(~M, [1 1], #(x)sum(x.data(:)), 'Bordersize', [1 1], 'TrimBorder', 0).*M
Sounds like you are looking to apply a (two dimensional) filter:
M = [1 1 0; 1 0 1; 1 1 1]==0;
F = filter2(ones(3),M);
F(M)=0
The middle line basically does the work (applying the filter) to create the count. The last line ensures that the mines stay at value 0.

count node degree in matlab from a adjacency matrix

this is my matrix that displays a sample network graph
matrix =
0 1 1 1
1 0 1 0
0 0 0 1
1 1 1 0
where its a 4x4 matrix
1) 2) 3) 4)
1) 0 1 1 1
2) 1 0 1 0
3) 0 0 0 1
4) 1 1 1 0
i want to count this 4x4 matrix like
row 1 counts how many 1s i have and adds column 1 number of 1's to it and returns 1)=5 as total 1's in row 1 and col 1 = 5
i want my output to be like
1=5
2=4
3=4
4=5
This must be it -
out = sum([matrix matrix'],2)
Example run -
matrix =
1 1 1 1
1 0 0 0
0 1 0 1
0 0 1 1
out =
6
3
4
5
The above code would count 1s twice when they appear on the diagonal, which if you don't want, use this -
out1 = sum([matrix matrix'],2) - diag(matrix)
Example run -
matrix =
1 1 1 1
1 0 0 0
0 1 0 1
0 0 1 1
out1 =
5
3
4
4
I agree with the answer of Divakar, but once your graph gets larger and larger, you might not want to transpose the entire matrix. I suggest doing the sum first and then transposing afterwards:
sum(matrix,1)'+sum(matrix,2)-diag(matrix);
matrix =
0 1 1 1
1 0 1 0
0 0 0 1
1 1 1 0
degree=sum(matrix,1)'+sum(matrix,2)-diag(matrix)
degree =
5
4
4
5