def test_3_opt_2(self): route = [0, 3, 2, 1, 4, 5, 6, 7, 8] result = tsp_3_opt(self.graph2, route) new_route_cost = route_cost(self.graph2, result) old_route_cost = route_cost(self.graph2, route) print(new_route_cost) print(old_route_cost) assert new_route_cost < old_route_cost
def test_permutation_algorithm(): graph = np.array([[0, 5, 2, 1, 1, 4], [5, 0, 6, 2, 2, 5], [2, 6, 0, 7, 4, 2], [1, 2, 7, 0, 8, 4], [1, 2, 4, 8, 0, 5], [4, 5, 2, 4, 5, 0]]) route = [0, 1, 2, 3, 4, 5] result = permutations_tsp(graph) print(result) assert route_cost(graph, route) > route_cost(graph, result)
def test_permutation_algorithm_2(): graph = np.array([[0, 4, 3, 4, 5, 1, 2, 3, 4], [4, 0, 1, 4, 3, 4, 6, 2, 1], [3, 1, 0, 1, 4, 3, 2, 1, 9], [4, 4, 1, 0, 4, 6, 1, 2, 3], [5, 3, 4, 4, 0, 1, 2, 5, 3], [1, 4, 3, 6, 1, 0, 2, 5, 3], [2, 6, 2, 1, 2, 2, 0, 3, 5], [3, 2, 1, 2, 5, 5, 3, 0, 9], [4, 1, 9, 3, 3, 3, 5, 0, 0]]) route = [0, 1, 2, 3, 4, 5, 6, 7, 8] result = permutations_tsp(graph) print(route_cost(graph, result)) assert route_cost(graph, route) > route_cost(graph, result)
def test_2_opt_algorithm(self): graph = np.array([[0, 5, 2, 1, 1, 4], [5, 0, 6, 2, 2, 5], [2, 6, 0, 7, 4, 2], [1, 2, 7, 0, 8, 4], [1, 2, 4, 8, 0, 5], [4, 5, 2, 4, 5, 0]]) route = [0, 1, 2, 3, 4, 5] result = tsp_2_opt(graph, route) new_route_cost = route_cost(graph, result) old_route_cost = route_cost(graph, route) print(new_route_cost) print(old_route_cost) print(result) assert old_route_cost > new_route_cost
def branch_and_bound_tsp_bfs(graph: ndarray): """ Branch and bound by BFS, lower bound is spanning tree""" number_of_nodes = len(graph) bnb_tree = Tree(number_of_nodes) # top level node top_lower_bound = 0 for node in graph: top_lower_bound += np.sum(np.sort(node[node.nonzero()])[:2]) # top node top_node = Node(top_lower_bound / 2, [0], graph) bnb_tree.add_leaf(top_node) while not bnb_tree.optimized(): most_promising_leaf = bnb_tree.get_leaf_with_lowest_bound() bnb_tree.remove_leaf_from_list(most_promising_leaf) unvisited_nodes = list(bnb_tree.node_indexes - set(most_promising_leaf.visited_nodes)) for vertex in unvisited_nodes: lower_bound = calculate_two_neighbor_bound(graph, most_promising_leaf, vertex) new_leaf = Node(lower_bound, most_promising_leaf.visited_nodes + [vertex], most_promising_leaf) bnb_tree.add_leaf(new_leaf) if len(new_leaf.visited_nodes) is number_of_nodes: new_leaf.visited_nodes.append(0) bnb_tree.set_solution(route_cost(graph, new_leaf.visited_nodes)) print(*new_leaf.visited_nodes, sep=", ") print('Solution found %s' % (str(route_cost(graph, new_leaf.visited_nodes)))) bnb_tree.remove_leaf_from_list(new_leaf) print('Best solution found: %s' % str(bnb_tree.best_solution_value))
def simulated_annealing(graph, path=None, temperature=1, n_of_iter=1000, alpha=0.95): if path is None: path = christofides_tsp(graph) changed = True while changed: temp_solution = [node for node in path] for iter in range(n_of_iter): new_solution = _get_next_solution(path) new_route_cost = route_cost(graph, new_solution) current_route_cost = route_cost(graph, path) if new_route_cost < current_route_cost: path = new_solution else: if np.exp( (current_route_cost - new_route_cost) / (temperature * Constants.BOLTZMANN)) > random.random(): path = new_solution temperature = _decrease_temperature(temperature, alpha) if temp_solution == path: changed = False # just to start with the same node -> we will need to cycle the results. cycled = cycle(path) skipped = dropwhile(lambda x: x != 0, cycled) sliced = islice(skipped, None, len(path)) path = list(sliced) return path
def tsp_2_opt(graph, route): """ Approximate the optimal path of travelling salesman according to 2-opt algorithm Args: graph: 2d numpy array as graph route: list of nodes Returns: optimal path according to 2-opt algorithm Examples: >>> import numpy as np >>> graph = np.array([[ 0, 300, 250, 190, 230], >>> [300, 0, 230, 330, 150], >>> [250, 230, 0, 240, 120], >>> [190, 330, 240, 0, 220], >>> [230, 150, 120, 220, 0]]) >>> tsp_2_opt(graph) """ improved = True best_found_route = route best_found_route_cost = route_cost(graph, best_found_route) while improved: improved = False for i in range(1, len(best_found_route) - 1): for k in range(i + 1, len(best_found_route) - 1): new_route = _swap_2opt(best_found_route, i, k) new_route_cost = route_cost(graph, new_route) if new_route_cost < best_found_route_cost: best_found_route_cost = new_route_cost best_found_route = new_route improved = True break if improved: break return best_found_route
def permutations_tsp(graph): """ Creates all permutations from the added graph check all the combinations and the route costs and then returns the best solution. BEWARE: this method is computationally expensive, therefore it shouldn't be run on over 12 nodes Args: graph: graph Returns: list of nodes [] """ route = range(0, len(graph)) # generate all permutations all_routes = [list(i) for i in permutations(route)] # calculate all costs cost_all_routes = [route_cost(graph, i) for i in all_routes] # find the lowest cost best_route = all_routes[cost_all_routes.index(min(cost_all_routes))] return best_route