20 KiB
20 KiB
None
<html>
<head>
</head>
</html>
Make sure you run this at the begining
In [ ]:
import os
import sys
import math
import numpy as np
import matplotlib.pyplot as plt
# Append template path to sys path
sys.path.append(os.getcwd() + "/template")
In [ ]:
from utils.load_data import load_data
from utils.load_data import log
from utils.visualize_tsp import plotTSP
from utils.tsp import TSP
from utils.tsp import TSP_Bench
from utils.tsp import TSP_Bench_ALL
Workshop Starts Here¶
Get familiar with your dataset¶
There are problems at different levels. 3 simple, 2 medium, 1 hard.
In [ ]:
for root, _, files in os.walk('./template/data'):
if(files):
for f in files:
print(str(root) + "/" + f)
In [ ]:
ulysses16 = np.array(load_data("./template/data/simple/ulysses16.tsp"))
In [ ]:
ulysses16[:]
In [ ]:
plt.scatter(ulysses16[:, 0], ulysses16[:, 1])
for i in range(0, 16):
plt.annotate(i, (ulysses16[i, 0], ulysses16[i, 1]+0.5))
Naive Solution: In Order¶
In [ ]:
simple_sequence = list(range(0, 16))
print(simple_sequence)
In [ ]:
plotTSP([simple_sequence], ulysses16, num_iters=1)
Naive Solution: Random Permutation¶
In [ ]:
random_permutation = np.random.permutation(16).tolist()
print(random_permutation)
In [ ]:
plotTSP([random_permutation], ulysses16, num_iters=1)
Best Solution¶
In [ ]:
best_ulysses16 = [0, 13, 12, 11, 6, 5, 14, 4, 10, 8, 9, 15, 2, 1, 3, 7]
plotTSP([best_ulysses16], ulysses16, num_iters=1)
Calculate Fitness (Sum of all Distances)¶
In [ ]:
def dist(node_0, node_1, coords):
"""
Euclidean distance between two nodes.
"""
coord_0, coord_1 = coords[node_0], coords[node_1]
return math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)
In [ ]:
print("Coordinate of City 0:", ulysses16[0])
In [ ]:
print("Coordinate of City 1:", ulysses16[1])
In [ ]:
print("Distance Between", dist(0, 1, ulysses16))
In [ ]:
def fitness(solution, coords):
N = len(coords)
cur_fit = 0
for i in range(len(solution)):
cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords)
return cur_fit
In [ ]:
print ("Order Fitness:\t", fitness(simple_sequence, ulysses16))
print ("Random Fitness:\t", fitness(random_permutation, ulysses16))
print ("Best Fitness:\t", fitness(best_ulysses16, ulysses16))
Naive Random Model¶
In [ ]:
import math
import random
from model.base_model import Model
import numpy as np
class MyRandomModel(Model):
def __init__(self):
super().__init__()
def init(self, nodes):
"""
Put your initialization here.
"""
super().init(nodes)
def fit(self, max_it):
"""
Put your iteration process here.
"""
random_solutions = []
for i in range(0, max_it):
solution = np.random.permutation(self.N).tolist()
random_solutions.append(solution)
self.fitness_list.append(self.fitness(solution))
self.best_solution = random_solutions[self.fitness_list.index(min(self.fitness_list))]
return self.best_solution, self.fitness_list
In [ ]:
tsp_file = './template/data/simple/ulysses16.tsp'
In [ ]:
best_solution, fitness_list, time = TSP_Bench(tsp_file, MyRandomModel, max_it=100)
In [ ]:
plt.plot(fitness_list, 'o-')
Ant Colony Optimization¶
In [ ]:
import math
import random
from model.base_model import Model
class MyACOModel(Model):
def __init__(self):
super().__init__()
class Edge:
def __init__(self, a, b, weight, initial_pheromone):
self.a = a
self.b = b
self.weight = weight
self.pheromone = initial_pheromone
class Ant:
def __init__(self, alpha, beta, num_nodes, edges):
self.alpha = alpha
self.beta = beta
self.num_nodes = num_nodes
self.edges = edges
self.tour = None
self.distance = 0.0
def _select_node(self):
roulette_wheel = 0.0
unvisited_nodes = [node for node in range(self.num_nodes) if node not in self.tour]
heuristic_total = 0.0
for unvisited_node in unvisited_nodes:
heuristic_total += self.edges[self.tour[-1]][unvisited_node].weight
for unvisited_node in unvisited_nodes:
roulette_wheel += pow(self.edges[self.tour[-1]][unvisited_node].pheromone, self.alpha) * \
pow((heuristic_total / self.edges[self.tour[-1]][unvisited_node].weight), self.beta)
random_value = random.uniform(0.0, roulette_wheel)
wheel_position = 0.0
for unvisited_node in unvisited_nodes:
wheel_position += pow(self.edges[self.tour[-1]][unvisited_node].pheromone, self.alpha) * \
pow((heuristic_total / self.edges[self.tour[-1]][unvisited_node].weight), self.beta)
if wheel_position >= random_value:
return unvisited_node
def find_tour(self):
self.tour = [random.randint(0, self.num_nodes - 1)]
while len(self.tour) < self.num_nodes:
self.tour.append(self._select_node())
return self.tour
def get_distance(self):
self.distance = 0.0
for i in range(self.num_nodes):
self.distance += self.edges[self.tour[i]][self.tour[(i + 1) % self.num_nodes]].weight
return self.distance
def init(self, nodes, *args):
super().init(nodes)
mode, colony_size, elitist_weight, min_scaling_factor, alpha, beta, rho, pheromone_deposit_weight, initial_pheromone, labels = args
self.mode = mode[0]
self.colony_size = colony_size
self.elitist_weight = elitist_weight
self.min_scaling_factor = min_scaling_factor
self.rho = rho
self.pheromone_deposit_weight = pheromone_deposit_weight
self.num_nodes = len(nodes)
self.nodes = nodes
if labels is not None:
self.labels = labels
else:
self.labels = range(1, self.num_nodes + 1)
self.edges = [[None] * self.num_nodes for _ in range(self.num_nodes)]
for i in range(self.num_nodes):
for j in range(i + 1, self.num_nodes):
self.edges[i][j] = self.edges[j][i] = self.Edge(i, j, math.sqrt(
pow(self.nodes[i][0] - self.nodes[j][0], 2.0) + pow(self.nodes[i][1] - self.nodes[j][1], 2.0)),
initial_pheromone)
self.ants = [self.Ant(alpha, beta, self.num_nodes, self.edges) for _ in range(self.colony_size)]
self.global_best_tour = None
self.global_best_distance = float("inf")
def _add_pheromone(self, tour, distance, weight=1.0):
pheromone_to_add = self.pheromone_deposit_weight / distance
for i in range(self.num_nodes):
self.edges[tour[i]][tour[(i + 1) % self.num_nodes]].pheromone += weight * pheromone_to_add
def _acs(self, max_it):
for step in range(0, max_it):
# print('[step]', step)
for ant in self.ants:
self._add_pheromone(ant.find_tour(), ant.get_distance())
if ant.distance < self.global_best_distance:
self.global_best_tour = ant.tour
self.global_best_distance = ant.distance
self.fitness_list.append(ant.distance)
for i in range(self.num_nodes):
for j in range(i + 1, self.num_nodes):
self.edges[i][j].pheromone *= (1.0 - self.rho)
def _elitist(self, max_it):
for step in range(0, max_it):
# print('[step]', step)
for ant in self.ants:
self._add_pheromone(ant.find_tour(), ant.get_distance())
if ant.distance < self.global_best_distance:
self.global_best_tour = ant.tour
self.global_best_distance = ant.distance
self.fitness_list.append(ant.distance)
self._add_pheromone(self.global_best_tour, self.global_best_distance, weight=self.elitist_weight)
for i in range(self.num_nodes):
for j in range(i + 1, self.num_nodes):
self.edges[i][j].pheromone *= (1.0 - self.rho)
def fit(self, max_it=1000):
"""
Execute simulated annealing algorithm.
"""
# Initialize with the greedy solution.
if self.mode == 'ACS':
self._acs(max_it)
elif self.mode == 'Elitist':
self._elitist(max_it)
else:
print("Un supported")
# print('Sequence : <- {0} ->'.format(' - '.join(str(self.labels[i]) for i in self.global_best_tour)))
# print('Total distance travelled to complete the tour : {0}\n'.format(round(self.global_best_distance, 2)))
return self.global_best_tour, self.fitness_list
In [ ]:
tsp_file = './template/data/simple/ulysses16.tsp'
In [ ]:
# Set hypter-parameters
mode='ACS',
colony_size=10
elitist_weight=1.0
min_scaling_factor=0.001
alpha=1.0
beta=3.0
rho=0.1
pheromone_deposit_weight=1.0
initial_pheromone=1.0
labels = None
In [ ]:
best_solution, fitness_list, time = TSP_Bench(tsp_file, MyACOModel, mode, colony_size, elitist_weight, min_scaling_factor, alpha, beta, rho, pheromone_deposit_weight, initial_pheromone, labels, max_it=1000, timeout=300)
Your Smart Model¶
In [ ]:
import math
import random
from model.base_model import Model
class MyModel(Model):
def __init__(self):
super().__init__()
def init(self, nodes):
"""
Put your initialization here.
"""
super().init(nodes)
self.log("Nothing to initialize in your model now")
def fit(self, max_it):
"""
Put your iteration process here.
"""
self.log("Naive Random Solution")
self.best_solution = np.random.permutation(self.N).tolist()
self.fitness_list.append(self.fitness(self.best_solution))
return self.best_solution, self.fitness_list
Test your Model¶
In [ ]:
tsp_problem = './template/data/simple/ulysses16.tsp'
In [ ]:
best_solution, fitness_list, time = TSP_Bench(tsp_file, MyModel)
Test All Dataset¶
In [ ]:
for root, _, files in os.walk('./template/data'):
if(files):
for f in files:
print(str(root) + "/" + f)
In [ ]:
def plot_results(best_solutions, times, title):
fig = plt.figure()
nodes = [len(s) for s in best_solutions]
data = np.array([[node, time] for node, time in sorted(zip(nodes, times))])
plt.plot(data[:, 0], data[:, 1], 'o-')
fig.suptitle(title, fontsize=20)
In [ ]:
tsp_path = './template/data'
In [ ]:
print("Random Search")
best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MyRandomModel)
In [ ]:
plot_results(best_solutions, times, "Random Model")
In [ ]:
# Set hypter-parameters
mode='ACS',
colony_size=10
elitist_weight=1.0
min_scaling_factor=0.001
alpha=1.0
beta=3.0
rho=0.1
pheromone_deposit_weight=1.0
initial_pheromone=1.0
labels = None
In [ ]:
print("Ant Colony Optimization")
best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MyACOModel, mode, colony_size, elitist_weight, min_scaling_factor, alpha, beta, rho, pheromone_deposit_weight, initial_pheromone, labels, max_it=100, timeout=600)
In [ ]:
plot_results(best_solutions, times, "Ant Colony Optimization")
In [ ]: