Updated selection implementation, added with/without replacement variation
This commit is contained in:
@ -23,10 +23,10 @@ class GA:
|
||||
# Termination varibles
|
||||
self.current_generation = 0
|
||||
self.current_fitness = 0
|
||||
self.generation_goal = 35
|
||||
self.generation_goal = 50
|
||||
self.fitness_goal = 3
|
||||
# Mutation variables
|
||||
self.mutation_rate = 0.075
|
||||
self.mutation_rate = 0.05
|
||||
|
||||
# Rerun already computed fitness
|
||||
self.update_fitness = True
|
||||
@ -35,7 +35,7 @@ class GA:
|
||||
self.initialization_impl = Initialization_Types().random_initialization
|
||||
self.fitness_function_impl = Fitness_Examples().is_it_5
|
||||
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.termination_impl = Termination_Types().generation_based
|
||||
|
||||
|
||||
@ -25,9 +25,10 @@ class Crossover_Types:
|
||||
new_gene_set = []
|
||||
parent_one = crossover_pool[i].get_genes()
|
||||
parent_two = crossover_pool[i+1].get_genes()
|
||||
halfway_point = int(ga.chromosome_length/2)
|
||||
new_gene_set.extend(parent_one[0:halfway_point])
|
||||
new_gene_set.extend(parent_two[halfway_point:])
|
||||
#halfway_point = int(ga.chromosome_length/2)
|
||||
split_point = random.randint(0,ga.chromosome_length)
|
||||
new_gene_set.extend(parent_one[0:split_point])
|
||||
new_gene_set.extend(parent_two[split_point:])
|
||||
new_chromosome = Chromosome(new_gene_set)
|
||||
new_population.add_chromosome(new_chromosome)
|
||||
|
||||
|
||||
@ -5,9 +5,9 @@ import random
|
||||
# Create the Genetic algorithm
|
||||
ga = EasyGA.GA()
|
||||
|
||||
ga.gene_impl = [random.randrange,1,10]
|
||||
ga.gene_impl = [random.randrange,1,25]
|
||||
|
||||
# Run Everyhting
|
||||
# Run Everything
|
||||
ga.evolve()
|
||||
|
||||
# Print the current population
|
||||
|
||||
@ -9,22 +9,69 @@ class Selection_Types:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def tournament_selection(self, ga):
|
||||
"""This example currently uses a 'with replacement' approach (chromosomes are placed back into the pool after participating)"""
|
||||
class Tournament:
|
||||
def with_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
|
||||
|
||||
while (total_selected <= ga.population_size*2):
|
||||
#create & gather tournament group
|
||||
tournament_group = []
|
||||
|
||||
for i in range(tournament_size):
|
||||
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
|
||||
#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
|
||||
@ -43,6 +90,7 @@ class Selection_Types:
|
||||
tournament_group = tournament_group_temp
|
||||
|
||||
#After sorting by fitness, randomly select a chromosome based on selection_probability
|
||||
selected_chromosome_tournament_index = 0
|
||||
for i in range(tournament_size):
|
||||
random_num = random.uniform(0,1)
|
||||
|
||||
@ -51,14 +99,18 @@ class Selection_Types:
|
||||
if random_num <= selection_probability:
|
||||
tournament_group[i].selected = True
|
||||
total_selected += 1
|
||||
selected_chromosome_tournament_index = i
|
||||
break
|
||||
else:
|
||||
if random_num <= selection_probability*((1-selection_probability)**(i-1)):
|
||||
tournament_group[i].selected = True
|
||||
total_selected += 1
|
||||
selected_chromosome_tournament_index = i
|
||||
break
|
||||
|
||||
return total_selected,selected_chromosome_tournament_index
|
||||
|
||||
def create_new_population(self, ga):
|
||||
new_population = ga.crossover_impl(ga)
|
||||
|
||||
#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
|
||||
|
||||
|
||||
|
||||
def roulette_selection(self, ga):
|
||||
"""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
|
||||
|
||||
Reference in New Issue
Block a user