GenericAI_Sweeper/genetic.py

278 lines
10 KiB
Python
Raw Normal View History

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)