dedpo dedpo - 7 months ago 74
Python Question

shortest path tsp algorithm

Now below is a dictonary, I am trying find the shortest path.we have to go to all 5 houses based on shortest time. Each key is a house, each list of values is the time in seconds. For example, the first house has a time of 0 because it's obvious, now from 1st house to second house has 74 seconds... and so on. Each index is a time represenation to the next house.

now second row, with 2 as key. from second house to first house it's 74 seconds, and now from 2nd house to third house it's 4069 seconds as show below.

I am trying to find the best algo for this i am confused what should i use? combinations? permutations?

The goal is to find the shortest path FROM house to house with represetation below and SUM of all time traveld in the shortest path you find

list = 0, 74 , 2213, 816, 1172 ,


The shortest path.

1 -> 2 -> 5 -> 4 -> 3 -> 1


WE HAVE to return to first house again thats why 1 is shown again

numbers 1 through 5, represents houses
list


  1. go through each key,value find the minimum and index of the min. Add the time to a time_list

  2. access the next home(keys) with the index found in previous

  3. match the index of min to the next home, in the home ignore zero and
    the times already encounters in previous home times


Answer

You could try to reduce the amount of paths to be checked by tracking the current house and all the houses visited so far. Let's say you have paths [1, 2, 3, 4] and [1, 3, 2, 4] you can check which one is shorter and only continue with it. Here's a example with the data that you provided, it's storing the distances in 2D array instead of dict but the principle is the same:

dist = [
    [0, 74, 4109, 3047, 2266], 
    [74, 0, 4069, 2999, 2213],
    [4109, 4069, 0, 1172, 1972], 
    [3047, 2999, 1172, 0, 816], 
    [2266, 2213, 1972, 816, 0]
]

# Helper function to calculate path length
def path_len(path):
    return sum(dist[i][j] for i, j in zip(path, path[1:]))

# Set of all nodes to visit
to_visit = set(xrange(len(dist)))

# Current state {(node, visited_nodes): shortest_path}
state = {(i, frozenset([0, i])): [0, i] for i in xrange(1, len(dist[0]))}

for _ in xrange(len(dist) - 2):
    next_state = {}
    for position, path in state.iteritems():
        current_node, visited = position

        # Check all nodes that haven't been visited so far
        for node in to_visit - visited:
            new_path = path + [node]
            new_pos = (node, frozenset(new_path))

            # Update if (current node, visited) is not in next state or we found shorter path
            if new_pos not in next_state or path_len(new_path) < path_len(next_state[new_pos]):
                next_state[new_pos] = new_path

    state = next_state

# Find the shortest path from possible candidates
shortest = min((path + [0] for path in state.itervalues()), key=path_len)
print 'path: {0}, length: {1}'.format(shortest, path_len(shortest))

It will output one of the shortest paths and the total distance:

path: [0, 2, 3, 4, 1, 0], length: 8384

Note that with data you provided there are two possible solutions which have equal length: [0, 2, 3, 4, 1, 0] and [0, 1, 4, 3, 2, 0].

Comments