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.fitness_function_impl = Fitness_Examples.index_dependent_values
# 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
self.parent_selection_impl = Parent_Selection.Tournament.with_replacement
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
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):
"""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"""
"""Single point crossover is when a "point" is selected and the genetic
make up of the two parent chromosomes are swapped at that point"""
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()
for i in range(len(crossover_pool)):
if i + 1 < len(crossover_pool):

View File

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

View File

@ -6,13 +6,16 @@ class Mutation_Methods:
pass
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:
chromosome_set = ga.population.get_all_chromosomes()
chromosome_mutate_num = int(len(chromosome_set)*ga.mutation_rate)
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:
chromosome_set[random.randint(0,ga.population_size-1)] = temp_population.get_all_chromosomes()[chromosome_mutate_num]
chromosome_mutate_num -= 1
@ -20,7 +23,8 @@ class Mutation_Methods:
return chromosome_set
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)
if chromosome_set == None:
@ -29,10 +33,12 @@ class Mutation_Methods:
for i in range(len(chromosome_set)):
random_num = random.uniform(0,1)
"""If a chromosome was selected to be mutated"""
if (random_num <= ga.mutation_rate):
while gene_mutate_count > 0:
dummy_population = ga.initialization_impl(ga) #Really inefficient, but works for now
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]
gene_mutate_count -= 1
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 Tournament:
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:
tournament_size = 5
# Probability used for determining if a chromosome should enter the mating pool.

View File

@ -4,7 +4,7 @@ import random
# Create the Genetic algorithm
ga = EasyGA.GA()
ga.population_size = 15
ga.population_size = 100
ga.chromosome_length = 10
ga.generation_goal = 100
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
class Survivor_Selection:
def repeated_crossover(ga, next_population): #Might be cheating? I don't know honestly - RG
while len(next_population.get_all_chromosomes()) < ga.population_size:
crossover_pool = ga.population.mating_pool
"""Survivor selection determines which individuals should be brought to the next generation"""
split_point = random.randint(0,ga.chromosome_length)
chromosome_list = []
for i in range(len(crossover_pool)):
if i + 1 < len(crossover_pool):
new_gene_set = []
parent_one = crossover_pool[i].get_genes()
parent_two = crossover_pool[i+1].get_genes()
new_gene_set.extend(parent_one[0:split_point])
new_gene_set.extend(parent_two[split_point:])
new_chromosome = create_chromosome(new_gene_set)
chromosome_list.append(new_chromosome)
for i in range(len(chromosome_list)):
next_population.add_chromosome(chromosome_list[i])
if len(next_population.get_all_chromosomes()) >= ga.population_size:
break
return next_population
def remove_two_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
""" Pretty sure this isn't actually survivor selection - seems like its 'cheating'
def repeated_crossover(ga, next_population):
while len(next_population.get_all_chromosomes()) < ga.population_size:
crossover_pool = ga.population.mating_pool
split_point = random.randint(0,ga.chromosome_length)
chromosome_list = []
for i in range(len(crossover_pool)):
if i + 1 < len(crossover_pool):
new_gene_set = []
parent_one = crossover_pool[i].get_genes()
parent_two = crossover_pool[i+1].get_genes()
new_gene_set.extend(parent_one[0:split_point])
new_gene_set.extend(parent_two[split_point:])
new_chromosome = create_chromosome(new_gene_set)
chromosome_list.append(new_chromosome)
for i in range(len(chromosome_list)):
next_population.add_chromosome(chromosome_list[i])
if len(next_population.get_all_chromosomes()) >= ga.population_size:
break
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