Several Changes
Crossover/Mutation: - Split into individual and population subclasses. - Added sequential population crossover selection. - Renamed and reimplemented mutation methods. EasyGA: - Improved make_obj methods for the chromosomes and populations to take arguments. Initialization: - Improved to shorter code. - Fixed repeated error messages Chromosome: - Changed get/set_genes to get/set_gene_list.
This commit is contained in:
@ -49,14 +49,19 @@ class GA:
|
||||
# Default EasyGA implimentation structure
|
||||
self.initialization_impl = Initialization_Methods.random_initialization
|
||||
self.fitness_function_impl = Fitness_Examples.index_dependent_values
|
||||
self.make_population = create_population
|
||||
self.make_chromosome = create_chromosome
|
||||
self.make_gene = create_gene
|
||||
|
||||
# Selects which chromosomes should be automaticly moved to the next population
|
||||
self.survivor_selection_impl = Survivor_Selection.fill_in_best
|
||||
|
||||
# Methods for accomplishing parent-selection -> Crossover -> Mutation
|
||||
self.parent_selection_impl = Parent_Selection.Tournament.with_replacement
|
||||
self.crossover_impl = Crossover_Methods.single_point_crossover
|
||||
self.mutation_impl = Mutation_Methods.per_gene_mutation
|
||||
self.crossover_individual_impl = Crossover_Methods.Individual.single_point_crossover
|
||||
self.crossover_population_impl = Crossover_Methods.Population.random_selection
|
||||
self.mutation_individual_impl = Mutation_Methods.Individual.single_gene
|
||||
self.mutation_population_impl = Mutation_Methods.Population.random_selection
|
||||
|
||||
# The type of termination to impliment
|
||||
self.termination_impl = Termination_Methods.generation_based
|
||||
@ -72,11 +77,10 @@ class GA:
|
||||
self.population.set_all_chromosomes(self.sort_by_best_fitness(self.population.get_all_chromosomes()))
|
||||
else:
|
||||
self.parent_selection_impl(self)
|
||||
next_population = self.crossover_impl(self)
|
||||
next_population = self.crossover_population_impl(self)
|
||||
next_population = self.survivor_selection_impl(self, next_population)
|
||||
next_population.set_all_chromosomes(self.mutation_impl(self, next_population.get_all_chromosomes()))
|
||||
|
||||
self.population = next_population
|
||||
self.mutation_population_impl(self)
|
||||
self.set_all_fitness(self.population.chromosome_list)
|
||||
self.population.set_all_chromosomes(self.sort_by_best_fitness(self.population.get_all_chromosomes()))
|
||||
|
||||
@ -100,7 +104,8 @@ class GA:
|
||||
|
||||
def initialize_population(self):
|
||||
"""Initialize the population using the initialization
|
||||
implimentation that is currently set"""
|
||||
implimentation that is currently set
|
||||
"""
|
||||
self.population = self.initialization_impl(self)
|
||||
|
||||
|
||||
@ -132,18 +137,3 @@ class GA:
|
||||
chromosome_set = chromosome_set_temp
|
||||
|
||||
return chromosome_set
|
||||
|
||||
|
||||
def make_gene(self,value):
|
||||
"""Let's the user create a gene."""
|
||||
return create_gene(value)
|
||||
|
||||
|
||||
def make_chromosome(self):
|
||||
"""Let's the user create a chromosome."""
|
||||
return create_chromosome()
|
||||
|
||||
|
||||
def make_population(self):
|
||||
"""Let's the user create a population."""
|
||||
return create_population()
|
||||
|
||||
@ -3,29 +3,34 @@ from initialization.chromosome_structure.chromosome import Chromosome
|
||||
from initialization.population_structure.population import Population
|
||||
|
||||
class Crossover_Methods:
|
||||
def single_point_crossover(ga):
|
||||
"""Single point crossover is when a "point" is selected and the genetic
|
||||
make up of the two parent chromosomes are swapped at that point"""
|
||||
|
||||
crossover_pool = ga.population.mating_pool
|
||||
class Population:
|
||||
"""Methods for selecting chromosomes to crossover"""
|
||||
|
||||
"""The structure of GA requires that the crossover method return a population strictly with offspring chromosomes"""
|
||||
new_population = Population()
|
||||
for i in range(len(crossover_pool)):
|
||||
if i + 1 < len(crossover_pool):
|
||||
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)
|
||||
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)
|
||||
def sequential_selection(ga):
|
||||
"""Select sequential pairs from the mating pool"""
|
||||
|
||||
return new_population
|
||||
mating_pool = ga.population.mating_pool
|
||||
return Population([ga.crossover_individual_impl(mating_pool[index], mating_pool[index+1]) for index in range(len(mating_pool)-1)])
|
||||
|
||||
def multi_point_crossover(ga, number_of_points = 2):
|
||||
"""Multi point crossover is when a specific number (More then one) of
|
||||
"points" are created to merge the genetic makup of the chromosomes."""
|
||||
|
||||
def random_selection(ga):
|
||||
"""Select random pairs from the mating pool"""
|
||||
|
||||
mating_pool = ga.population.mating_pool
|
||||
return Population([ga.crossover_individual_impl(random.choice(mating_pool), random.choice(mating_pool)) for n in mating_pool])
|
||||
|
||||
|
||||
class Individual:
|
||||
"""Methods for crossing parents"""
|
||||
|
||||
def single_point_crossover(parent_one, parent_two):
|
||||
"""Cross two parents by swapping genes at one random point"""
|
||||
|
||||
index = random.randint(0, parent_one.size()-1)
|
||||
return Chromosome(parent_one.get_gene_list()[:index] + parent_two.get_gene_list()[index:])
|
||||
|
||||
|
||||
def multi_point_crossover(parent_one, parent_two):
|
||||
"""Cross two parents by swapping genes at multiple points"""
|
||||
pass
|
||||
|
||||
@ -27,7 +27,7 @@ class Chromosome:
|
||||
del self.gene_list[index]
|
||||
|
||||
|
||||
def get_genes(self):
|
||||
def get_gene_list(self):
|
||||
return self.gene_list
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ class Chromosome:
|
||||
self.gene_list[index] = gene
|
||||
|
||||
|
||||
def set_genes(self, genes):
|
||||
def set_gene_list(self, genes):
|
||||
self.gene_list = genes
|
||||
|
||||
|
||||
|
||||
@ -7,27 +7,26 @@ class Initialization_Methods:
|
||||
"""Initialization examples that are used as defaults and examples"""
|
||||
|
||||
def random_initialization(ga):
|
||||
"""Takes the initialization inputs and choregraphs them to output the type of population with the given parameters."""
|
||||
"""Takes the initialization inputs and returns a population with the given parameters."""
|
||||
|
||||
# Create the population object
|
||||
population = create_population()
|
||||
|
||||
# Fill the population with chromosomes
|
||||
for i in range(ga.population_size):
|
||||
chromosome = create_chromosome()
|
||||
#Fill the Chromosome with genes
|
||||
for j in range(ga.chromosome_length):
|
||||
# Using the chromosome_impl to set every index inside of the chromosome
|
||||
if ga.chromosome_impl != None:
|
||||
# Each chromosome location is specified with its own function
|
||||
chromosome.add_gene(create_gene(ga.chromosome_impl(j)))
|
||||
# Will break if chromosome_length != len(lists) in domain
|
||||
return create_population([
|
||||
create_chromosome([
|
||||
create_gene(ga.chromosome_impl(j))
|
||||
for j in range(ga.chromosome_length)])
|
||||
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]
|
||||
chromosome.add_gene(create_gene(function(*ga.gene_impl[1:])))
|
||||
return create_population([
|
||||
create_chromosome([
|
||||
create_gene(function(*ga.gene_impl[1:]))
|
||||
for j in range(ga.chromosome_length)])
|
||||
for i in range(ga.population_size)])
|
||||
|
||||
# Exit because no gene creation method specified
|
||||
else:
|
||||
#Exit because either were not specified
|
||||
print("You did not specify any initialization constraints.")
|
||||
break
|
||||
population.add_chromosome(chromosome)
|
||||
return population
|
||||
return None
|
||||
|
||||
@ -2,45 +2,62 @@ import random
|
||||
|
||||
class Mutation_Methods:
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
class Population:
|
||||
"""Methods for selecting chromosomes to mutate"""
|
||||
|
||||
def random_mutation(ga, chromosome_set = None):
|
||||
"""Will take the input population and randomly reset entire chromosomes based on the GA's mutation rate"""
|
||||
def random_selection(ga):
|
||||
"""Selects random chromosomes"""
|
||||
|
||||
"""Defaulting to the GA's current population if no input is explicitly given"""
|
||||
if chromosome_set == None:
|
||||
chromosome_set = ga.population.get_all_chromosomes()
|
||||
# Loop through the population
|
||||
for index in range(ga.population.size()):
|
||||
|
||||
chromosome_mutate_num = int(len(chromosome_set)*ga.mutation_rate)
|
||||
temp_population = ga.initialization_impl(ga)
|
||||
# Randomly apply mutations
|
||||
if random.uniform(0, 1) < ga.mutation_rate:
|
||||
ga.population.set_chromosome(ga.mutation_individual_impl(ga, ga.population.get_all_chromosomes()[index]), index)
|
||||
|
||||
"""While more chromosomes need to be mutated, grab a random chromosome and re-initialize it entirely"""
|
||||
while chromosome_mutate_num > 0:
|
||||
chromosome_set[random.randint(0,ga.population_size-1)] = temp_population.get_all_chromosomes()[chromosome_mutate_num]
|
||||
chromosome_mutate_num -= 1
|
||||
|
||||
return chromosome_set
|
||||
class Individual:
|
||||
"""Methods for mutating a single chromosome"""
|
||||
|
||||
def per_gene_mutation(ga, chromosome_set = None, gene_mutate_count = 1):
|
||||
"""Will iterate through all chromosomes, and if its selected, will randomly replace one of its genes based on initialization values"""
|
||||
def whole_chromosome(ga, chromosome):
|
||||
"""Makes a completely random chromosome"""
|
||||
|
||||
gene_mutate_count_static = int(gene_mutate_count)
|
||||
# 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())])
|
||||
|
||||
if chromosome_set == None:
|
||||
chromosome_set = ga.population.get_all_chromosomes()
|
||||
# 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:]))
|
||||
for j in range(chromosome.size())])
|
||||
|
||||
for i in range(len(chromosome_set)):
|
||||
random_num = random.uniform(0,1)
|
||||
# Exit because no gene creation method specified
|
||||
else:
|
||||
print("You did not specify any initialization constraints.")
|
||||
return None
|
||||
|
||||
"""If a chromosome was selected to be mutated"""
|
||||
if (random_num <= ga.mutation_rate):
|
||||
while gene_mutate_count > 0:
|
||||
dummy_population = ga.initialization_impl(ga) #Really inefficient, but works for now
|
||||
random_index = random.randint(0, ga.chromosome_length-1)
|
||||
"""Replaces a random gene in the actual chromosome with a gene from a newly initialized chromosome"""
|
||||
chromosome_set[i].get_genes()[random_index] = dummy_population.get_all_chromosomes()[random.randint(0,ga.population_size-1)].get_genes()[random_index]
|
||||
gene_mutate_count -= 1
|
||||
gene_mutate_count = int(gene_mutate_count_static)
|
||||
|
||||
return chromosome_set
|
||||
def single_gene(ga, chromosome):
|
||||
"""Makes a completely random chromosome"""
|
||||
chromosome.set_fitness(None)
|
||||
|
||||
# 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)
|
||||
|
||||
# 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)
|
||||
|
||||
# Exit because no gene creation method specified
|
||||
else:
|
||||
print("You did not specify any initialization constraints.")
|
||||
|
||||
return chromosome
|
||||
|
||||
Reference in New Issue
Block a user