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:
@ -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
|
||||||
|
|||||||
@ -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):
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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]
|
||||||
|
|||||||
@ -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
|
||||||
Reference in New Issue
Block a user