Added comments & fixed small bug

Mostly added comments, but also fixed a small bug in parent selection where the tournament size would be much smaller than it should be.
This commit is contained in:
RyleyGG
2020-10-12 09:23:41 -04:00
parent c3d9ef8bd1
commit 94d7c52666
7 changed files with 50 additions and 46 deletions

View File

@ -45,7 +45,7 @@ class GA:
self.initialization_impl = Initialization_Methods.random_initialization self.initialization_impl = Initialization_Methods.random_initialization
self.fitness_function_impl = Fitness_Examples.index_dependent_values self.fitness_function_impl = Fitness_Examples.index_dependent_values
# Selects which chromosomes should be automaticly moved to the next population # Selects which chromosomes should be automaticly moved to the next population
self.survivor_selection_impl = Survivor_Selection.remove_two_worst self.survivor_selection_impl = Survivor_Selection.remove_worst
# Methods for accomplishing parent-selection -> Crossover -> Mutation # Methods for accomplishing parent-selection -> Crossover -> Mutation
self.parent_selection_impl = Parent_Selection.Tournament.with_replacement self.parent_selection_impl = Parent_Selection.Tournament.with_replacement
self.crossover_impl = Crossover_Methods.single_point_crossover self.crossover_impl = Crossover_Methods.single_point_crossover

View File

@ -3,19 +3,13 @@ from initialization.chromosome_structure.chromosome import Chromosome
from initialization.population_structure.population import Population from initialization.population_structure.population import Population
class Crossover_Methods: class Crossover_Methods:
""" Crossover explination goes here.
Points - Defined as sections between the chromosomes genetic makeup
"""
def __init__(self):
pass
def single_point_crossover(ga): def single_point_crossover(ga):
"""Single point crossover is when a "point" is selected and the genetic """Single point crossover is when a "point" is selected and the genetic
make up of the two parent chromosomes are "Crossed" or better known as swapped""" make up of the two parent chromosomes are swapped at that point"""
crossover_pool = ga.population.mating_pool crossover_pool = ga.population.mating_pool
"""The structure of GA requires that the crossover method return a population strictly with offspring chromosomes"""
new_population = Population() new_population = Population()
for i in range(len(crossover_pool)): for i in range(len(crossover_pool)):
if i + 1 < len(crossover_pool): if i + 1 < len(crossover_pool):

View File

@ -16,11 +16,9 @@ class Fitness_Examples:
return fitness return fitness
def index_dependent_values(chromosome): def index_dependent_values(chromosome):
"""A very simple case test function - If the chromosomes gene value is a 5 add one """Test of the GA's ability to improve fitness when the value is index-dependent"""
to the chromosomes overall fitness value.""" """If a gene is equal to its index in the chromosome + 1, fitness is incremented"""
# Overall fitness value
fitness = 0 fitness = 0
# For each gene in the chromosome
for i in range(len(chromosome.gene_list)): for i in range(len(chromosome.gene_list)):
if (chromosome.gene_list[i].value == i+1): if (chromosome.gene_list[i].value == i+1):
fitness += 1 fitness += 1

View File

@ -6,13 +6,16 @@ class Mutation_Methods:
pass pass
def random_mutation(ga, chromosome_set = None): def random_mutation(ga, chromosome_set = None):
"""Will take the input population and randomly reset entire chromosomes based on the GA's mutation rate"""
"""Defaulting to the GA's current population if no input is explicitly given"""
if chromosome_set == None: if chromosome_set == None:
chromosome_set = ga.population.get_all_chromosomes() chromosome_set = ga.population.get_all_chromosomes()
chromosome_mutate_num = int(len(chromosome_set)*ga.mutation_rate) chromosome_mutate_num = int(len(chromosome_set)*ga.mutation_rate)
temp_population = ga.initialization_impl(ga) temp_population = ga.initialization_impl(ga)
"""While more chromosomes need to be mutated, grab a random chromosome and re-initialize it entirely"""
while chromosome_mutate_num > 0: while chromosome_mutate_num > 0:
chromosome_set[random.randint(0,ga.population_size-1)] = temp_population.get_all_chromosomes()[chromosome_mutate_num] chromosome_set[random.randint(0,ga.population_size-1)] = temp_population.get_all_chromosomes()[chromosome_mutate_num]
chromosome_mutate_num -= 1 chromosome_mutate_num -= 1
@ -20,7 +23,8 @@ class Mutation_Methods:
return chromosome_set return chromosome_set
def per_gene_mutation(ga, chromosome_set = None, gene_mutate_count = 1): def per_gene_mutation(ga, chromosome_set = None, gene_mutate_count = 1):
"""Will iterate through all chromosomes, and if its selected, will randomly replace one of its genes based on initialization values"""
gene_mutate_count_static = int(gene_mutate_count) gene_mutate_count_static = int(gene_mutate_count)
if chromosome_set == None: if chromosome_set == None:
@ -29,10 +33,12 @@ class Mutation_Methods:
for i in range(len(chromosome_set)): for i in range(len(chromosome_set)):
random_num = random.uniform(0,1) random_num = random.uniform(0,1)
"""If a chromosome was selected to be mutated"""
if (random_num <= ga.mutation_rate): if (random_num <= ga.mutation_rate):
while gene_mutate_count > 0: while gene_mutate_count > 0:
dummy_population = ga.initialization_impl(ga) #Really inefficient, but works for now dummy_population = ga.initialization_impl(ga) #Really inefficient, but works for now
random_index = random.randint(0, ga.chromosome_length-1) random_index = random.randint(0, ga.chromosome_length-1)
"""Replaces a random gene in the actual chromosome with a gene from a newly initialized chromosome"""
chromosome_set[i].get_genes()[random_index] = dummy_population.get_all_chromosomes()[random.randint(0,ga.population_size-1)].get_genes()[random_index] chromosome_set[i].get_genes()[random_index] = dummy_population.get_all_chromosomes()[random.randint(0,ga.population_size-1)].get_genes()[random_index]
gene_mutate_count -= 1 gene_mutate_count -= 1
gene_mutate_count = int(gene_mutate_count_static) gene_mutate_count = int(gene_mutate_count_static)

