How to create Adjacency Matrix for dataset in Matlab? - matlab

i am a new user of matlab and need help in creating adjacency matrix from a data set.
dataset is in the following pattern
A=[
0 1
0 2
0 5
1 2
1 3
1 4
2 3
2 5
3 1
3 4
3 5
4 0
4 2
5 2
5 4
];
the adjacency matrix for above will be
M= 0 1 1 0 0 1
0 0 1 1 1 0
0 0 0 1 0 1
0 1 0 0 1 1
1 0 1 0 0 0
0 0 1 0 1 0
i need code to perform the above task in matlab

You could use sparse. Please take a look at that function, give your problem a try, and then check by hovering the mouse over the following rectangle:
full(sparse(A(:,1)+1, A(:,2)+1, 1))

Welcome to SO! Please read the following guide on how to ask good questions.
To elaborate on #Ankur's comment, please also take a look at this Open letter to students with homework problems: "...If your question is just a copy paste of homework problem, expect it to be downvoted, closed, and deleted - potentially in quite short order."
What you need to do is pretty straight-forward:
First you preallocate your M matrix, using either M=zeros(6); or M(6,6)=0; (this option assumes M does not exist).
Next thing you should note is that MATLAB uses "1-based indexing", which means that you can't use the indices in A as-is and you first need to increment them by 1.
After incrementing the indices, we see that "A+1" contains the coordinates of M that should have a 1 in them (I noticed that the adjacency matrix is asymmetric in your case). From here it's a matter of accessing the correct cells, and this can be done using sub2ind(...).
Finally, the code to generate M is:
M=zeros(6);
M(sub2ind(size(M), A(:,1)+1, A(:,2)+1))=1;

I don't understand your matrix A, but supposing that A is of the same dimensions as the sought adjacency matrix M, and that you simply want to keep all the zero entries as "0", but want to make the positive entries equal to "1", then just do:
M = (A>0)
As pointed out in a comment by #Dev-iL above, this is a "problem of how to modify values of a matrix in known positions. It doesn't really involve adjacency..."

Related

how to work with diagonals of a matrix in matlab without using loops?

