import random class Genetic(): pass def calc_cost(self, mines_list): self.mined_tile_count = len(mines_list) total_cost = 0 i = 0 while i < (self.mined_tile_count - 1): total_cost = total_cost + self.manhattan_cost_counter(mines_list, i) i = i + 1 return total_cost def manhattan_cost_counter(self, mines_list, i): x1, y1 = mines_list[i][0], mines_list[i][1] x2, y2 = mines_list[i+1][0], mines_list[i+1][1] return abs(x2 - x1) + abs(y2 - y1) def population_initialization(self, mines_list, i): first_mine = mines_list[0] x = len(mines_list)-1 shuffled_coordinates = [] while x > 0: shuffled_coordinates.append(mines_list[x]) x = x - 1 mine_chromosome = [] while i > 0: child = random.sample(shuffled_coordinates, len(shuffled_coordinates)) child.insert(0, first_mine) #child.insert(x, first_mine) mine_chromosome.append(child) i = i - 1 return mine_chromosome def fitness_function(self, generations): total_cost = 0 chromosome_count = 0 chromosome_costs = [] y = 0 #problem - wyjście poza liste if len(generations) == 0: return first_cost = self.calc_cost(generations[y]) cheapest_chromosome = generations[y] lowest_cost = first_cost highest_cost = first_cost for i in generations: chromosome_costs.append(self.calc_cost(i)) total_cost = total_cost + self.calc_cost(i) chromosome_count = chromosome_count + 1 if self.calc_cost(i) < lowest_cost: lowest_cost = self.calc_cost(i) cheapest_chromosome = i if self.calc_cost(i) > highest_cost: highest_cost = self.calc_cost(i) average_fitness = total_cost/chromosome_count chromosome_fitness = [] total_chromosome_fitness = 0 l = 0 for i in chromosome_costs: chromosome_fitness.append(round(((average_fitness/chromosome_costs[l])*10), 2)) total_chromosome_fitness += round(((average_fitness/chromosome_costs[l])*10),2) l = l + 1 return(chromosome_fitness, lowest_cost, highest_cost, average_fitness, cheapest_chromosome) def fitness_population_selection(self, first_generation, chromosome_fitness): x = len(chromosome_fitness) roulette_table = [] average_population = [] i = 0 interval = 0 while x > 0: interval = interval + chromosome_fitness[i] roulette_table.append(round(interval, 2)) x = x - 1 i = i + 1 x = len(chromosome_fitness)/2 max = roulette_table[i - 1] while x > 0: i = 0 n = random.uniform(0, max) while n > roulette_table[i]: i = i + 1 average_population.append(first_generation[i]) x = x - 1 return average_population def crossover(self, average_population): post_crossover_population = [] x = len(average_population) - 1 if x <= 0: print("no enough chromosomes to crossover") return while x > 0: parent_1 = average_population[x] parent_2 = average_population[x-1] child_1 = [] child_2 = [] crossover_decision = random.randint(1, 100) if (crossover_decision < 11) and (parent_1 != parent_2): crossover_point = random.randint(1, (len(average_population[x])-3)) l = 0 k = crossover_point while k >= 0: child_1.append(parent_1[l]) l = l + 1 k = k - 1 k = crossover_point while k < (len(parent_1) - 1): for i in parent_2: if i not in child_1: child_1.append(i) k = k + 1 l = 0 k = crossover_point while k >= 0: child_2.append(parent_2[l]) l = l + 1 k = k - 1 k = crossover_point while k >= 0: child_2.append(parent_2[l]) l = l + 1 k = k - 1 k = crossover_point while k < (len(parent_1) - 1): for i in parent_1: if i not in child_2: child_2.append(i) k = k + 1 #child_1.append(0) #child_2.append(0) else: child_1 = parent_1 child_2 = parent_2 post_crossover_population.append(child_1) post_crossover_population.append(child_2) x = x - 1 return post_crossover_population def mutation(self, post_crossover_popualtion): k = len(post_crossover_popualtion) - 1 while k >= 0: mutation_decision = random.randint(0, 100) if mutation_decision < 3: mutated_chromosome = post_crossover_popualtion[k] post_crossover_popualtion.remove(mutated_chromosome) l = len(mutated_chromosome) - 1 x = random.randint(1, l) y = random.randint(1, l) while x == y: y = random.randint(1, l) replacement = mutated_chromosome[x] mutated_chromosome[y] = replacement post_crossover_popualtion.insert(k, mutated_chromosome) k = k - 1 post_mutation_population = post_crossover_popualtion return post_mutation_population def optimize(self, post_mutation_population, mine_list): post_optimization_population = post_mutation_population i = len(post_mutation_population) l = 1 while l < i: k = 1 while k >= 0: if post_mutation_population[l] == post_mutation_population[k - 1]: post_optimization_population.remove(post_mutation_population[k-1]) x = len(mine_list) - 2 shuffled_coordinates = [] while x > 0: shuffled_coordinates.append(mine_list[x]) x = x - 1 x = len(mine_list) - 1 new_chromosome = random.sample(shuffled_coordinates, len(shuffled_coordinates)) new_chromosome.insert(0, mine_list[0]) new_chromosome.insert(x, mine_list[0]) post_optimization_population.append(new_chromosome) k = k - 1 l = l + 1 return post_optimization_population def genetic_algorythm(self, coordinates): self.full_cost = self.calc_cost(coordinates) self.first_generation = self.population_initialization(coordinates,10) self.fitness, self.lowest_cost, self.highest_cost, self.average_fitness_of_first_genetation, self.cheapest_individual = self.fitness_function(self.first_generation) self.average_population = self.fitness_population_selection(self.first_generation, self.fitness) self.population_after_crossover = self.crossover(self.average_population) if self.population_after_crossover == None: print("Finished in " + str(self.which_generation) + "generations") return self.population_after_mutation = self.mutation(self.population_after_crossover) self.population_after_optimization = self.optimize(self.population_after_mutation, coordinates) self.max_cost = self.highest_cost self.min_cost = self.lowest_cost self.cheapest_route = self.cheapest_individual i = 2 self.which_generation = 1 while i < 41: print(" ") print("***********") print("Generation " + str(i)) print("***********") print(" ") if self.fitness_function(self.population_after_optimization) == None: return self.fitness, self.lowest_cost, self.highest_cost, self.average_fitness_of_first_genetation, self.cheapest_individual = self.fitness_function(self.population_after_optimization) if self.highest_cost > self.max_cost: self.max_cost = self.highest_cost if self.lowest_cost < self.min_cost: self.min_cost = self.lowest_cost self.cheapest_route = self.cheapest_individual self.which_generation = i print("New lowest cost: " + str(self.min_cost)) print("New cheapest route: " + str(self.cheapest_route)) self.average_population = self.fitness_population_selection(self.population_after_mutation, self.fitness) self.population_after_crossover = self.crossover(self.average_population) if self.population_after_crossover == None: print("Finished") return self.population_after_mutation = self.mutation(self.population_after_crossover) self.population_after_optimization = self.optimize(self.population_after_mutation, coordinates) i = i + 1 if(self.min_cost)/(self.average_fitness_of_first_genetation) < (0.7): print("Finished after " + str(i)+ " generations") break print("Average fitness of first generation: " + str(self.average_fitness_of_first_genetation)) print("Relation of efficiency growth: " + str((self.min_cost)/(self.average_fitness_of_first_genetation))) print("Lowest cost is " + str(self.min_cost)) print("Cheapest route is: " + str(self.cheapest_route)) def run(self): Mines = [[1,1], [2,4], [3,1], [4,7], [5,3], [7,6]] self.genetic_algorythm(Mines)