Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
DataScienceUWL
GitHub Repository: DataScienceUWL/DS775
Path: blob/main/Lessons/Lesson 05 - Local Optimization/scripts/animate_tour.py
871 views
1
# execute this cell for a *slow* animation of the local search
2
from IPython.display import display, clear_output
3
import json
4
import numpy as np
5
import matplotlib.pyplot as plt
6
import seaborn as sns
7
sns.set_style("darkgrid")
8
9
# load problem data
10
with open("data/Caps48.json", "r") as tsp_data:
11
tsp = json.load(tsp_data)
12
dist_mat = tsp["DistanceMatrix"]
13
optimal_tour = tsp["OptTour"]
14
opt_dist = tsp["OptDistance"]/1000 # converted to kilometers
15
xy_meters = np.array(tsp["Coordinates"])
16
17
def sub_tour_reversal(tour):
18
# reverse a random tour segment
19
num_cities = len(tour)
20
i, j = np.sort(np.random.choice(num_cities, 2, replace=False))
21
return np.concatenate((tour[0:i], tour[j:-num_cities + i - 1:-1],
22
tour[j + 1:num_cities]))
23
24
def tour_distance(tour, dist_mat):
25
distance = dist_mat[tour[-1]][tour[0]]
26
for gene1, gene2 in zip(tour[0:-1], tour[1:]):
27
distance += dist_mat[gene1][gene2]
28
return distance/1000 # convert to kilometers
29
30
# initialize with a random tour
31
n = 48
32
current_tour = np.random.permutation(np.arange(n))
33
current_dist = tour_distance(current_tour, dist_mat)
34
35
# plot initial tour
36
meters_to_pxl = 0.0004374627441064968
37
intercept_x = 2.464
38
intercept_y = 1342.546
39
xy_pixels = np.zeros(xy_meters.shape)
40
xy_pixels[:,0] = meters_to_pxl * xy_meters[:,0] + intercept_x
41
xy_pixels[:,1] = -meters_to_pxl * xy_meters[:,1] + intercept_y
42
43
fig, ax = plt.subplots(1, 1, figsize=(9, 6))
44
im = plt.imread('images/caps48.png')
45
implot = ax.imshow(im)
46
plt.setp(ax.get_xticklabels(), visible=False)
47
plt.setp(ax.get_yticklabels(), visible=False)
48
ax.tick_params(axis='both', which='both', length=0)
49
50
loop_tour = np.append(current_tour, current_tour[0])
51
lines, = ax.plot(xy_pixels[loop_tour, 0],
52
xy_pixels[loop_tour, 1],
53
c='b',
54
linewidth=1,
55
linestyle='-')
56
dst_label = plt.text(100, 1200, '{:d} km'.format(int(current_dist)))
57
58
# local search with graphing
59
max_moves_no_improve = 5000
60
num_moves_no_improve = 0
61
while( num_moves_no_improve < max_moves_no_improve):
62
num_moves_no_improve += 1
63
new_tour = sub_tour_reversal(current_tour)
64
new_dist = tour_distance(new_tour, dist_mat)
65
if new_dist < current_dist:
66
current_tour = new_tour
67
current_dist = new_dist
68
num_moves_no_improve = 0
69
70
loop_tour = np.append(current_tour, current_tour[0])
71
lines.set_data(xy_pixels[loop_tour, 0], xy_pixels[loop_tour, 1])
72
dst_label.set_text('{:d} km'.format(int(current_dist)))
73
clear_output(wait=True)
74
display(fig)
75