I am working on python 3 and networkx 2.0. For enumerating all simple paths between 2 nodes, I am using nx.all_simple_paths.
My graph is an undirected multigraph, nx.MultiGraph. Unfortunately, nx.all_simple_paths enumerates all the paths without including the edge key value. So it is not possible to distinguish easily between paths containing different parallel edges.
edge = [(1,2,1), (1,2,2), (1,2,3), (2,3,1), (2,3,2)]
g = nx.MultiGraph()
g.add_edges_from(edge)
for path in map(nx.utils.pairwise, nx.all_simple_paths(g,1,3)):
print(list(path))
Output for the above snippet is: (u, v)
[(1, 2), (2, 3)]
[(1, 2), (2, 3)]
[(1, 2), (2, 3)]
[(1, 2), (2, 3)]
[(1, 2), (2, 3)]
[(1, 2), (2, 3)]
But the desired output is: (u, v, key)
[(1, 2, 1), (2, 3, 1)]
[(1, 2, 1), (2, 3, 2)]
[(1, 2, 2), (2, 3, 1)]
[(1, 2, 2), (2, 3, 2)]
[(1, 2, 3), (2, 3, 1)]
[(1, 2, 3), (2, 3, 2)]
The reason why I would like the key value is that it would make my subsequent computations more efficient for mapping the corresponding edges.
I also tried to add key values while searching as follows:
def all_simple_paths(G, source=1, target=3, cutoff=(len(g) - 1)):
if cutoff < 1:
return
visited = []
for src, _, key in G.edges(source, keys=True):
visited.append((src,key))
stack = [((v, key) for u, v, key in G.edges(source, keys=True))]
# print(list(stack))
while stack:
children = stack[-1]
# print('children: ')
child = next(children, None)
# print(child)
if child is None:
# print('pop happened!')
stack.pop()
visited.pop()
elif len(visited) < cutoff:
# print('visited <cutoff: ')
# print(visited)
# print(list(child)[0])
if child[0] == target:
# print('child is target')
print(visited + [target])
yield visited + [target]
elif child not in visited:
# print("child not in visited")
visited.append(child)
# print(visited)
stack.append(((v, k) for u, v, k in G.edges(child, keys=True)))
else: # len(visited) == cutoff:
# print('at cutoff')
count = ([child] + list(children)).count(target)
# print('count: ')
# print(count)
count = 1 # Dynamic count is not working
for i in range(count):
# print(visited + [target])
yield visited + [target]
stack.pop()
visited.pop()
Output of the modified program (between nodes 1 and 3) is:
[(1, 1), (2, 1), 3]
[(1, 1), (2, 2), 3]
[(1, 1), (2, 3), 3]
[(1, 2), (2, 1), 3]
[(1, 2), (2, 2), 3]
[(1, 2), (2, 3), 3]
[(1, 3), (2, 1), 3]
[(1, 3), (2, 2), 3]
[(1, 3), (2, 3), 3]
The output is still not perfect. The key of edge 3 (refer the above output) is still missing and the count attribute in len(visited) == cutoff" is not dynamic (by default it returns 0)
To get the desired output simply use nx.all_simple_edge_paths instead of nx.all_simple_paths
import networkx as nx
edge = [(1,2,1), (1,2,2), (1,2,3), (2,3,1), (2,3,2)]
g = nx.MultiGraph()
g.add_edges_from(edge)
for path in nx.all_simple_edge_paths(g,1,3):
print(path)
Output:
[(1, 2, 1), (2, 3, 1)]
[(1, 2, 1), (2, 3, 2)]
[(1, 2, 2), (2, 3, 1)]
[(1, 2, 2), (2, 3, 2)]
[(1, 2, 3), (2, 3, 1)]
[(1, 2, 3), (2, 3, 2)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With