Merge pull request #14 from danielwilczak101/jack

Updating with jacks code.
This commit is contained in:
Daniel Wilczak
2020-10-15 01:03:44 -04:00
committed by GitHub
8 changed files with 168 additions and 70 deletions

View File

@ -27,7 +27,7 @@ class GA:
self.chromosome_length = 10
self.population_size = 10
self.chromosome_impl = None
self.gene_impl = [random.randint,1,10]
self.gene_impl = None
self.population = None
self.target_fitness_type = 'maximum'
self.update_fitness = True
@ -68,10 +68,9 @@ class GA:
def evolve_generation(self, number_of_generations = 1, consider_termination = True):
"""Evolves the ga the specified number of generations."""
# Evolve the specified number of generations
# and if consider_termination flag is set then
# also check if termination conditions reached
while(number_of_generations > 0 and (not consider_termination or self.termination_impl(self))):
while(number_of_generations > 0 # Evolve the specified number of generations
and (not consider_termination # and if consider_termination flag is set
or self.termination_impl(self))): # then also check if termination conditions reached
# If its the first generation then initialize the population
if self.current_generation == 0:
@ -81,13 +80,13 @@ class GA:
# Otherwise evolve the population
else:
self.population.reset_mating_pool()
self.set_all_fitness()
self.population.sort_by_best_fitness(self)
self.parent_selection_impl(self)
next_population = self.crossover_population_impl(self)
self.survivor_selection_impl(self, next_population)
self.crossover_population_impl(self)
self.survivor_selection_impl(self)
self.mutation_population_impl(self)
self.population.update()
number_of_generations -= 1
self.current_generation += 1
@ -134,4 +133,6 @@ class GA:
etc.
"""
return sorted(chromosome_set, key = lambda chromosome: chromosome.get_fitness(), reverse = True)
return sorted(chromosome_set, # list to be sorted
key = lambda chromosome: chromosome.get_fitness(), # by fitness
reverse = True) # from highest to lowest fitness

View File

@ -12,7 +12,15 @@ class Crossover_Methods:
"""
mating_pool = ga.population.get_mating_pool()
return ga.make_population([ga.crossover_individual_impl(ga, mating_pool[index], mating_pool[index-1]) for index in range(len(mating_pool))])
for index in range(len(mating_pool)): # for each parent in the mating pool
ga.population.add_child( # add a child
ga.crossover_individual_impl( # by crossing
ga, #
mating_pool[index], # the parent and
mating_pool[index-1] # the previous parent
)
)
def random_selection(ga):
@ -21,7 +29,15 @@ class Crossover_Methods:
"""
mating_pool = ga.population.get_mating_pool()
return ga.make_population([ga.crossover_individual_impl(ga, parent, random.choice(mating_pool)) for parent in mating_pool])
for parent in mating_pool: # for each parent in the mating pool
ga.population.add_child( # add a child
ga.crossover_individual_impl( # by crossing
ga, #
parent, # the parent and
random.choice(mating_pool) # a random parent
)
)
class Individual:
@ -41,18 +57,27 @@ class Crossover_Methods:
def uniform(ga, parent_one, parent_two):
"""Cross two parents by swapping all genes randomly"""
return ga.make_chromosome([
random.choice([parent_one.get_gene(i), parent_two.get_gene(i)])
for i in range(parent_one.size())])
return ga.make_chromosome([ # Make a new chromosome
random.choice([ # by selecting random genes from
parent_one.get_gene(i), # each parent
parent_two.get_gene(i) #
]) #
for i in range(parent_one.size())]) # for each gene
class Arithmetic:
"""Crossover methods for numerical genes"""
def int_random(ga, parent_one, parent_two):
"""Cross two parents by taking a random integer value between each of the genes"""
return ga.make_chromosome([
ga.make_gene(random.randint(*sorted([parent_one.get_gene(i).get_value(), parent_two.get_gene(i).get_value()])))
for i in range(parent_one.size())])
return ga.make_chromosome([ # Make a new chromosome
ga.make_gene( # filled with new genes
random.randint(*sorted([ # by choosing random integers between
parent_one.get_gene(i).get_value(), # the parents' genes
parent_two.get_gene(i).get_value() #
]))) #
for i in range(parent_one.size())]) # for each gene
def int_weighted(ga, parent_one, parent_two):
@ -60,16 +85,26 @@ class Crossover_Methods:
# the percentage of genes taken from the first gene
weight = 0.25
return ga.make_chromosome([
ga.make_gene(int(weight*parent_one.get_gene(i).get_value()+(1-weight)*parent_two.get_gene(i).get_value()))
for i in range(parent_one.size())])
return ga.make_chromosome([ # Make a new chromosome
ga.make_gene(int( # filled with new integer genes
weight*parent_one.get_gene(i).get_value()+ # with weight% from parent one and
(1-weight)*parent_two.get_gene(i).get_value() # (100-weight)% from parent two
)) #
for i in range(parent_one.size())]) # for each gene
def float_random(ga, parent_one, parent_two):
"""Cross two parents by taking a random numeric value between each of the genes"""
return ga.make_chromosome([
ga.make_gene(random.uniform(parent_one.get_gene(i).get_value(), parent_two.get_gene(i).get_value()))
for i in range(parent_one.size())])
return ga.make_chromosome([ # Make a new chromosome
ga.make_gene( # filled with new genes
random.uniform( # by taking a random float between
parent_one.get_gene(i).get_value(), # the parents' genes
parent_two.get_gene(i).get_value() #
) #
) #
for i in range(parent_one.size())]) # for each gene
def float_weighted(ga, parent_one, parent_two):
@ -77,6 +112,10 @@ class Crossover_Methods:
# the percentage of genes taken from the first gene
weight = 0.25
return ga.make_chromosome([
ga.make_gene(weight*parent_one.get_gene(i).get_value()+(1-weight)*parent_two.get_gene(i).get_value())
for i in range(parent_one.size())])
return ga.make_chromosome([ # Make a new chromosome
ga.make_gene( # filled with new float genes
weight*parent_one.get_gene(i).get_value()+ # with weight% from parent one and
(1-weight)*parent_two.get_gene(i).get_value() # (100-weight)% from parent two
) #
for i in range(parent_one.size())]) # for each gene

View File

@ -12,16 +12,15 @@ class Initialization_Methods:
if ga.chromosome_impl != None:
return ga.make_population([
ga.make_chromosome([
ga.make_gene(ga.chromosome_impl(j))
for j in range(ga.chromosome_length)])
ga.make_gene(value)
for value in ga.chromosome_impl()])
for i in range(ga.population_size)])
# Using the gene_impl to set every gene to be the same
elif ga.gene_impl != None:
function = ga.gene_impl[0]
return ga.make_population([
ga.make_chromosome([
ga.make_gene(function(*ga.gene_impl[1:]))
ga.make_gene(ga.gene_impl())
for j in range(ga.chromosome_length)])
for i in range(ga.population_size)])

View File

@ -25,14 +25,13 @@ class Mutation_Methods:
# Using the chromosome_impl to set every index inside of the chromosome
if ga.chromosome_impl != None:
return ga.make_chromosome([
ga.make_gene(ga.chromosome_impl(j))
for j in range(chromosome.size())])
ga.make_gene(value)
for value in ga.chromosome_impl()])
# Using the gene_impl
elif ga.gene_impl != None:
function = ga.gene_impl[0]
return ga.make_chromosome([
ga.make_gene(function(*ga.gene_impl[1:]))
ga.make_gene(ga.gene_impl())
for j in range(chromosome.size())])
# Exit because no gene creation method specified
@ -48,13 +47,12 @@ class Mutation_Methods:
# Using the chromosome_impl
if ga.chromosome_impl != None:
index = random.randint(0, chromosome.size()-1)
chromosome.set_gene(ga.make_gene(ga.chromosome_impl(index)), index)
chromosome.set_gene(ga.make_gene(ga.chromosome_impl()[index]), index)
# Using the gene_impl
elif ga.gene_impl != None:
function = ga.gene_impl[0]
index = random.randint(0, chromosome.size()-1)
chromosome.set_gene(ga.make_gene(function(*ga.gene_impl[1:])), index)
chromosome.set_gene(ga.make_gene(ga.gene_impl()), index)
# Exit because no gene creation method specified
else:

View File

@ -110,8 +110,10 @@ class Parent_Selection:
print("Selection probability must be between 0 and 1 to select parents.")
return
max_fitness = ga.population.get_chromosome(0).get_fitness()
# Error if the highest fitness is not positive
if ga.population.get_chromosome(0).get_fitness() <= 0:
if max_fitness <= 0:
print("Error using stochastic roulette selection, best fitness must be positive.")
print("Consider using tournament selection.")
return
@ -123,5 +125,5 @@ class Parent_Selection:
index = random.randint(0, ga.population.size()-1)
# Probability of becoming a parent is fitness/max_fitness
if random.uniform(ga.selection_probability, 1) < ga.population.get_chromosome(index).get_fitness() / ga.population.get_chromosome(0).get_fitness():
if random.uniform(ga.selection_probability, 1) < ga.population.get_chromosome(index).get_fitness()/max_fitness:
ga.population.set_parent(index)

View File

@ -5,7 +5,7 @@ import EasyGA
ga = EasyGA.GA()
ga.population_size = 25
ga.generation_goal = 100
ga.gene_impl = [random.randint,0,10]
ga.gene_impl = lambda: random.randint(1, 10)
ga.selection_probability = 0.5
ga.fitness_function_impl = EasyGA.Fitness_Examples.near_5
ga.parent_selection_impl = EasyGA.Parent_Selection.Roulette.stochastic_selection

View File

@ -10,6 +10,43 @@ class Population:
self.fitness = None
self.mating_pool = []
self.next_population = []
def update(self):
self.set_chromosome_list(self.next_population)
self.reset_mating_pool()
self.reset_next_population()
def remove_chromosome(self, index):
"""Removes a chromosome from the indicated index from the population"""
del self.chromosome_list[index]
def remove_parent(self, index):
"""Removes a parent from the indicated index from the mating pool"""
del self.mating_pool[index]
def remove_child(self, index):
"""Removes a child from the indicated index from the next population"""
del self.next_population[index]
def reset_mating_pool(self):
"""Clears the mating pool"""
self.mating_pool = []
def reset_next_population(self):
"""Clears the next population"""
self.next_population = []
def append_children(self, chromosome_list):
"""Appends a list of chromosomes to the next population"""
self.next_population += chromosome_list
def sort_by_best_fitness(self, ga):
@ -22,6 +59,11 @@ class Population:
return len(self.chromosome_list)
def total_children(self):
"""Returns the size of the next population"""
return len(self.next_population)
def get_closet_fitness(self,value):
"""Get the chomosome that has the closets fitness to the value defined"""
pass
@ -39,19 +81,9 @@ class Population:
self.mating_pool.append(chromosome)
def remove_chromosome(self, index):
"""Removes a chromosome from the indicated index from the population"""
del self.chromosome_list[index]
def remove_parent(self, index):
"""Removes a parent from the indicated index from the mating pool"""
del self.mating_pool[index]
def reset_mating_pool(self):
"""Clears the mating pool"""
self.mating_pool = []
def add_child(self, chromosome):
"""Adds a chromosome to the next population"""
self.next_population.append(chromosome)
def get_chromosome(self, index):
@ -64,6 +96,11 @@ class Population:
return self.mating_pool[index]
def get_child(self, index):
"""Returns the child at the given index in the next population"""
return self.next_population[index]
def get_chromosome_list(self):
"""Returns all chromosomes in the population"""
return self.chromosome_list
@ -74,16 +111,16 @@ class Population:
return self.mating_pool
def get_next_population(self):
"""Returns chromosomes in the next population"""
return self.next_population
def get_fitness(self):
"""Returns the population's fitness"""
return self.fitness
def set_parent(self, index):
"""Sets the indexed chromosome from the population as a parent"""
self.add_parent(self.get_chromosome(index))
def set_chromosome_list(self, chromosome_list):
"""Sets the chromosome list"""
self.chromosome_list = chromosome_list
@ -99,6 +136,11 @@ class Population:
self.chromosome_list[index] = chromosome
def set_parent(self, index):
"""Sets the indexed chromosome from the population as a parent"""
self.add_parent(self.get_chromosome(index))
def set_fitness(self, fitness):
"""Sets the fitness value of the population"""
self.fitness = fitness

