[new] Different test time for different problems
This commit is contained in:
parent
2b8e4e197e
commit
3a4ab95699
|
|
@ -2,9 +2,8 @@ import os
|
|||
import signal
|
||||
import json
|
||||
|
||||
from utils.tsp import TSP
|
||||
from utils.tsp import TSP_Bench_ALL
|
||||
from tsp import TSP_Bench_ALL
|
||||
from model.my_model import MyModel
|
||||
|
||||
if __name__ == "__main__":
|
||||
TSP_Bench_ALL("./data", MyModel)
|
||||
TSP_Bench_ALL('./', MyModel)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import math
|
||||
import random
|
||||
from model.base_model import Model
|
||||
import numpy as np
|
||||
|
||||
class MyModel(Model):
|
||||
def __init__(self):
|
||||
|
|
@ -13,15 +12,13 @@ class MyModel(Model):
|
|||
"""
|
||||
super().init(nodes)
|
||||
|
||||
def fit(self, max_it):
|
||||
self.log("Nothing to initialize in your model now")
|
||||
|
||||
def fit(self, max_it=1000):
|
||||
"""
|
||||
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 = np.random.permutation(self.N).tolist()
|
||||
self.fitness_list.append(self.fitness(self.best_solution))
|
||||
|
||||
self.best_solution = random_solutions[self.fitness_list.index(min(self.fitness_list))]
|
||||
return self.best_solution, self.fitness_list
|
||||
return self.best_solution, self.fitness_list
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
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):
|
||||
super().init(nodes)
|
||||
|
||||
# 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
|
||||
|
||||
self.mode = str(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
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
import math
|
||||
import random
|
||||
from model.base_model import Model
|
||||
|
||||
class MyASModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def init(self, nodes):
|
||||
"""
|
||||
Put your initialization here.
|
||||
"""
|
||||
super().init(nodes)
|
||||
|
||||
def getMST(self, node):
|
||||
MST = []
|
||||
distances = []
|
||||
for i in range(0, self.N):
|
||||
if i != node:
|
||||
MST.append(i)
|
||||
distances.append(self.dist(node, i))
|
||||
return [x for _,x in sorted(zip(distances, MST))]
|
||||
|
||||
def fit(self, max_it=1000):
|
||||
"""
|
||||
Put your iteration process here.
|
||||
"""
|
||||
|
||||
MST_solutions = []
|
||||
|
||||
for i in range(0, self.N):
|
||||
solution = [i]
|
||||
MST_solutions.append(solution)
|
||||
|
||||
# Breadth First: Set each city as starting point, then go to next city simultaneously
|
||||
for step in range(0, self.N - 1):
|
||||
# print("[step]", step)
|
||||
unvisited_list = list(range(0, self.N))
|
||||
# For each search path
|
||||
for i in range(0, self.N):
|
||||
cur_city = MST_solutions[i][-1]
|
||||
unvisited_list = list( set(range(0, self.N)) - set(MST_solutions[i]) )
|
||||
closest_neighbour = -1
|
||||
min_f = math.inf
|
||||
|
||||
for j in unvisited_list:
|
||||
g = self.dist(cur_city, j)
|
||||
sub_unvisited_list = unvisited_list.copy()
|
||||
sub_unvisited_list.remove(j)
|
||||
|
||||
sub_cur_city = self.getMST(j)[0]
|
||||
h = 0
|
||||
while len(sub_unvisited_list) > 0:
|
||||
if(len(unvisited_list) == 2):
|
||||
break
|
||||
else:
|
||||
for k in self.getMST(sub_cur_city):
|
||||
if k in sub_unvisited_list:
|
||||
h = h + self.dist(sub_cur_city, k)
|
||||
sub_cur_city = k
|
||||
sub_unvisited_list.remove(k)
|
||||
break
|
||||
# Get f(x) = g(x) + h(x)
|
||||
|
||||
f = g + h
|
||||
if(f < min_f):
|
||||
closest_neighbour = j
|
||||
min_f = f
|
||||
MST_solutions[i].append(closest_neighbour)
|
||||
|
||||
for i in range(0, self.N):
|
||||
self.fitness_list.append(self.fitness(MST_solutions[i]))
|
||||
|
||||
self.best_solution = MST_solutions[ self.fitness_list.index(min(self.fitness_list)) ]
|
||||
|
||||
return self.best_solution, self.fitness_list
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import math
|
||||
import random
|
||||
from model.base_model import Model
|
||||
|
||||
class MyBFSModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def init(self, nodes):
|
||||
"""
|
||||
Put your initialization here.
|
||||
"""
|
||||
super().init(nodes)
|
||||
|
||||
def fit(self, max_it=1000):
|
||||
"""
|
||||
Put your iteration process here.
|
||||
"""
|
||||
|
||||
UCS_solutions = []
|
||||
|
||||
for i in range(0, self.N):
|
||||
solution = [i]
|
||||
UCS_solutions.append(solution)
|
||||
|
||||
# Breadth First: Set each city as starting point, then go to next city simultaneously
|
||||
for step in range(0, self.N - 1):
|
||||
# print("[step]", step)
|
||||
unvisited_list = list(range(0, self.N))
|
||||
# For each search path
|
||||
for i in range(0, self.N):
|
||||
cur_city = UCS_solutions[i][-1]
|
||||
unvisited_list = list( set(range(0, self.N)) - set(UCS_solutions[i]) )
|
||||
# print(unvisited_list)
|
||||
closest_neighbour = -1
|
||||
shortest_distance = math.inf
|
||||
for j in unvisited_list:
|
||||
if(self.dist(cur_city, j) < shortest_distance):
|
||||
closest_neighbour = j
|
||||
shortest_distance = self.dist(cur_city, j)
|
||||
UCS_solutions[i].append(closest_neighbour)
|
||||
|
||||
for i in range(0, self.N):
|
||||
self.fitness_list.append(self.fitness(UCS_solutions[i]))
|
||||
|
||||
self.best_solution = UCS_solutions[ self.fitness_list.index(min(self.fitness_list)) ]
|
||||
self.fitness_list.append(self.fitness(self.best_solution))
|
||||
|
||||
return self.best_solution, self.fitness_list
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import math
|
||||
import random
|
||||
from model.base_model import Model
|
||||
|
||||
class MyDFSModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def init(self, nodes):
|
||||
"""
|
||||
Put your initialization here.
|
||||
"""
|
||||
super().init(nodes)
|
||||
|
||||
def fit(self, max_it=1000):
|
||||
"""
|
||||
Put your iteration process here.
|
||||
"""
|
||||
|
||||
MST_solutions = []
|
||||
# Depth First: Set one city as starting point, iterate to the end, then select next city as starting point.
|
||||
for i in range(0, self.N):
|
||||
solution = []
|
||||
solution.append(i)
|
||||
unvisited_list = list(range(0, self.N))
|
||||
cur_city = i
|
||||
# print("[starting]", i)
|
||||
for steps in range(self.N - 1):
|
||||
# print(unvisited_list)
|
||||
unvisited_list.remove(cur_city)
|
||||
closest_neighbour = -1
|
||||
shortest_distance = math.inf
|
||||
for j in unvisited_list:
|
||||
if(self.dist(cur_city, j) < shortest_distance):
|
||||
closest_neighbour = j
|
||||
shortest_distance = self.dist(cur_city, j)
|
||||
solution.append(closest_neighbour)
|
||||
cur_city = closest_neighbour
|
||||
MST_solutions.append(solution)
|
||||
self.fitness_list.append(self.fitness(solution))
|
||||
|
||||
self.best_solution = MST_solutions[ self.fitness_list.index(min(self.fitness_list)) ]
|
||||
|
||||
return self.best_solution, self.fitness_list
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import math
|
||||
import random
|
||||
from model.base_model import Model
|
||||
|
||||
class MyDPBModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def init(self, nodes):
|
||||
"""
|
||||
Put your initialization here.
|
||||
"""
|
||||
super().init(nodes)
|
||||
|
||||
def getMST(self, node):
|
||||
MST = []
|
||||
distances = []
|
||||
for i in range(0, self.N):
|
||||
if i != node:
|
||||
MST.append(i)
|
||||
distances.append(self.dist(node, i))
|
||||
return [x for _,x in sorted(zip(distances, MST))]
|
||||
|
||||
def fit(self, max_it=1000):
|
||||
"""
|
||||
Put your iteration process here.
|
||||
"""
|
||||
|
||||
MST_solutions = []
|
||||
|
||||
for i in range(0, self.N):
|
||||
solution = [i]
|
||||
MST_solutions.append(solution)
|
||||
|
||||
MSTs = []
|
||||
for i in range(0, self.N):
|
||||
MSTs.append([-1] * self.N)
|
||||
|
||||
# Breadth First: Set each city as starting point, then go to next city simultaneously
|
||||
for step in range(0, self.N - 1):
|
||||
# print("[step]", step)
|
||||
unvisited_list = list(range(0, self.N))
|
||||
# For each search path
|
||||
for i in range(0, self.N):
|
||||
cur_city = MST_solutions[i][-1]
|
||||
unvisited_list = list( set(range(0, self.N)) - set(MST_solutions[i]) )
|
||||
|
||||
if MSTs[cur_city][0] == -1:
|
||||
MST = self.getMST(cur_city)
|
||||
MSTs[cur_city] = MST
|
||||
|
||||
for j in MSTs[cur_city]:
|
||||
if(j in unvisited_list):
|
||||
MST_solutions[i].append(j)
|
||||
break
|
||||
|
||||
for i in range(0, self.N):
|
||||
self.fitness_list.append(self.fitness(MST_solutions[i]))
|
||||
|
||||
self.best_solution = MST_solutions[ self.fitness_list.index(min(self.fitness_list)) ]
|
||||
self.fitness_list.append(self.fitness(self.best_solution))
|
||||
|
||||
return self.best_solution, self.fitness_list
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import math
|
||||
import random
|
||||
from model.base_model import Model
|
||||
|
||||
class MyDPDModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def init(self, nodes):
|
||||
"""
|
||||
Put your initialization here.
|
||||
"""
|
||||
super().init(nodes)
|
||||
|
||||
def getMST(self, node):
|
||||
MST = []
|
||||
distances = []
|
||||
for i in range(0, self.N):
|
||||
if i != node:
|
||||
MST.append(i)
|
||||
distances.append(self.dist(node, i))
|
||||
return [x for _,x in sorted(zip(distances, MST))]
|
||||
|
||||
def fit(self, max_it=1000):
|
||||
"""
|
||||
Put your iteration process here.
|
||||
"""
|
||||
|
||||
MST_solutions = []
|
||||
|
||||
# Depth First: Set one city as starting point, iterate to the end, then select next city as starting point.
|
||||
MSTs = []
|
||||
for i in range(0, self.N):
|
||||
MSTs.append([-1] * self.N)
|
||||
for i in range(0, self.N):
|
||||
solution = []
|
||||
solution.append(i)
|
||||
unvisited_list = list(range(0, self.N))
|
||||
cur_city = i
|
||||
# print("[starting]", i)
|
||||
for steps in range(self.N - 1):
|
||||
# print(unvisited_list)
|
||||
unvisited_list.remove(cur_city)
|
||||
if MSTs[cur_city][0] == -1:
|
||||
MST = self.getMST(cur_city)
|
||||
MSTs[cur_city] = MST
|
||||
|
||||
for j in MSTs[cur_city]:
|
||||
if(j in unvisited_list):
|
||||
solution.append(j)
|
||||
cur_city = j
|
||||
break
|
||||
# print(solution)
|
||||
MST_solutions.append(solution)
|
||||
self.fitness_list.append(self.fitness(solution))
|
||||
|
||||
self.best_solution = MST_solutions[ self.fitness_list.index(min(self.fitness_list)) ]
|
||||
|
||||
return self.best_solution, self.fitness_list
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
import math
|
||||
import random
|
||||
from model.base_model import Model
|
||||
from random import randint, sample
|
||||
|
||||
class Gene: # City
|
||||
def __init__(self, name, lat, lng):
|
||||
self.name = name
|
||||
self.lat = lat
|
||||
self.lng = lng
|
||||
|
||||
def get_distance_to(self, dest):
|
||||
return math.sqrt( (self.lng - dest.lng) ** 2 + (self.lat - dest.lat) ** 2 )
|
||||
|
||||
class Individual: # Route: possible solution to TSP
|
||||
def __init__(self, genes):
|
||||
assert(len(genes) > 3)
|
||||
self.genes = genes
|
||||
self.__reset_params()
|
||||
|
||||
def swap(self, gene_1, gene_2):
|
||||
self.genes[0]
|
||||
a, b = self.genes.index(gene_1), self.genes.index(gene_2)
|
||||
self.genes[b], self.genes[a] = self.genes[a], self.genes[b]
|
||||
self.__reset_params()
|
||||
|
||||
def add(self, gene):
|
||||
self.genes.append(gene)
|
||||
self.__reset_params()
|
||||
|
||||
@property
|
||||
def fitness(self):
|
||||
if self.__fitness == 0:
|
||||
self.__fitness = 1 / self.travel_cost # Normalize travel cost
|
||||
return self.__fitness
|
||||
|
||||
@property
|
||||
def travel_cost(self): # Get total travelling cost
|
||||
if self.__travel_cost == 0:
|
||||
for i in range(len(self.genes)):
|
||||
origin = self.genes[i]
|
||||
if i == len(self.genes) - 1:
|
||||
dest = self.genes[0]
|
||||
else:
|
||||
dest = self.genes[i+1]
|
||||
|
||||
self.__travel_cost += origin.get_distance_to(dest)
|
||||
|
||||
return self.__travel_cost
|
||||
|
||||
def __reset_params(self):
|
||||
self.__travel_cost = 0
|
||||
self.__fitness = 0
|
||||
|
||||
class Population: # Population of individuals
|
||||
def __init__(self, individuals):
|
||||
self.individuals = individuals
|
||||
|
||||
@staticmethod
|
||||
def gen_individuals(sz, genes):
|
||||
individuals = []
|
||||
for _ in range(sz):
|
||||
individuals.append(Individual(sample(genes, len(genes))))
|
||||
return Population(individuals)
|
||||
|
||||
def add(self, route):
|
||||
self.individuals.append(route)
|
||||
|
||||
def rmv(self, route):
|
||||
self.individuals.remove(route)
|
||||
|
||||
def get_fittest(self):
|
||||
fittest = self.individuals[0]
|
||||
for route in self.individuals:
|
||||
if route.fitness > fittest.fitness:
|
||||
fittest = route
|
||||
|
||||
return fittest
|
||||
|
||||
class MyGAModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.iteration = 0
|
||||
|
||||
def init(self, nodes):
|
||||
super().init(nodes)
|
||||
|
||||
def evolve(self, pop, tourn_size, mut_rate):
|
||||
new_generation = Population([])
|
||||
pop_size = len(pop.individuals)
|
||||
elitism_num = pop_size // 4
|
||||
|
||||
# Elitism
|
||||
for _ in range(elitism_num):
|
||||
fittest = pop.get_fittest()
|
||||
new_generation.add(fittest)
|
||||
pop.rmv(fittest)
|
||||
|
||||
# Crossover
|
||||
for _ in range(elitism_num, pop_size):
|
||||
parent_1 = self.selection(new_generation, tourn_size)
|
||||
parent_2 = self.selection(new_generation, tourn_size)
|
||||
child = self.crossover(parent_1, parent_2)
|
||||
new_generation.add(child)
|
||||
|
||||
# Mutation
|
||||
for i in range(elitism_num, pop_size):
|
||||
self.mutate(new_generation.individuals[i], mut_rate)
|
||||
|
||||
return new_generation
|
||||
|
||||
def crossover(self, parent_1, parent_2):
|
||||
def fill_with_parent1_genes(child, parent, genes_n):
|
||||
start_at = randint(0, len(parent.genes)-genes_n-1)
|
||||
finish_at = start_at + genes_n
|
||||
for i in range(start_at, finish_at):
|
||||
child.genes[i] = parent_1.genes[i]
|
||||
|
||||
def fill_with_parent2_genes(child, parent):
|
||||
j = 0
|
||||
for i in range(0, len(parent.genes)):
|
||||
if child.genes[i] == None:
|
||||
while parent.genes[j] in child.genes:
|
||||
j += 1
|
||||
child.genes[i] = parent.genes[j]
|
||||
j += 1
|
||||
|
||||
genes_n = len(parent_1.genes)
|
||||
child = Individual([None for _ in range(genes_n)])
|
||||
fill_with_parent1_genes(child, parent_1, genes_n // 2)
|
||||
fill_with_parent2_genes(child, parent_2)
|
||||
|
||||
return child
|
||||
|
||||
def mutate(self, individual, rate):
|
||||
for _ in range(len(individual.genes)):
|
||||
if random.random() < rate:
|
||||
sel_genes = sample(individual.genes, 2)
|
||||
individual.swap(sel_genes[0], sel_genes[1])
|
||||
|
||||
def selection(self, population, competitors_n):
|
||||
return Population(sample(population.individuals, competitors_n)).get_fittest()
|
||||
|
||||
def fit(self, max_it=100):
|
||||
"""
|
||||
Execute simulated annealing algorithm.
|
||||
"""
|
||||
pop_size = 1000
|
||||
mut_rate = 0.9
|
||||
tourn_size = 100
|
||||
|
||||
genes = [Gene(num, city[0], city[1]) for num, city in enumerate(self.coords)]
|
||||
self.genes = genes
|
||||
|
||||
population = Population.gen_individuals(pop_size, genes)
|
||||
|
||||
|
||||
for it in range(0, max_it):
|
||||
mut_rate = mut_rate * 0.95
|
||||
if mut_rate < 0.05:
|
||||
mut_rate = 0.05
|
||||
population = self.evolve(population, tourn_size, mut_rate)
|
||||
cost = population.get_fittest().travel_cost
|
||||
|
||||
it += 1
|
||||
self.fitness_list.append(cost)
|
||||
# print("[step] ", it, " [mut] ", mut_rate, " [best] ", self.fitness_list[self.fitness_list.index(min(self.fitness_list))])
|
||||
|
||||
self.best_solution = [gene.name for gene in population.get_fittest().genes]
|
||||
|
||||
return self.best_solution, self.fitness_list
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
import math
|
||||
import random
|
||||
import numpy as np
|
||||
from model.base_model import Model
|
||||
|
||||
class MyHillClimbModel(Model):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def init(self, nodes):
|
||||
"""
|
||||
Put your initialization here.
|
||||
"""
|
||||
super().init(nodes)
|
||||
|
||||
def random_tour(self):
|
||||
return np.random.permutation(self.N).tolist()
|
||||
|
||||
def all_pairs(self, size, shuffle=random.shuffle):
|
||||
r1 = list(range(size))
|
||||
r2 = list(range(size))
|
||||
if shuffle:
|
||||
shuffle(r1)
|
||||
shuffle(r2)
|
||||
for i in r1:
|
||||
for j in r2:
|
||||
yield (i,j)
|
||||
|
||||
def move_operator(self, tour):
|
||||
'''generator to return all possible variations
|
||||
where the section between two cities are swapped'''
|
||||
for i,j in self.all_pairs(len(tour)):
|
||||
if i != j:
|
||||
copy=tour[:]
|
||||
if i < j:
|
||||
copy[i:j+1]=reversed(tour[i:j+1])
|
||||
else:
|
||||
copy[i+1:]=reversed(tour[:j])
|
||||
copy[:j]=reversed(tour[i+1:])
|
||||
if copy != tour: # no point returning the same tour
|
||||
yield copy
|
||||
|
||||
def fit(self, max_it=100):
|
||||
"""
|
||||
Put your iteration process here.
|
||||
"""
|
||||
|
||||
self.best_solution = self.random_tour()
|
||||
best_score = -self.fitness(self.best_solution)
|
||||
|
||||
num_evaluations = 0
|
||||
|
||||
while num_evaluations < max_it:
|
||||
# examine moves around our current position
|
||||
move_made = False
|
||||
for next_solution in self.move_operator(self.best_solution):
|
||||
if num_evaluations >= max_it:
|
||||
print("Max iteration reached:", max_it)
|
||||
break
|
||||
|
||||
# see if this move is better than the current
|
||||
next_score = -self.fitness(next_solution)
|
||||
num_evaluations += 1
|
||||
if next_score > best_score:
|
||||
self.best_solution = next_solution
|
||||
self.fitness_list.append(self.fitness(self.best_solution))
|
||||
best_score=next_score
|
||||
move_made=True
|
||||
break # depth first search
|
||||
|
||||
if not move_made:
|
||||
break # we couldn't find a better move (must be at a local maximum)
|
||||
|
||||
return self.best_solution, self.fitness_list
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
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=1000):
|
||||
"""
|
||||
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
|
||||
|
|
@ -2,21 +2,24 @@ import math
|
|||
import random
|
||||
from model.base_model import Model
|
||||
|
||||
class SimAnneal(Model):
|
||||
def __init__(self, T=-1, alpha=-1, stopping_T=-1):
|
||||
class MySAModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.iteration = 0
|
||||
|
||||
self.T = T
|
||||
def init(self, nodes):
|
||||
super().init(nodes)
|
||||
|
||||
# Set hyper-parameters
|
||||
T = -1
|
||||
stopping_temperature = -1
|
||||
alpha = 0.99
|
||||
|
||||
self.T = math.sqrt(self.N) if T == -1 else T
|
||||
self.alpha = 0.995 if alpha == -1 else alpha
|
||||
self.stopping_temperature = 1e-8 if stopping_T == -1 else stopping_T
|
||||
self.stopping_temperature = 1e-8 if stopping_temperature == -1 else stopping_temperature
|
||||
|
||||
def init(self, coords):
|
||||
super().init(coords)
|
||||
|
||||
if (self.T == -1):
|
||||
self.T = math.sqrt(self.N)
|
||||
self.T_save = self.T # save inital T to reset if batch annealing is used
|
||||
|
||||
def initial_solution(self):
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
import math
|
||||
import random
|
||||
from model.base_model import Model
|
||||
|
||||
class MyUCSModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def init(self, nodes):
|
||||
"""
|
||||
Put your initialization here.
|
||||
"""
|
||||
super().init(nodes)
|
||||
|
||||
def getMST(self, node):
|
||||
MST = []
|
||||
distances = []
|
||||
for i in range(0, self.N):
|
||||
if i != node:
|
||||
MST.append(i)
|
||||
distances.append(self.dist(node, i))
|
||||
return [x for _,x in sorted(zip(distances, MST))]
|
||||
|
||||
def fit(self, max_it=1000):
|
||||
"""
|
||||
Put your iteration process here.
|
||||
"""
|
||||
|
||||
UCS_solutions = []
|
||||
UCS_losses = []
|
||||
|
||||
for i in range(0, self.N):
|
||||
solution = [i]
|
||||
UCS_solutions.append(solution)
|
||||
UCS_losses.append(math.inf)
|
||||
|
||||
MSTs = []
|
||||
for i in range(0, self.N):
|
||||
MSTs.append([-1] * self.N)
|
||||
|
||||
# Breadth First: Set each city as starting point, then go to next city simultaneously
|
||||
min_loss = math.inf
|
||||
while(len(UCS_solutions[ UCS_losses.index(min(UCS_losses)) ]) != self.N):
|
||||
unvisited_list = list(range(0, self.N))
|
||||
min_loss = min(UCS_losses)
|
||||
# For each search path
|
||||
for i in range(0, self.N):
|
||||
if UCS_losses[i] == min_loss:
|
||||
cur_city = UCS_solutions[i][-1]
|
||||
unvisited_list = list( set(range(0, self.N)) - set(UCS_solutions[i]) )
|
||||
if MSTs[cur_city][0] == -1:
|
||||
MST = self.getMST(cur_city)
|
||||
MSTs[cur_city] = MST
|
||||
|
||||
for j in MSTs[cur_city]:
|
||||
if(j in unvisited_list):
|
||||
UCS_solutions[i].append(j)
|
||||
|
||||
N = len(UCS_solutions[i])
|
||||
cur_fit = 0
|
||||
for k in range(len(UCS_solutions[i])):
|
||||
coord_0, coord_1 = self.coords[UCS_solutions[i][k % N]], self.coords[UCS_solutions[i][(k + 1) % N]]
|
||||
cur_fit += math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)
|
||||
UCS_losses[i] = cur_fit
|
||||
# if(UCS_losses[i] < min_loss):
|
||||
# min_loss = UCS_losses[i]
|
||||
break
|
||||
self.best_solution = UCS_solutions[ UCS_losses.index(min(UCS_losses)) ]
|
||||
self.fitness_list.append(self.fitness(self.best_solution))
|
||||
|
||||
return self.best_solution, self.fitness_list
|
||||
|
|
@ -26,40 +26,7 @@ def fitness(solution, coords):
|
|||
cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords)
|
||||
return cur_fit
|
||||
|
||||
def TSP_Bench(tsp_file, model, *args, max_it=1000, timeout=60):
|
||||
|
||||
start = timeit.default_timer()
|
||||
|
||||
# Model Running
|
||||
best_solution, fitness_list = TSP(tsp_file, model, *args, max_it=max_it,timeout=timeout)
|
||||
# Model End
|
||||
|
||||
stop = timeit.default_timer()
|
||||
print('[*] Running for: {time:.2f} seconds'.format(time=(stop - start)))
|
||||
|
||||
print()
|
||||
return best_solution, fitness_list, (stop - start)
|
||||
|
||||
def TSP_Bench_ALL(tsp_file_path, model, *args, max_it=1000, timeout=60):
|
||||
best_solutions = []
|
||||
fitness_lists = []
|
||||
times = []
|
||||
for root, _, files in os.walk(tsp_file_path):
|
||||
if(files):
|
||||
for f in files:
|
||||
# Get input file name
|
||||
tsp_file = str(root) + '/' + str(f)
|
||||
log(tsp_file)
|
||||
|
||||
# Run TSP
|
||||
best_solution, fitness_list, time = TSP_Bench(tsp_file, model, *args, max_it=max_it,timeout=timeout)
|
||||
best_solutions.append(best_solution)
|
||||
fitness_lists.append(fitness_lists)
|
||||
times.append(time)
|
||||
|
||||
return best_solutions, fitness_lists, times
|
||||
|
||||
def TSP(tsp_file, model, *args, max_it=1000, timeout=60):
|
||||
def TSP(tsp_file, model, timeout=60):
|
||||
|
||||
best_solution = []
|
||||
fitness_list = []
|
||||
|
|
@ -76,8 +43,8 @@ def TSP(tsp_file, model, *args, max_it=1000, timeout=60):
|
|||
|
||||
# Try your algorithm
|
||||
try:
|
||||
model.init(nodes, *args)
|
||||
best_solution, fitness_list = model.fit(max_it)
|
||||
model.init(nodes)
|
||||
best_solution, fitness_list = model.fit()
|
||||
except Exception as exc:
|
||||
if(str(exc) == "Timeout"):
|
||||
log("Timeout -3")
|
||||
|
|
@ -144,4 +111,60 @@ def TSP(tsp_file, model, *args, max_it=1000, timeout=60):
|
|||
with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.json', 'w') as outfile:
|
||||
json.dump(data, outfile)
|
||||
|
||||
return best_solution, fitness_list
|
||||
return best_solution, fitness_list
|
||||
|
||||
def TSP_Bench_ONE(tsp_file, model, timeout=60):
|
||||
|
||||
start = timeit.default_timer()
|
||||
|
||||
# Model Running
|
||||
best_solution, fitness_list = TSP(tsp_file, model, timeout=timeout)
|
||||
# Model End
|
||||
|
||||
stop = timeit.default_timer()
|
||||
print('[*] Running for: {time:.2f} seconds'.format(time=(stop - start)))
|
||||
|
||||
print()
|
||||
return best_solution, fitness_list, (stop - start)
|
||||
|
||||
def TSP_Bench_PATH(tsp_file_path, model, timeout=60):
|
||||
best_solutions = []
|
||||
fitness_lists = []
|
||||
times = []
|
||||
for root, _, files in os.walk(tsp_file_path):
|
||||
if(files):
|
||||
for f in files:
|
||||
# Get input file name
|
||||
tsp_file = os.path.join(root, str(f))
|
||||
log(tsp_file)
|
||||
|
||||
# Run TSP
|
||||
best_solution, fitness_list, time = TSP_Bench_ONE(tsp_file, model, timeout=timeout)
|
||||
best_solutions.append(best_solution)
|
||||
fitness_lists.append(fitness_lists)
|
||||
times.append(time)
|
||||
|
||||
return best_solutions, fitness_lists, times
|
||||
|
||||
def TSP_Bench_ALL(root, model):
|
||||
best_solutions_all = []
|
||||
fitness_lists_all = []
|
||||
times_all = []
|
||||
|
||||
best_solutions_simple, fitness_lists_simple, times_simple = TSP_Bench_PATH(os.path.join(root, "data/simple/"), model, timeout=60)
|
||||
best_solutions_medium, fitness_lists_medium, times_medium = TSP_Bench_PATH(os.path.join(root, "data/medium/"), model, timeout=180)
|
||||
best_solutions_hard, fitness_lists_hard, times_hard = TSP_Bench_PATH(os.path.join(root, "data/hard/"), model, timeout=300)
|
||||
|
||||
best_solutions_all.append(best_solutions_simple)
|
||||
best_solutions_all.append(best_solutions_medium)
|
||||
best_solutions_all.append(best_solutions_hard)
|
||||
|
||||
fitness_lists_all.append(fitness_lists_simple)
|
||||
fitness_lists_all.append(fitness_lists_medium)
|
||||
fitness_lists_all.append(fitness_lists_hard)
|
||||
|
||||
times_all.append(times_simple)
|
||||
times_all.append(times_medium)
|
||||
times_all.append(times_hard)
|
||||
|
||||
return [item for sublist in best_solutions_all for item in sublist], [item for sublist in fitness_lists_all for item in sublist], [item for sublist in times_all for item in sublist]
|
||||
Loading…
Reference in New Issue