python-3.xgraphcyclic-graph

get all possible paths in directed cyclic graph


I've a directed cyclic graph, want to find all possible paths starting from given (or by default root) node without repeating the same path again.

In this graph "direct_cyclic_graph", Let's say "A" is root node.

Here, node "B", "D", and "C" is cyclic.

My code :

def find_all_possible_paths(graph, start, path=[]):
    path = path + [start]
    paths = [path]
   
    if len(graph[start]) == 0:
        return [path]
    for node in graph[start]:
        if node not in path:
            newpaths = find_all_possible_paths(graph, node, path)
            for newpath in newpaths:
                paths.append(newpath)
        else:
            return paths
    return paths

direct_cyclic_graph = nx.DiGraph()
direct_cyclic_graph.add_edge('A','B')
direct_cyclic_graph.add_edge('A','C')
direct_cyclic_graph.add_edge('A','E')
direct_cyclic_graph.add_edge('B','D')
direct_cyclic_graph.add_edge('C','B')
direct_cyclic_graph.add_edge('D','C')
direct_cyclic_graph.add_edge('D','F')

print(find_all_possible_paths(direct_cyclic_graph , 'A'))
**Output** 

[
 ['A'], 
 ['A', 'B'], 
 ['A', 'B', 'D'], 
 ['A', 'B', 'D', 'C'], 
 ['A', 'B', 'D', 'F'], 
 ['A', 'C'], 
 ['A', 'C', 'B'], 
 ['A', 'C', 'B', 'D'], 
 ['A', 'E']
]

**Expected **

I'm just missing one path i.e. ['A', 'C', 'B', 'D', 'F'] apart from that I'm able to get all.

Not sure what am I missing in my code. Pls help.


Solution

  • The problem is in this part:

        else:
            return paths
    

    That breaks the loop, while there might be more neighbors to visit. You should just do nothing in the current iteration, but still have the loop continue. So remove these two lines of code, so you get this:

    import networkx as nx
    
    def find_all_possible_paths(graph, start, path=[]):
        path = path + [start]
        paths = [path]
    
        if len(graph[start]) == 0:
            return [path]
        for node in graph[start]:
            if node not in path:
                newpaths = find_all_possible_paths(graph, node, path)
                for newpath in newpaths:
                    paths.append(newpath)
        return paths
    
    direct_cyclic_graph = nx.DiGraph()
    direct_cyclic_graph.add_edge('A','B')
    direct_cyclic_graph.add_edge('A','C')
    direct_cyclic_graph.add_edge('A','E')
    direct_cyclic_graph.add_edge('B','D')
    direct_cyclic_graph.add_edge('C','B')
    direct_cyclic_graph.add_edge('D','C')
    direct_cyclic_graph.add_edge('D','F')
    
    for path in find_all_possible_paths(direct_cyclic_graph , 'A'):
        print(path)
    

    The output of the above program is:

    ['A']
    ['A', 'B']
    ['A', 'B', 'D']
    ['A', 'B', 'D', 'C']
    ['A', 'B', 'D', 'F']
    ['A', 'C']
    ['A', 'C', 'B']
    ['A', 'C', 'B', 'D']
    ['A', 'C', 'B', 'D', 'F']
    ['A', 'E']
    

    ... including the missing path near the end.

    Other remarks