View File

@ -3,25 +3,42 @@ import random
class Survivor_Selection:
"""Survivor selection determines which individuals should be brought to the next generation"""
def fill_in_best(ga, next_population):
def fill_in_best(ga):
"""Fills in the next population with the best chromosomes from the last population"""
ga.population.set_chromosome_list(ga.population.get_chromosome_list()[:ga.population.size()-next_population.size()] + next_population.get_chromosome_list())
# add in chromosomes starting from
# the first chromosome in the population
# until the next population is full
ga.population.append_children(
ga.population.get_chromosome_list()[:ga.population.size()-len(ga.population.next_population)]
)
def fill_in_random(ga, next_population):
def fill_in_random(ga):
"""Fills in the next population with random chromosomes from the last population"""
ga.population.set_chromosome_list([
random.choice(ga.population.get_chromosome_list())
for n in range(ga.population.size()-next_population.size())]
+ next_population.get_chromosome_list())
ga.population.append_children([ # add in chromosomes
random.choice( # randomly
ga.population.get_chromosome_list() # from the population
) # until the next population is full
for n in range(ga.population.size()-ga.population.total_children())])
def fill_in_parents_then_random(ga, next_population):
def fill_in_parents_then_random(ga):
"""Fills in the next population with all parents followed by random chromosomes from the last population"""
ga.population.set_chromosome_list([
random.choice(ga.population.get_chromosome_list())
for n in range(ga.population.size()-len(ga.population.get_mating_pool())-next_population.size())]
+ ga.population.get_mating_pool() + next_population.get_chromosome_list())
ga.population.append_children([ # add in chromosomes
random.choice( # randomly
ga.population.get_chromosome_list() # from the population
) # until the next population is full
for n in range(ga.population.size()-ga.population.total_children())])
ga.population.append_children( # add in chromosomes
ga.population.get_mating_pool() # from the mating pool
) #
ga.population.append_children([ # add in chromosomes
random.choice( # randomly
ga.population.get_chromosome_list() # from the population
) # until the next population is full
for n in range(ga.population.size()-ga.population.total_children())])