-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathanneal.py
78 lines (67 loc) · 3.08 KB
/
anneal.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
import math
import random
import matplotlib.pyplot as plt
from util import City, read_cities, write_cities_and_return_them, generate_cities, visualize_tsp, path_cost
class SimAnneal(object):
def __init__(self, cities, temperature=-1, alpha=-1, stopping_temperature=-1, stopping_iter=-1):
self.cities = cities
self.num_cities = len(cities)
self.temperature = math.sqrt(self.num_cities) if temperature == -1 else temperature
self.T_save = self.temperature
self.alpha = 0.999 if alpha == -1 else alpha
self.stopping_temperature = 1e-8 if stopping_temperature == -1 else stopping_temperature
self.stopping_iter = 100000 if stopping_iter == -1 else stopping_iter
self.iteration = 1
self.route = None
self.best_fitness = float("Inf")
self.progress = []
self.cur_cost = None
def greedy_solution(self):
start_node = random.randint(0, self.num_cities) # start from a random node
unvisited = self.cities[:]
del unvisited[start_node]
route = [cities[start_node]]
while len(unvisited):
index, nearest_city = min(enumerate(unvisited), key=lambda item: item[1].distance(route[-1]))
route.append(nearest_city)
del unvisited[index]
current_cost = path_cost(route)
self.progress.append(current_cost)
return route, current_cost
def accept_probability(self, candidate_fitness):
return math.exp(-abs(candidate_fitness - self.cur_cost) / self.temperature)
def accept(self, guess):
guess_cost = path_cost(guess)
if guess_cost < self.cur_cost:
self.cur_cost, self.route = guess_cost, guess
if guess_cost < self.best_fitness:
self.best_fitness, self.route = guess_cost, guess
else:
if random.random() < self.accept_probability(guess_cost):
self.cur_cost, self.route = guess_cost, guess
def run(self):
self.route, self.cur_cost = self.greedy_solution()
while self.temperature >= self.stopping_temperature and self.iteration < self.stopping_iter:
guess = list(self.route)
left_index = random.randint(2, self.num_cities - 1)
right_index = random.randint(0, self.num_cities - left_index)
guess[right_index: (right_index + left_index)] = reversed(guess[right_index: (right_index + left_index)])
self.accept(guess)
self.temperature *= self.alpha
self.iteration += 1
self.progress.append(self.cur_cost)
print("Best fitness obtained: ", self.best_fitness)
def visualize_routes(self):
visualize_tsp('simulated annealing TSP', self.route)
def plot_learning(self):
fig = plt.figure(1)
plt.plot([i for i in range(len(self.progress))], self.progress)
plt.ylabel("Distance")
plt.xlabel("Iterations")
plt.show(block=False)
if __name__ == "__main__":
cities = read_cities(64)
sa = SimAnneal(cities, stopping_iter=15000)
sa.run()
sa.plot_learning()
sa.visualize_routes()