Assignment 11.1: Traveling salesman problem and branch-and-bound (4 points)

In traveling salesman problem, the task is to find the shortest possible route that visits each city exactly once and returns to the origin city. The problem is known to be NP-hard. See Sec. 11.4.4 of the background material for the introduction to the problem. 

No efficient (polynomial time) algorithm is known for the problem. With a small amount of cities we can test all the possible permutations using backtracking and select the shortest route. However, the computation time quickly becomes unbearable when the amount of cities increases. Using branch-and-bound we can reduce the computation time remarkably by reducing the number of solutions to be investigated. This approach still always produce the optimal solution, but can be used with a larger number of cities than the simple backtracking. 

Create a Python function salesman(city_map: list) that solves the traveling salesman problem using branch-and-bound algorithm. The function takes a distance matrix (city_map[i][j] tells the distance between \(i\)th and \(j\)th city) of the cities as an input value and returns a order of the cities traversed in a list. Cities are labeled as integers starting from zero and the traverse always starts from the first city (\(0\)th city).

Target:
Note, that testing all permutations with simple backtracking is too slow. In order the achieve either of the targets, the function needs to use branch-and-bound. To obtain 4 points, a more accurate estimate for the lower bound is needed.

A code template with an example program:

def salesman(city_map):
    # TODO
    

if __name__ == "__main__":
    
    cost = 0

    city_map = [
    #     0   1   2   3   4
        [ 0, 12, 19, 16, 29],   # 0
        [12,  0, 27, 25,  5],   # 1
        [19, 27,  0,  8,  4],   # 2
        [16, 25,  8,  0, 14],   # 3
        [29,  5,  4, 14,  0]    # 4
        ]

    path = salesman(city_map)
    for i in range(len(city_map)):
        cost += city_map[path[i]][path[i+1]]
    
    print(path)     # [0, 1, 4, 2, 3, 0]
    print(cost)     # 45

Submit your solution in CodeGrade as salesman.py.


Assignment 11.2: The bin packing problem and approximation algorithms (4 points)

When the size of the problem increases even the more sophisticated exact algorithms (e.g. branch-and-bound and dynamic programming) become insufficient. In such cases, we typically need to settle for approximation algorithms. Such algorithms do not (always) provide the optimal solutions, but usually provide a good solution fast.

Bin packing problem: given a set of \(n\) items with sizes \([s_1, s_2, s_3, … , s_n]\), find a way to pack the items to bins with size \(S\) so that the total amount of bins is minimized.

Design and implement an approximation algorithm for the bin packing problem. The algorithm must be able to find a solution for very large set of items. Therefore, brute-force approach or other algorithms that always find the optimal solution are not suitable. You will get points based on how close the solutions your algorithm produces are to the optimal solutions. 

Create a function binpack(items: list, S: int) in Python. The function takes list of items and a maximum bin size \(S\) as an input value and returns a list of all bins. Each bin is a list of items.

Target: 
Note that to get the points, you do not need to find a solution that has a theoretical worst case of 1% larger than the optimum. It is enough that you obtain good enough solution for the cases that are used in CodeGrade. Even quite simple solutions produce almost always much better solution than the theoretical worst case.

A code template with an example program:

def binpack(items, S):
    # TODO
    
 
if __name__ == "__main__":

    items = [9, 3, 3, 6, 10, 4, 6, 8, 6, 3]
    B = 10

    bins = binpack(items, B)

    for i in range(len(bins)):
        print(f"bin {i+1}: {bins[i]}")

# A possible output:
#   bin 1: [9]
#   bin 2: [3, 3, 4]
#   bin 3: [6, 3]
#   bin 4: [10]
#   bin 5: [6]
#   bin 6: [8]
#   bin 7: [6]

Submit your solution in CodeGrade as binpack.py.