Updated selection implementation, added with/without replacement variation

This commit is contained in:
RyleyGG
2020-10-04 15:54:38 -04:00
parent 89df506469
commit c18a531034
4 changed files with 101 additions and 50 deletions

View File

@ -23,10 +23,10 @@ class GA:
# Termination varibles # Termination varibles
self.current_generation = 0 self.current_generation = 0
self.current_fitness = 0 self.current_fitness = 0
self.generation_goal = 35 self.generation_goal = 50
self.fitness_goal = 3 self.fitness_goal = 3
# Mutation variables # Mutation variables
self.mutation_rate = 0.075 self.mutation_rate = 0.05
# Rerun already computed fitness # Rerun already computed fitness
self.update_fitness = True self.update_fitness = True
@ -35,7 +35,7 @@ class GA:
self.initialization_impl = Initialization_Types().random_initialization self.initialization_impl = Initialization_Types().random_initialization
self.fitness_function_impl = Fitness_Examples().is_it_5 self.fitness_function_impl = Fitness_Examples().is_it_5
self.mutation_impl = Mutation_Types().random_mutation self.mutation_impl = Mutation_Types().random_mutation
self.selection_impl = Selection_Types().tournament_selection self.selection_impl = Selection_Types().Tournament().with_replacement
self.crossover_impl = Crossover_Types().single_point_crossover self.crossover_impl = Crossover_Types().single_point_crossover
self.termination_impl = Termination_Types().generation_based self.termination_impl = Termination_Types().generation_based

View File

@ -25,9 +25,10 @@ class Crossover_Types:
new_gene_set = [] new_gene_set = []
parent_one = crossover_pool[i].get_genes() parent_one = crossover_pool[i].get_genes()
parent_two = crossover_pool[i+1].get_genes() parent_two = crossover_pool[i+1].get_genes()
halfway_point = int(ga.chromosome_length/2) #halfway_point = int(ga.chromosome_length/2)
new_gene_set.extend(parent_one[0:halfway_point]) split_point = random.randint(0,ga.chromosome_length)
new_gene_set.extend(parent_two[halfway_point:]) new_gene_set.extend(parent_one[0:split_point])
new_gene_set.extend(parent_two[split_point:])
new_chromosome = Chromosome(new_gene_set) new_chromosome = Chromosome(new_gene_set)
new_population.add_chromosome(new_chromosome) new_population.add_chromosome(new_chromosome)

View File

@ -5,9 +5,9 @@ import random
# Create the Genetic algorithm # Create the Genetic algorithm
ga = EasyGA.GA() ga = EasyGA.GA()
ga.gene_impl = [random.randrange,1,10] ga.gene_impl = [random.randrange,1,25]
# Run Everyhting # Run Everything
ga.evolve() ga.evolve()
# Print the current population # Print the current population

View File

