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 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)

View File

@ -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