graphshortestpath function visiting all nodes
Mostrar comentarios más antiguos
Hi,
Is there a way I can manipulate this function in order to force the path include all nodes? I mean, how can I change the code in order to include each node to find the shortest path , but with the constrain that we must visit all nodes?
Thank you in advance
3 comentarios
Christine Tobler
el 6 de Mzo. de 2018
Do you want to visit each node exactly once, or would it be okay to visit some of the nodes twice, as long as each node is visited at least once? Also, is your graph directed or undirected?
Jason
el 6 de Mzo. de 2018
Editada: Walter Roberson
el 6 de Mzo. de 2018
Jason
el 6 de Mzo. de 2018
Respuesta aceptada
Más respuestas (2)
Christine Tobler
el 6 de Mzo. de 2018
As Steve Lord has said, in general this is an NP-complete problem, so could become quite expensive. For the 6-node graph you are looking at, this is easy to compute using an exhaustive search (I will use the graph object instead of the bioinfo variants here):
W = [5 1 5 4 6 1 1 4 7 2 6 7 3 2 1 2 3 8 2 8];
DG = sparse([1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6],...
[2 3 1 3 4 5 1 2 4 5 2 3 5 6 2 3 4 6 4 5],W);
g = graph(DG);
% Construct all possible ways that we could traverse all nodes, starting at
% node 1 and ending at node 6:
paths = perms(2:5);
paths = [ones(size(paths, 1), 1) paths 6*ones(size(paths, 1), 1)];
% Check if a path is feasible (edges exist between all node pairs), and how
% long it is
dist = NaN(size(paths, 1), 1);
for ii=1:size(paths, 1)
path = paths(ii, :);
edgeID = findedge(g, path(1:end-1), path(2:end));
if all(edgeID ~= 0)
dist(ii) = sum(g.Edges.Weight(edgeID));
end
end
[~, id] = min(dist)
paths(id, :)
p = plot(g, 'EdgeLabel', g.Edges.Weight);
highlight(p, paths(id, :), 'EdgeColor', 'red')
28 comentarios
Jason
el 6 de Mzo. de 2018
Jason
el 6 de Mzo. de 2018
Jason
el 7 de Mzo. de 2018
Steven Lord
el 7 de Mzo. de 2018
Do you have an undirected graph or a directed digraph? If your network is undirected and you try to construct the graph using the adjacency matrix input A, that input must be symmetric or you must specify the TYPE input when constructing your graph.
Steven Lord
el 7 de Mzo. de 2018
If it is a directed graph then you need to use digraph rather than graph. The graph function creates an undirected graph.
As for why it's so complicated, did you read the second link in my answer? The key point from that article: "Both problems [determining whether a graph has a Hamiltonian path or whether it has a Hamiltonian cycle] are NP-complete." The phrase NP-complete is itself a link to another Wikipedia article, whose key paragraph is the following (I added some emphasis on a few key points.)
"Although any given solution to an NP-complete problem can be verified quickly (in polynomial time), there is no known efficient way to locate a solution in the first place; the most notable characteristic of NP-complete problems is that no fast solution to them is known. That is, the time required to solve the problem using any currently known algorithm increases very quickly as the size of the problem grows. As a consequence, determining whether it is possible to solve these problems quickly, called the P versus NP problem, is one of the principal unsolved problems in computer science today."
Note that P versus NP is one of the Millennium Prize problems and is worth US $1 million in prize money if you can solve it.
The question "Is there a Hamiltonian path in my graph?" is simple to ask but not so simple to answer for larger graphs. You want an even harder variant of that, not just looking for a Hamiltonian path but a shortest Hamiltonian path.
For a small graph, use Christine's exhaustive approach. For a larger graph, use Christine's exhaustive approach and wait a while or implement one or more of the algorithms whose papers are linked in the References section on the "Hamiltonian path problem" Wikipedia page.
Jason
el 7 de Mzo. de 2018
Christine Tobler
el 9 de Mzo. de 2018
Sorry I just realized I forgot to check up on this post. The shortest path between two nodes will likely not go through all the nodes - so it's a question of where the priority is.
I'm not quite sure what answer you are looking for. Could you tell me in a small example, what answer you are getting, and what answer you are expecting to get?
Jason
el 9 de Mzo. de 2018
Steven Lord
el 9 de Mzo. de 2018
We understand what you have asked for. Computing that can be extremely difficult and/or time consuming.
Can you tell us why you want what you have asked for, how you would use it if you were able to compute it? There may be a way to accomplish what you want to do with a different approach or technique, one that avoids the NP-complete problem of finding a Hamiltonian path or cycle.
Jason
el 9 de Mzo. de 2018
Jason
el 9 de Mzo. de 2018
Christine Tobler
el 12 de Mzo. de 2018
So you are looking for a variant of the code above, but instead of "start at node 1, visit each of nodes 2-5 once, end at node 6" you are looking for "start at node 1, visit each of nodes 2-5 once, end at node 1"? That can easily be achieved with a small change:
W = [3 1 5 4 1 5 4 3 5 4 2 1 3 1 3 3 5 2 4 1];
DG = sparse([1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5],...
[2 3 4 5 1 3 4 5 1 2 4 5 1 2 3 5 1 2 3 4],W);
g = digraph(DG);
% Construct all possible ways that we could traverse all nodes, starting at
% node 1 and ending at node 6:
paths = perms(2:5);
paths = [ones(size(paths, 1), 1) paths];
% Check if a path is feasible (edges exist between all node pairs), and how
% long it is
dist = NaN(size(paths, 1), 1);
for ii=1:size(paths, 1)
path = paths(ii, :);
edgeID = findedge(g, path(1:end), path([2:end 1]));
if all(edgeID ~= 0)
dist(ii) = sum(g.Edges.Weight(edgeID));
end
end
[~, id] = min(dist)
mypath = paths(id, :)
p = plot(g, 'EdgeLabel', g.Edges.Weight);
highlight(p, mypath([1:end 1]), 'EdgeColor', 'red')
Note this will not work for every possible graph: It's possible that no path that visits all nodes exists (for example if one node has no outgoing / no incoming edges).
Jason
el 12 de Mzo. de 2018
Jason
el 12 de Mzo. de 2018
Steven Lord
el 12 de Mzo. de 2018
id is the index of the minimum distance and the path that achieves that minimum distance, not the minimum distance itself. For the distance itself you'd want dist(id) (or replace the ~ in the min call with a variable in which you want the minimum distance to be stored.)
Let's look at each of the paths and their corresponding distances in tabular form.
pathsAndDistances = table(dist, paths)
Each row of the paths variable in the pathsAndDistances tables contains a 1 followed by a permutation of the vector 2:5. If you had a digraph with 6 or 7 nodes, those rows would each contain a 1 followed by a permutation of the vector 2:6 or 2:7 respectively.
Jason
el 13 de Mzo. de 2018
Steven Lord
el 13 de Mzo. de 2018
The body of the loop isn't very long. Take a look at the documentation for the findedge function. Under what circumstances does it return 0? When it returns something other than 0, what does that return value represent?
Once you know that, under what circumstances would the if statement condition be satisfied?
As for perms, the documentation describes what it does and includes several examples showing what it does.
Jason
el 13 de Mzo. de 2018
Steven Lord
el 13 de Mzo. de 2018
Do you want a path or a cycle? If you want a cycle it doesn't really matter where you start. If you want a path and want to start from a different place, permute the numbers of the other nodes then put your starting node at the start of the matrix of permutations.
Jason
el 13 de Mzo. de 2018
Steven Lord
el 13 de Mzo. de 2018
The output of perms.
Jason
el 14 de Mzo. de 2018
Steven Lord
el 19 de Mzo. de 2018
path(1:end), path([2:end 1])
How many edges does g have that end at node 1 (which is the first column of each row in the paths variable?) You can find this using the predecessors function.
Rather than waiting for us to respond, if your code does something other than what you expect I recommend using the debugging tools to step through the code and make sure it's doing exactly what you think it's doing and what it should be doing.
Jason
el 19 de Mzo. de 2018
Steven Lord
el 19 de Mzo. de 2018
Move the ones call after the paths variable rather than before.
Steven Lord
el 6 de Mzo. de 2018
0 votos
Categorías
Más información sobre Graph and Network Algorithms en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!