Assum I have a matrix of logicals MxN:
mask=[0 0 0 0 0;
0 1 1 0 0;
0 1 1 0 0;
0 0 0 0 0;
0 0 0 0 0];
in this case M=N=5.
A second matrix A with the sizes 'MxNx3' (RGB image). I want to pass a function values of A with respect to the mask. For example all values that are not part of the mask:
foo(A(~mask));
Sure this line of code is useless since mask gives me indices of only one of the RGB colors.
what is the correct way to do this?
Can I get away with a one line?
You can use repmat to repeat your mask 3 times in the third dimension. This will create a nnz(~mask) * 3 element vector. You can reshape the result of the repmat operation such that the rows are the true elements in your mask and the columns are the third dimension
foo(reshape(A(~repmat(mask, [1 1 3])), [], 3))
You could also do something like this answer to accomplish something similar.
Related
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.)
I have this code
function adj=edgeL2adjj(e)
Av = [e; fliplr(e)];
nodes = unique(Av(:, 1:2)); % get all nodes, sorted
adj = zeros(numel(nodes)); % initialize adjacency matrix
% across all edges
for i=1:size(Av,1)
adj(nodes==Av(i,1),(nodes==Av(i,2))) = 1;
end
end
to convert an edge list to an adjacency matrix but if I input u=[8 5;1 4;3 5;6 7]
and then I divide u into two set [8 5;1 4], [3 5,6 7] and apply previous code on [3 5;6 7] I will get a 7 x 7 matrix.
but I want a 8 x 8 matrix to any input.
You have a 7x7 matrix because numel(nodes)=7. Indeed node #2 is not present in u. I suggest you to give this function a second input, that is the maximum number of nodes in your network (in this case, 8) and preallocate the adjacency matrix with such input parameter instead of numel(nodes). Or, alternatively, you can preallocate a zeros() square matrix by giving in input not numel(nodes), but the maximum value in input u. The first option will make your code more robust, the second option will make your code robust as long as the 8-th node is in input u.
Also, there is no need for the fliplr(): if your graph is undirected (that is, the adjacency matrix is symmetric) you can rely on such structure inside the for-loop, without concatenation in Av.
Such function can indeed be simplified as follows:
function adj=edgeL2adjj(e)
adj=zeros(max(max(e))); % initialize adjacency matrix
% across all edges
for i=1:size(e,1)
adj(e(i,1),e(i,2))=1;
adj(e(i,2),e(i,1))=1;
end
end
If the input e is your matrix:
e= [8 5;1 4;3 5;6 7];
such code returns
adj =
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0
As you can see you simply exploit the input e. The maximum value is 8, so you build a square 8x8 matrix. Also inside the for-loop by swapping the column indices 1 and 2 in e, you automatically take care of the symmetric structure of the adjacency matrix. Finally, this code automatically sort you out in case of missing nodes: indeed, as you can see, the second row and the second column in adj are all-zeros because node #2 is not present in the edge list e.
Note: I do not recommend to split your input edge list. In this manner, you will loose all the global informations regarding your network. Indeed you will have (let's say) two "sub-networks" which you later have to concatenate (in terms of adjacency matrix). That is, if you split e in two sub-matrices, you'll have two adjacency matrices. By taking into account the code as it is now in my answer, the first matrix will be 8x8 whereas the second will be 7x7 because max(max([3 5;6 7]))=7.
If I may, I'd like to offer an altogether different solution to your problem, which avoids looping over all edges (always a good idea to avoid loops in MATLAB!).
Since you have all your row and column indices, your edge list basically already specifies a (albeit sparse) matrix. You can simply allocate the matrix like this:
function adj = edgeL2adjj(e)
r = e(:,1);
c = e(:,2);
vals = ones(size(r));
% maximum node index determines matrix dimensions
n_nodes = max(e(:));
% create sparse matrix
adj = sparse(r, c, vals, n_nodes, n_nodes);
% if really necessary, you can just convert it to a full matrix
adj = full(adj);
end
If you know you always want the graph to have the same dimensions, even if you only use part of your edges as an input to the function, you could just pass n_nodes as an input instead of determining it from e:
function adj = edgeL2adjj(e, n_nodes)
I have a binary sparse matrix H of size 600*1200 constructed by concatenating square permutation matrices of size 200, thus sparse matrix have 3 ones in each column and 6 ones in each row. Now am trying to transform the matrix into reduced echelon form.
This is my code:
[m,n]=size(H);
for i=1:m
ind=find(H(:,i),1,'last');
if ind<=i
continue;
end
if ind~=i
temp=H(ind,:);
H(ind,:)=H(i,:);
H(i,:)=temp;
end
I=find(H(:,i));
% Guassian elimination
for j=1:length(I)
if I(j)~=i
H(I(j),:)=mod(H(I(j),:)+H(i,:),2);
end
end
end
But whichever H matrix generated, I can't get rid of other entries at 400th column,
how can I fix this, help
Since Gaussian elimination does not involve rearrangement of columns, the first 600 columns of the resulting matrix will only form the identity matrix if the first 600 columns of the original matrix were linearly independent. Otherwise, you are going to have "short" columns with other entries in them, as the Wikipedia article shows.
The way your matrix is structured, the first 400 columns are guaranteed to be linearly dependent. Indeed, the sum of the first 200 columns is the all-1 vector, and so is the sum of the columns 201-400. This is why you are seeing these entries in the 400th column.
To create identity matrix on the left you need to rearrange columns. One way, which looks a bit redundant but is very easy to code, is to
run your algorithm
rearrange columns (it's easy to identify the desired columns after rref)
do rref again.
Here is the code that does steps 2-3.
for i = 1:m
j = find(H(i,:),1,'first');
[H(:,i), H(:,j)] = deal(H(:,j), H(:,i));
end
H = rref(H)
Sample input into rref:
1 0 1 0 1
0 1 0 0 1
1 0 1 1 0
0 0 0 0 1
Output of your code:
1 0 1 1 0
0 1 0 0 1
0 0 0 1 1
0 0 0 0 1
After the column swap and second rref:
1 0 0 0 1
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
This question already has answers here:
Construct this matrix based on two vectors MATLAB
(3 answers)
Closed 8 years ago.
I have a vector y = [0; 2; 4]
I want to convert each element of it into vector, where all elements are zero but element with index equal to digit is 1.
I'd like to do it without loops.
For example [0; 2; 4] should be converted to
[1 0 0 0 0 0 0 0 0 0;
0 0 1 0 0 0 0 0 0 0;
0 0 0 0 1 0 0 0 0 0]
(in this example vector first index is 0)
The usual trick with sparse can be used to simplify the process. Let n denote the desired number of columns. Then
result = full(sparse(1:numel(y), y+1, 1, numel(y), n));
For example, y = [0;2;4] and 10 produce
result =
1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
First you need to decide how many digits you want to represent each number. In your case, you have 10 digits per number, so let's keep that in mind.
Once you do this, it's just a matter of indexing each element in your matrix. In your case, you have 10 digits per number. As such, do something like this:
y = [0; 2; 4]; %// Your digits array
out = zeros(numel(y), 10); %// 10 digits per number
ind = sub2ind(size(out), [1:numel(y)].', y+1);
out(ind) = 1;
The output should look like this:
out =
1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
Let's go through this code slowly. y defines the digits you want per row of the output matrix. out allocates a matrix of zeroes where the number of rows is defined by how many digits you want in y. out will thus store your resulting matrix that you have shown us in your post.
The number of columns is 10, but you change this to be whatever you want. ind uses a command called sub2ind. This allows to completely vectorize the assignment of values in your out matrix and avoids a for loop. The first parameter is an array of values that defines how many rows and columns are in your matrix that you are trying to assign things to. In this case, it's just the size of out. The second and third parameters are the rows and columns you want to access in your matrix. In this case, the rows vary from 1 to as many elements as there are in y. In our case, this is 3. We want to generate one number per row, which is why it goes from 1 to 3. The columns denote where we want to set the digit to one for each row. As MATLAB indexes starting at 1, we have to make sure that we take y and add by 1. ind thus creates the column-major indices in order to access our matrix. The last statement finally accesses these locations and assigns a 1 to each location, thus producing our matrix.
Hope this helps!
Given a binary matrix in which every row and column contains exactly only one 1, I need to rearrange the matrix columnwise so that it will become an identity matrix. For example, given a binary matrix:
Binary = [ 0 1 0 0 0
0 0 1 0 0
1 0 0 0 0
0 0 0 0 1
0 0 0 1 0 ]
To get the identity matrix we rearrange the column as 2 3 1 5 4.
How can we optimally rearrange the columns for any given arbitrary square binary matrix?
A very simple way to do this is to use the function FIND like so:
[index,~] = find(Binary.'); %'# Transpose the matrix and find the row indices
%# of the non-zero entries
And you can test that it work as follows:
>> Binary(:,index)
ans =
1 0 0 0 0 %# Yup, that's an identity matrix alright!
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
OLD APPROACH:
This isn't as compact or efficient as the above solution, but you could also transpose the matrix and use SORTROWS to sort the columns (now transposed into the rows) and return the sort indices. This will actually sort values in ascending order, which will give you an anti-diagonal matrix, so you will want to flip the vector of indices using FLIPUD. Here's the code:
[~,index] = sortrows(Binary.'); %'# Transpose and sort the matrix
index = flipud(index); %# Flip the index vector
If you know the matrix can be manipulated into an identity matrix, why don't you just create an identity matrix with the same dimensions?
identity_matrix=eye(length(Binary))