From 3d10adb2d9c9128b069b362c6dce658bcae2b27b Mon Sep 17 00:00:00 2001 From: SimpleArt <71458112+SimpleArt@users.noreply.github.com> Date: Thu, 19 Nov 2020 22:28:04 -0500 Subject: [PATCH] Fixed scope of function decorators --- src/crossover/crossover_methods.py | 43 ++++++------ src/mutation/mutation_methods.py | 46 ++++++------- .../parent_selection_methods.py | 65 ++++++++++--------- .../survivor_selection_methods.py | 12 ++-- 4 files changed, 85 insertions(+), 81 deletions(-) diff --git a/src/crossover/crossover_methods.py b/src/crossover/crossover_methods.py index 5eb10dd..96590be 100644 --- a/src/crossover/crossover_methods.py +++ b/src/crossover/crossover_methods.py @@ -1,20 +1,28 @@ import random +def append_children_from_mating_pool(crossover_method): + def helper(ga): + mating_pool = ga.population.mating_pool + ga.population.append_children( + [chromosome for chromosome in crossover_method(ga, mating_pool)] + ) + return helper + +def values_to_chromosome(crossover_method): + def helper(ga, parent_1, parent_2): + return ga.make_chromosome([ + ga.make_gene(value) + for value in crossover_method(ga, parent_1, parent_2)]) + return helper + + class Crossover_Methods: class Population: """Methods for selecting chromosomes to crossover.""" - def __append_children_from_mating_pool(crossover_method): - def helper(ga): - mating_pool = ga.population.mating_pool - ga.population.append_children([ - [chromosome for cromosome in crossover_method(ga, mating_pool)] - ) - return helper - - @__append_children_from_mating_pool + @append_children_from_mating_pool def sequential_selection(ga, mating_pool): """Select sequential pairs from the mating pool. Every parent is paired with the previous parent. @@ -29,7 +37,7 @@ class Crossover_Methods: ) - @__append_children_from_mating_pool + @append_children_from_mating_pool def random_selection(ga, mating_pool): """Select random pairs from the mating pool. Every parent is paired with a random parent. @@ -46,13 +54,6 @@ class Crossover_Methods: class Individual: """Methods for crossing parents.""" - def __values_to_chromosome(crossover_method): - def helper(ga, parent_1, parent_2): - return ga.make_chromosome([ - ga.make_gene(value) - for value in crossover_method(ga, parent_1, parent_2)]) - return helper - def single_point(ga, parent_1, parent_2): """Cross two parents by swapping genes at one random point.""" @@ -77,7 +78,7 @@ class Crossover_Methods: class Arithmetic: """Crossover methods for numerical genes.""" - @Individual._Individual__values_to_chromosome + @values_to_chromosome def int_random(ga, parent_1, parent_2): """Cross two parents by taking a random integer value between each of the genes.""" @@ -88,7 +89,7 @@ class Crossover_Methods: yield random.randint(*sorted([value_1, value_2])) - @Individual._Individual__values_to_chromosome + @values_to_chromosome def int_weighted(ga, parent_1, parent_2): """Cross two parents by taking a a weighted average of the genes.""" @@ -102,7 +103,7 @@ class Crossover_Methods: yield int(weight*value_1+(1-weight)*value_2) - @Individual._Individual__values_to_chromosome + @values_to_chromosome def float_random(ga, parent_one, parent_two): """Cross two parents by taking a random numeric value between each of the genes.""" @@ -113,7 +114,7 @@ class Crossover_Methods: yield random.uniform([value_1, value_2]) - @Individual._Individual__values_to_chromosome + @values_to_chromosome def float_weighted(ga, parent_one, parent_two): """Cross two parents by taking a a weighted average of the genes.""" diff --git a/src/mutation/mutation_methods.py b/src/mutation/mutation_methods.py index 322015e..911d7df 100644 --- a/src/mutation/mutation_methods.py +++ b/src/mutation/mutation_methods.py @@ -1,20 +1,33 @@ import random from math import ceil +def loop_selections(selection_method): + def helper(ga): + # Loop until enough mutations occur + for n in range(ceil(len(ga.population)*ga.chromosome_mutation_rate)): + selection_method(ga) + return helper + + +def loop_mutations(mutation_method): + def helper(ga, old_chromosome): + chromosome = ga.make_chromosome(list(old_chromosome)) + + # Loops until enough mutations occur + for n in range(ceil(len(chromosome)*ga.gene_mutation_rate)): + mutation_method(ga, chromosome) + + return chromosome + return helper + + class Mutation_Methods: class Population: """Methods for selecting chromosomes to mutate""" - def __loop_selections(selection_method): - def helper(ga): - # Loop until enough mutations occur - for n in range(ceil(len(ga.population)*ga.chromosome_mutation_rate)): - selection_method(ga) - return helper - - @__loop_selections + @loop_selections def random_selection(ga): """Selects random chromosomes""" @@ -22,7 +35,7 @@ class Mutation_Methods: ga.population[index] = ga.mutation_individual_impl(ga, ga.population[index]) - @__loop_selections + @loop_selections def random_selection_then_cross(ga): """Selects random chromosomes and self-crosses with parent""" @@ -34,19 +47,8 @@ class Mutation_Methods: class Individual: """Methods for mutating a single chromosome""" - def __loop_mutations(mutation_method): - def helper(ga, old_chromosome): - chromosome = ga.make_chromosome(list(old_chromosome)) - # Loops until enough mutations occur - for n in range(ceil(len(chromosome)*ga.gene_mutation_rate)): - mutation_method(ga, chromosome) - - return chromosome - return helper - - - @__loop_mutations + @loop_mutations def individual_genes(ga, chromosome): """Mutates a random gene in the chromosome and resets the fitness.""" index = random.randint(0, len(chromosome)-1) @@ -68,7 +70,7 @@ class Mutation_Methods: """Methods for mutating a chromosome by changing the order of the genes.""" - @Individual._Individual__loop_mutations + @loop_mutations def swap_genes(ga, chromosome): """Mutates a random gene in the chromosome and resets the fitness.""" diff --git a/src/parent_selection/parent_selection_methods.py b/src/parent_selection/parent_selection_methods.py index cd1f009..4763e17 100644 --- a/src/parent_selection/parent_selection_methods.py +++ b/src/parent_selection/parent_selection_methods.py @@ -1,36 +1,37 @@ import random -class Parent_Selection: - - def __check_selection_probability(selection_method): - def helper(ga): - if 0 < ga.selection_probability < 1: - selection_method(ga) - else: - raise Exception("Selection probability must be greater than 0 to select parents.") - return helper - - - def __check_positive_fitness(selection_method): - def helper(ga): - if ga.get_chromosome_fitness(0) == 0 or ga.get_chromosome_fitness(-1) < 0: - raise Exception("Converted fitness values must be all positive. Consider using rank selection instead.") - else: - selection_method(ga) - return helper - - - def __ensure_sorted(selection_method): - def helper(ga): - ga.population.sort_by_best_fitness(ga) +def check_selection_probability(selection_method): + def helper(ga): + if 0 < ga.selection_probability < 1: selection_method(ga) - return helper + else: + raise Exception("Selection probability must be greater than 0 to select parents.") + return helper + + +def check_positive_fitness(selection_method): + def helper(ga): + if ga.get_chromosome_fitness(0) == 0 or ga.get_chromosome_fitness(-1) < 0: + raise Exception("Converted fitness values must be all positive. Consider using rank selection instead.") + else: + selection_method(ga) + return helper + + +def ensure_sorted(selection_method): + def helper(ga): + ga.population.sort_by_best_fitness(ga) + selection_method(ga) + return helper + + +class Parent_Selection: class Rank: - @Parent_Selection._Parent_Selection__check_selection_probability - @Parent_Selection._Parent_Selection__ensure_sorted + @check_selection_probability + @ensure_sorted def tournament(ga): """ Will make tournaments of size tournament_size and choose the winner (best fitness) @@ -68,9 +69,9 @@ class Parent_Selection: class Fitness: - @Parent_Selection._Parent_Selection__check_selection_probability - @Parent_Selection._Parent_Selection__check_positive_fitness - @Parent_Selection._Parent_Selection__ensure_sorted + @check_selection_probability + @check_positive_fitness + @ensure_sorted def roulette(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 @@ -105,9 +106,9 @@ class Parent_Selection: break - @Parent_Selection._Parent_Selection__check_selection_probability - @Parent_Selection._Parent_Selection__check_positive_fitness - @Parent_Selection._Parent_Selection__ensure_sorted + @check_selection_probability + @check_positive_fitness + @ensure_sorted def stochastic(ga): """Stochastic 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 diff --git a/src/survivor_selection/survivor_selection_methods.py b/src/survivor_selection/survivor_selection_methods.py index 48d9128..8a75120 100644 --- a/src/survivor_selection/survivor_selection_methods.py +++ b/src/survivor_selection/survivor_selection_methods.py @@ -1,13 +1,13 @@ import random +def append_to_next_population(survivor_method): + return lambda ga: ga.population.append_children(survivor_method(ga)) + class Survivor_Selection: """Survivor selection determines which individuals should be brought to the next generation""" - def __append_to_next_population(survivor_method): - return lambda ga: ga.population.append_children(survivor_method(ga)) - - @__append_to_next_population + @append_to_next_population def fill_in_best(ga): """Fills in the next population with the best chromosomes from the last population""" @@ -15,7 +15,7 @@ class Survivor_Selection: return ga.population[:needed_amount] - @__append_to_next_population + @append_to_next_population def fill_in_random(ga): """Fills in the next population with random chromosomes from the last population""" @@ -23,7 +23,7 @@ class Survivor_Selection: return [random.choice(ga.population) for n in range(needed_amount)] - @__append_to_next_population + @append_to_next_population def fill_in_parents_then_random(ga): """Fills in the next population with all parents followed by random chromosomes from the last population"""