Search code examples
pythoncomputer-science

How can i avoid using a deep copy for this graph path search


I'm doing a graph search from source to destination. If I add the path object to the results array, it keeps updating when I add the unique path, so I have to deepcopy it. How could I have avoided a deepcopy? Is there a better way to solve this?

Eg. start 'A', end 'X' -> [['A', 'B'], ['A', 'B', 'E']]

graph = {}

graph['A'] = ['B', 'C', 'E']
graph['B'] = ['A', 'X', 'E']
graph['E'] = ['X', 'B', 'Z']

import copy

def find_paths(start, end, graph):
    res = []
    path = []
    v = dict()
    traverse_paths(start, end, graph, v, path, res)
    return res

def traverse_paths(start, end, graph, v, path, res):
    v[start] = True
    if start in graph:
        path += [start]
        node_list = graph[start]
        if end in node_list:
            res += [copy.deepcopy(path)]
        for node in node_list:
            if node in v:
                continue
            traverse_paths(node, end, graph, v, path, res)

start = 'A'
end = 'X'
print(find_paths(start, end, graph))

The above code was also not returning every viable path to X , here is the correct code:

def find_paths(s, end, g):
    res = []
    v = dict()

    def search(s, end, path, res):
        v[s] = True
        path += [s]
        print(path, 'PATH CURRENT')

        if s == end:
            res += [path]

        for l in g[s]:
            if l not in v:
                search(l, end, path[::], res)
        print('DONE', v, s)
        del v[s]
        return res

    return search(s, end, [], res)

start = 'A'
end = 'X'
print(find_paths(start, end, graph))

Solution

  • When I used

    res += [path[::]]
    

    It added a copy of the path, instead of a reference to the path object

    Here is the correct code

    def find_paths(s, end, g):
        res = []
        v = dict()
    
        def search(s, end, path, res):
            v[s] = True
            path += [s]
    
            if s == end:
                res += [path]
    
            for l in g[s]:
                if l not in v:
                    search(l, end, path[::], res)
            del v[s]
            return res
    
        return search(s, end, [], res)
    
    start = 'A'
    end = 'X'
    print(find_paths(start, end, graph))