From aca811e22835127a548ce09821f4d0e793975208 Mon Sep 17 00:00:00 2001 From: Lewy Date: Sun, 20 Jun 2021 18:02:11 +0200 Subject: [PATCH] GA implementation in env - use ga in traktor environment on field variables - adjusted fitness function --- AI/GeneticAlgorithm.py | 139 ++++++++++++++++++++++++----------------- AI/ga_methods.py | 46 +++++++++++++- main.py | 4 +- 3 files changed, 129 insertions(+), 60 deletions(-) diff --git a/AI/GeneticAlgorithm.py b/AI/GeneticAlgorithm.py index 9d39f6f..9d5974d 100644 --- a/AI/GeneticAlgorithm.py +++ b/AI/GeneticAlgorithm.py @@ -1,85 +1,91 @@ -import numpy +import random + +import keyboard as keyboard + +import field as F +from ga_methods import * +from src import mapschema as maps -import ga_methods # Genetic Algorithm -if __name__ == "__main__": +def genetic_algorithm_setup(field): + population_units = ["", "w", "p", "s"] - """ - The y=target is to maximize this equation ASAP: - y = w1x1+w2x2+w3x3+w4x4+w5x5+6wx6 - where (x1,x2,x3,x4,x5,x6)=(4,-2,3.5,5,-11,-4.7) - What are the best values for the 6 weights w1 to w6? - We are going to use the genetic algorithm for the best possible values after a number of generations. - """ + # new_population to be + population_text = [] - # Inputs of the equation. - equation_inputs = [4, -2, 3.5, 5, -11, -4.7] + # Populate the population_text array + for row in range(D.GSIZE): + population_text.append([]) + for column in range(D.GSIZE): + population_text[row].append(random.choice(population_units)) - # Number of the weights we are looking to optimize. - num_weights = len(equation_inputs) + # printer + for _ in population_text: + print(population_text) """ Genetic algorithm parameters: Mating pool size Population size """ + + # units per population in generation sol_per_pop = 8 num_parents_mating = 4 - # Defining the population size. - pop_size = (sol_per_pop, - num_weights) # The population will have sol_per_pop chromosome where each chromosome has num_weights genes. - # Creating the initial population. - new_population = numpy.random.uniform(low=-4.0, high=4.0, size=pop_size) - print(new_population) + population_values = [] + fitness_row = [] - """ - new_population[0, :] = [2.4, 0.7, 8, -2, 5, 1.1] - new_population[1, :] = [-0.4, 2.7, 5, -1, 7, 0.1] - new_population[2, :] = [-1, 2, 2, -3, 2, 0.9] - new_population[3, :] = [4, 7, 12, 6.1, 1.4, -4] - new_population[4, :] = [3.1, 4, 0, 2.4, 4.8, 0] - new_population[5, :] = [-2, 3, -7, 6, 3, 3] - """ + # population Fitness + for i in range(0, D.GSIZE): + for j in range(D.GSIZE): + fitness_row.append(local_fitness(field, i, j, population_text)) + population_values.append(fitness_row) best_outputs = [] - num_generations = 1000 - for generation in range(num_generations): - print("Generation : ", generation) - # Measuring the fitness of each chromosome in the population. - fitness = ga_methods.cal_pop_fitness(equation_inputs, new_population) - print("Fitness") - print(fitness) + num_generations = 10 - best_outputs.append(numpy.max(numpy.sum(new_population * equation_inputs, axis=1))) - # The best result in the current iteration. - print("Best result : ", numpy.max(numpy.sum(new_population * equation_inputs, axis=1))) + generation = 0 - # Selecting the best parents in the population for mating. - parents = ga_methods.select_mating_pool(new_population, fitness, - num_parents_mating) - print("Parents") - print(parents) + while generation < num_generations: + if keyboard.is_pressed('space'): + generation += 1 - # Generating next generation using crossover. - offspring_crossover = ga_methods.crossover(parents, - offspring_size=(pop_size[0] - parents.shape[0], num_weights)) - print("Crossover") - print(offspring_crossover) + print("Generation : ", generation) + # Measuring the fitness of each chromosome in the population. - # Adding some variations to the offspring using mutation. - offspring_mutation = ga_methods.mutation(offspring_crossover, num_mutations=2) - print("Mutation") - print(offspring_mutation) + fitness = cal_pop_fitness(population_values) + print("Fitness") + print(fitness) - # Creating the new population based on the parents and offspring. - new_population[0:parents.shape[0], :] = parents - new_population[parents.shape[0]:, :] = offspring_mutation + # best_outputs.append(best_Output(new_population)) + # The best result in the current iteration. + # print("Best result : ", best_Output(new_population)) + + # Selecting the best parents in the population for mating. + parents = select_mating_pool(new_population, fitness, + num_parents_mating) + print("Parents") + print(parents) + + # Generating next generation using crossover. + offspring_crossover = crossover(parents, offspring_size=(pop_size[0] - parents.shape[0], num_weights)) + print("Crossover") + print(offspring_crossover) + + # Adding some variations to the offspring using mutation. + offspring_mutation = mutation(offspring_crossover, num_mutations=2) + print("Mutation") + print(offspring_mutation) + + # Creating the new population based on the parents and offspring. + new_population[0:parents.shape[0], :] = parents + new_population[parents.shape[0]:, :] = offspring_mutation # Getting the best solution after iterating finishing all generations. # At first, the fitness is calculated for each solution in the final generation. - fitness = ga_methods.cal_pop_fitness(equation_inputs, new_population) + fitness = cal_pop_fitness(new_population) # Then return the index of that solution corresponding to the best fitness. best_match_idx = numpy.where(fitness == numpy.max(fitness)) @@ -92,3 +98,24 @@ if __name__ == "__main__": matplotlib.pyplot.xlabel("Iteration") matplotlib.pyplot.ylabel("Fitness") matplotlib.pyplot.show() + + # return best iteration of field + return 0 + + +if __name__ == "__main__": + + # Define the map of the field + mapschema = maps.createField() + + # Create field array + field = [] + + # Populate the field array + for row in range(D.GSIZE): + field.append([]) + for column in range(D.GSIZE): + fieldbit = F.Field(row, column, mapschema[column][row]) + field[row].append(fieldbit) + + genetic_algorithm_setup(field) diff --git a/AI/ga_methods.py b/AI/ga_methods.py index 42195d0..fdcb328 100644 --- a/AI/ga_methods.py +++ b/AI/ga_methods.py @@ -1,13 +1,49 @@ import numpy +import src.dimensions as D + + # Genetic Algorithm methods -x = "Hello world" + +def local_fitness(field, x, y, plants): + soil_value = 0 + if field[x][y].field_type == "soil": + soil_value = 1 + else: + soil_value = 0.5 + + if plants[x][y] == "": + plant_value = 0 + elif plants[x][y] == "w": + plant_value = 1 + elif plants[x][y] == "p": + plant_value = 2 + elif plants[x][y] == "s": + plant_value = 3 + + neighbour_bonus = 1 + if x - 1 >= 0: + if plants[x][y] == plants[x - 1][y]: + neighbour_bonus += 1 + if x + 1 < D.GSIZE: + if plants[x][y] == plants[x + 1][y]: + neighbour_bonus += 1 + if y - 1 >= 0: + if plants[x][y] == plants[x][y - 1]: + neighbour_bonus += 1 + if y + 1 < D.GSIZE: + if plants[x][y] == plants[x][y + 1]: + neighbour_bonus += 1 + + # TODO * multiculture_bonus + local_fitness_value = (soil_value + plant_value) * (0.5 * neighbour_bonus + 1) + return local_fitness_value -def cal_pop_fitness(equation_inputs, pop): +def cal_pop_fitness(pop): # Calculating the fitness value of each solution in the current population. # The fitness function calulates the sum of products between each input and its corresponding weight. - fitness = numpy.sum(pop * equation_inputs, axis=1) + fitness = sum(map(sum, pop)) return fitness @@ -50,3 +86,7 @@ def mutation(offspring_crossover, num_mutations=1): offspring_crossover[idx, gene_idx] = offspring_crossover[idx, gene_idx] + random_value gene_idx = gene_idx + mutations_counter return offspring_crossover + + +def best_Output(new_population): + return numpy.max(numpy.sum(new_population * equation_inputs, axis=1)) diff --git a/main.py b/main.py index c9dc836..7203e66 100644 --- a/main.py +++ b/main.py @@ -43,13 +43,15 @@ if __name__ == "__main__": fieldbit = F.Field(row, column, mapschema[column][row]) field[row].append(fieldbit) + # genetic_algorithm_setup(field) + # Create Tractor object tractor = T.Tractor(field, [0, 0]) # Define the map of plants mapschema = maps.createPlants() - # Createt plants array + # Create plants array plants = [] # Populate the plants array