Lets say I have a matrix and I want to change it's elements.
How can I tell matlab to go the element in the (i,j) place? for
example:
matrix(i;j) ---> if i=j (then do something for example matrix(i;j)^2
else ( do something else)
matrix=rand(n)
if (i=j)
matrix(i,j)=(matrix(i.j))^
else matrix(i,j)=matrix(i,j)*3
end
now how can I reach the matrix's diagonals? I am new to matlab and I didn't find an answer yet :\
I am looking for a hint or something but I can't use loops!
hey i got the answer but lets say i also want the opposite diagonal to be in square how can i do this ?? plz any help
> if a=1 2 3
> 4 5 6
> 7 8 9 i want a at the end to be a= 1 6 9
> 12 25 18
> 49 24 81
It is obvious that you do not know the basics of MATLAB. Here I will try to explain what you need a little bit, but I encourage you to read the basic documentations of programming MATLAB.
If your matrix is called A then each element can be accessed through the indices (number of row and column) of that element, for instance A(2,3) gives you the element on the second row and third column.
Also diag(A) gives all the diagonal elements of A as a vector.
What you have mentioned can be done in different ways, some of which are more efficient than the others but might be more difficult for a beginner. One of the simplest methods is using two for-loops. The first loop moves on the rows of the matrix while the second moves on the column. The goal is to check all the elements one by one.
Here, we use two variables ii and jj to count for matrix rows and columns.
ii moves on the rows, so it has to count from 1 to the number of rows your matrix has. The same is done for columns using variable jj. Moreover, to find the number of rows and columns of the matrix we use function size.
Inside the two for-loops we check if the element is a on the main diagonal with ii==jj and if its not then you do something else to that elements.
for ii=1:size(A,1)
for jj=1:size(A,2)
if ii==jj
A(ii,jj) = A(ii,jj)^2;
else
A(ii,jj) = A(ii,jj)*3;
end
end
end
A way more efficient solution is as follows:
diag(diag(A)).^2 + (tril(A,-1)+triu(A,1))*3
The firs part calculates a diagonal matrix with the elements on the main diagonal of A. The second part gets the upper and lower triangular parts of matrix.
Example:
A = [1 2 3 4;
1 2 3 4;
4 3 2 1;
4 3 2 1];
>> diag(diag(A))
ans =
1 0 0 0
0 2 0 0
0 0 2 0
0 0 0 1
>> (tril(A,-1)+triu(A,1))
ans =
0 2 3 4
1 0 3 4
4 3 0 1
4 3 2 0
Where
diag(diag(A)) + (tril(A,-1)+triu(A,1)) equals to A

Adding numbers based on 2 matrices according to a constraint matlab

I have 2 matrices; Matrix A and Matrix B.
Matrix A = [1 3 6 2 7;
2 1 5 3 4;
8 3 7 2 1]
Matrix B = [0 0 1 0 0;
0 0 0 0 1;
0 1 0 0 0]
and I want to check if the '1' in matrix B is placed in a place in matrix A where it is greater than or equal to 6 then leave it as it is. But if it is smaller than 6, then go to the place of the number that is less than this number in matrix A and put a '1' in this place in matrix B and add the 2 numbers and recheck if the sum is equal to or greater than 6 and so on.
As you can see in matrix B row 2 the 1 is put in the place of 4 in matrix A. Since the 4 is less than 6 then I will go to the second smaller number than the 4 which in this case is 3 and add 3 and 4 together. This will give us 7 which is greater than 6 so we will stop. So here for example the output matrix will be:
Matrix output = [0 0 1 0 0;
0 0 0 1 1;
0 1 0 1 1]
The steps:
Go to the number that is just smaller than it. In this case go to 3 as it is the one that is just smaller than the 4. I can explain more:
check the place of the 1 in Matrix B and see its value in Matrix A.
If the number in Matrix A is greater than 6, leave it as it is and leave the 1 in Matrix B as it is and go to another row.
If the number in Matrix A is smaller than 6, then what we want is that we want add this number to another number and make it equal to or greater than 6.
This number is the one that is just smaller than it. For example if the row has [2 5 6 1 3] and the 1 is placed in the place of the 5 and 5 is less than the constraint. So we have to go to the 3 as it is the one that is just smaller than the 5 and add them together.
After adding them put 1's in the places of both numbers and check the constraints again. If it satisfies the constraint leave them and go to another row. If not go the one that is just smaller than the number again and do the same.
Thank you so much.
This code is working when matrix B is empty and it puts the 1 in the place of the highest number and it checks the constraint. If it is less than the number it will go to the second highest number and add and recheck and so on.. But what I want now is to solve it with predefined 0s and 1s
B=zeros(size(A));
for k=1:size(A,1)
a=A(k,:)
[b,ia]=sort(a,'descend')
c=cumsum(b)
jj=find(c>=6,1)
idx=ia(1:jj)
B(k,idx)=1
end
This one took a while, but I think I got it in the end...
Doing most of the process without loop except the final stage, plugging in the index row by row to change B which can be done by a arrayfun. I think there might be a few redundant steps, but I think it is pretty fast.
C = A';
D = B' > 0 ;
E = repmat(max(C(D),1),[1 size(A,2)]);
F = A-E<=0;
G = A.*F;
[H ind] = sort (G,2,'descend');
I = (cumsum(H,2) >=6)*-1 +1;
Indent = ones(size(A,1),1);
J = [Indent I];
K = J(:,1:size(A,2)).*ind;
for t= 1:size(A,1)
B(t,K(t,K(t,:)~=0)) = 1;
end
>> B =
0 0 1 0 0
0 0 0 1 1
0 1 0 1 1

Find indices where array changes

I have an array something like this:
[0 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0 1 1 ... ]
I want to find the indices where 0 changes to 1 and 1 changes to 0. So for the following array:
changes = [5 10 14 17 20]
I know how to use find and a vector predicate expression like find(A > 3) to search for simpler conditions, but this has me stuck. I could write a big loop and do it, but I feel there must be something built-in or otherwise easier to achieve the same thing.
A very simple approach which works with all values as start would be:
changes = find(diff(value))+1;
This will also return the expected result changes = [5 10 14 17 20].
Figured out a solution.
find(circshift(value, [0, 1]) ~= value)
For my application, the array is guaranteed to begin and end with 0s, otherwise it will not work properly.
Dennis K's solution works for your binary data. If you wish to find transitions in general, I recommend Run Length Encoding. I don't think MATLAB has a builtin, but (shameless plug), you can use seqle .

Count the number of the first zero elements

I would line to find the number of the first consecutive zero elements. For example in [0 0 1 -5 3 0] we have two zero consecutive elements that appear first in the vector.
could you please suggest a way without using for loops?
V=[0 0 1 -5 3 0] ;
k=find(V);
Number_of_first_zeros=k(1)-1;
Or,
Number_of_first_zeros=find(V,1,'first')-1;
To solve #The minion comment (if that was the purpose):
Number_of_first_zeros=find(V(find(~V,1,'first'):end),1,'first')-find(~V,1,'first');
Use a logical array to find the zeros and then look at where the zeros and ones are alternating.
V=[1 2 0 0 0 3 5123];
diff(V==0)
ans =
0 1 0 0 -1 0
Create sample data
V=[1 2 0 0 0 3 5123];
Find the zeros. The result will be a logical array where 1 represents the location of the zeros
D=V==0
D =
0 0 1 1 1 0 0
Take the difference of that array. 1 would then represent the start and -1 would represent the end.
T= diff(D)
ans =
0 1 0 0 -1 0
find(T==1) would give you the start and find(T==-1) would give you the end. The first index+1 of T==1 would be the start of the first set of zeros and the first index of T==-1 would be the end of the first set of zeros.
You could find position the first nonzero element using find.
I=find(A, 1);
The number of leading zeros is then I-1.
My solution is quite complex yet it doesn't use the loops and it does the trick. I am pretty sure, that there is a more direct approach.
Just in case no one else posts a working solution here my idea.
x=[1 2 4 0 20 0 10 1 23 45];
x1=find(x==0);
if numel(x1)>1
x2=[x1(2:end), 0];
x3=x2-x1;
y=find(x3~=1);
y(1)
elseif numel(x1)==1
display(1)
else
display('No zero found')
end
x is the dataset. x1 contains the index of all zero elements. x2 contains all those indices except the first one (because matrix dimensions must agree, one zero is added. x3 is the difference between the index and the previous index of zeros in your dataset. Now I find all those differences which are not 1 (do not correspond to sequences of zeros) and the first index (of this data is the required result. The if case is needed in case you have only one or no zero at all.
I'm assuming your question is the following: for the following vector [0 0 1 -5 3 0], I would like to find the index of the first element of a pair of 0 values. Is this correct? Therefore, the desired output for your vector would be '1'?
To extend the other answers to find any such pairs, not just 0 0 (eg. 0 1, 0 2, 3 4 etc), then this might help.
% define the pattern
ptrn = [ 0 0 ];
difference = ptrn(2) - ptrn(1)
V = [0 0 1 -5 3 0 0 2 3 4 0 0 1 0 0 0]
x = diff(V) == difference
indices = find(x)
indices =
1 6 11 14 15

Resorting rows in matrix in non-decreasing order based on the entries of an arbitrary column

I am working with nx2 matrices in Matlab, and what I'm trying to do is fairly simple in principle. I randomly generate a square matrix, I run it through a series of functions and I get an mx2 matrix. I use the unique function on the rows to get rid of repeated rows and I end up with an nx2 matrix. What I'm having trouble doing is further reducing this matrix so that for all entries in the first column that have the exact same entry, only keep the row with the highest number on the second column.
I was using a loop to check the ith and (i+1)th entries of the first column and store the rows with the highest value in the second column, but I am trying to avoid for-loops as much as possible.
If anyone has an idea or suggestion please let me know!
Example:
0 0 0 0
0 1 0 1 0 3
A= 0 3 ---> unique(A, 'rows') = 0 3 --WANT--> 1 1
1 0 1 0 2 4
1 0 1 1
0 0 2 1
2 1 2 4
1 1
2 4
What you are looking for is:
[u,~,n] = unique(A(:,1));
B = [u, accumarray(n, A(:,2), [], #max)];
I don't exactly understand your problem description, but it sounds like sortrows() may be of some help to you.