Fixed scope of function decorators
This commit is contained in:
@ -1,20 +1,28 @@
|
|||||||
import random
|
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 Crossover_Methods:
|
||||||
|
|
||||||
class Population:
|
class Population:
|
||||||
"""Methods for selecting chromosomes to crossover."""
|
"""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):
|
def sequential_selection(ga, mating_pool):
|
||||||
"""Select sequential pairs from the mating pool.
|
"""Select sequential pairs from the mating pool.
|
||||||
Every parent is paired with the previous parent.
|
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):
|
def random_selection(ga, mating_pool):
|
||||||
"""Select random pairs from the mating pool.
|
"""Select random pairs from the mating pool.
|
||||||
Every parent is paired with a random parent.
|
Every parent is paired with a random parent.
|
||||||
@ -46,13 +54,6 @@ class Crossover_Methods:
|
|||||||
class Individual:
|
class Individual:
|
||||||
"""Methods for crossing parents."""
|
"""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):
|
def single_point(ga, parent_1, parent_2):
|
||||||
"""Cross two parents by swapping genes at one random point."""
|
"""Cross two parents by swapping genes at one random point."""
|
||||||
@ -77,7 +78,7 @@ class Crossover_Methods:
|
|||||||
class Arithmetic:
|
class Arithmetic:
|
||||||
"""Crossover methods for numerical genes."""
|
"""Crossover methods for numerical genes."""
|
||||||
|
|
||||||
@Individual._Individual__values_to_chromosome
|
@values_to_chromosome
|
||||||
def int_random(ga, parent_1, parent_2):
|
def int_random(ga, parent_1, parent_2):
|
||||||
"""Cross two parents by taking a random integer value between each of the genes."""
|
"""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]))
|
yield random.randint(*sorted([value_1, value_2]))
|
||||||
|
|
||||||
|
|
||||||
@Individual._Individual__values_to_chromosome
|
@values_to_chromosome
|
||||||
def int_weighted(ga, parent_1, parent_2):
|
def int_weighted(ga, parent_1, parent_2):
|
||||||
"""Cross two parents by taking a a weighted average of the genes."""
|
"""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)
|
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):
|
def float_random(ga, parent_one, parent_two):
|
||||||
"""Cross two parents by taking a random numeric value between each of the genes."""
|
"""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])
|
yield random.uniform([value_1, value_2])
|
||||||
|
|
||||||
|
|
||||||
@Individual._Individual__values_to_chromosome
|
@values_to_chromosome
|
||||||
def float_weighted(ga, parent_one, parent_two):
|
def float_weighted(ga, parent_one, parent_two):
|
||||||
"""Cross two parents by taking a a weighted average of the genes."""
|
"""Cross two parents by taking a a weighted average of the genes."""
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,33 @@
|
|||||||
import random
|
import random
|
||||||
from math import ceil
|
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 Mutation_Methods:
|
||||||
|
|
||||||
class Population:
|
class Population:
|
||||||
"""Methods for selecting chromosomes to mutate"""
|
"""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):
|
def random_selection(ga):
|
||||||
"""Selects random chromosomes"""
|
"""Selects random chromosomes"""
|
||||||
|
|
||||||
@ -22,7 +35,7 @@ class Mutation_Methods:
|
|||||||
ga.population[index] = ga.mutation_individual_impl(ga, ga.population[index])
|
ga.population[index] = ga.mutation_individual_impl(ga, ga.population[index])
|
||||||
|
|
||||||
|
|
||||||
@__loop_selections
|
@loop_selections
|
||||||
def random_selection_then_cross(ga):
|
def random_selection_then_cross(ga):
|
||||||
"""Selects random chromosomes and self-crosses with parent"""
|
"""Selects random chromosomes and self-crosses with parent"""
|
||||||
|
|
||||||
@ -34,19 +47,8 @@ class Mutation_Methods:
|
|||||||
class Individual:
|
class Individual:
|
||||||
"""Methods for mutating a single chromosome"""
|
"""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
|
@loop_mutations
|
||||||
for n in range(ceil(len(chromosome)*ga.gene_mutation_rate)):
|
|
||||||
mutation_method(ga, chromosome)
|
|
||||||
|
|
||||||
return chromosome
|
|
||||||
return helper
|
|
||||||
|
|
||||||
|
|
||||||
@__loop_mutations
|
|
||||||
def individual_genes(ga, chromosome):
|
def individual_genes(ga, chromosome):
|
||||||
"""Mutates a random gene in the chromosome and resets the fitness."""
|
"""Mutates a random gene in the chromosome and resets the fitness."""
|
||||||
index = random.randint(0, len(chromosome)-1)
|
index = random.randint(0, len(chromosome)-1)
|
||||||
@ -68,7 +70,7 @@ class Mutation_Methods:
|
|||||||
"""Methods for mutating a chromosome
|
"""Methods for mutating a chromosome
|
||||||
by changing the order of the genes."""
|
by changing the order of the genes."""
|
||||||
|
|
||||||
@Individual._Individual__loop_mutations
|
@loop_mutations
|
||||||
def swap_genes(ga, chromosome):
|
def swap_genes(ga, chromosome):
|
||||||
"""Mutates a random gene in the chromosome and resets the fitness."""
|
"""Mutates a random gene in the chromosome and resets the fitness."""
|
||||||
|
|
||||||
|
|||||||
@ -1,36 +1,37 @@
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
class Parent_Selection:
|
def check_selection_probability(selection_method):
|
||||||
|
def helper(ga):
|
||||||
def __check_selection_probability(selection_method):
|
if 0 < ga.selection_probability < 1:
|
||||||
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)
|
|
||||||
selection_method(ga)
|
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:
|
class Rank:
|
||||||
|
|
||||||
@Parent_Selection._Parent_Selection__check_selection_probability
|
@check_selection_probability
|
||||||
@Parent_Selection._Parent_Selection__ensure_sorted
|
@ensure_sorted
|
||||||
def tournament(ga):
|
def tournament(ga):
|
||||||
"""
|
"""
|
||||||
Will make tournaments of size tournament_size and choose the winner (best fitness)
|
Will make tournaments of size tournament_size and choose the winner (best fitness)
|
||||||
@ -68,9 +69,9 @@ class Parent_Selection:
|
|||||||
|
|
||||||
class Fitness:
|
class Fitness:
|
||||||
|
|
||||||
@Parent_Selection._Parent_Selection__check_selection_probability
|
@check_selection_probability
|
||||||
@Parent_Selection._Parent_Selection__check_positive_fitness
|
@check_positive_fitness
|
||||||
@Parent_Selection._Parent_Selection__ensure_sorted
|
@ensure_sorted
|
||||||
def roulette(ga):
|
def roulette(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
|
||||||
chromosomes in the population. The stronger the fitness the higher the probability
|
chromosomes in the population. The stronger the fitness the higher the probability
|
||||||
@ -105,9 +106,9 @@ class Parent_Selection:
|
|||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
@Parent_Selection._Parent_Selection__check_selection_probability
|
@check_selection_probability
|
||||||
@Parent_Selection._Parent_Selection__check_positive_fitness
|
@check_positive_fitness
|
||||||
@Parent_Selection._Parent_Selection__ensure_sorted
|
@ensure_sorted
|
||||||
def stochastic(ga):
|
def stochastic(ga):
|
||||||
"""Stochastic roulette selection works based off of how strong the fitness is of the
|
"""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
|
chromosomes in the population. The stronger the fitness the higher the probability
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
|
def append_to_next_population(survivor_method):
|
||||||
|
return lambda ga: ga.population.append_children(survivor_method(ga))
|
||||||
|
|
||||||
class Survivor_Selection:
|
class Survivor_Selection:
|
||||||
"""Survivor selection determines which individuals should be brought to the next generation"""
|
"""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):
|
def fill_in_best(ga):
|
||||||
"""Fills in the next population with the best chromosomes from the last population"""
|
"""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]
|
return ga.population[:needed_amount]
|
||||||
|
|
||||||
|
|
||||||
@__append_to_next_population
|
@append_to_next_population
|
||||||
def fill_in_random(ga):
|
def fill_in_random(ga):
|
||||||
"""Fills in the next population with random chromosomes from the last population"""
|
"""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)]
|
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):
|
def fill_in_parents_then_random(ga):
|
||||||
"""Fills in the next population with all parents followed by random chromosomes from the last population"""
|
"""Fills in the next population with all parents followed by random chromosomes from the last population"""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user