Gaming.ingrs
Gaming.ingrs

Reputation: 281

Find all paths in DAG from starting node

I am trying to find all paths in DAG from selected node.

So I am randomly generating list of tuples that looks like:

glavnaLista = [(6, 7), (6, 15), (15, 16), (16, 21), (15, 9), (9, 13), (13, 4), (4, 1), (1, 5)]

From this list we can see that node "6" is starting point of graph

Now I am creating graph:

G = nx.DiGraph() 
    G.add_edges_from(glavnaLista)

So it looks like this picture

Now I am trying to find all paths (completed) from starting node with code:

def find_all_paths(graph, start, path=[]):

    path = path + [start]
    if start not in graph:
        return [path]
    paths = [path]
    for node in graph[start]:
        if node not in path:
            newpaths = find_all_paths(graph, node, path)
            for newpath in newpaths:
                print (newpath)
                paths.append(newpath)        
    return paths

Result is list of all paths:

[[6], [6, 7], [6, 15], [6, 15, 16], [6, 15, 16, 21], [6, 15, 9], [6, 15, 9, 13], [6, 15, 9, 13, 4], [6, 15, 9, 13, 4, 1], [6, 15, 9, 13, 4, 1, 5]]

But my problem is that I don't need paths that are not full (not going to the ending node), my list should have only full paths:

[6, 7]
[6, 15, 9, 13, 4, 1, 5]
[6, 15, 16, 21]

My idea is to check if the node has both neighbours, and if it doesn't than add path to list but I am not sure how to implement this as I am fairly new to python.

Upvotes: 1

Views: 2853

Answers (2)

Shahrokh Ghaderi
Shahrokh Ghaderi

Reputation: 11

You can write an easy recursive function which utilize DFS + backtracking to do the job(if it's a DAG):

def find_all_paths(graph, start):
    if not graph[u]:
        return [[u]]
    paths = []
    for v in graph[u]:
        for v_path in find_all_paths(graph, v):
            paths.append([u] + v_path)
    return paths

Upvotes: 1

Yonlif
Yonlif

Reputation: 1790

what you are trying to create is actually the tree created from BFS or DFS traversal over a DAG. You can do this by changing your code a bit.

First of all notice that you have some unnecessary code parts:

def find_all_paths(graph, start, path=[]):
    path = path + [start]
    paths = [path]
    for node in graph[start]:
        newpaths = find_all_paths(graph, node, path)
        for newpath in newpaths:
            print (newpath)
            paths.append(newpath)        
    return paths

Since we assume this is a DAG we can get rid of some conditions...

Now we want to generate the paths of a DFS traversal. The print here will print a path after each iteration but we would like to print the path after we reached an end.
So we will add a simple if statement to check if this is the end of the path and if it is we will print the path:

def find_all_paths(graph, start, path=[]):
    path = path + [start]
    paths = [path]
    if len(graph[start]) == 0:  # No neighbors
        print(path)
    for node in graph[start]:
        newpaths = find_all_paths(graph, node, path)
        for newpath in newpaths:
            paths.append(newpath)
    return paths

Result:

[6, 7]
[6, 15, 16, 21]
[6, 15, 9, 13, 4, 1, 5]

Upvotes: 3

Related Questions