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
def append_to_next_population(population_method):
def _append_to_next_population(population_method):
"""Appends the new chromosomes to the next population.
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.
Exception may occur when using ga.adapt, which will catch
the error and try again with valid weight.
@ -27,7 +27,7 @@ def check_weight(individual_method):
return new_method
def genes_to_chromosome(individual_method):
def _genes_to_chromosome(individual_method):
"""Converts a collection of genes into a chromosome.
Note: Will recreate the gene list if given gene list.
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.
Returns a generator of genes to avoid storing a new list.
"""
@ -55,18 +55,18 @@ def values_to_genes(individual_method):
class Crossover_Methods:
# Private method decorators, see above.
_append_to_next_population = append_to_next_population
_check_weight = check_weight
_genes_to_chromosome = genes_to_chromosome
_values_to_genes = values_to_genes
# Allowing access to decorators when importing class
_append_to_next_population = _append_to_next_population
_check_weight = _check_weight
_genes_to_chromosome = _genes_to_chromosome
_values_to_genes = _values_to_genes
class Population:
"""Methods for selecting chromosomes to crossover."""
@append_to_next_population
@_append_to_next_population
def sequential_selection(ga, mating_pool):
"""Select sequential pairs from the mating pool.
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):
"""Select random pairs from the mating pool.
Every parent is paired with a random parent.
@ -101,8 +101,8 @@ class Crossover_Methods:
"""Methods for crossing parents."""
@check_weight
@genes_to_chromosome
@_check_weight
@_genes_to_chromosome
def single_point(ga, parent_1, parent_2, weight = 0.5):
"""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:]
@check_weight
@genes_to_chromosome
@_check_weight
@_genes_to_chromosome
def multi_point(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by swapping genes at multiple points."""
pass
@check_weight
@genes_to_chromosome
@_check_weight
@_genes_to_chromosome
def uniform(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by swapping all genes randomly."""
@ -143,8 +143,8 @@ class Crossover_Methods:
class Arithmetic:
"""Crossover methods for numerical genes."""
@genes_to_chromosome
@values_to_genes
@_genes_to_chromosome
@_values_to_genes
def average(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by taking the average of the genes."""
@ -161,8 +161,8 @@ class Crossover_Methods:
yield value
@genes_to_chromosome
@values_to_genes
@_genes_to_chromosome
@_values_to_genes
def extrapolate(ga, parent_1, parent_2, weight = 0.5):
"""Cross two parents by extrapolating towards the first parent.
@ -182,9 +182,9 @@ class Crossover_Methods:
yield value
@check_weight
@genes_to_chromosome
@values_to_genes
@_check_weight
@_genes_to_chromosome
@_values_to_genes
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."""

View File

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

View File

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

View File

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

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."""
def new_method(ga):
@ -20,7 +20,7 @@ def add_by_fitness_goal(termination_impl):
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."""
def new_method(ga):
@ -35,7 +35,7 @@ def add_by_generation_goal(termination_impl):
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."""
def new_method(ga):
@ -59,15 +59,15 @@ def add_by_tolerance_goal(termination_impl):
class Termination_Methods:
"""Example functions that can be used to terminate the the algorithms loop"""
# Private method decorators, see above.
_add_by_fitness_goal = add_by_fitness_goal
_add_by_generation_goal = add_by_generation_goal
_add_by_tolerance_goal = add_by_tolerance_goal
# Allowing access to decorators when importing class
_add_by_fitness_goal = _add_by_fitness_goal
_add_by_generation_goal = _add_by_generation_goal
_add_by_tolerance_goal = _add_by_tolerance_goal
@add_by_fitness_goal
@add_by_generation_goal
@add_by_tolerance_goal
@_add_by_fitness_goal
@_add_by_generation_goal
@_add_by_tolerance_goal
def fitness_generation_tolerance(ga):
"""Terminate GA when any of the
- fitness,