Changed for more general usage and cleaned up previous push

This commit is contained in:
SimpleArt
2020-12-30 09:08:43 -05:00
parent 0c59c429eb
commit 21c12c2bcd

View File

@ -6,20 +6,6 @@ import random
randround = lambda x: int(x + random.random()) randround = lambda x: int(x + random.random())
@function_info
def _append_to_next_population(population_method):
"""Appends the new chromosomes to the next population.
Also modifies the input to include the mating pool.
"""
def new_method(ga):
ga.population.append_children(
population_method(ga, ga.population.mating_pool)
)
return new_method
@function_info @function_info
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.
@ -30,9 +16,9 @@ def _check_weight(individual_method):
def new_method(ga, parent_1, parent_2, *, weight = individual_method.__kwdefaults__.get('weight', None)): def new_method(ga, parent_1, parent_2, *, weight = individual_method.__kwdefaults__.get('weight', None)):
if weight is None: if weight is None:
return individual_method(ga, parent_1, parent_2) individual_method(ga, parent_1, parent_2)
elif 0 < weight < 1: elif 0 < weight < 1:
return individual_method(ga, parent_1, parent_2, weight = weight) individual_method(ga, parent_1, parent_2, weight = weight)
else: else:
raise ValueError(f"Weight must be between 0 and 1 when using {individual_method.__name__}.") raise ValueError(f"Weight must be between 0 and 1 when using {individual_method.__name__}.")
@ -41,23 +27,13 @@ def _check_weight(individual_method):
@function_info @function_info
def _gene_by_gene(individual_method): def _gene_by_gene(individual_method):
"""Perform crossover by making a single new chromosome """Perform crossover by making a single new chromosome by combining each gene by gene."""
by combining each gene by gene.
"""
def new_method(ga, parent_1, parent_2, *, weight = individual_method.__kwdefaults__.get('weight', None)): def new_method(ga, parent_1, parent_2, *, weight = individual_method.__kwdefaults__.get('weight', 'None')):
# Without any weight ga.population.add_child(
if weight is None:
yield (
individual_method(ga, value_1, value_2) individual_method(ga, value_1, value_2)
for value_1, value_2 if weight == 'None' else
in zip(parent_1.gene_value_iter, parent_2.gene_value_iter)
)
# With a weight
else:
yield (
individual_method(ga, value_1, value_2, weight = weight) individual_method(ga, value_1, value_2, weight = weight)
for value_1, value_2 for value_1, value_2
in zip(parent_1.gene_value_iter, parent_2.gene_value_iter) in zip(parent_1.gene_value_iter, parent_2.gene_value_iter)
@ -69,7 +45,6 @@ def _gene_by_gene(individual_method):
class Crossover_Methods: class Crossover_Methods:
# Allowing access to decorators when importing class # Allowing access to decorators when importing class
_append_to_next_population = _append_to_next_population
_check_weight = _check_weight _check_weight = _check_weight
_gene_by_gene = _gene_by_gene _gene_by_gene = _gene_by_gene
@ -78,7 +53,6 @@ class Crossover_Methods:
"""Methods for selecting chromosomes to crossover.""" """Methods for selecting chromosomes to crossover."""
@_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.
@ -86,20 +60,19 @@ class Crossover_Methods:
""" """
for index in range(len(mating_pool)): # for each parent in the mating pool for index in range(len(mating_pool)): # for each parent in the mating pool
yield from ga.crossover_individual_impl( # apply crossover to ga.crossover_individual_impl( # apply crossover to
mating_pool[index], # the parent and mating_pool[index], # the parent and
mating_pool[index-1], # the previous parent mating_pool[index-1], # the previous parent
) )
@_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.
""" """
for parent in mating_pool: # for each parent in the mating pool for parent in mating_pool: # for each parent in the mating pool
yield from ga.crossover_individual_impl( # apply crossover to ga.crossover_individual_impl( # apply crossover to
parent, # the parent and parent, # the parent and
random.choice(mating_pool), # a random parent random.choice(mating_pool), # a random parent
) )
@ -118,8 +91,8 @@ class Crossover_Methods:
# Weighted random integer from 0 to minimum parent length - 1 # Weighted random integer from 0 to minimum parent length - 1
swap_index = int(ga.weighted_random(weight) * minimum_parent_length) swap_index = int(ga.weighted_random(weight) * minimum_parent_length)
yield parent_1[:swap_index] + parent_2[swap_index:] ga.population.add_child(parent_1[:swap_index] + parent_2[swap_index:])
yield parent_2[:swap_index] + parent_1[swap_index:] ga.population.add_child(parent_2[:swap_index] + parent_1[swap_index:])
@_check_weight @_check_weight
@ -174,7 +147,7 @@ class Crossover_Methods:
if type(value_1) == type(value_2) == int: if type(value_1) == type(value_2) == int:
value = randround(value) value = randround(value)
yield value return value
class Permutation: class Permutation:
@ -222,7 +195,7 @@ class Crossover_Methods:
gene_list_1[input_index] = gene_list_2.pop(-1) gene_list_1[input_index] = gene_list_2.pop(-1)
input_index += 1 input_index += 1
yield gene_list_1 ga.population.add_child(gene_list_1)
@_check_weight @_check_weight
@ -282,4 +255,4 @@ class Crossover_Methods:
gene_list_1[input_index] = gene_list_2.pop(-1) gene_list_1[input_index] = gene_list_2.pop(-1)
input_index += 1 input_index += 1
yield gene_list_1 ga.population.add_child(gene_list_1)