Renamed decorators for consistency

This commit is contained in:
SimpleArt
2020-12-03 00:21:52 -05:00
parent 3271d7d271
commit 85855c2746
5 changed files with 85 additions and 86 deletions

View File

@ -1,6 +1,6 @@
import random import random
def append_to_next_population(population_method): def _append_to_next_population(population_method):
"""Appends the new chromosomes to the next population. """Appends the new chromosomes to the next population.
Also modifies the input to include the mating pool. Also modifies the input to include the mating pool.
""" """
@ -11,7 +11,7 @@ def append_to_next_population(population_method):
) )
def check_weight(individual_method): def _check_weight(individual_method):
"""Checks if the weight is between 0 and 1 before running. """Checks if the weight is between 0 and 1 before running.
Exception may occur when using ga.adapt, which will catch Exception may occur when using ga.adapt, which will catch
the error and try again with valid weight. the error and try again with valid weight.
@ -27,7 +27,7 @@ def check_weight(individual_method):
return new_method return new_method
def genes_to_chromosome(individual_method): def _genes_to_chromosome(individual_method):
"""Converts a collection of genes into a chromosome. """Converts a collection of genes into a chromosome.
Note: Will recreate the gene list if given gene list. Note: Will recreate the gene list if given gene list.
Built-in methods do not construct gene lists Built-in methods do not construct gene lists
@ -40,7 +40,7 @@ def genes_to_chromosome(individual_method):
) )
def values_to_genes(individual_method): def _values_to_genes(individual_method):
"""Converts a collection of values into genes. """Converts a collection of values into genes.
Returns a generator of genes to avoid storing a new list. Returns a generator of genes to avoid storing a new list.
""" """
@ -55,18 +55,18 @@ def values_to_genes(individual_method):
class Crossover_Methods: class Crossover_Methods:
# Private method decorators, see above. # Allowing access to decorators when importing class
_append_to_next_population = append_to_next_population _append_to_next_population = _append_to_next_population
_check_weight = check_weight _check_weight = _check_weight
_genes_to_chromosome = genes_to_chromosome _genes_to_chromosome = _genes_to_chromosome
_values_to_genes = values_to_genes _values_to_genes = _values_to_genes
class Population: class Population:
"""Methods for selecting chromosomes to crossover.""" """Methods for selecting chromosomes to crossover."""
@append_to_next_population @_append_to_next_population
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.
@ -82,7 +82,7 @@ class Crossover_Methods:
) )
@append_to_next_population @_append_to_next_population
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.
@ -101,8 +101,8 @@ class Crossover_Methods:
"""Methods for crossing parents.""" """Methods for crossing parents."""
@check_weight @_check_weight
@genes_to_chromosome @_genes_to_chromosome
def single_point(ga, parent_1, parent_2, weight = 0.5): def single_point(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by swapping genes at one random point.""" """Cross two parents by swapping genes at one random point."""
@ -124,15 +124,15 @@ class Crossover_Methods:
return parent_2[:-swap_index] + parent_1[-swap_index:] return parent_2[:-swap_index] + parent_1[-swap_index:]
@check_weight @_check_weight
@genes_to_chromosome @_genes_to_chromosome
def multi_point(ga, parent_1, parent_2, weight = 0.5): def multi_point(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by swapping genes at multiple points.""" """Cross two parents by swapping genes at multiple points."""
pass pass
@check_weight @_check_weight
@genes_to_chromosome @_genes_to_chromosome
def uniform(ga, parent_1, parent_2, weight = 0.5): def uniform(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by swapping all genes randomly.""" """Cross two parents by swapping all genes randomly."""
@ -143,8 +143,8 @@ class Crossover_Methods:
class Arithmetic: class Arithmetic:
"""Crossover methods for numerical genes.""" """Crossover methods for numerical genes."""
@genes_to_chromosome @_genes_to_chromosome
@values_to_genes @_values_to_genes
def average(ga, parent_1, parent_2, weight = 0.5): def average(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by taking the average of the genes.""" """Cross two parents by taking the average of the genes."""
@ -161,8 +161,8 @@ class Crossover_Methods:
yield value yield value
@genes_to_chromosome @_genes_to_chromosome
@values_to_genes @_values_to_genes
def extrapolate(ga, parent_1, parent_2, weight = 0.5): def extrapolate(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by extrapolating towards the first parent. """Cross two parents by extrapolating towards the first parent.
@ -182,9 +182,9 @@ class Crossover_Methods:
yield value yield value
@check_weight @_check_weight
@genes_to_chromosome @_genes_to_chromosome
@values_to_genes @_values_to_genes
def random(ga, parent_1, parent_2, weight = 0.5): def random(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by taking a random integer or float value between each of the genes.""" """Cross two parents by taking a random integer or float value between each of the genes."""

View File

@ -1,7 +1,7 @@
import random import random
from math import ceil from math import ceil
def check_chromosome_mutation_rate(population_method): def _check_chromosome_mutation_rate(population_method):
"""Checks if the chromosome mutation rate is a float between 0 and 1 before running.""" """Checks if the chromosome mutation rate is a float between 0 and 1 before running."""
def new_method(ga): def new_method(ga):
@ -18,7 +18,7 @@ def check_chromosome_mutation_rate(population_method):
return new_method return new_method
def check_gene_mutation_rate(individual_method): def _check_gene_mutation_rate(individual_method):
"""Checks if the gene mutation rate is a float between 0 and 1 before running.""" """Checks if the gene mutation rate is a float between 0 and 1 before running."""
def new_method(ga, index): def new_method(ga, index):
@ -35,7 +35,7 @@ def check_gene_mutation_rate(individual_method):
return new_method return new_method
def reset_fitness(individual_method): def _reset_fitness(individual_method):
"""Resets the fitness value of the chromosome.""" """Resets the fitness value of the chromosome."""
def new_method(ga, chromosome): def new_method(ga, chromosome):
@ -45,7 +45,7 @@ def reset_fitness(individual_method):
return new_method return new_method
def loop_random_selections(population_method): def _loop_random_selections(population_method):
"""Runs the population method until enough chromosomes are mutated. """Runs the population method until enough chromosomes are mutated.
Provides the indexes of selected chromosomes to mutate using Provides the indexes of selected chromosomes to mutate using
random.sample to get all indexes fast. random.sample to get all indexes fast.
@ -63,7 +63,7 @@ def loop_random_selections(population_method):
return new_method return new_method
def loop_random_mutations(individual_method): def _loop_random_mutations(individual_method):
"""Runs the individual method until enough """Runs the individual method until enough
genes are mutated on the indexed chromosome. genes are mutated on the indexed chromosome.
""" """
@ -83,27 +83,26 @@ def loop_random_mutations(individual_method):
class Mutation_Methods: class Mutation_Methods:
# Private method decorators, see above. _check_chromosome_mutation_rate = _check_chromosome_mutation_rate
_check_chromosome_mutation_rate = check_chromosome_mutation_rate _check_gene_mutation_rate = _check_gene_mutation_rate
_check_gene_mutation_rate = check_gene_mutation_rate _reset_fitness = _reset_fitness
_reset_fitness = reset_fitness _loop_random_selections = _loop_random_selections
_loop_random_selections = loop_random_selections _loop_random_mutations = _loop_random_mutations
_loop_random_mutations = loop_random_mutations
class Population: class Population:
"""Methods for selecting chromosomes to mutate""" """Methods for selecting chromosomes to mutate"""
@check_chromosome_mutation_rate @_check_chromosome_mutation_rate
@loop_random_selections @_loop_random_selections
def random_selection(ga, index): def random_selection(ga, index):
"""Selects random chromosomes.""" """Selects random chromosomes."""
ga.mutation_individual_impl(ga, ga.population[index]) ga.mutation_individual_impl(ga, ga.population[index])
@check_chromosome_mutation_rate @_check_chromosome_mutation_rate
@loop_random_selections @_loop_random_selections
def random_avoid_best(ga, index): def random_avoid_best(ga, index):
"""Selects random chromosomes while avoiding the best chromosomes. (Elitism)""" """Selects random chromosomes while avoiding the best chromosomes. (Elitism)"""
@ -114,9 +113,9 @@ class Mutation_Methods:
class Individual: class Individual:
"""Methods for mutating a single chromosome.""" """Methods for mutating a single chromosome."""
@check_gene_mutation_rate @_check_gene_mutation_rate
@reset_fitness @_reset_fitness
@loop_random_mutations @_loop_random_mutations
def individual_genes(ga, chromosome, index): def individual_genes(ga, chromosome, index):
"""Mutates a random gene in the chromosome.""" """Mutates a random gene in the chromosome."""
@ -137,9 +136,9 @@ class Mutation_Methods:
"""Methods for mutating a chromosome """Methods for mutating a chromosome
by numerically modifying the genes.""" by numerically modifying the genes."""
@check_gene_mutation_rate @_check_gene_mutation_rate
@reset_fitness @_reset_fitness
@loop_random_mutations @_loop_random_mutations
def reflect_genes(ga, chromosome, index): def reflect_genes(ga, chromosome, index):
"""Reflects genes against the best chromosome.""" """Reflects genes against the best chromosome."""
@ -152,9 +151,9 @@ 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."""
@check_gene_mutation_rate @_check_gene_mutation_rate
@reset_fitness @_reset_fitness
@loop_random_mutations @_loop_random_mutations
def swap_genes(ga, chromosome, index): def swap_genes(ga, chromosome, index):
"""Swaps two random genes in the chromosome.""" """Swaps two random genes in the chromosome."""

View File

@ -1,6 +1,6 @@
import random import random
def check_selection_probability(selection_method): def _check_selection_probability(selection_method):
"""Raises an exception if the selection_probability """Raises an exception if the selection_probability
is not between 0 and 1. Otherwise runs the selection is not between 0 and 1. Otherwise runs the selection
method. method.
@ -15,7 +15,7 @@ def check_selection_probability(selection_method):
return new_method return new_method
def check_positive_fitness(selection_method): def _check_positive_fitness(selection_method):
"""Raises an exception if the population contains a """Raises an exception if the population contains a
chromosome with negative fitness. Otherwise runs chromosome with negative fitness. Otherwise runs
the selection method. the selection method.
@ -30,7 +30,7 @@ def check_positive_fitness(selection_method):
return new_method return new_method
def ensure_sorted(selection_method): def _ensure_sorted(selection_method):
"""Sorts the population by fitness """Sorts the population by fitness
and then runs the selection method. and then runs the selection method.
""" """
@ -42,7 +42,7 @@ def ensure_sorted(selection_method):
return new_method return new_method
def compute_parent_amount(selection_method): def _compute_parent_amount(selection_method):
"""Computes the amount of parents """Computes the amount of parents
needed to be selected, and passes it needed to be selected, and passes it
as another argument for the method. as another argument for the method.
@ -57,11 +57,11 @@ def compute_parent_amount(selection_method):
class Parent_Selection: class Parent_Selection:
# Private method decorators, see above. # Allowing access to decorators when importing class
_check_selection_probability = check_selection_probability _check_selection_probability = _check_selection_probability
_check_positive_fitness = check_positive_fitness _check_positive_fitness = _check_positive_fitness
_ensure_sorted = ensure_sorted _ensure_sorted = _ensure_sorted
_compute_parent_amount = compute_parent_amount _compute_parent_amount = _compute_parent_amount
class Rank: class Rank:
@ -69,9 +69,9 @@ class Parent_Selection:
i.e. the n-th best chromosome has a fixed probability of being selected, i.e. the n-th best chromosome has a fixed probability of being selected,
regardless of their chances""" regardless of their chances"""
@check_selection_probability @_check_selection_probability
@ensure_sorted @_ensure_sorted
@compute_parent_amount @_compute_parent_amount
def tournament(ga, parent_amount): def tournament(ga, parent_amount):
""" """
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)
@ -108,9 +108,9 @@ class Parent_Selection:
return return
@check_selection_probability @_check_selection_probability
@ensure_sorted @_ensure_sorted
@compute_parent_amount @_compute_parent_amount
def stochastic(ga, parent_amount): def stochastic(ga, parent_amount):
""" """
Selects parents using the same probability approach as tournament selection, Selects parents using the same probability approach as tournament selection,
@ -133,10 +133,10 @@ class Parent_Selection:
class Fitness: class Fitness:
@check_selection_probability @_check_selection_probability
@ensure_sorted @_ensure_sorted
@check_positive_fitness @_check_positive_fitness
@compute_parent_amount @_compute_parent_amount
def roulette(ga, parent_amount): def roulette(ga, parent_amount):
"""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
@ -175,9 +175,9 @@ class Parent_Selection:
break break
@check_selection_probability @_check_selection_probability
@ensure_sorted @_ensure_sorted
@compute_parent_amount @_compute_parent_amount
def stochastic(ga, parent_amount): def stochastic(ga, parent_amount):
""" """
Selects parents using the same probability approach as roulette selection, Selects parents using the same probability approach as roulette selection,

View File

@ -1,6 +1,6 @@
import random import random
def append_to_next_population(survivor_method): def _append_to_next_population(survivor_method):
"""Appends the selected chromosomes to the next population.""" """Appends the selected chromosomes to the next population."""
return lambda ga:\ return lambda ga:\
@ -10,11 +10,11 @@ def append_to_next_population(survivor_method):
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"""
# Private method decorator, see above. # Allowing access to decorators when importing class
_append_to_next_population = append_to_next_population _append_to_next_population = _append_to_next_population
@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"""
@ -22,7 +22,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"""
@ -30,7 +30,7 @@ class Survivor_Selection:
return random.sample(ga.population, needed_amount) return random.sample(ga.population, 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"""

View File

@ -1,4 +1,4 @@
def add_by_fitness_goal(termination_impl): def _add_by_fitness_goal(termination_impl):
"""Adds termination by fitness goal to the method.""" """Adds termination by fitness goal to the method."""
def new_method(ga): def new_method(ga):
@ -20,7 +20,7 @@ def add_by_fitness_goal(termination_impl):
return new_method return new_method
def add_by_generation_goal(termination_impl): def _add_by_generation_goal(termination_impl):
"""Adds termination by generation goal to the method.""" """Adds termination by generation goal to the method."""
def new_method(ga): def new_method(ga):
@ -35,7 +35,7 @@ def add_by_generation_goal(termination_impl):
return new_method return new_method
def add_by_tolerance_goal(termination_impl): def _add_by_tolerance_goal(termination_impl):
"""Adds termination by tolerance goal to the method.""" """Adds termination by tolerance goal to the method."""
def new_method(ga): def new_method(ga):
@ -59,15 +59,15 @@ def add_by_tolerance_goal(termination_impl):
class Termination_Methods: class Termination_Methods:
"""Example functions that can be used to terminate the the algorithms loop""" """Example functions that can be used to terminate the the algorithms loop"""
# Private method decorators, see above. # Allowing access to decorators when importing class
_add_by_fitness_goal = add_by_fitness_goal _add_by_fitness_goal = _add_by_fitness_goal
_add_by_generation_goal = add_by_generation_goal _add_by_generation_goal = _add_by_generation_goal
_add_by_tolerance_goal = add_by_tolerance_goal _add_by_tolerance_goal = _add_by_tolerance_goal
@add_by_fitness_goal @_add_by_fitness_goal
@add_by_generation_goal @_add_by_generation_goal
@add_by_tolerance_goal @_add_by_tolerance_goal
def fitness_generation_tolerance(ga): def fitness_generation_tolerance(ga):
"""Terminate GA when any of the """Terminate GA when any of the
- fitness, - fitness,