diff --git a/run.py b/run.py index 96683ee..4d62172 100644 --- a/run.py +++ b/run.py @@ -4,7 +4,7 @@ from src.TSP_solver import SolverTSP, available_improvers, available_solvers import numpy as np -def add(solver, improve, index, results, name, verbose, show_plots): +def use_solver_to_compute_solution(solver, improve, index, results, name, verbose, show_plots): solver.bind(improve) solver.compute_solution(return_value=False, verbose=verbose) @@ -39,19 +39,20 @@ def run(show_plots=False, verbose=False): for solver_name in solvers_names: for improve in improvers_names: solver = SolverTSP(solver_name, prob_instance) - add(solver, improve, index, results, problem_path, verbose, show_plots) + use_solver_to_compute_solution(solver, improve, index, results, problem_path, verbose, show_plots) for improve2 in [j for j in improvers_names if j not in [improve]]: - add(solver, improve2, index, results, problem_path, verbose, show_plots) + use_solver_to_compute_solution(solver, improve2, index, results, problem_path, verbose, show_plots) for improve3 in [j for j in improvers_names if j not in [improve, improve2]]: - add(solver, improve3, index, results, problem_path, verbose, show_plots) + use_solver_to_compute_solution(solver, improve3, index, results, problem_path, verbose, + show_plots) solver.pop() solver.pop() if prob_instance.exist_opt and show_plots: + solver.algorithm_name="optimal" solver.solution = np.concatenate([prob_instance.optimal_tour, [prob_instance.optimal_tour[0]]]) - solver.method = "optimal" solver.plot_solution() index = pd.MultiIndex.from_tuples(index, names=['problem', 'method']) diff --git a/src/TSP_solver.py b/src/TSP_solver.py index 2b02e18..2562102 100644 --- a/src/TSP_solver.py +++ b/src/TSP_solver.py @@ -31,6 +31,7 @@ class SolverTSP: self.name_method = "initialized with " + algorithm_name self.solved = False self.problem_instance = problem_instance + self.solution = None def bind(self, local_or_meta): assert local_or_meta in available_improvers, f"the {local_or_meta} method is not available currently." @@ -79,11 +80,9 @@ class SolverTSP: def check_if_solution_is_valid(self, solution): # rights_values = np.sum( # [self.check_validation(i, solution[:-1]) for i in np.arange(self.problem_instance.nPoints)]) - rights_values = np.sum([1 if np.sum(solution[:-1] == i) == 1 else 0 for i in np.arange(self.problem_instance.nPoints)]) + rights_values = np.sum( + [1 if np.sum(solution[:-1] == i) == 1 else 0 for i in np.arange(self.problem_instance.nPoints)]) return rights_values == self.problem_instance.nPoints - # return True - # else: - # return False # def check_validation(self, node, solution): # if np.sum(solution == node) == 1: diff --git a/src/constructive_algorithms.py b/src/constructive_algorithms.py index 6697ad9..df0738a 100644 --- a/src/constructive_algorithms.py +++ b/src/constructive_algorithms.py @@ -25,16 +25,16 @@ def nearest_neighbor(instance_, starting_node=0): def best_nearest_neighbor(instance_): - solutions, lens = [], [] + solutions, lengths = [], [] for start in range(instance_.nPoints): new_solution = nearest_neighbor(instance_, starting_node=start) solutions.append(new_solution) - lens.append(compute_length(new_solution, instance_.dist_matrix)) + lengths.append(compute_length(new_solution, instance_.dist_matrix)) - if lens is []: - return None # Todo understand this return + if lengths is []: + return None else: - solution = solutions[np.argmin(lens)] + solution = solutions[np.argmin(lengths)] return solution @@ -52,21 +52,21 @@ def multi_fragment_check_if_not_close(edge_to_append, sol): return True partial_tour = [from_city] end = False - iterazione = 0 + iteration = 0 while not end: if len(sol[str(from_city)]) == 1: if from_city == n1: return_value = False end = True - elif iterazione > 1: - # print(f"iterazione {iterazione}, elementi dentro partial {len(partial_tour)}", + elif iteration > 1: + # print(f"iterazione {iteration}, elementi dentro partial {len(partial_tour)}", # f"from city {from_city}") return_value = True end = True else: from_city = sol[str(from_city)][0] partial_tour.append(from_city) - iterazione += 1 + iteration += 1 else: # print(from_city, partial_tour, sol[str(from_city)]) for node_connected in sol[str(from_city)]: @@ -75,7 +75,7 @@ def multi_fragment_check_if_not_close(edge_to_append, sol): from_city = node_connected partial_tour.append(node_connected) # print(node_connected, sol[str(from_city)]) - iterazione += 1 + iteration += 1 return return_value @@ -85,17 +85,17 @@ def multi_fragment_create_solution(start_sol, sol, n): n1, n2 = start_sol from_city = n2 sol_list = [n1, n2] - iterazione = 0 + iteration = 0 while not end: for node_connected in sol[str(from_city)]: - iterazione += 1 + iteration += 1 if node_connected not in sol_list: from_city = node_connected sol_list.append(node_connected) # print(f"prossimo {node_connected}", # f"possibili {sol[str(from_city)]}", # f"ultim tour {sol_list[-5:]}") - if iterazione > 300: + if iteration > 300: if len(sol_list) == n: end = True sol_list.append(n1) diff --git a/src/simulated_annealing.py b/src/simulated_annealing.py index 57dfaf9..6751fcd 100644 --- a/src/simulated_annealing.py +++ b/src/simulated_annealing.py @@ -14,7 +14,7 @@ def sa(solution, instance, constant_temperature=0.95, iterations_for_each_temp=1 # main loop while temperature > 0.001: for it in range(iterations_for_each_temp): - next_sol, delta_E = random_sol_from_neig(current_sol, instance) + next_sol, delta_E = random_sol_from_neigh(current_sol, instance) if delta_E < 0: current_sol = next_sol current_len += delta_E @@ -32,13 +32,13 @@ def sa(solution, instance, constant_temperature=0.95, iterations_for_each_temp=1 return best_sol.tolist() -def random_sol_from_neig(solution, instance): +def random_sol_from_neigh(solution, instance): i, j = np.random.choice(np.arange(1, len(solution) - 1), 2, replace=False) i, j = np.sort([i, j]) - return swap2opt(solution, i, j), gain(i, j, solution, instance.dist_matrix) + return sa_swap2opt(solution, i, j), gain(i, j, solution, instance.dist_matrix) -def swap2opt(tsp_sequence, i, j): +def sa_swap2opt(tsp_sequence, i, j): new_tsp_sequence = np.copy(tsp_sequence) new_tsp_sequence[i:j + 1] = np.flip(tsp_sequence[i:j + 1], axis=0) # flip or swap ? return new_tsp_sequence diff --git a/src/two_dot_five_opt.py b/src/two_dot_five_opt.py index 6092a54..0caf6d0 100644 --- a/src/two_dot_five_opt.py +++ b/src/two_dot_five_opt.py @@ -11,8 +11,8 @@ def step2dot5opt(solution, matrix_dist, distance): for i in range(1, seq_length - 1): for j in range(i + 1, seq_length): # 2opt swap - twoOpt_tsp_sequence = swap2opt(tsp_sequence, i, j) - twoOpt_len = distance + gain(i, j, tsp_sequence, matrix_dist) + two_opt_tsp_sequence = swap2opt(tsp_sequence, i, j) + two_opt_len = distance + gain(i, j, tsp_sequence, matrix_dist) # node shift 1 first_shift_tsp_sequence = shift1(tsp_sequence, i, j) first_shift_len = distance + shift_gain1(i, j, tsp_sequence, matrix_dist) @@ -20,9 +20,9 @@ def step2dot5opt(solution, matrix_dist, distance): second_shift_tsp_sequence = shift2(tsp_sequence, i, j) second_shift_len = distance + shift_gain2(i, j, tsp_sequence, matrix_dist) - best_len, best_method = min([twoOpt_len, first_shift_len, second_shift_len]), np.argmin( - [twoOpt_len, first_shift_len, second_shift_len]) - sequences = [twoOpt_tsp_sequence, first_shift_tsp_sequence, second_shift_tsp_sequence] + best_len, best_method = min([two_opt_len, first_shift_len, second_shift_len]), np.argmin( + [two_opt_len, first_shift_len, second_shift_len]) + sequences = [two_opt_tsp_sequence, first_shift_tsp_sequence, second_shift_tsp_sequence] if best_len < distance: uncrosses += 1 tsp_sequence = sequences[best_method]