View File

@ -7,7 +7,7 @@ from initialization.chromosome_structure.chromosome import Chromosome
class Parent_Selection: class Parent_Selection:
class Tournament: class Tournament:
def with_replacement(ga): def with_replacement(ga):
tournament_size = int(len(ga.population.get_all_chromosomes())*ga.parent_ratio*ga.tournament_size_ratio) tournament_size = int(len(ga.population.get_all_chromosomes())*ga.tournament_size_ratio)
if tournament_size < 5: if tournament_size < 5:
tournament_size = 5 tournament_size = 5
# Probability used for determining if a chromosome should enter the mating pool. # Probability used for determining if a chromosome should enter the mating pool.

View File

@ -4,7 +4,7 @@ import random
# Create the Genetic algorithm # Create the Genetic algorithm
ga = EasyGA.GA() ga = EasyGA.GA()
ga.population_size = 15 ga.population_size = 100
ga.chromosome_length = 10 ga.chromosome_length = 10
ga.generation_goal = 100 ga.generation_goal = 100
ga.gene_impl = [random.randint,1,10] ga.gene_impl = [random.randint,1,10]

View File

@ -5,32 +5,38 @@ from initialization.population_structure.population import Population
from initialization.chromosome_structure.chromosome import Chromosome from initialization.chromosome_structure.chromosome import Chromosome
class Survivor_Selection: class Survivor_Selection:
def repeated_crossover(ga, next_population): #Might be cheating? I don't know honestly - RG """Survivor selection determines which individuals should be brought to the next generation"""
while len(next_population.get_all_chromosomes()) < ga.population_size:
crossover_pool = ga.population.mating_pool
split_point = random.randint(0,ga.chromosome_length) """ Pretty sure this isn't actually survivor selection - seems like its 'cheating'
chromosome_list = [] def repeated_crossover(ga, next_population):
for i in range(len(crossover_pool)): while len(next_population.get_all_chromosomes()) < ga.population_size:
if i + 1 < len(crossover_pool): crossover_pool = ga.population.mating_pool
new_gene_set = []
parent_one = crossover_pool[i].get_genes() split_point = random.randint(0,ga.chromosome_length)
parent_two = crossover_pool[i+1].get_genes() chromosome_list = []
new_gene_set.extend(parent_one[0:split_point]) for i in range(len(crossover_pool)):
new_gene_set.extend(parent_two[split_point:]) if i + 1 < len(crossover_pool):
new_chromosome = create_chromosome(new_gene_set) new_gene_set = []
chromosome_list.append(new_chromosome) parent_one = crossover_pool[i].get_genes()
parent_two = crossover_pool[i+1].get_genes()
new_gene_set.extend(parent_one[0:split_point])
for i in range(len(chromosome_list)): new_gene_set.extend(parent_two[split_point:])
next_population.add_chromosome(chromosome_list[i]) new_chromosome = create_chromosome(new_gene_set)
if len(next_population.get_all_chromosomes()) >= ga.population_size: chromosome_list.append(new_chromosome)
break
return next_population
for i in range(len(chromosome_list)):
def remove_two_worst(ga, next_population): next_population.add_chromosome(chromosome_list[i])
iterator = 0 if len(next_population.get_all_chromosomes()) >= ga.population_size:
while len(next_population.get_all_chromosomes()) < ga.population_size: break
next_population.add_chromosome(ga.population.get_all_chromosomes()[iterator]) return next_population
iterator += 1 """
return next_population
"""Will bring all but the worst-performing chromosomes from the current generation"""
"""The exact number of chromosomes removed depends on how many offspring were generated by parent selection"""
def remove_worst(ga, next_population):
iterator = 0
while len(next_population.get_all_chromosomes()) < ga.population_size:
next_population.add_chromosome(ga.population.get_all_chromosomes()[iterator])
iterator += 1
return next_population