Added ga.adapt()

This commit is contained in:
SimpleArt
2020-11-27 19:12:40 -05:00
parent a87103b80c
commit 1197447d7e
3 changed files with 81 additions and 9 deletions

View File

@ -79,6 +79,8 @@ class GA(Attributes):
number_of_generations -= 1
self.current_generation += 1
self.adapt()
def evolve(self, number_of_generations = 1, consider_termination = True):
"""Runs the ga until the termination point has been satisfied."""
@ -93,6 +95,64 @@ class GA(Attributes):
return self.termination_impl(self)
def adapt(self):
"""Modifies the parent ratio and mutation rates
based on the adapt rate and percent converged.
"""
# Don't adapt
if self.adapt_rate is None or self.adapt_rate <= 0:
return
# How much converged
best_fitness = self.population[0].fitness
threshhold_fitness = self.population[round(self.percent_converged*len(self.population)/4)].fitness
# Closeness required for convergence
tol = 0.01 if self.tolerance_goal is None else self.tolerance_goal
tol *= 1 + abs(best_fitness)
# Change rates with:
multiplier = 1 + self.adapt_rate
# Minimum and maximum rates allowed
min_val = 0.05
max_val = 0.75
limit = max_val / multiplier
# Too few converged: cross more and mutate less
if abs(best_fitness - threshhold_fitness) > tol:
threshhold_fitness = self.population[round(self.percent_converged*len(self.population)/8)].fitness
# Way too few converged
if abs(best_fitness - threshhold_fitness) > tol:
multiplier **= 2
limit = max_val / multiplier
self.parent_ratio = min(max_val, self.parent_ratio*multiplier)
self.selection_probability = min(max_val, self.selection_probability*multiplier)
self.chromosome_mutation_rate = max(min_val, self.chromosome_mutation_rate/multiplier)
self.gene_mutation_rate = max(min_val, self.gene_mutation_rate/multiplier)
# Too many converged: cross less and mutate more
else:
threshhold_fitness = self.population[round(self.percent_converged*len(self.population)/2)].fitness
# Way too many converged
if abs(best_fitness - threshhold_fitness) > tol:
multiplier **= 2
limit = max_val / multiplier
self.parent_ratio = max(min_val, self.parent_ratio/multiplier)
self.selection_probability = max(min_val, self.selection_probability/multiplier)
self.chromosome_mutation_rate = min(max_val, self.chromosome_mutation_rate*multiplier)
self.gene_mutation_rate = min(max_val, self.gene_mutation_rate*multiplier)
def initialize_population(self):
"""Initialize the population using
the initialization implimentation
@ -117,18 +177,25 @@ class GA(Attributes):
chromosome.fitness = self.fitness_function_impl(chromosome)
def sort_by_best_fitness(self, chromosome_list):
def sort_by_best_fitness(self, chromosome_list, in_place = False):
"""Sorts the chromosome list by fitness based on fitness type.
1st element has best fitness.
2nd element has second best fitness.
etc.
"""
return sorted(
chromosome_list, # list to be sorted
key = lambda chromosome: chromosome.fitness, # by fitness
reverse = (self.target_fitness_type == 'max') # ordered by fitness type
)
if in_place:
return chromosome_list.sort( # list to be sorted
key = lambda chromosome: chromosome.fitness, # by fitness
reverse = (self.target_fitness_type == 'max') # ordered by fitness type
)
else:
return sorted(
chromosome_list, # list to be sorted
key = lambda chromosome: chromosome.fitness, # by fitness
reverse = (self.target_fitness_type == 'max') # ordered by fitness type
)
def get_chromosome_fitness(self, index):

View File

@ -66,6 +66,7 @@ class Attributes:
percent_converged = 0.50,
chromosome_mutation_rate = 0.15,
gene_mutation_rate = 0.05,
adapt_rate = 0.05,
initialization_impl = Initialization_Methods.random_initialization,
fitness_function_impl = Fitness_Examples.is_it_5,
make_population = create_population,
@ -111,6 +112,7 @@ class Attributes:
self.fitness_goal = deepcopy(fitness_goal)
self.tolerance_goal = deepcopy(tolerance_goal)
self.percent_converged = deepcopy(percent_converged)
self.adapt_rate = deepcopy(adapt_rate)
# Mutation variables
self.chromosome_mutation_rate = deepcopy(chromosome_mutation_rate)

View File

@ -46,13 +46,16 @@ class Population:
def append_children(self, chromosome_list):
"""Appends a list of chromosomes to the next population"""
self.next_population += chromosome_list
"""Appends a list of chromosomes to the next population.
Appends to the front so that chromosomes with fitness
values already will stay sorted.
"""
self.next_population = chromosome_list + self.next_population
def sort_by_best_fitness(self, ga):
"""Sorts the population by fitness"""
self.chromosome_list = ga.sort_by_best_fitness(self.chromosome_list)
ga.sort_by_best_fitness(self.chromosome_list, in_place = True)
def add_chromosome(self, chromosome, index = None):