Avoid division by zero between matrices in MATLAB [duplicate] - matlab

This question already has an answer here:
Matlab element-wise division by zero
(1 answer)
Closed 7 years ago.
I'm using matlab and I have two matrices :
G =
1 1 1 1
1 1 1 1
and the scond:
m =
4 4 4 4
0 0 0 0
I want this result :
x =
1/4 1/4 1/4 1/4
0 0 0 0
What I did so far is this :
x = G ./ m
But it returns :
x =
1/4 1/4 1/4 1/4
NaN NaN NaN NaN
How can I avoid the divison by zero by placing a default value "0" if there is a division by zero ?

You can convert the NaNs back to zero:
x = G ./ m;
x(isnan(x))=0; % thanks to comment by #nkjt
Or, if you have also NaNs in matrix m that you want to save, you can do:
x(m==0)=0;

One option would be to preallocate x and then only use division on the parts where m is not zero.
x = zeros(size(m)); % output is same size as m
n = m~=0; % find indexes
x(n)=G(n)./m(n);

Related

How does Y = eye(K)(y, :); replace a "for" loop? Coursera

Working on an assignment from Coursera Machine Learning. I'm curious how this works... From an example, this much simpler code:
% K is the number of classes.
K = num_labels;
Y = eye(K)(y, :);
seems to be a substitute for the following:
I = eye(num_labels);
Y = zeros(m, num_labels);
for i=1:m
Y(i, :)= I(y(i), :);
end
and I have no idea how. I'm having some difficulty Googling this info as well.
Thanks!
Your variable y in this case must be an m-element vector containing integers in the range of 1 to num_labels. The goal of the code is to create a matrix Y that is m-by-num_labels where each row k will contain all zeros except for a 1 in column y(k).
A way to generate Y is to first create an identity matrix using the function eye. This is a square matrix of all zeroes except for ones along the main diagonal. Row k of the identity matrix will therefore have one non-zero element in column k. We can therefore build matrix Y out of rows indexed from the identity matrix, using y as the row index. We could do this with a for loop (as in your second code sample), but that's not as simple and efficient as using a single indexing operation (as in your first code sample).
Let's look at an example (in MATLAB):
>> num_labels = 5;
>> y = [2 3 3 1 5 4 4 4]; % The columns where the ones will be for each row
>> I = eye(num_labels)
I =
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
>> Y = I(y, :)
Y =
% 1 in column ...
0 1 0 0 0 % 2
0 0 1 0 0 % 3
0 0 1 0 0 % 3
1 0 0 0 0 % 1
0 0 0 0 1 % 5
0 0 0 1 0 % 4
0 0 0 1 0 % 4
0 0 0 1 0 % 4
NOTE: Octave allows you to index function return arguments without first placing them in a variable, but MATLAB does not (at least, not very easily). Therefore, the syntax:
Y = eye(num_labels)(y, :);
only works in Octave. In MATLAB, you have to do it as in my example above, or use one of the other options here.
The first set of code is Octave, which has some additional indexing functionality that MATLAB does not have. The second set of code is how the operation would be performed in MATLAB.
In both cases Y is a matrix generated by re-arranging the rows of an identity matrix. In both cases it may also be posible to calculate Y = T*y for a suitable linear transformation matrix T.
(The above assumes that y is a vector of integers that are being used as an indexing variables for the rows. If that's not the case then the code most likely throws an error.)

Matlab/Octave: how to write n-dimensional zero padding algorithm without eval

I would like to write a "syntactical sugar" Octave or Matlab zero-padding function, to which the user sends an n-dimensional object and a vector of <= n entries. The vector contains new, equal or larger dimensions for the object, and the object is zero-padded to match these dimensions. Any dimensions not specified are left alone. One expected use is, given for example a 5d block X of 3d medical image volumes, I can call
y = simplepad(X, [128 128 128]);
and thus pad the first three dimensions to a power of two for wavelet analysis (in fact I use a separate function nextpwr2 to find these dimensions) while leaving the others.
I have racked my brains on how to write this method avoiding the dreaded eval, but cannot thus far find a way. Can anyone suggest a solution? Here is more or less what I have:
function y = simplepad(x, pad)
szx = size(x);
n_pad = numel(pad);
szy = [pad szx(n_pad+1:end)];
y = zeros(szy);
indices_string = '(';
for n = 1:numel(szx)
indices_string = [indices_string, '1:', num2str(szx(n))];
if n < numel(szx)
indices_string = [indices_string, ','];
else
indices_string = [indices_string, ')'];
end
end
command = ['y',indices_string,'=x;'];
eval(command);
end
Here's a solution that should handle all the little corner cases:
function A = simplepad(A, pad)
% Add singleton dimensions (i.e. ones) to the ends of the old size of A
% or pad as needed so they can be compared directly to one another:
oldSize = size(A);
dimChange = numel(pad)-numel(oldSize);
oldSize = [oldSize ones(1, dimChange)];
pad = [pad ones(1, -dimChange)];
% If all of the sizes in pad are less than or equal to the sizes in
% oldSize, there is no padding done:
if all(pad <= oldSize)
return
end
% Use implicit zero expansion to pad:
pad = num2cell(pad);
A(pad{:}) = 0;
end
And a few test cases:
>> M = magic(3)
M =
8 1 6
3 5 7
4 9 2
>> simplepad(M, [1 1]) % No change, since the all values are smaller
ans =
8 1 6
3 5 7
4 9 2
>> simplepad(M, [1 4]) % Ignore the 1, pad the rows
ans =
8 1 6 0
3 5 7 0
4 9 2 0
>> simplepad(M, [4 4]) % Pad rows and columns
ans =
8 1 6 0
3 5 7 0
4 9 2 0
0 0 0 0
>> simplepad(M, [4 4 2]) % Pad rows and columns and add a third dimension
ans(:,:,1) =
8 1 6 0
3 5 7 0
4 9 2 0
0 0 0 0
ans(:,:,2) =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
As I understand, you want just pass the some dynamic arguments to function.
You can do this by converting these arguments to cell and call your function with passing cell content. So, your function will look like:
function y = simplepad(x, pad)
szx = size(x);
n_pad = numel(pad);
szy = [pad szx(n_pad+1:end)];
y = x;
szyc = num2cell(szy);
y(szyc{:}) = 0; % warning: assume x array only grows
end

Inserting columns to a matrix in Matlab

I'd like to insert columns to a matrix, but the insertion column positions within the matrix differ by row. How can I do this without using for-loop?
Following is a simplified example in MATLAB;
From A,X,P, I want to get APX without using for-loop.
>> A = zeros(4,5) % inclusive matrix
A =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>> X = [9,8;5,7;8,3;6,7] % data to insert
X =
9 8
5 7
8 3
6 7
>> P = [3;2;4;1] % insertion position within the matrix
P =
3
2
4
1
>> APX = [0,0,9,8,0;0,5,7,0,0;0,0,0,8,3;6,7,0,0,0] % what I want
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0
It's simply determining the right column-major indices to access the matrix so you can populate it with your desired values. This first requires generating the right row and column values to access the right positions in APX so you can use X to populate those positions.
Using P, each element tells you which column you should start populating for each row of X. You will need to generate column indices in increasing order up to as many columns as there are in X. To generate the row indices, simply create a matrix that is the same size as X where each column spans from 0 up to as many rows as there are in X minus 1 (i.e. 0:size(X,2)-1). This matrix gives you the correct offsets so that you can take P and add it with this matrix. Once you do that you will have a column index matrix that tells you specifically where each element should go with regards to the columns of the output matrix per row of P. Finally, use sub2ind to generate the column-major indices using the rows and columns generated above to place X in APX.
In other words:
P = [3;2;4;1];
X = [9,8;5,7;8,3;6,7];
rowInd = repmat((1:size(X,1)).', 1, size(X,2)); %'
colInd = bsxfun(#plus, P, 0:size(X,2)-1);
APX = zeros(size(X,1), max(colInd(:)));
APX(sub2ind(size(APX), rowInd, colInd)) = X;
To generate the row locations, we use repmat to create a matrix that is the same size as X where each column spans from 1 up to as many rows as X. To generate the column locations, we use bsxfun to create a matrix where each column is the vector P but increasing by 1 per column. We then create APX to be of compatible size then use sub2ind to finally populate the matrix.
With your above test inputs, we get:
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0
Minor Note
You really should actually try using loops before trying it vectorized. Though using loops was slow in previous versions of MATLAB, MATLAB R2015b has an improved JIT engine where loops are now competitive. You should time your code using loops and ensuring that it is justifiable before switching to vectorized implementations.

Finding the column index for the 1 in each row of a matrix

I have the following matrix in Matlab:
M = [0 0 1
1 0 0
0 1 0
1 0 0
0 0 1];
Each row has exactly one 1. How can I (without looping) determine a column vector so that the first element is a 2 if there is a 1 in the second column, the second element is a 3 for a one in the third column etc.? The above example should turn into:
M = [ 3
1
2
1
3];
You can actually solve this with simple matrix multiplication.
result = M * (1:size(M, 2)).';
3
1
2
1
3
This works by multiplying your M x 3 matrix with a 3 x 1 array where the elements of the 3x1 are simply [1; 2; 3]. Briefly, for each row of M, element-wise multiplication is performed with the 3 x 1 array. Only the 1's in the row of M will yield anything in the result. Then the result of this element-wise multiplication is summed. Because you only have one "1" per row, the result is going to be the column index where that 1 is located.
So for example for the first row of M.
element_wise_multiplication = [0 0 1] .* [1 2 3]
[0, 0, 3]
sum(element_wise_multiplication)
3
Update
Based on the solutions provided by #reyryeng and #Luis below, I decided to run a comparison to see how the performance of the various methods compared.
To setup the test matrix (M) I created a matrix of the form specified in the original question and varied the number of rows. Which column had the 1 was chosen randomly using randi([1 nCols], size(M, 1)). Execution times were analyzed using timeit.
When run using M of type double (MATLAB's default) you get the following execution times.
If M is a logical, then the matrix multiplication takes a hit due to the fact that it has to be converted to a numerical type prior to matrix multiplication, whereas the other two have a bit of a performance improvement.
Here is the test code that I used.
sizes = round(linspace(100, 100000, 100));
times = zeros(numel(sizes), 3);
for k = 1:numel(sizes)
M = generateM(sizes(k));
times(k,1) = timeit(#()M * (1:size(M, 2)).');
M = generateM(sizes(k));
times(k,2) = timeit(#()max(M, [], 2), 2);
M = generateM(sizes(k));
times(k,3) = timeit(#()find(M.'), 2);
end
figure
plot(range, times / 1000);
legend({'Multiplication', 'Max', 'Find'})
xlabel('Number of rows in M')
ylabel('Execution Time (ms)')
function M = generateM(nRows)
M = zeros(nRows, 3);
col = randi([1 size(M, 2)], 1, size(M, 1));
M(sub2ind(size(M), 1:numel(col), col)) = 1;
end
You can also abuse find and observe the row positions of the transpose of M. You have to transpose the matrix first as find operates in column major order:
M = [0 0 1
1 0 0
0 1 0
1 0 0
0 0 1];
[out,~] = find(M.');
Not sure if this is faster than matrix multiplication though.
Yet another approach: use the second output of max:
[~, result] = max(M.', [], 1);
Or, as suggested by #rayryeng, use max along the second dimension instead of transposing M:
[~, result] = max(M, [], 2);
For
M = [0 0 1
1 0 0
0 1 0
1 0 0
0 0 1];
this gives
result =
3 1 2 1 3
If M contains more than one 1 in a given row, this will give the index of the first such 1.

Nodes that form a loop in adjacency matrix (Matlab)

I have an adjacency matrix with directed edges. Computing A^3, would help me detect if there are any cycles of length 3 (triangle) in the matrix. But, I want to know which nodes form the triangle. How can I achieve this in Matlab?
Thanks
The problem with matrix multiplication is that it adds up all the rows. When you multiply the first row of matrix P by the first column of matrix Q, it does an element-wise multiplication and then generates the sum of the resulting vector, throwing away all of the data about the intermediate nodes. Well, we want that vector, so let's stop it from adding them up.
Say we have our adjacency matrix A:
A =
0 1 0 0 0
0 0 1 0 0
1 0 0 1 0
0 0 0 0 0
0 0 0 1 0
and we want to find out if there are any paths (not cycles, yet) from node x to node z passing through node y. Row x tells us what nodes have edges from x to y, and column z tells us what nodes have edges from y to z. If we do an element-wise AND of row x and column z, we should get a vector of all of the nodes y that are connected to both x and z.
For example, if we AND row 1 and column 3 for this adjacency matrix:
A =
0 1 0 0 0
x x 1 x x
x x 0 x x
x x 0 x x
x x 0 x x
>> A(1,:) & A(:,3).' %// remember to transpose the column first...
ans =
0 1 0 0 0
We see that they're connected by node 2. Awesome, now we know that for this case we have a path 1->2->3. In general though, there could be multiple paths from 1 to 3, so we're going to use the whole vector.
Now all we have to do is make sure that there's a path from node 3 back to node 1. Well, that's row 3, column 1 in our adjacency matrix. If we AND A(3,1) with our vector, we should the same vector back if there's an edge from 3 to 1 and get zeros back if there isn't (and thus, no cycle).
>> (A(1,:) & A(:,3).') & A(3,1)
ans =
0 1 0 0 0
Generalizing this, the vector for each path from x to z is
C(x,:,z) = (A(x,:) & A(:,z).') & A(z,x);
Unfortunately I have been unable to find a way to vectorize this, so a double for loop will have to suffice for now:
for x = 1:size(A,1)
for z = 1:size(A,2)
C(x,:,z) = (A(x,:) & A(:,z).') & A(z,x);
end
end
The resulting matrix will have C(x,y,z) = 1 if there is a cycle from x to y to z (and back), and 0 otherwise. Note that each cycle will be listed 3 times:
C(x,y,z) == C(y,z,x) == C(z,x,y)