-
Notifications
You must be signed in to change notification settings - Fork 1
/
Tabu.py
134 lines (110 loc) · 4.54 KB
/
Tabu.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# Tabu Search Implementation provided by BENBELGACEM Rahma Aya, refactored into a command line program by Smail KOURTA
import numpy as np
import random
import argparse
import Parser
import time
import copy
def generate_first_solution(graphe, v_depart=None):
# Faire une copie du graphe vu qu'il va subir a des modification
_graphe = graphe.copy()
# La liste chemin gardera trace de notre parcour
chemin = []
# Selection d'un point de depart
if v_depart is None:
depart = v_depart = np.random.randint(0, len(graphe))
depart = v_depart
chemin.append(v_depart)
# Creation de l'ensemble des noeuds non visités
noeudsNonVisite = set(
np.delete(np.arange(0, len(graphe)), v_depart).flatten())
# Mise a zero du coup de la solution
cout = 0
while (len(noeudsNonVisite) != 0):
# Retourner le plus proche voisin
v_suivante = np.argmin(_graphe[v_depart, :])
# Màj du chemin
chemin.append(v_suivante)
# Màj du cout
cout += _graphe[v_depart, v_suivante]
# Visiter le prochain neoud
noeudsNonVisite.remove(v_suivante)
v_depart = v_suivante
# Mettre vers les noeuds deja visité a l'infini
_graphe[v_depart, chemin] = _graphe[chemin, v_depart] = float("inf")
# Ajouter le cout de retour
cout += graphe[v_suivante, depart]
return chemin, cout
def find_neighborhood(solution, matrice):
neighborhood_of_solution = []
for n in solution[1:-1]:
idx1 = solution.index(n)
for kn in solution[1:-1]:
idx2 = solution.index(kn)
if n == kn:
continue
_tmp = copy.deepcopy(solution)
_tmp[idx1] = kn
_tmp[idx2] = n
distance = 0
for i in range(len(matrice)):
distance += matrice[_tmp[i - 1]][_tmp[i]]
_tmp.append(distance)
if _tmp not in neighborhood_of_solution:
neighborhood_of_solution.append(_tmp)
indexOfLastItemInTheList = len(neighborhood_of_solution[0]) - 1
neighborhood_of_solution.sort(key=lambda x: x[indexOfLastItemInTheList])
return neighborhood_of_solution
def tabu_search(matrice, iters, size, start_node=None):
# Generation d'une solution initial
solution, best_cost = generate_first_solution(matrice, start_node)
# Initialisation de la liste tabou
tabu_list = list()
best_solution_ever = solution
for count in range(iters):
# Generation des voisins de la solution
neighborhood = find_neighborhood(solution, matrice)
index_of_best_solution = 0
best_solution = neighborhood[index_of_best_solution]
best_cost_index = len(best_solution) - 1
found = False
while found is False:
for i in range(len(best_solution)):
if best_solution[i] != solution[i]:
first_exchange_node = best_solution[i]
second_exchange_node = solution[i]
break
if [first_exchange_node, second_exchange_node] not in tabu_list and [second_exchange_node,
first_exchange_node] not in tabu_list:
tabu_list.append([first_exchange_node, second_exchange_node])
found = True
solution = best_solution[:-1]
cost = neighborhood[index_of_best_solution][best_cost_index]
if cost < best_cost:
best_cost = cost
best_solution_ever = solution
else:
index_of_best_solution = index_of_best_solution + 1
best_solution = neighborhood[index_of_best_solution]
if len(tabu_list) >= size:
_ = tabu_list.pop(0)
return best_solution_ever, best_cost
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("instance")
parser.add_argument("--iterations",
help="Number of Iterations", )
parser.add_argument("--size",
help="Size of Tabu List", )
parser.add_argument("--start",
help="Starting Node", default=0)
args = parser.parse_args()
instance = Parser.TSPInstance(args.instance)
instance.readData()
start_time = time.time()
tour, cost = tabu_search(np.array(instance.data), iters=int(
args.iterations), size=int(args.size), start_node=int(args.start))
end_time = time.time()
print(tour)
print(cost)
print(end_time - start_time)