Updated selection implementation, added with/without replacement variation
This commit is contained in:
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
selection_probability = 0.95
|
#3rd best is given probability of selection_probability*(1-selection_probability)**2
|
||||||
total_selected = 0 #Total Chromosomes selected
|
selection_probability = 0.95
|
||||||
|
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):
|
|
||||||
tournament_group.append(random.choice(ga.population.get_all_chromosomes()))
|
|
||||||
|
|
||||||
|
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
|
#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,47 +99,49 @@ 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
|
||||||
|
|
||||||
new_population = ga.crossover_impl(ga)
|
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)
|
#If the crossover doesn't create enough chromosomes (ugly right now pls no judgerino, can be changed)
|
||||||
#Just does single-point crossover at random indices
|
#Just does single-point crossover at random indices
|
||||||
while len(new_population.chromosomes) < ga.population_size:
|
while len(new_population.chromosomes) < ga.population_size:
|
||||||
crossover_pool = []
|
crossover_pool = []
|
||||||
for i in range(ga.population_size):
|
for i in range(ga.population_size):
|
||||||
if ga.population.get_all_chromosomes()[i].selected:
|
if ga.population.get_all_chromosomes()[i].selected:
|
||||||
crossover_pool.append(ga.population.get_all_chromosomes()[i])
|
crossover_pool.append(ga.population.get_all_chromosomes()[i])
|
||||||
|
|
||||||
split_point = random.randint(0,ga.chromosome_length)
|
split_point = random.randint(0,ga.chromosome_length)
|
||||||
chromosome_list = []
|
chromosome_list = []
|
||||||
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):
|
||||||
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()
|
||||||
new_gene_set.extend(parent_one[0:split_point])
|
new_gene_set.extend(parent_one[0:split_point])
|
||||||
new_gene_set.extend(parent_two[split_point:])
|
new_gene_set.extend(parent_two[split_point:])
|
||||||
new_chromosome = Chromosome(new_gene_set)
|
new_chromosome = Chromosome(new_gene_set)
|
||||||
chromosome_list.append(new_chromosome)
|
chromosome_list.append(new_chromosome)
|
||||||
|
|
||||||
for i in range(len(chromosome_list)):
|
for i in range(len(chromosome_list)):
|
||||||
new_population.add_chromosome(chromosome_list[i])
|
new_population.add_chromosome(chromosome_list[i])
|
||||||
if len(new_population.chromosomes) >= ga.population_size:
|
if len(new_population.chromosomes) >= ga.population_size:
|
||||||
break
|
break
|
||||||
|
|
||||||
new_chromosome_set = ga.mutation_impl(ga, new_population.get_all_chromosomes())
|
|
||||||
new_population.set_all_chromosomes(new_chromosome_set)
|
|
||||||
|
|
||||||
return new_population
|
|
||||||
|
|
||||||
|
new_chromosome_set = ga.mutation_impl(ga, new_population.get_all_chromosomes())
|
||||||
|
new_population.set_all_chromosomes(new_chromosome_set)
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user