Reputation: 65
I am attempting to implement an "all paths" algorithm described in this question's top answer using Python.
So far, I have defined the function as such:
def AllPaths(start, end, edges):
print(start)
if (start == end):
return
for i in range(0, len(edges)):
if edges[i][1] == start:
AllPaths(edges[i][0], end, edges)
I have included print(start)
to try give myself an idea of the function's behaviour.
For example, if the initial function call is as such:
edges = [ (1, 2), (1, 3), (2, 3), (3, 4) ]
AllPaths(edges[len(edges) - 1][1], edges[0][0], edges)
With the starting node being 4 and the ending node being 1, the output of the function is:
4
3
1
2
1
Somewhere in that output, it is telling me that all paths between node 4 and node 1 consists of:
[ (4, 3), (3, 1) ]
[ (4, 3), (3, 2), (2, 1) ]
But how do I form these collections during execution and, if I wanted to keep track of how many distinct paths there are, how would this be counted during execution?
Upvotes: 0
Views: 40
Reputation: 11331
If you don't mind that I won't follow the backward traversal route, which I find rather odd, then here's a suggestion on how to modify your function to see what's going on:
def all_paths(start, end, edges):
if start == end:
return [[end]]
paths = []
for edge in edges:
if edge[0] == start:
paths += [[start] + path
for path in all_paths(edge[1], end, edges)]
return paths
Output for edges = [(1, 2), (1, 3), (2, 3), (3, 4)]
and start = 1; end = 4
:
[[1, 2, 3, 4],
[1, 3, 4]]
If you want a direct edges-result then I'd suggest:
def all_paths(start, end, edges):
paths = []
for edge in edges:
if edge[0] == start:
if edge[1] == end:
return [[edge]]
else:
paths += [[edge] + path
for path in all_paths(edge[1], end, edges)]
return paths
Output for the same input:
[[(1, 2), (2, 3), (3, 4)],
[(1, 3), (3, 4)]]
But a warning: If you have loops in the graph, e.g. edges = [(1, 2), (1, 3), (3, 1), (2, 3), (3, 4)]
, then these algorithms will crash (recursion won't stop). In these cases something like
def all_paths(start, end, edges):
edges = set(edges)
paths = []
for edge in edges:
if edge[0] == start:
if edge[1] == end:
paths += [[start, end]]
else:
new_edges = edges.difference({edge})
paths += [[start] + path
for path in all_paths(edge[1], end, new_edges)]
return paths
which removes visited edges is better. Result for start = 1; end = 4
:
[[1, 2, 3, 1, 3, 4],
[1, 2, 3, 4],
[1, 3, 1, 2, 3, 4],
[1, 3, 4]]
I hope that this is at least a little bit what you were looking for.
Upvotes: 1