Cleaned up spacing
This commit is contained in:
@ -80,14 +80,16 @@ class GA(Attributes):
|
||||
self.current_generation += 1
|
||||
|
||||
|
||||
def evolve(self):
|
||||
def evolve(self, number_of_generations = 1, consider_termination = True):
|
||||
"""Runs the ga until the termination point has been satisfied."""
|
||||
|
||||
while self.active():
|
||||
self.evolve_generation()
|
||||
self.evolve_generation(number_of_generations, consider_termination)
|
||||
|
||||
|
||||
def active(self):
|
||||
"""Returns if the ga should terminate based on the termination implimented."""
|
||||
|
||||
return self.termination_impl(self)
|
||||
|
||||
|
||||
@ -96,6 +98,7 @@ class GA(Attributes):
|
||||
the initialization implimentation
|
||||
that is currently set.
|
||||
"""
|
||||
|
||||
self.population = self.initialization_impl(self)
|
||||
|
||||
|
||||
@ -122,10 +125,10 @@ class GA(Attributes):
|
||||
"""
|
||||
|
||||
return sorted(
|
||||
chromosome_list, # list to be sorted
|
||||
key = lambda chromosome: chromosome.fitness, # by fitness
|
||||
reverse = (self.target_fitness_type == 'max') # ordered by fitness type
|
||||
)
|
||||
chromosome_list, # list to be sorted
|
||||
key = lambda chromosome: chromosome.fitness, # by fitness
|
||||
reverse = (self.target_fitness_type == 'max') # ordered by fitness type
|
||||
)
|
||||
|
||||
|
||||
def get_chromosome_fitness(self, index):
|
||||
@ -133,9 +136,10 @@ class GA(Attributes):
|
||||
at the specified index after conversion based
|
||||
on the target fitness type.
|
||||
"""
|
||||
|
||||
return self.convert_fitness(
|
||||
self.population[index].fitness
|
||||
)
|
||||
self.population[index].fitness
|
||||
)
|
||||
|
||||
|
||||
def convert_fitness(self, fitness_value):
|
||||
|
||||
@ -35,17 +35,17 @@ class Attributes:
|
||||
attributes have been catigorized to explain sections in the ga process."""
|
||||
|
||||
target_fitness_type_dict = {
|
||||
'min' : 'min',
|
||||
'minimize' : 'min',
|
||||
'minimise' : 'min',
|
||||
'minimization' : 'min',
|
||||
'minimisation' : 'min',
|
||||
'max' : 'max',
|
||||
'maximize' : 'max',
|
||||
'maximise' : 'max',
|
||||
'maximization' : 'max',
|
||||
'maximisation' : 'max'
|
||||
}
|
||||
'min' : 'min',
|
||||
'minimize' : 'min',
|
||||
'minimise' : 'min',
|
||||
'minimization' : 'min',
|
||||
'minimisation' : 'min',
|
||||
'max' : 'max',
|
||||
'maximize' : 'max',
|
||||
'maximise' : 'max',
|
||||
'maximization' : 'max',
|
||||
'maximisation' : 'max'
|
||||
}
|
||||
|
||||
def __init__(self,
|
||||
chromosome_length = 10,
|
||||
|
||||
@ -6,10 +6,10 @@ class Matplotlib_Graph:
|
||||
|
||||
# Common graphing functions
|
||||
type_of_graph_dict = {
|
||||
'line' : plt.plot,
|
||||
'scatter' : plt.scatter,
|
||||
'bar' : plt.bar
|
||||
}
|
||||
'line' : plt.plot,
|
||||
'scatter' : plt.scatter,
|
||||
'bar' : plt.bar
|
||||
}
|
||||
|
||||
def __init__(self, database):
|
||||
self.database = database
|
||||
@ -31,9 +31,9 @@ class Matplotlib_Graph:
|
||||
# Query for Y data
|
||||
self.y = self.database.get_generation_total_fitness(config_id)
|
||||
|
||||
# If using log then the values have to be positive numbers
|
||||
if self.yscale == "log":
|
||||
# If using log then the values have to be positive numbers
|
||||
self.y = [abs(ele) for ele in self.y]
|
||||
self.y = [abs(ele) for ele in self.y]
|
||||
|
||||
self.type_of_graph(self.x, self.y)
|
||||
plt.xlabel('Generation')
|
||||
@ -53,9 +53,9 @@ class Matplotlib_Graph:
|
||||
# Query for Y data
|
||||
self.y = self.database.get_highest_chromosome(config_id)
|
||||
|
||||
# If using log then the values have to be positive numbers
|
||||
if self.yscale == "log":
|
||||
# If using log then the values have to be positive numbers
|
||||
self.y = [abs(ele) for ele in self.y]
|
||||
self.y = [abs(ele) for ele in self.y]
|
||||
|
||||
self.type_of_graph(self.x, self.y)
|
||||
plt.xlabel('Generation')
|
||||
@ -75,9 +75,9 @@ class Matplotlib_Graph:
|
||||
# Query for Y data
|
||||
self.y = self.database.get_lowest_chromosome(config_id)
|
||||
|
||||
# If using log then the values have to be positive numbers
|
||||
if self.yscale == "log":
|
||||
# If using log then the values have to be positive numbers
|
||||
self.y = [abs(ele) for ele in self.y]
|
||||
self.y = [abs(ele) for ele in self.y]
|
||||
|
||||
self.type_of_graph(self.x, self.y)
|
||||
plt.xlabel('Generation')
|
||||
|
||||
@ -11,14 +11,17 @@ class SQL_Database:
|
||||
|
||||
def default_config_id(method):
|
||||
"""Decorator used to set the default config_id"""
|
||||
|
||||
def new_method(self, config_id = None):
|
||||
input_id = self.config_id if config_id is None else config_id
|
||||
return method(self, input_id)
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
def format_query_data(method):
|
||||
"""Decorator used to format query data"""
|
||||
|
||||
def new_method(self, config_id):
|
||||
query = method(self, config_id)
|
||||
|
||||
@ -31,6 +34,7 @@ class SQL_Database:
|
||||
query = query[0]
|
||||
|
||||
return query
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
@ -48,9 +52,9 @@ class SQL_Database:
|
||||
def sql_type_of(self, obj):
|
||||
"""Returns the sql type for the object"""
|
||||
|
||||
if type(obj) == int:
|
||||
if isinstance(obj, int):
|
||||
return 'INT'
|
||||
elif type(obj) == float:
|
||||
elif isinstance(obj, float):
|
||||
return 'REAL'
|
||||
else:
|
||||
return 'TEXT'
|
||||
@ -84,7 +88,12 @@ class SQL_Database:
|
||||
""" Insert one chromosome into the database"""
|
||||
|
||||
# Structure the insert data
|
||||
db_chromosome = (self.config_id, generation, chromosome.fitness, repr(chromosome))
|
||||
db_chromosome = (
|
||||
self.config_id,
|
||||
generation,
|
||||
chromosome.fitness,
|
||||
repr(chromosome)
|
||||
)
|
||||
|
||||
# Create sql query structure
|
||||
sql = ''' INSERT INTO data(config_id, generation, fitness, chromosome)
|
||||
@ -101,13 +110,14 @@ class SQL_Database:
|
||||
|
||||
# Structure the insert data
|
||||
db_chromosome_list = [
|
||||
(
|
||||
self.config_id,
|
||||
ga.current_generation,
|
||||
chromosome.fitness,
|
||||
repr(chromosome)
|
||||
)
|
||||
for chromosome in ga.population
|
||||
(
|
||||
self.config_id,
|
||||
ga.current_generation,
|
||||
chromosome.fitness,
|
||||
repr(chromosome)
|
||||
)
|
||||
for chromosome
|
||||
in ga.population
|
||||
]
|
||||
|
||||
# Create sql query structure
|
||||
@ -158,9 +168,12 @@ class SQL_Database:
|
||||
attribute variables and adds them as columns in the database table config"""
|
||||
|
||||
# Structure the config table
|
||||
sql = "CREATE TABLE IF NOT EXISTS config (id INTEGER PRIMARY KEY,"
|
||||
sql += ",".join(var + ' ' + self.sql_type_of(var) for var in self.get_var_names(ga))
|
||||
sql += "); "
|
||||
sql = "CREATE TABLE IF NOT EXISTS config (id INTEGER PRIMARY KEY," \
|
||||
+ ",".join(
|
||||
var + ' ' + self.sql_type_of(var)
|
||||
for var
|
||||
in self.get_var_names(ga)
|
||||
) + "); "
|
||||
|
||||
return sql
|
||||
|
||||
@ -179,11 +192,11 @@ class SQL_Database:
|
||||
db_config_list[i] = str(db_config_list[i])
|
||||
|
||||
# Create sql query structure
|
||||
sql = "INSERT INTO config ("
|
||||
sql += ",".join(self.get_var_names(ga))
|
||||
sql += ") VALUES("
|
||||
sql += ( ",?"*len(db_config_list) )[1:]
|
||||
sql += ") "
|
||||
sql = "INSERT INTO config (" \
|
||||
+ ",".join(self.get_var_names(ga)) \
|
||||
+ ") VALUES(" \
|
||||
+ ( ",?"*len(db_config_list) )[1:] \
|
||||
+ ") "
|
||||
|
||||
# For some reason it has to be in var = array(tuple()) form
|
||||
db_config_list = [tuple(db_config_list)]
|
||||
@ -202,7 +215,6 @@ class SQL_Database:
|
||||
|
||||
cur = self.conn.cursor()
|
||||
cur.execute(query)
|
||||
|
||||
return cur.fetchall()
|
||||
|
||||
|
||||
@ -270,6 +282,7 @@ class SQL_Database:
|
||||
@property
|
||||
def conn(self):
|
||||
"""Getter function for conn"""
|
||||
|
||||
# Return if the connection has already been set
|
||||
if self._conn is not None:
|
||||
return self._conn
|
||||
@ -279,6 +292,7 @@ class SQL_Database:
|
||||
try:
|
||||
# Check if you can connect to the database
|
||||
self._conn = self.create_connection()
|
||||
|
||||
except:
|
||||
# if the connection doesnt exist then print error
|
||||
raise Exception("""You are required to run a ga before you
|
||||
@ -296,6 +310,7 @@ class SQL_Database:
|
||||
@property
|
||||
def config_id(self):
|
||||
"""Getter function for config_id"""
|
||||
|
||||
# Return if the config_id has already been set
|
||||
if self._config_id is not None:
|
||||
return self._config_id
|
||||
@ -305,10 +320,11 @@ class SQL_Database:
|
||||
try:
|
||||
# Check if you can connect to the database
|
||||
self._config_id = self.get_most_recent_config_id()
|
||||
|
||||
except:
|
||||
# if the config_id doesnt exist then print error
|
||||
raise Exception("""You are required to run a ga before you
|
||||
can connect to the database. Run ga.evolve() or ga.active()""")
|
||||
can connect to the database. Run ga.evolve() or ga.active()""")
|
||||
|
||||
|
||||
@config_id.setter
|
||||
|
||||
@ -2,7 +2,11 @@ def chromosomes_to_population(initialize):
|
||||
"""Makes a population from chromosomes."""
|
||||
return lambda ga:\
|
||||
ga.make_population(
|
||||
[initialize(ga) for _ in range(ga.population_size)]
|
||||
[
|
||||
initialize(ga)
|
||||
for _
|
||||
in range(ga.population_size)
|
||||
]
|
||||
)
|
||||
|
||||
def genes_to_chromosome(initialize):
|
||||
@ -15,19 +19,20 @@ def genes_to_chromosome(initialize):
|
||||
def values_to_genes(initialize):
|
||||
"""Converts a collection of values to genes."""
|
||||
return lambda ga:\
|
||||
(ga.make_gene(value) for value in initialize(ga))
|
||||
(
|
||||
ga.make_gene(value)
|
||||
for value
|
||||
in initialize(ga)
|
||||
)
|
||||
|
||||
|
||||
class Initialization_Methods:
|
||||
"""Initialization examples that are used as defaults and examples"""
|
||||
|
||||
# Private method decorators, see above.
|
||||
def _chromosomes_to_population(initialize):
|
||||
return chromosomes_to_population(initialize)
|
||||
def _genes_to_chromosome(initialize):
|
||||
return genes_to_chromosome(initialize)
|
||||
def _value_to_gene(initialize):
|
||||
return value_to_gene(initialize)
|
||||
_chromosomes_to_population = chromosomes_to_population
|
||||
_genes_to_chromosome = genes_to_chromosome
|
||||
_value_to_gene = value_to_gene
|
||||
|
||||
|
||||
@chromosomes_to_population
|
||||
|
||||
@ -4,7 +4,7 @@ from math import ceil
|
||||
def check_chromosome_mutation_rate(population_method):
|
||||
"""Checks if the chromosome mutation rate is a float between 0 and 1 before running."""
|
||||
|
||||
def new_population_method(ga):
|
||||
def new_method(ga):
|
||||
|
||||
if not isinstance(ga.chromosome_mutation_rate, float):
|
||||
raise TypeError("Chromosome mutation rate must be a float.")
|
||||
@ -15,13 +15,13 @@ def check_chromosome_mutation_rate(population_method):
|
||||
else:
|
||||
raise ValueError("Chromosome mutation rate must be between 0 and 1.")
|
||||
|
||||
return new_population_method
|
||||
return new_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_individual_method(ga, index):
|
||||
def new_method(ga, index):
|
||||
|
||||
if not isinstance(ga.gene_mutation_rate, float):
|
||||
raise TypeError("Gene mutation rate must be a float.")
|
||||
@ -32,19 +32,19 @@ def check_gene_mutation_rate(individual_method):
|
||||
else:
|
||||
raise ValueError("Gene mutation rate must be between 0 and 1.")
|
||||
|
||||
return new_individual_method
|
||||
return new_method
|
||||
|
||||
|
||||
def loop_selections(population_method):
|
||||
"""Runs the population method until enough chromosomes are mutated."""
|
||||
|
||||
def new_population_method(ga):
|
||||
def new_method(ga):
|
||||
|
||||
# Loop the population method until enough chromosomes are mutated.
|
||||
for _ in range(ceil(len(ga.population)*ga.chromosome_mutation_rate)):
|
||||
population_method(ga)
|
||||
|
||||
return new_population_method
|
||||
return new_method
|
||||
|
||||
|
||||
def loop_mutations(individual_method):
|
||||
@ -53,26 +53,22 @@ def loop_mutations(individual_method):
|
||||
"""
|
||||
|
||||
# Change input from index to chromosome.
|
||||
def new_individual_method(ga, index):
|
||||
def new_method(ga, index):
|
||||
|
||||
# Loop the individual method until enough genes are mutated.
|
||||
for _ in range(ceil(len(ga.population[index])*ga.gene_mutation_rate)):
|
||||
individual_method(ga, ga.population[index])
|
||||
|
||||
return new_individual_method
|
||||
return new_method
|
||||
|
||||
|
||||
class Mutation_Methods:
|
||||
|
||||
# Private method decorators, see above.
|
||||
def _check_chromosome_mutation_rate(population_method):
|
||||
return check_chromosome_mutation_rate(population_method)
|
||||
def _check_gene_mutation_rate(individual_method):
|
||||
return check_gene_mutation_rate(individual_method)
|
||||
def _loop_selections(population_method):
|
||||
return loop_selections(population_method)
|
||||
def _loop_mutations(individual_method):
|
||||
return loop_mutations(individual_method)
|
||||
_check_chromosome_mutation_rate = check_chromosome_mutation_rate
|
||||
_check_gene_mutation_rate = check_gene_mutation_rate
|
||||
_loop_selections = loop_selections
|
||||
_loop_mutations = loop_mutations
|
||||
|
||||
|
||||
class Population:
|
||||
@ -92,7 +88,10 @@ class Mutation_Methods:
|
||||
def random_avoid_best(ga):
|
||||
"""Selects random chromosomes while avoiding the best chromosomes. (Elitism)"""
|
||||
|
||||
index = random.randrange(int(len(ga.population)*ga.gene_mutation_rate/2), len(ga.population))
|
||||
index = random.randrange(
|
||||
int(len(ga.population)*ga.gene_mutation_rate/2),
|
||||
len(ga.population)
|
||||
)
|
||||
ga.mutation_individual_impl(ga, index)
|
||||
|
||||
|
||||
|
||||
@ -5,12 +5,14 @@ def check_selection_probability(selection_method):
|
||||
is not between 0 and 1. Otherwise runs the selection
|
||||
method.
|
||||
"""
|
||||
def helper(ga):
|
||||
|
||||
def new_method(ga):
|
||||
if 0 < ga.selection_probability < 1:
|
||||
selection_method(ga)
|
||||
else:
|
||||
raise Exception("Selection probability must be between 0 and 1 to select parents.")
|
||||
return helper
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
def check_positive_fitness(selection_method):
|
||||
@ -18,33 +20,34 @@ def check_positive_fitness(selection_method):
|
||||
chromosome with negative fitness. Otherwise runs
|
||||
the selection method.
|
||||
"""
|
||||
def helper(ga):
|
||||
|
||||
def new_method(ga):
|
||||
if ga.get_chromosome_fitness(0) > 0 and ga.get_chromosome_fitness(-1) >= 0:
|
||||
selection_method(ga)
|
||||
else:
|
||||
raise Exception("Converted fitness values must be all positive. Consider using rank selection instead.")
|
||||
return helper
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
def ensure_sorted(selection_method):
|
||||
"""Sorts the population by fitness
|
||||
and then runs the selection method.
|
||||
"""
|
||||
def helper(ga):
|
||||
|
||||
def new_method(ga):
|
||||
ga.population.sort_by_best_fitness(ga)
|
||||
selection_method(ga)
|
||||
return helper
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
class Parent_Selection:
|
||||
|
||||
# Private method decorators, see above.
|
||||
def _check_selection_probability(selection_method):
|
||||
return check_selection_probability(selection_method)
|
||||
def _check_positive_fitness(selection_method):
|
||||
return check_positive_fitness(selection_method)
|
||||
def _ensure_sorted(selection_method):
|
||||
return ensure_sorted(selection_method)
|
||||
_check_selection_probability = check_selection_probability
|
||||
_check_positive_fitness = check_positive_fitness
|
||||
_ensure_sorted = ensure_sorted
|
||||
|
||||
|
||||
class Rank:
|
||||
@ -62,13 +65,16 @@ class Parent_Selection:
|
||||
# Use no less than 5 chromosomes per tournament.
|
||||
tournament_size = int(len(ga.population)*ga.tournament_size_ratio)
|
||||
if tournament_size < 5:
|
||||
tournament_size = 5
|
||||
tournament_size = min(5, len(ga.population))
|
||||
|
||||
# Repeat tournaments until the mating pool is large enough.
|
||||
while True:
|
||||
|
||||
# Generate a random tournament group and sort by fitness.
|
||||
tournament_group = sorted([random.randrange(len(ga.population)) for _ in range(tournament_size)])
|
||||
tournament_group = sorted(random.sample(
|
||||
range(len(ga.population)),
|
||||
k = tournament_size
|
||||
))
|
||||
|
||||
# For each chromosome, add it to the mating pool based on its rank in the tournament.
|
||||
for index in range(tournament_size):
|
||||
@ -101,7 +107,11 @@ class Parent_Selection:
|
||||
"""
|
||||
|
||||
# The sum of all the fitnessess in a population
|
||||
fitness_sum = sum(ga.get_chromosome_fitness(index) for index in range(len(ga.population)))
|
||||
fitness_sum = sum(
|
||||
ga.get_chromosome_fitness(index)
|
||||
for index
|
||||
in range(len(ga.population))
|
||||
)
|
||||
|
||||
# A list of ranges that represent the probability of a chromosome getting chosen
|
||||
probability = [ga.selection_probability]
|
||||
|
||||
@ -150,7 +150,7 @@ class Population:
|
||||
to get a backend representation of the population.
|
||||
"""
|
||||
return ''.join(
|
||||
f'Chromosome - {index} {chromosome} ' +
|
||||
f'/ Fitness = {chromosome.fitness}\n'
|
||||
for index, chromosome in enumerate(self)
|
||||
f'Chromosome - {index} {chromosome} / Fitness = {chromosome.fitness}\n'
|
||||
for index, chromosome
|
||||
in enumerate(self)
|
||||
)
|
||||
|
||||
@ -2,15 +2,16 @@ import random
|
||||
|
||||
def append_to_next_population(survivor_method):
|
||||
"""Appends the selected chromosomes to the next population."""
|
||||
return lambda ga: ga.population.append_children(survivor_method(ga))
|
||||
|
||||
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"""
|
||||
|
||||
# Private method decorator, see above.
|
||||
def _append_to_next_population(survivor_method):
|
||||
return append_to_next_population(survivor_method)
|
||||
_append_to_next_population = append_to_next_population
|
||||
|
||||
|
||||
@append_to_next_population
|
||||
@ -33,8 +34,11 @@ class Survivor_Selection:
|
||||
def fill_in_parents_then_random(ga):
|
||||
"""Fills in the next population with all parents followed by random chromosomes from the last population"""
|
||||
|
||||
# Remove dupes from the mating pool
|
||||
mating_pool = set(ga.population.mating_pool)
|
||||
|
||||
needed_amount = len(ga.population) - len(ga.population.next_population)
|
||||
parent_amount = min(len(ga.population.mating_pool), needed_amount)
|
||||
parent_amount = min(needed_amount, len(mating_pool))
|
||||
random_amount = needed_amount - parent_amount
|
||||
|
||||
# Only parents are used.
|
||||
@ -43,5 +47,8 @@ class Survivor_Selection:
|
||||
|
||||
# Parents need to be removed from the random sample to avoid dupes.
|
||||
else:
|
||||
return ga.population.mating_pool +\
|
||||
random.sample(set(ga.population)-set(ga.population.mating_pool), random_amount)
|
||||
return mating_pool \
|
||||
+ random.sample(
|
||||
set(ga.population) - mating_pool,
|
||||
random_amount
|
||||
)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
def add_by_fitness_goal(termination_impl):
|
||||
"""Adds termination by fitness goal to the method."""
|
||||
|
||||
def helper(ga):
|
||||
def new_method(ga):
|
||||
|
||||
# If fitness goal is set, check it.
|
||||
if ga.fitness_goal is not None:
|
||||
@ -16,13 +16,14 @@ def add_by_fitness_goal(termination_impl):
|
||||
|
||||
# Check other termination methods
|
||||
return termination_impl(ga)
|
||||
return helper
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
def add_by_generation_goal(termination_impl):
|
||||
"""Adds termination by generation goal to the method."""
|
||||
|
||||
def helper(ga):
|
||||
def new_method(ga):
|
||||
|
||||
# If generation goal is set, check it.
|
||||
if ga.generation_goal is not None and ga.current_generation >= ga.generation_goal:
|
||||
@ -30,18 +31,19 @@ def add_by_generation_goal(termination_impl):
|
||||
|
||||
# Check other termination methods
|
||||
return termination_impl(ga)
|
||||
return helper
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
def add_by_tolerance_goal(termination_impl):
|
||||
"""Adds termination by tolerance goal to the method."""
|
||||
|
||||
def helper(ga):
|
||||
def new_method(ga):
|
||||
|
||||
# If tolerance is set, check it.
|
||||
if ga.tolerance_goal is not None:
|
||||
best_fitness = ga.population[0].fitness
|
||||
threshhold_fitness = ga.population[int(ga.percent_converged*len(ga.population))].fitness
|
||||
threshhold_fitness = ga.population[round(ga.percent_converged*len(ga.population))].fitness
|
||||
tol = ga.tolerance_goal * (1 + abs(best_fitness))
|
||||
|
||||
# Terminate if the specified amount of the population has converged to the specified tolerance
|
||||
@ -50,19 +52,17 @@ def add_by_tolerance_goal(termination_impl):
|
||||
|
||||
# Check other termination methods
|
||||
return termination_impl(ga)
|
||||
return helper
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
class Termination_Methods:
|
||||
"""Example functions that can be used to terminate the the algorithms loop"""
|
||||
|
||||
# Private method decorators, see above.
|
||||
def _add_by_fitness_goal(termination_impl):
|
||||
return add_by_fitness_goal(termination_impl)
|
||||
def _add_by_generation_goal(termination_impl):
|
||||
return add_by_generation_goal(termination_impl)
|
||||
def _add_by_tolerance_goal(termination_impl):
|
||||
return add_by_tolerance_goal(termination_impl)
|
||||
_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
|
||||
|
||||
Reference in New Issue
Block a user