I am using the MATLAB function graphallshortestpaths to compute shortest paths between vertices of an undirected network. The undirected network is given as a weighted edge list file, which you can find here.
This is the MATLAB code that I use to compute the shortest paths:
A=load('genome_edge_list');
%Extract the edges
E=[A(:,1);A(:,2)];
%Extract the vertices
V=unique(E);
%N is the number of vertices
N=length(V);
%Take the inverse of the weights
A(:,3)=1./A(:,3);
%Create a sparse weighted adjacency matrix
B=sparse(A(:,1),A(:,2),A(:,3),N,N);
%Make B symmetric
B=sparse(full(B)+full(B)');
%Compute shortest paths
D=graphallshortestpaths(B,'directed',false);
Now, the matrix D that MATLAB gives as output is not symmetric. However, since the input to graphallshortestpaths is a symmetric matrix in sparse format, the output ought to be a symmetric matrix. So what am I doing wrong?
The only related question that I could find on mathworks is this question, however in that question the OP clearly is not giving a symmetric matrix as input, which explains why the matrix returned by MATLAB is not symmetric.
EDIT:
To see how far off D and D' are, I computed the following:
E=D';
C=D==E;
find(C==0)
this returns the following linear indices:
33133
543038
1363077
1398421
1398786
1399373
but the values of D and E at those indices are the same, e.g. D(33133)= 0.1024=E(33133). Now, if I take the difference of the two matrices, then I find that the difference at those indices is -1.0000e-05. It therefore seems to be a rounding error, as #beaker points out. However, as I write in my comment below, I don't understand how this can occur, as graphsallshortestpaths computes the distance between node i and j only once, so the values of D(i,j) and D(i,j) should be the result of the same computation.
Couple or remarks:
As #beaker mentioned in the comment, it could well be a numerical issue. I would be particularly weary of the line where you take the inverse and do A(:,3)=1./A(:,3);. Try to output some debug values and see if this inverse does what you intended.
On the line where you make B symmetric: are you sure you want to do full(b)' and not full(b).'? The first one takes the hermitian, the second the transpose!
Also on the same line where you make B symmetric: perhaps you are missing a 0.5 factor in there? So instead of B=sparse(full(B)+full(B)'); something like B=sparse((full(B)+full(B).').*0.5); (see this answer).
I also think you unintentionally wrote H instead of E on the second line, right?
Okay, so I'm working on a problem related to quantum chaos and one of the things I need to do is to map the unit cube in n-dimensions to a parallelepiped in n-dimensions and find all integer points in the interior of this parallelepiped. I have been trying to do this using the following scheme:
Given the linear map B and the dimension of the cube n, we find the coordinates of the corners of the unit hypercube by converting numbers j from 0 to (2^n -1) into their binary representation and turning them into vectors that describe the vertices of the cube.
The next step was to apply the map B to each of these vectors, which gives me a set of 2^n vectors describing the coordinates of the vertices of the parallelepiped in n dimensions
Now, we take the maximum and minimum value attained by any of these vertices in each coordinate direction, i.e the first element of my vectors might have a maximum value of 4 across all of the vertices and a minimum value of -3 etc. This gives me an n-dimensional rectangular prism that contains my parallelepiped and some extra unwanted space.
I now find all points with integer coordinates in this bounding rectangular prism described as vectors in n dimensions
Finally, I apply the inverse of the map B to each of the points and throw away any points that have any coefficients greater than 1 as they must originally have lain outside my unit hypercube.
My issue arises in step 4, I'm struggling to come up with a way of generating all vectors with integer coordinates in my rectangular hyper-prism such that I can change the number of dimensions n on the fly. Ideally, i'd like to be able to increase n at will until it becomes too computationally heavy to do so, but every method of finding all integer points in the prism i've tried so far has relied on n for loops to permute each element and thus I need to rewrite the code every time.
So I guess my question is this, is there any way to code this up so that I can change n on the fly? Also, any thoughts on the idea of the algorithm itself would be appreciated :) It wouldn't surprise me if i've overcomplicated things massively...
EDIT:
Of course as soon as I post the question I see a lovely little link in the side-bar where a clever method has been given already for how to do this: Generate a matrix containing all combinations of elements taken from n vectors
I'll leave this up for the moment just in case anyone has any comments on the method in general, but otherwise (since I can't upvote yet I'll just say it here) Luis Mendo, you are a hero!
Suppose the matrix below as a directed graph adjacency matrix with 3 nodes.
A=[.35 .076 .12;.0054 .83 .09; .31 .92 .019]
How can I find the strongest path between two specific nodes in matlab or ucinet?
I need some way to tell matlab that find every possible paths between two nodes, then sum up the weights of edges in each path and find the maximum weighted path, then show that path.
For example if we consider marix A and want to find the strongest path from node 1 to node 3, we have two possible paths: one direct path from node 1 to node 3 and one path from node 1 to node 2 and node 2 to node 3. in the first path we have A(1,3)=.12 and for second path we have A(1,2)+ A(2,3)= .076+.09=.166, so the second path is strongest path from node 1 to node 3, and we have it as 1-2-3. Is there any way to do something like this in matlab or ucinet?
Big thanks in advance
To find strongest path between two nodes in a directed graph in MATLAB, you can use Graph::longestPath in the Symbolic Math Toolbox (note that the Dijkstra algorithm to find the shortest path graphshortestpath is in the Bioinformatics Toolbox)
Let A be the adjacency matrix for the graph G = (V,E). A(i,j) = 1 if the nodes i and j are connected with an edge, A(i,j) = 0 otherwise.
My objective is the one of understanding whether G is acyclic or not. A cycle is defined in the following way:
i and j are connected: A(i,j) = 1
j and k are connected: A(j,k) = 1
k and i are connected: A(k,i) = 1
I have implemented a solution which navigates the matrix as follows:
Start from an edge (i,j)
Select the set O of edges which are outgoing from j, i.e., all the 1s in the j-th row of A
Navigate O in a DFS fashion
If one of the paths generated from this navigation leads to the node i, then a cycle is detected
Obviously this solution is very slow, since I have to evaluate all the paths in the matrix. If A is very big, the required overhead is very huge. I was wondering whether there is a way of navigating the adjacency matrix so as to find cycles without using an expensive algorithm such as DFS.
I would like to implement my solution in MATLAB.
Thanks in advance,
Eleanore.
I came across this question when answering this math.stackexchange question. For future readers, I feel like I need to point out (as others have already) that Danil Asotsky's answer is incorrect, and provide an alternative approach. The theorem Danil is referring to is that the (i,j) entry of A^k counts the number of walks of length k from i to j in G. The key thing here is that a walk is allowed to repeat vertices. So even if a diagonal entries of A^k is positive, each walk the entry is counting may contain repeated vertices, and so wouldn't count as a cycle.
Counterexample: A path of length 4 would contain a 4-cycle according to Danil's answer (not to mention that the answer would imply P=NP because it would solve the Hamilton cycle problem).
Anyways, here is another approach. A graph is acyclic if and only if it is a forest, i.e., it has c components and exactly n-c edges, where n is the number of vertices. Fortunately, there is a way to calculate the number of components using the Laplacian matrix L, which is obtained by replacing the (i,i) entry of -A with the sum of entries in row i of A (i.e., the degree of vertex labeled i). Then it is known that the number of components of G is n-rank(L) (i.e., the multiplicity of 0 as an eigenvalue of L).
So G has a cycle if and only if the number of edges is at least n-(n-rank(L))+1. On the other hand, by the handshaking lemma, the number of edges is exactly half of trace(L). So:
G is acyclic if and only if 0.5*trace(L)=rank(L). Equivalently, G has a cycle if and only if 0.5*trace(L) >= rank(L)+1.
Based on the observation of Danil, you need to compute A^n, a slightly more efficient way of doing so is
n = size(A,1);
An = A;
for ii = 2:n
An = An * A; % do not re-compute A^n from skratch
if trace(An) ~= 0
fprintf(1, 'got cycles\n');
end
end
If A is the adjacency matrix of the directed or undirected graph G, then the matrix A^n (i.e., the matrix product of n copies of A) has following property: the entry in row i and column j gives the number of (directed or undirected) walks of length n from vertex i to vertex j.
E.g. if for some integer n matrix A^n contain at least one non-zero diagonal entry, than graph has cycle of size n.
Most easy way check for non-zero diagonal elements of matrix is calculate matrix trace(A) = sum(diag(A)) (in our case elements of matrix power will be always non-negative).
Matlab solution can be following:
for n=2:size(A,1)
if trace(A^n) ~= 0
fprintf('Graph contain cycle of size %d', n)
break;
end
end
This approach uses DFS, but is very efficient, because we don't repeat nodes in subsequent DFS's.
High-level approach:
Initialize the values of all the nodes to -1.
Do a DFS from each unexplored node, setting that node's value to that of an auto-incremented value starting from 0.
For these DFS's, update each node's value with previous node's value + i/n^k where that node is the ith child of the previous node and k is the depth explored, skipping already explored nodes (except for checking for a bigger value).
So, an example for n = 10:
0.1 0.11 0.111
j - k - p
0 / \ 0.12
i \ 0.2 l
m
1 1.1
q - o
...
You can also use i/branching factor+1 for each node to reduce the significant digits of the numbers, but that requires additional calculation to determine.
So above we did a DFS from i, which had 2 children j and m. m had no children, j had 2 children, .... Then we finished with i and started another DFS from the next unexplored node q.
Whenever you encounter a bigger value, you know that a cycle occurred.
Complexity:
You check every node at most once, and at every node you do n checks, so complexity is O(n^2), which is the same as looking at every entry in the matrix once (which you can't do much better than).
Note:
I'll also just note that an adjacency list will probably be faster than an adjacency matrix unless it's a very dense graph.
That is the problem I also found. The explanation, I thought, is the following:
when we talk about cycle, implicitly we mean directed cycles. The adjacency matrix that you have has a different meaning when you consider the directed graph; it is indeed a directed cycle of length 2. So, the solution of $A^n$ is actually for directed graphs. For undirected graphs, I guess a fix would be to just consider the upper triangular version of the matrix (the rest filled with zero) and repeat the procedure. Let me know if this is the right answer.
If digraph G is represented by its Adjacency matrix M then M'=(I - M ) will be singular if there is a cycle in it.
I : identity matrix of same order of M
Some more thoughts on the matrix approach... The example cited is the adjacency matrix for a disconnected graph (nodes 1&2 are connected, and nodes 3&4 are connected, but neither pair is connected to the other pair). When you calculate A^2, the answer (as stated) is the identity matrix. However, since Trace(A^2) = 4, this indicates that there are 2 loops each of length 2 (which is correct). Calculating A^3 is not permitted until these loops are properly identified and removed from the matrix. This is an involved procedure requiring several steps and is detailed nicely by R.L. Norman, "A Matrix Method for Location of Cycles of a Directed Graph," AIChE J, 11-3 (1965) pp. 450-452. Please note: it is unclear from the author whether this approach is guaranteed to find ALL cycles, UNIQUE cycles, and/or ELEMENTARY cycles. My experience suggests that it definitely does not identify ONLY unique cycles.
I cannot add a comment directly, but this comment by Casteels (#casteels) is incorrect:
#Pushpendre My point is that if Danil's answer was correct for directed >graphs, then it would be correct for undirected graphs as well, which it is >not. The counterexample in my previous comment does not have the adjacency >matrix you wrote down; I said to replace each edge with a directed edge in >each direction. This gives the same adjacency matrix as the undirected case. >Are you sure you are not confusing cycle with closed walk? – Casteels Apr 24 >'15 at 9:20
As soon as a directed graph has two vertices with arcs in both directions, then it has a cycle of length 2, and the square of its adjacency matrix (which, in the 'construction' proposed above, would indeed be equal to that of the underlying undirected graph), will have a non-zero diagonal coefficient (as does the square of every adjacency matrix of a non-empty undirected graph, since an edge immediately gives a (non-elementary) walk of length 2 from a vertex to itself). So in that case, Danil's answer essentially correctly detects a cycle. The reasoning above is not correct.
Danil's answer is indeed correct for directed graphs. In a digraph, a single arc cannot be traversed both ways, so every closed directed walk must contain a directed cycle, which will create a non-zero coefficient on the diagonal of some power of the original adjacency matrix of the directed graph. So one can keep computing the powers of the matrix increasingly from 1 to the number of vertices, stopping as soon as a diagonal coefficient is non-zero.
On matlab, I have an adjacency matrix and using a function, I would like to find out how to plot a histogram showing the degrees of separation between 2 given nodes(up to 10).
As of now I only have a function that finds a node's neighbours. Basically it'll be similar to the notion of 6 degrees of separation, except with 10.
Thanks!
function n=neighbour(A,v)
global n;
for i=1:length(v)
a=find(A(:,v(i))+A(v(i),:)');
n=setdiff(a(:)',v(i));
end
end
In general, this is solved using the Floyd–Warshall algorithm, which computes the shortest paths between all pairs of nodes in a graph.
Since you're using Matlab and because the distance between any two connected nodes is always the same ("1 step"), you could use a trick that involves matrix multiplication: if you have an adjacency matrix A, then raising A to the Nth power gives you a new matrix that tells you how many paths of length N exist between each pair of nodes. So, in a loop, raise A to the 1st power, the 2nd power, etc, and note at which power each element becomes nonzero. The maximum path length is equal to the number of nodes, so you can stop there.
Scale-Free Network Visualization, including histogram of the degrees of separation can be found in this link, might be helpful...