0

Good Morning!

I'm working on an algorithm to find paths between two given nodes (start and end), a graph (represented as it's adjacency list) and a list containing the current visited nodes. This is the code I've done in Python:

def find_path(graph, start, end, visited):
    path = []
    
    if graph[start][end] == 1:
        return [start,end]
    
    if start not in visited:
        visited.append(start)
        path.insert(0, start)

    for neighbour in range(0, len(graph)):
        if graph[start][neighbour] == 1 and neighbour not in visited:
            path.extend(find_path(graph, neighbour, end, visited))
            
    return path

I may have something wrong because given this:

visited = []
    g1 = [[0, 1, 1, 0, 0],
          [1, 0, 1, 1, 0],
          [1, 1, 0, 0, 1],
          [0, 1, 0, 0, 1],
          [0, 0, 1, 1, 0]]
    
    print(find_path(g1, 0, 4, visited))
    
    assert find_path(g1, 0, 4, visited) in [[0, 2, 4], [0, 2, 1, 3, 4], [0, 1, 2, 4], [0, 1, 3, 4]]

This is the result I get: [0, 1, 2, 4, 3, 4, 2, 4] and of course an assertion error.

Why does it add each subpath?

Julen
  • 11
  • 6
  • Should your dfs only return the first found path or all possible paths? – qouify Sep 26 '21 at 08:37
  • @qouify it's a college work and It isn't very clear but I think a list of all possible paths. If there's not any paths between those nodes returns an empty list – Julen Sep 26 '21 at 08:39
  • I would say that the main problem is that you never remove elements from `path`. Suppose that after your recursive call in your for loop you have not found a path to the destination, then path will have been extended with a useless list of edges. – qouify Sep 26 '21 at 08:42
  • and so how do I decide which one to remove? I mean, if I have to return a list of paths, how do I decide to remove one or another? – Julen Sep 26 '21 at 08:45

1 Answers1

0

Here is a corrected version that returns the first path found from start to end:

def find_path(graph, start, end, visited):
    path = []
    
    if graph[start][end] == 1:
        return [start, end]
    
    if start not in visited:
        visited.append(start)
        path.insert(0, start)

    for neighbour in range(0, len(graph)):
        if graph[start][neighbour] == 1 and neighbour not in visited:
            found_path = find_path(graph, neighbour, end, visited)
            if found_path is not None:  # a path from neighbour to
                                        # end has been found
                path.extend(found_path)
                return path

    return None  #  no path found

visited = []
g1 = [[0, 1, 1, 0, 0],
      [1, 0, 1, 1, 0],
      [1, 1, 0, 0, 1],
      [0, 1, 0, 0, 1],
      [0, 0, 1, 1, 0]]
    
print(find_path(g1, 0, 4, visited))

visited = []
assert find_path(g1, 0, 4, visited) in [[0, 2, 4], [0, 2, 1, 3, 4], [0, 1, 2, 4], [0, 1, 3, 4]]
qouify
  • 3,698
  • 2
  • 15
  • 26