class Instance(object): """ Instance class representing the TSP Instance """ def __init__(self, nodes, alpha, beta, decay, q): # Make a list of nodes as variables which are JSONifiable nodes_var = [] for node in nodes: nodes_var.append(vars(node)) self.nodes = nodes_var self.alpha = alpha self.beta = beta self.decay = decay self.q = q self.min_pheromone = 0.01 self.local_deposit = 0.1 self.distances = [] self.pheromones = [] colony = Colony() self.ants = colony.ants self.shortest_path = colony.shortest_path self.min_distance = colony.min_distance # Initialise the distances between nodes and pheromone trails for i in range(len(nodes)): distances = [] pheromones = [] for j in range(len(nodes)): distances.append(0 if i == j else nodes[i].distance(nodes[j])) pheromones.append(self.min_pheromone) self.distances.append(distances) self.pheromones.append(pheromones) def get_path_distance(self, path): """ Returns the total total distance of a path taken """ length = len(path) distance = 0 for i in range(length): distance += self.distances[path[i]][path[(i + 1) % length]] return distance def update_pheromones(self, colony): """ Updates pheromones between nodes globally, a way of letting ants know on future generations about the strongest paths to take. """ # Decay all pheromone trails for i in range(len(self.nodes)): for j in range(len(self.nodes)): self.pheromones[i][j] *=(1- self.decay) # Add to edge pheromones if edge was part of successful tour for ant in colony.ants: distance = self.get_path_distance(ant.path) if distance <= colony.min_distance: for i, j in ant.nodes_traversed(): self.pheromones[i][j] += self.q / distance # Keep pheromone trails greater than or equal to 0.01, so nodes do not become # completely unviable choices. for i in range(len(self.nodes)): for j in range(len(self.nodes)): self.pheromones[i][j] = max(self.pheromones[i][j], self.min_pheromone) def aco(self, gens, current_gen, client): """ Returns the generation reached and the shortest path found by the aco algorithm along with its distance """ # The time at the start of the algorithm time_start = time.time() # Initalise the colony and its parameters self.colony = Colony() self.colony.ants = self.ants self.colony.shortest_path = self.shortest_path self.colony.min_distance = self.min_distance # Initialise an array to be append with nodes shortest_path = [] # Do generations from the current generation to the generation number needed for i in range(current_gen, gens): # The current time time_now = time.time() time_elapsed = time_now-time_start # If exectutiion time has reached 25 seconds, return result if (time_elapsed) > 25: break # Ants within colony perform their tours self.colony.perform_tours(self) # Get the shortest tour found by the ants shortest_path = self.colony.shortest_path # Global update of pheromones self.update_pheromones(self.colony) # Generation successful, thus increase the generation reached gen_reached = i+1 # Update Instance parameters to be returned to client self.shortest_path = shortest_path self.min_distance = self.colony.min_distance msg = "Generation " + str(i) + " distance " + str(round(self.colony.min_distance, 3)) + " path " + str(shortest_path) # Emit a message using SocketIO for a dynamic console socketio.emit('my event', msg, room=client) socketio.sleep(0.00000000001) return gen_reached, shortest_path, self.colony.min_distance