code reworking WIP

This commit is contained in:
Dario Mantegazza 2020-09-28 09:30:21 +02:00
parent 11f6a75f74
commit a60ce57e19
3 changed files with 77 additions and 81 deletions

51
run.py
View File

@ -1,57 +1,56 @@
import pandas as pd
from src.io_tsp import Instance
from src.TSP_solver import SolverTSP
from src.io_tsp import ProblemInstance
from src.TSP_solver import SolverTSP, available_improvers, available_solvers
import numpy as np
def add(solver, instance, improve, index, results, name, verbose, show_plots):
def add(solver, improve, index, results, name, verbose, show_plots):
solver.bind(improve)
solver(instance, return_value=False, verbose=verbose)
solver.compute_solution(return_value=False, verbose=verbose)
if verbose:
print(f"the total length for the solution found is {solver.found_length}",
f"while the optimal length is {instance.best_sol}",
f"while the optimal length is {solver.problem_instance.best_sol}",
f"the gap is {solver.gap}%",
f"the solution is found in {solver.time_to_solve} seconds", sep="\n")
f"the solution is found in {solver.duration} seconds", sep="\n")
index.append((name, solver.name_method))
results.append([solver.found_length, instance.best_sol, solver.gap, solver.time_to_solve])
results.append([solver.found_length, solver.problem_instance.best_sol, solver.gap, solver.duration])
if show_plots:
solver.plot_solution()
def run(show_plots=False, verbose=False):
# names = [name_ for name_ in os.listdir("./problems") if "tsp" in name_]
names = ["eil76.tsp"]
initializers = SolverTSP.available_initializers.keys()
improvements = SolverTSP.available_improvements.keys()
# problems = glob.glob('./problems/*.tsp')
problems = ["./problems/eil76.tsp"]
solvers_names = available_solvers.keys()
improvers_names = available_improvers.keys()
results = []
index = []
for name in names:
filename = f"problems/{name}"
instance = Instance(filename)
for problem_path in problems:
prob_instance = ProblemInstance(problem_path)
if verbose:
print("\n\n#############################")
instance.print_info()
prob_instance.print_info()
if show_plots:
instance.plot_data()
prob_instance.plot_data()
for init in initializers:
for improve in improvements:
solver = SolverTSP(init)
add(solver, instance, improve, index, results, name, verbose, show_plots)
for improve2 in [j for j in improvements if j not in [improve]]:
add(solver, instance, improve2, index, results, name, verbose, show_plots)
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)
for improve2 in [j for j in improvers_names if j not in [improve]]:
add(solver, improve2, index, results, problem_path, verbose, show_plots)
for improve3 in [j for j in improvements if j not in [improve, improve2]]:
add(solver, instance, improve3, index, results, name, 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)
solver.pop()
solver.pop()
if instance.exist_opt and show_plots:
solver.solution = np.concatenate([instance.optimal_tour, [instance.optimal_tour[0]]])
if prob_instance.exist_opt and show_plots:
solver.solution = np.concatenate([prob_instance.optimal_tour, [prob_instance.optimal_tour[0]]])
solver.method = "optimal"
solver.plot_solution()

View File