@ -9,22 +9,69 @@ class Selection_Types:
def __init__(self): def __init__(self):
pass pass
def tournament_selection(self, ga): class Tournament:
"""This example currently uses a 'with replacement' approach (chromosomes are placed back into the pool after participating)""" def with_replacement(self, ga):
tournament_size = int(len(ga.population.get_all_chromosomes())/10) #currently hard-coded for purposes of the example. tournament_size = int(len(ga.population.get_all_chromosomes())/10) #currently hard-coded for purposes of the example.
if tournament_size < 3:
tournament_size = int(len(ga.population.get_all_chromosomes())/3)
#selection_probability is the likelihood that a chromosome will be selected. #selection_probability is the likelihood that a chromosome will be selected.
#best chromosome in a tournament is given a selection probablity of selection_probability #best chromosome in a tournament is given a selection probablity of selection_probability
#2nd best is given probability of selection_probability*(1-selection_probability) #2nd best is given probability of selection_probability*(1-selection_probability)
#3rd best is given probability of selection_probability*(1-selection_probability)**2
selection_probability = 0.95 selection_probability = 0.95
total_selected = 0 #Total Chromosomes selected total_selected = 0 #Total Chromosomes selected
while (total_selected <= ga.population_size*2): while (total_selected <= ga.population_size*2):
#create & gather tournament group #create & gather tournament group
tournament_group = [] tournament_group = []
for i in range(tournament_size): for i in range(tournament_size):
tournament_group.append(random.choice(ga.population.get_all_chromosomes())) tournament_group.append(random.choice(ga.population.get_all_chromosomes()))
total_selected = self.selection(tournament_group, tournament_size, total_selected, selection_probability)[0]
new_population = self.create_new_population(ga)
return new_population
def without_replacement(self, ga):
tournament_size = int(len(ga.population.get_all_chromosomes())/10) #currently hard-coded for purposes of the example.
if tournament_size < 3:
tournament_size = int(len(ga.population.get_all_chromosomes())/3)
#selection_probability is the likelihood that a chromosome will be selected.
#best chromosome in a tournament is given a selection probablity of selection_probability
#2nd best is given probability of selection_probability*(1-selection_probability)
#3rd best is given probability of selection_probability*(1-selection_probability)**2
selection_probability = 0.95
total_selected = 0 #Total Chromosomes selected
available_chromosome_indices = []
for i in range(len(ga.population.get_all_chromosomes())):
available_chromosome_indices.append(i)
continue_selecting = True
while (continue_selecting):
#create & gather tournament group
tournament_group = []
for i in range(tournament_size):
selected_chromosome_index = random.choice(available_chromosome_indices)
tournament_group.append(ga.population.get_all_chromosomes()[selected_chromosome_index])
winning_chromosome_index = self.selection(tournament_group, tournament_size, total_selected, selection_probability)[1]
for i in range(len(available_chromosome_indices)):
if tournament_group[winning_chromosome_index].selected:
del available_chromosome_indices[i]
break
#print(winning_chromosome_index)
#print(available_chromosome_indices)
if len(available_chromosome_indices) < 1:
continue_selecting = False
new_population = self.create_new_population(ga)
return new_population
def selection(self, tournament_group, tournament_size, total_selected, selection_probability):
#Sort the tournament contenders based on their fitness #Sort the tournament contenders based on their fitness
#currently hard-coded to only consider higher fitness = better; can be changed once this impl is agreed on #currently hard-coded to only consider higher fitness = better; can be changed once this impl is agreed on
#also currently uses bubble sort because its easy #also currently uses bubble sort because its easy
@ -43,6 +90,7 @@ class Selection_Types:
tournament_group = tournament_group_temp tournament_group = tournament_group_temp
#After sorting by fitness, randomly select a chromosome based on selection_probability #After sorting by fitness, randomly select a chromosome based on selection_probability
selected_chromosome_tournament_index = 0
for i in range(tournament_size): for i in range(tournament_size):
random_num = random.uniform(0,1) random_num = random.uniform(0,1)
@ -51,14 +99,18 @@ class Selection_Types:
if random_num <= selection_probability: if random_num <= selection_probability:
tournament_group[i].selected = True tournament_group[i].selected = True
total_selected += 1 total_selected += 1
selected_chromosome_tournament_index = i
break break
else: else:
if random_num <= selection_probability*((1-selection_probability)**(i-1)): if random_num <= selection_probability*((1-selection_probability)**(i-1)):
tournament_group[i].selected = True tournament_group[i].selected = True
total_selected += 1 total_selected += 1
selected_chromosome_tournament_index = i
break break
return total_selected,selected_chromosome_tournament_index
def create_new_population(self, ga):
new_population = ga.crossover_impl(ga) new_population = ga.crossover_impl(ga)
#If the crossover doesn't create enough chromosomes (ugly right now pls no judgerino, can be changed) #If the crossover doesn't create enough chromosomes (ugly right now pls no judgerino, can be changed)
@ -91,8 +143,6 @@ class Selection_Types:
return new_population return new_population
def roulette_selection(self, ga): def roulette_selection(self, ga):
"""Roulette selection works based off of how strong the fitness is of the """Roulette selection works based off of how strong the fitness is of the
chromosomes in the population. The stronger the fitness the higher the probability chromosomes in the population. The stronger the fitness the higher the probability