Solve Travelling Salesman Problem using DP

Claim

In this post, I am using the same notation as in the video below and the wiki page (https://en.wikipedia.org/wiki/Held%E2%80%93Karp_algorithm)

 

Our problem is given a matrix costs in which costs[i][j] is the traveling cost going from node i to node j, we are asked to return the minimum cost for traveling from node 0 and visit every other node exactly once and return back to node 0.

We use g(x, S) to denote the minimum cost  for a travel which starts from node x, visits every node in S exactly once and returns to node 0. The detailed DP process can be illustrated in the following example.

Let’s say we have a 5×5 costs matrix, which means we have 5 node.

In the first round, we calculate:

g(1, ∅) = costs(1,0)   # minimum cost of travel from node 1 and ends at node 0 without visiting any other node
g(2, ∅) = costs(2,0)
g(3, ∅) = costs(3,0)
g(4, ∅) = costs(4,0)

In the second round, we calculate:

# minimum cost of travel from node 1 and ends at node 0 with visiting only one other node
g(1, {2}) = costs(1,2) + g(2, ∅)   
g(1, {3}) = costs(1,3) + g(3, ∅)
g(1, {4}) = costs(1,4) + g(4, ∅)


# minimum cost of travel from node 2 and ends at node 0 with visiting only one other node
...

In the third round, we calculate:

# minimum cost of travel from node 1 and ends at node 0 with visiting two other nodes
g(1, {2,3}) = min(costs(1,2)+g(2,{3}), costs(1,3)+g(3,{2}))  # either you choose to go from 1 to 2 first, or go from 1 to 3 first   
g(1, {3,4}) = min(costs(1,3)+g(3,{4}), costs(1,4)+g(4,{3}))
g(1, {2,4}) = min(costs(1,2)+g(2,{4}), costs(1,4)+g(4,{2}))


# minimum cost of travel from node 2 and ends at node 0 with visiting two other nodes
...

In the fourth round, we calculate:

# minimum cost of travel from node 1 and ends at node 0 with visiting three other nodes
# either you choose to go from 1 to 2 first, or go from 1 to 3 first or go from 1 to 4 first 
g(1, {2,3,4}) = min(costs(1,2)+g(2,{3,4}), costs(1,3)+g(3,{2,4}), costs(1,4)+g(4,{2,3}))

# minimum cost of travel from node 2 and ends at node 0 with visiting three other nodes
...

 

After the four rounds above, we can calculate our ultimate goal, g(0, {1,2,3,4}):

g(0, {1, 2,3,4}) = min(costs(0,1)+g(1,{2,3,4}),
                       costs(0,2)+g(2,{1,3,4}),
                       costs(0,3)+g(3,{1,2,4}),
                       costs(0,4)+g(4,{1,2,3}))

 

Now here it is an implementation in Python:

from itertools import *
class Solution:
    def shortest(self, costs):
        '''
        costs: List[List[n]]
        '''
        def to_str(l):
            return '-'.join([str(ll) for ll in l])

    # nodes excluding the starting node 
    nodes = set([i for i,v in enumerate(costs) if i])
    g = {}
    for x in xrange(1, len(costs)):
        g[x] = {}
        g[x][''] = costs[x][0]   

    for k in xrange(1, len(costs)-1):
        for x in xrange(1, len(costs)):
            for c in combinations(node-set([x]), k):
                g[x][to_str(c)] = min([costs[x][e] + g[e][to_str(c-set([e]))] for e in c])

    return min([costs[0][e] +g[e][to_str(nodes-set([e]))] for e in nodes])

In the code `g` is a dictionary. Its value its another dictionary. For example, if we want to refer to g(1, {2,3,4}), we can access it by `g[1][‘2-3-4’]`.

 

Let’s analyze the time complexity and the space complexity for this DP algorithm. 

  • Space complexity: before calculating g(0, {1,2,3,4}), we need to store:
g(1, {∅}), g(1, {2}), g(1,{3}), g(1,{4}), g(1,{2,3}), g(1, {2,4}), g(1, {3,4}), g(1, {2,3,4})
g(2, {∅}), g(2, {1}), g(2,{3}), g(2,{4}), g(2,{1,2}), g(2, {1,3}), g(2, {3,4}), g(2, {1,3,4})
...

Therefore, for each row here, we need to store g(.) values of number $latex \sum\limits_{k=1}^{n-2} C_{n-1}^k = O(2^n) $ (n is total number of nodes: 0, 1, .., n-1). We have n-1 rows here. So in total space complexity is $latex O(n2^n)$.

  • Time complexity: we know we have $latex O(n2^n)$ g(.) values to store. We get each of these values by taking min function over O(n) possible candidates(See Python code line 20). Therefore, the total time complexity is $latex O(n^2 2^n)$.

 

Leave a comment

Your email address will not be published. Required fields are marked *