@ -8,99 +8,95 @@ from src.two_dot_five_opt import loop2dot5opt
from src.simulated_annealing import sa
from src.constructive_algorithms import random_method, nearest_neighbor, best_nearest_neighbor, multi_fragment_mf
available_solvers = {"random": random_method,
"nearest_neighbors": nearest_neighbor,
"best_nn": best_nearest_neighbor,
"multi_fragment": multi_fragment_mf
}
available_improvers = {"2-opt": loop2opt,
"2.5-opt": loop2dot5opt,
"simulated_annealing": sa}
class SolverTSP:
solution: ndarray
found_length: float
available_initializers = {"random": random_method,
"nearest_neighbors": nearest_neighbor,
"best_nn": best_nearest_neighbor,
"multi_fragment": multi_fragment_mf
}
available_improvements = {"2-opt": loop2opt,
"2.5-opt": loop2dot5opt,
"simulated_annealing": sa}
# ,
# "simulated_annealing": Simulated_Annealing,
# "iterated_local_search": Iterated_Local_Search}
def __init__(self, initializer):
# self.available_methods = {"random": self.random_method, "nearest_neighbors": self.nn,
# "best_nn": self.best_nn, "multi_fragment": self.mf}
self.initializer = initializer
self.methods = [initializer]
self.name_method = "initialized with " + initializer
def __init__(self, algorithm_name, problem_instance):
assert algorithm_name in available_solvers, f"the {algorithm_name} initializer is not available currently."
self.duration = np.inf
self.algorithm_name = algorithm_name
self.algorithms = [algorithm_name]
self.name_method = "initialized with " + algorithm_name
self.solved = False
assert initializer in self.available_initializers, f"the {initializer} initializer is not available currently."
self.problem_instance = problem_instance
def bind(self, local_or_meta):
assert local_or_meta in self.available_improvements, f"the {local_or_meta} method is not available currently."
self.methods.append(local_or_meta)
assert local_or_meta in available_improvers, f"the {local_or_meta} method is not available currently."
self.algorithms.append(local_or_meta)
self.name_method += ", improved with " + local_or_meta
def pop(self):
self.methods.pop()
self.algorithms.pop()
self.name_method = self.name_method[::-1][self.name_method[::-1].find("improved"[::-1]) + len("improved") + 2:][
::-1]
def __call__(self, instance_, verbose=True, return_value=True):
self.instance = instance_
def compute_solution(self, verbose=True, return_value=True):
self.solved = False
if verbose:
print(f"### solving with {self.methods} ####")
start = t()
self.solution = self.available_initializers[self.methods[0]](instance_)
print(f"### solving with {self.algorithms} ####")
start_time = t()
self.solution = available_solvers[self.algorithms[0]](self.problem_instance)
assert self.check_if_solution_is_valid(self.solution), "Error the solution is not valid"
for i in range(1, len(self.methods)):
self.solution = self.available_improvements[self.methods[i]](self.solution, self.instance)
for i in range(1, len(self.algorithms)):
self.solution = available_improvers[self.algorithms[i]](self.solution, self.problem_instance)
assert self.check_if_solution_is_valid(self.solution), "Error the solution is not valid"
end = t()
self.time_to_solve = np.around(end - start,3)
end_time = t()
self.duration = np.around(end_time - start_time, 3)
self.solved = True
self.evaluate_solution()
self._gap()
if verbose:
print(f"### solution found with {self.gap} % gap in {self.time_to_solve} seconds ####")
print(f"the total length for the solution found is {self.found_length}",
f"while the optimal length is {self.instance.best_sol}",
f"the gap is {self.gap}%",
f"the solution is found in {self.time_to_solve} seconds", sep="\n")
# if verbose:
# print(f"### solution found with {self.gap} % gap in {self.duration} seconds ####",
# f"the total length for the solution found is {self.found_length}",
# f"while the optimal length is {prob_instance.best_sol}",
# f"the gap is {self.gap}%")
if return_value:
return self.solution
def plot_solution(self):
assert self.solved, "You can't plot the solution, you need to solve it first!"
assert self.solved, "You can't plot the solution, you need to compute it first!"
plt.figure(figsize=(8, 8))
self._gap()
plt.title(f"{self.instance.name} solved with {self.name_method} solver, gap {self.gap}")
ordered_points = self.instance.points[self.solution]
plt.title(f"{self.problem_instance.name} solved with {self.name_method} solver, gap {self.gap}")
ordered_points = self.problem_instance.points[self.solution]
plt.plot(ordered_points[:, 1], ordered_points[:, 2], 'b-')
plt.show()
def check_if_solution_is_valid(self, solution):
rights_values = np.sum([self.check_validation(i, solution[:-1]) for i in np.arange(self.instance.nPoints)])
if rights_values == self.instance.nPoints:
return True
else:
return False
# 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)])
return rights_values == self.problem_instance.nPoints
# return True
# else:
# return False
def check_validation(self, node, solution):
if np.sum(solution == node) == 1:
return 1
else:
return 0
# def check_validation(self, node, solution):
# if np.sum(solution == node) == 1:
# return 1
# else:
# return 0
def evaluate_solution(self, return_value=False):
total_length = 0
starting_node = self.solution[0]
from_node = starting_node
for node in self.solution[1:]:
total_length += self.instance.dist_matrix[from_node, node]
total_length += self.problem_instance.dist_matrix[from_node, node]
from_node = node
self.found_length = total_length
@ -109,4 +105,5 @@ class SolverTSP:
def _gap(self):
self.evaluate_solution(return_value=False)
self.gap = np.round(((self.found_length - self.instance.best_sol) / self.instance.best_sol) * 100, 2)
self.gap = np.round(
((self.found_length - self.problem_instance.best_sol) / self.problem_instance.best_sol) * 100, 2)

View File

@ -6,7 +6,7 @@ from numpy.core._multiarray_umath import ndarray
from src.utils import distance_euc
class Instance:
class ProblemInstance:
nPoints: int
best_sol: int
name: str