This commit is contained in:
UmbertoJr 2019-11-18 08:21:05 +01:00
parent d29a162276
commit 2e9910d324
3 changed files with 73 additions and 61 deletions

1
run.py
View file

@ -23,7 +23,6 @@ def run(show_plots=False, verbose=False):
solver = Solver_TSP(init) solver = Solver_TSP(init)
for improve in improvements: for improve in improvements:
solver.bind(improve) solver.bind(improve)
end - start
solver(instance, return_value=False, verbose=verbose) solver(instance, return_value=False, verbose=verbose)
if verbose: if verbose:

View file

@ -46,6 +46,7 @@ class Solver_TSP:
print("init ok") print("init ok")
for i in range(1, len(self.methods)): for i in range(1, len(self.methods)):
self.solution = self.available_improvements[self.methods[i]](self.solution, self.instance) self.solution = self.available_improvements[self.methods[i]](self.solution, self.instance)
print(len(self.solution))
assert self.check_if_solution_is_valid(self.solution), "Error the solution is not valid" assert self.check_if_solution_is_valid(self.solution), "Error the solution is not valid"
print("improve ok") print("improve ok")

View file

@ -1,5 +1,6 @@
import os import os
import numpy as np import numpy as np
if 'AI' in os.getcwd(): if 'AI' in os.getcwd():
from src.utils import * from src.utils import *
else: else:
@ -65,86 +66,97 @@ class TwoOpt:
else: else:
return new_tsp_sequence.tolist(), new_len, uncross return new_tsp_sequence.tolist(), new_len, uncross
return new_tsp_sequence.tolist(), new_len, uncross # return new_tsp_sequence.tolist(), new_len, uncross
return new_tsp_sequence.tolist()
class TwoDotFiveOpt: class TwoDotFiveOpt:
@staticmethod @staticmethod
def step2dot5opt(solution, matrix_dist, distance): def step2dot5opt(solution, matrix_dist, distance):
""" """
One step of 2opt, one double loop and return first improved sequence One step of 2opt, one double loop and return first improved sequence
@param solution: @param solution:
@param matrix_dist: @param matrix_dist:
@param distance: @param distance:
@return: @return:
""" """
seq_length = len(solution) - 2 seq_length = len(solution) - 2
tsp_sequence = np.array(solution) tsp_sequence = np.array(solution)
uncrosses = 0 uncrosses = 0
for i in range(1, seq_length - 1): for i in range(1, seq_length - 1):
for j in range(i + 1, seq_length): for j in range(i + 1, seq_length):
# 2opt swap # 2opt swap
twoOpt_tsp_sequence = TwoOpt.swap2opt(tsp_sequence, i, j) twoOpt_tsp_sequence = TwoOpt.swap2opt(tsp_sequence, i, j)
twoOpt_len = distance + TwoOpt.gain(i, j , tsp_sequence, matrix_dist) twoOpt_len = distance + TwoOpt.gain(i, j, tsp_sequence, matrix_dist)
# node shift 1 # node shift 1
first_shift_tsp_sequence = TwoDotFiveOpt.shift1(tsp_sequence, i,j) first_shift_tsp_sequence = TwoDotFiveOpt.shift1(tsp_sequence, i, j)
first_shift_len = distance + TwoDotFiveOpt.shift_gain1(i,j, tsp_sequence, matrix_dist) first_shift_len = distance + TwoDotFiveOpt.shift_gain1(i, j, tsp_sequence, matrix_dist)
# node shift 2 # node shift 2
second_shift_tsp_sequence = TwoDotFiveOpt.shift2(tsp_sequence, i,j) second_shift_tsp_sequence = TwoDotFiveOpt.shift2(tsp_sequence, i, j)
second_shift_len = distance + TwoDotFiveOpt.shift_gain2(i,j, tsp_sequence, matrix_dist) second_shift_len = distance + TwoDotFiveOpt.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]) best_len, best_method = min([twoOpt_len, first_shift_len, second_shift_len]), np.argmin(
sequences = [twoOpt_tsp_sequence, first_shift_tsp_sequence, second_shift_tsp_sequence] [twoOpt_len, first_shift_len, second_shift_len])
if best_len < distance: sequences = [twoOpt_tsp_sequence, first_shift_tsp_sequence, second_shift_tsp_sequence]
uncrosses += 1 if best_len < distance:
tsp_sequence = sequences[best_method] uncrosses += 1
distance = best_len tsp_sequence = sequences[best_method]
# print(distance, best_method, [twoOpt_len, first_shift_len, second_shift_len]) distance = best_len
return tsp_sequence, distance, uncrosses # print(distance, best_method, [twoOpt_len, first_shift_len, second_shift_len])
return tsp_sequence, distance, uncrosses
@staticmethod @staticmethod
def shift1(tsp_sequence, i, j): def shift1(tsp_sequence, i, j):
new_tsp_sequence = np.concatenate([tsp_sequence[:i], tsp_sequence[i+1: j+1], [tsp_sequence[i]], tsp_sequence[j+1:]]) new_tsp_sequence = np.concatenate(
return new_tsp_sequence [tsp_sequence[:i], tsp_sequence[i + 1: j + 1], [tsp_sequence[i]], tsp_sequence[j + 1:]])
return new_tsp_sequence
@staticmethod @staticmethod
def shift_gain1(i, j , tsp_sequence, matrix_dist): def shift_gain1(i, j, tsp_sequence, matrix_dist):
old_link_len = (matrix_dist[tsp_sequence[i], tsp_sequence[i - 1]]+ matrix_dist[tsp_sequence[i], tsp_sequence[i + 1]] + matrix_dist[tsp_sequence[j], tsp_sequence[j + 1]]) old_link_len = (matrix_dist[tsp_sequence[i], tsp_sequence[i - 1]] + matrix_dist[
changed_links_len = (matrix_dist[tsp_sequence[i - 1], tsp_sequence[i + 1]] + matrix_dist[tsp_sequence[i], tsp_sequence[j]] + matrix_dist[tsp_sequence[i], tsp_sequence[j + 1]]) tsp_sequence[i], tsp_sequence[i + 1]] + matrix_dist[tsp_sequence[j], tsp_sequence[j + 1]])
return - old_link_len + changed_links_len changed_links_len = (matrix_dist[tsp_sequence[i - 1], tsp_sequence[i + 1]] + matrix_dist[
tsp_sequence[i], tsp_sequence[j]] + matrix_dist[tsp_sequence[i], tsp_sequence[j + 1]])
return - old_link_len + changed_links_len
@staticmethod @staticmethod
def shift2(tsp_sequence, i, j): def shift2(tsp_sequence, i, j):
new_tsp_sequence = np.concatenate([tsp_sequence[:i], [tsp_sequence[j]], tsp_sequence[i: j], tsp_sequence[j+1:]]) new_tsp_sequence = np.concatenate(
return new_tsp_sequence [tsp_sequence[:i], [tsp_sequence[j]], tsp_sequence[i: j], tsp_sequence[j + 1:]])
return new_tsp_sequence
@staticmethod @staticmethod
def shift_gain2(i, j , tsp_sequence, matrix_dist): def shift_gain2(i, j, tsp_sequence, matrix_dist):
old_link_len = (matrix_dist[tsp_sequence[i], tsp_sequence[i - 1]] + matrix_dist[tsp_sequence[j], tsp_sequence[j - 1]] + matrix_dist[tsp_sequence[j], tsp_sequence[j + 1]]) old_link_len = (matrix_dist[tsp_sequence[i], tsp_sequence[i - 1]] + matrix_dist[
changed_links_len = (matrix_dist[tsp_sequence[j], tsp_sequence[i - 1]] + matrix_dist[tsp_sequence[i], tsp_sequence[j]] + matrix_dist[tsp_sequence[j - 1], tsp_sequence[j + 1]]) tsp_sequence[j], tsp_sequence[j - 1]] + matrix_dist[tsp_sequence[j], tsp_sequence[j + 1]])
return - old_link_len + changed_links_len changed_links_len = (
matrix_dist[tsp_sequence[j], tsp_sequence[i - 1]] + matrix_dist[tsp_sequence[i], tsp_sequence[j]] +
matrix_dist[tsp_sequence[j - 1], tsp_sequence[j + 1]])
return - old_link_len + changed_links_len
@staticmethod @staticmethod
def loop2dot5opt(solution, instance, max_num_of_changes=400): # Iterate stoep2opt max_iter times (2-opt local search) def loop2dot5opt(solution, instance,
""" max_num_of_changes=400): # Iterate stoep2opt max_iter times (2-opt local search)
"""
@param solution: @param solution:
@param instance: @param instance:
@param max_num_of_changes: @param max_num_of_changes:
@return: @return:
""" """
matrix_dist = instance.dist_matrix matrix_dist = instance.dist_matrix
actual_len = compute_lenght(solution, matrix_dist) actual_len = compute_lenght(solution, matrix_dist)
new_tsp_sequence = np.copy(np.array(solution)) new_tsp_sequence = np.copy(np.array(solution))
uncross = 0 uncross = 0
while uncross < max_num_of_changes: while uncross < max_num_of_changes:
new_tsp_sequence, new_len, uncr_ = TwoDotFiveOpt.step2dot5opt(new_tsp_sequence, matrix_dist, actual_len) new_tsp_sequence, new_len, uncr_ = TwoDotFiveOpt.step2dot5opt(new_tsp_sequence, matrix_dist, actual_len)
uncross += uncr_ uncross += uncr_
# print(new_len, uncross) # print(new_len, uncross)
if new_len < actual_len: if new_len < actual_len:
actual_len = new_len actual_len = new_len
else: else:
return new_tsp_sequence.tolist(), actual_len, uncross return new_tsp_sequence.tolist(), actual_len, uncross
return new_tsp_sequence.tolist(), actual_len, uncross
# return new_tsp_sequence.tolist(), actual_len, uncross
return new_tsp_sequence.tolist()