Fixed scope of function decorators
This commit is contained in:
@ -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."""
|
||||
|
||||
|
||||
@ -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."""
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user