From 625143da7d6aa28bf2580bcf81b7268e7bccdf86 Mon Sep 17 00:00:00 2001 From: danielwilczak101 <44122838+danielwilczak101@users.noreply.github.com> Date: Wed, 30 Sep 2020 00:05:39 -0400 Subject: [PATCH] Added the termination features --- src/EasyGA.py | 64 ++++++++++++------- src/crossover/__init__.py | 1 + src/fitness_function/__init__.py | 3 +- .../default_fitness_example.py | 2 - src/fitness_function/is_the_value_5.py | 14 ++++ src/initialization/__init__.py | 2 +- src/run_testing.py | 3 +- src/termination_point/__init__.py | 3 + src/termination_point/fitness_based.py | 5 ++ src/termination_point/generation_based.py | 5 ++ 10 files changed, 72 insertions(+), 30 deletions(-) delete mode 100644 src/fitness_function/default_fitness_example.py create mode 100644 src/fitness_function/is_the_value_5.py create mode 100644 src/termination_point/fitness_based.py create mode 100644 src/termination_point/generation_based.py diff --git a/src/EasyGA.py b/src/EasyGA.py index 325bd91..65a1688 100644 --- a/src/EasyGA.py +++ b/src/EasyGA.py @@ -4,75 +4,91 @@ import random from initialization import population as create_population from initialization import chromosome as create_chromosome from initialization import gene as create_gene -from fitness_function import default_fitness_example +# Import the default fitness function +from fitness_function import is_the_value_5 +# Import default termination points +from termination_point import generation_based +from termination_point import fitness_based # Import functionality defaults from initialization import random_initialization class GA: def __init__(self): """Initialize the GA.""" - # Default variables + # Initilization variables + self.chromosome_length = 3 + self.population_size = 5 self.chromosome_impl = None self.gene_impl = None self.population = None + # Termination varibles self.current_generation = 0 - self.generations = 3 - self.chromosome_length = 3 - self.population_size = 5 + self.max_generations = 3 + self.current_fitness = 0 + self.goal_fitness = 3 + # Mutation variables self.mutation_rate = 0.03 # Defualt EastGA implimentation structure self.initialization_impl = random_initialization - self.fitness_funciton_impl = default_fitness_example + self.fitness_funciton_impl = is_the_value_5 #self.mutation_impl = PerGeneMutation(Mutation_rate) #self.selection_impl = TournamentSelection() #self.crossover_impl = FastSinglePointCrossover() - #self.termination_impl = GenerationTermination(Total_generations) + self.termination_impl = generation_based #self.evaluation_impl = TestEvaluation() # If we want the fitnesses to be updated by the computer self.update_fitness = True def initialize_population(self): - """Initialize the population""" + """Initialize the population using the initialization + implimentation that is currently set""" self.population = self.initialization_impl( self.population_size, self.chromosome_length, self.chromosome_impl, self.gene_impl) + def get_population_fitness(self,population): + """Will get and set the fitness of each chromosome in the population""" + # Get each chromosome in the population + for chromosome in population: + # Set the chromosomes fitness using the fitness function + chromosome.fitness = self.fitness_funciton_impl(chromosome) + def evolve(self): """Runs the ga until the termination point has been satisfied.""" - self.initialize_population() - #while(self.active()): - #if(self.current_generation == 0): - #initialize_population() + # While the termination point hasnt been reached keep running + while(self.active()): + # If its the first generation then initialize the population + if(self.current_generation == 0): + # Initialize the population + self.initialize_population() + # First get the fitness of the population + self.get_population_fitness(self.population.chromosomes) + + print(f"Ive completed generation - {self.current_generation}") + + self.current_generation += 1 - #get_fitness(population) - # run one iteration while the ga is active - #while self.active(): - #self.evolve_generation(1) def active(self): """Returns if the ga should terminate base on the termination implimented""" + # Send termination_impl the whole ga class return self.termination_impl(self) def evolve_generation(self, number_of_generations): """Evolves the ga the specified number of generations. If update_fitness is set then all fitness values are updated. - Otherwise only fitness values set to None (i.e. uninitialized fitness values) are updated.""" + Otherwise only fitness values set to None (i.e. uninitialized + fitness values) are updated.""" # run the specified number of times - for n in range(number_of_generations): + #for n in range(number_of_generations): - # for each chromosome in the population - for chromosome in self.population.get_all_chromosomes(): - - # if the fitness should be updated, update it - if self.update_fitness or chromosome.get_fitness() is None: - chromosome.set_fitness(self.fitness_impl(chromosome)) # apply selection, crossover, and mutation diff --git a/src/crossover/__init__.py b/src/crossover/__init__.py index e69de29..23b04b2 100644 --- a/src/crossover/__init__.py +++ b/src/crossover/__init__.py @@ -0,0 +1 @@ +# From file name import function name diff --git a/src/fitness_function/__init__.py b/src/fitness_function/__init__.py index d3ed36a..eb0a719 100644 --- a/src/fitness_function/__init__.py +++ b/src/fitness_function/__init__.py @@ -1 +1,2 @@ -from .default_fitness_example import default_fitness_example +# FROM (. means local) file_name IMPORT function_name +from .is_the_value_5 import is_the_value_5 diff --git a/src/fitness_function/default_fitness_example.py b/src/fitness_function/default_fitness_example.py deleted file mode 100644 index c85ecc4..0000000 --- a/src/fitness_function/default_fitness_example.py +++ /dev/null @@ -1,2 +0,0 @@ -def default_fitness_example(): - pass diff --git a/src/fitness_function/is_the_value_5.py b/src/fitness_function/is_the_value_5.py new file mode 100644 index 0000000..61d5428 --- /dev/null +++ b/src/fitness_function/is_the_value_5.py @@ -0,0 +1,14 @@ +def is_the_value_5(chromosome): + """A very simple case test function - If the chromosomes gene value is a 5 add one + to the chromosomes overall fitness value.""" + + # Overall fitness value + fitness = 0 + # For each gene in the chromosome + for gene in chromosome.genes: + # Check if its value = 5 + if(gene.value == 5): + # If its value is 5 then add one to + # the overal fitness of the chromosome. + fitness += 1 + return fitness diff --git a/src/initialization/__init__.py b/src/initialization/__init__.py index 1600eb1..13ed666 100644 --- a/src/initialization/__init__.py +++ b/src/initialization/__init__.py @@ -1,4 +1,4 @@ -# __init__.py +# FROM (. means local) file_name IMPORT function_name from .random_initialization import random_initialization from .population_structure.population import population from .chromosome_structure.chromosome import chromosome diff --git a/src/run_testing.py b/src/run_testing.py index 4422848..6bb59b9 100644 --- a/src/run_testing.py +++ b/src/run_testing.py @@ -4,11 +4,10 @@ import random ga = EasyGA.GA() ga.chromosome_length = 3 - +ga.max_generations = 5 # If the user wants to use a domain ga.gene_impl = [random.randrange,1,10] - # Run Everyhting ga.evolve() diff --git a/src/termination_point/__init__.py b/src/termination_point/__init__.py index e69de29..acd51c7 100644 --- a/src/termination_point/__init__.py +++ b/src/termination_point/__init__.py @@ -0,0 +1,3 @@ +# FROM (. means local) file_name IMPORT function_name +from .generation_based import generation_based +from .fitness_based import fitness_based diff --git a/src/termination_point/fitness_based.py b/src/termination_point/fitness_based.py new file mode 100644 index 0000000..a809130 --- /dev/null +++ b/src/termination_point/fitness_based.py @@ -0,0 +1,5 @@ +def fitness_based(ga): + status = True + if(ga.current_fitness > ga.goal_fitness): + status = False + return status diff --git a/src/termination_point/generation_based.py b/src/termination_point/generation_based.py new file mode 100644 index 0000000..9bf2005 --- /dev/null +++ b/src/termination_point/generation_based.py @@ -0,0 +1,5 @@ +def generation_based(ga): + status = True + if(ga.current_generation > ga.max_generations): + status = False + return status