GA implementation

- ADD crossover
- ADD mutation
- ADD next_gen preparation
- Project completed (with errors)

with Michał Malinowski
This commit is contained in:
Lewy 2021-06-21 03:24:07 +02:00
parent 7a14078390
commit 288d3cf30a
2 changed files with 72 additions and 46 deletions

View File

@ -1,5 +1,3 @@
import random
import keyboard as keyboard import keyboard as keyboard
import field as F import field as F
@ -11,7 +9,7 @@ from src import mapschema as maps
def genetic_algorithm_setup(field): def genetic_algorithm_setup(field):
population_units = ["", "w", "p", "s"] population_units = ["", "w", "p", "s"]
# new_population to be # TODO REPREZENTACJA OSOBNIKA - MACIERZ ROZKłADU PLONÓW
population_text = [] population_text = []
population_text_single = [] population_text_single = []
@ -55,7 +53,9 @@ def genetic_algorithm_setup(field):
# population Fitness # population Fitness
fitness = [] fitness = []
for i in range(0, population_size): for i in range(0, population_size):
print(len(population_text), i)
fitness.append((i, population_fitness(population_text[i], field, population_size))) fitness.append((i, population_fitness(population_text[i], field, population_size)))
print("Fitness") print("Fitness")
@ -73,33 +73,52 @@ def genetic_algorithm_setup(field):
# Selecting the best parents in the population for mating. # Selecting the best parents in the population for mating.
parents = [population_text[i[0]] for i in best] parents = [population_text[i[0]] for i in best]
print("Parents") 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. # Generating next generation using crossover.
offspring_x = random.randint(1, D.GSIZE - 2) offspring_x = random.randint(1, D.GSIZE - 2)
offspring_y = 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("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. # 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("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. # Creating next generation
new_population[0:parents.shape[0], :] = parents population_text = []
new_population[parents.shape[0]:, :] = offspring_mutation 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. # final Fitness
# At first, the fitness is calculated for each solution in the final generation. fitness = []
fitness = cal_pop_fitness(new_population) for i in range(0, population_size):
# Then return the index of that solution corresponding to the best fitness. fitness.append((i, population_fitness(population_text[i], field, population_size)))
best_match_idx = numpy.where(fitness == numpy.max(fitness))
print("Best solution : ", new_population[best_match_idx, :]) print("Final Fitness")
print("Best solution fitness : ", fitness[best_match_idx]) 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) pretty_printer(best_outputs)

View File

@ -1,3 +1,6 @@
import copy
import random
import matplotlib import matplotlib
import numpy import numpy
@ -25,6 +28,7 @@ def local_fitness(field, x, y, plants_case):
plant_value = 1 plant_value = 1
neighbour_bonus = 1 neighbour_bonus = 1
print(x, y)
if x - 1 >= 0: if x - 1 >= 0:
if plants_case[x][y] == plants_case[x - 1][y]: if plants_case[x][y] == plants_case[x - 1][y]:
neighbour_bonus += 1 neighbour_bonus += 1
@ -64,36 +68,39 @@ def population_fitness(population_text, field, population_size):
return fitness return fitness
def crossover(parents, offspring_size): def crossover(parents):
current_parrent = parents[0] ret = []
new_part = [] for i in range(0, len(parents)):
child = copy.deepcopy(parents[i])
offspring = numpy.empty(offspring_size) # Vertical randomization
# The point at which crossover takes place between two parents. Usually, it is at the center. width = random.randint(1, D.GSIZE / len(parents)) # width of stripes
crossover_point = numpy.uint8(offspring_size[1] / 2) 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 k in range(offspring_size[0]): for x in indexes_parents:
# Index of the first parent to mate. child[beginning:beginning + width] = parents[x][beginning:beginning + width]
parent1_idx = k % parents.shape[0] beginning += width
# Index of the second parent to mate. ret.append(child)
parent2_idx = (k + 1) % parents.shape[0] return ret
# 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 mutation(offspring_crossover, num_mutations=1): def mutation(population_units, offspring_crossover, num_mutants, num_mutations=10):
mutations_counter = numpy.uint8(offspring_crossover.shape[1] / num_mutations) for case in range(0, len(offspring_crossover)):
# Mutation changes a number of genes as defined by the num_mutations argument. The changes are random. for mutation in range(0, num_mutations):
for idx in range(offspring_crossover.shape[0]): mutation_x = random.randint(0, D.GSIZE - 1)
gene_idx = mutations_counter - 1 mutation_y = random.randint(0, D.GSIZE - 1)
for mutation_num in range(num_mutations): mutation_value = random.choice(population_units)
# The random value to be added to the gene. offspring_crossover[case][mutation_x][mutation_y] = mutation_value
random_value = numpy.random.uniform(-1.0, 1.0, 1) num_mutants -= 1
offspring_crossover[idx, gene_idx] = offspring_crossover[idx, gene_idx] + random_value
gene_idx = gene_idx + mutations_counter 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 return offspring_crossover