diff --git a/AI/GeneticAlgorithm.py b/AI/GeneticAlgorithm.py index 15ff7c3..5f1d62d 100644 --- a/AI/GeneticAlgorithm.py +++ b/AI/GeneticAlgorithm.py @@ -1,5 +1,3 @@ -import random - import keyboard as keyboard import field as F @@ -11,7 +9,7 @@ from src import mapschema as maps def genetic_algorithm_setup(field): population_units = ["", "w", "p", "s"] - # new_population to be + # TODO REPREZENTACJA OSOBNIKA - MACIERZ ROZKłADU PLONÓW population_text = [] population_text_single = [] @@ -55,7 +53,9 @@ def genetic_algorithm_setup(field): # population Fitness fitness = [] + for i in range(0, population_size): + print(len(population_text), i) fitness.append((i, population_fitness(population_text[i], field, population_size))) print("Fitness") @@ -73,33 +73,52 @@ def genetic_algorithm_setup(field): # Selecting the best parents in the population for mating. parents = [population_text[i[0]] for i in best] print("Parents") - print(parents) + for i in range(0, len(parents)): + print('\n'.join([''.join(['{:4}'.format(item) for item in row]) + for row in parents[i]])) + print("") # Generating next generation using crossover. offspring_x = random.randint(1, D.GSIZE - 2) offspring_y = random.randint(1, D.GSIZE - 2) - offspring_crossover = crossover(parents, offspring_size=(pop_size[0] - parents.shape[0], num_weights)) + offspring_crossover = crossover(parents) print("Crossover") - print(offspring_crossover) + for i in range(0, len(offspring_crossover)): + print('\n'.join([''.join(['{:4}'.format(item) for item in row]) + for row in offspring_crossover[i]])) + print("") # Adding some variations to the offspring using mutation. - offspring_mutation = mutation(offspring_crossover, num_mutations=2) + offspring_mutation = mutation(population_units, offspring_crossover, population_size - num_parents, + num_mutations=10) print("Mutation") - print(offspring_mutation) + for i in range(0, len(offspring_mutation)): + print('\n'.join([''.join(['{:4}'.format(item) for item in row]) + for row in offspring_mutation[i]])) + print("") - # Creating the new population based on the parents and offspring. - new_population[0:parents.shape[0], :] = parents - new_population[parents.shape[0]:, :] = offspring_mutation + # Creating next generation + population_text = [] + for k in range(0, len(parents)): + population_text.append(parents) + for k in range(0, len(offspring_mutation)): + population_text.append(offspring_mutation[k]) - # Getting the best solution after iterating finishing all generations. - # At first, the fitness is calculated for each solution in the final generation. - 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)) + # final Fitness + fitness = [] + for i in range(0, population_size): + fitness.append((i, population_fitness(population_text[i], field, population_size))) - print("Best solution : ", new_population[best_match_idx, :]) - print("Best solution fitness : ", fitness[best_match_idx]) + print("Final Fitness") + print(fitness) + + best = sorted(fitness, key=lambda tup: tup[1])[0:num_parents] + + print("Best solution : ", ) + for i in range(0, D.GSIZE): + print(population_text[best[0][0]][i]) + print("Best solution fitness : ", best[0][1]) pretty_printer(best_outputs) diff --git a/AI/ga_methods.py b/AI/ga_methods.py index f511de7..aff52ab 100644 --- a/AI/ga_methods.py +++ b/AI/ga_methods.py @@ -1,3 +1,6 @@ +import copy +import random + import matplotlib import numpy @@ -25,6 +28,7 @@ def local_fitness(field, x, y, plants_case): plant_value = 1 neighbour_bonus = 1 + print(x, y) if x - 1 >= 0: if plants_case[x][y] == plants_case[x - 1][y]: neighbour_bonus += 1 @@ -64,36 +68,39 @@ def population_fitness(population_text, field, population_size): return fitness -def crossover(parents, offspring_size): - current_parrent = parents[0] - new_part = [] - - offspring = numpy.empty(offspring_size) - # The point at which crossover takes place between two parents. Usually, it is at the center. - crossover_point = numpy.uint8(offspring_size[1] / 2) - - for k in range(offspring_size[0]): - # Index of the first parent to mate. - parent1_idx = k % parents.shape[0] - # Index of the second parent to mate. - parent2_idx = (k + 1) % parents.shape[0] - # The new offspring will have its first half of its genes taken from the first parent. - offspring[k, 0:crossover_point] = parents[parent1_idx, 0:crossover_point] - # The new offspring will have its second half of its genes taken from the second parent. - offspring[k, crossover_point:] = parents[parent2_idx, crossover_point:] - return offspring +def crossover(parents): + ret = [] + for i in range(0, len(parents)): + child = copy.deepcopy(parents[i]) + # Vertical randomization + width = random.randint(1, D.GSIZE / len(parents)) # width of stripes + indexes_parents = numpy.random.permutation(range(0, len(parents))) # sorting of stripes + beginning = random.randint(0, len(parents[0]) - width * len(parents)) # point we start putting the stripes from + for x in indexes_parents: + child[beginning:beginning + width] = parents[x][beginning:beginning + width] + beginning += width + ret.append(child) + return ret -def mutation(offspring_crossover, num_mutations=1): - mutations_counter = numpy.uint8(offspring_crossover.shape[1] / num_mutations) - # Mutation changes a number of genes as defined by the num_mutations argument. The changes are random. - for idx in range(offspring_crossover.shape[0]): - gene_idx = mutations_counter - 1 - for mutation_num in range(num_mutations): - # The random value to be added to the gene. - random_value = numpy.random.uniform(-1.0, 1.0, 1) - offspring_crossover[idx, gene_idx] = offspring_crossover[idx, gene_idx] + random_value - gene_idx = gene_idx + mutations_counter +def mutation(population_units, offspring_crossover, num_mutants, num_mutations=10): + for case in range(0, len(offspring_crossover)): + for mutation in range(0, num_mutations): + mutation_x = random.randint(0, D.GSIZE - 1) + mutation_y = random.randint(0, D.GSIZE - 1) + mutation_value = random.choice(population_units) + offspring_crossover[case][mutation_x][mutation_y] = mutation_value + num_mutants -= 1 + + while num_mutants > 0: + case = random.randint(0, len(offspring_crossover)) + for mutation in range(0, num_mutations): + mutation_x = random.randint(0, D.GSIZE - 1) + mutation_y = random.randint(0, D.GSIZE - 1) + mutation_value = random.choice(population_units) + offspring_crossover[case][mutation_x][mutation_y] = mutation_value + num_mutants -= 1 + return offspring_crossover