Update stochastic methods
- Added a stochastic rank selection and edited cleaner stochastic fitness selection using random.choices. - Edited stochastic fitness selection to allow negative converted fitness values. - Edited exception message for check_positive_fitness.
This commit is contained in:
@ -25,7 +25,7 @@ def check_positive_fitness(selection_method):
|
|||||||
if ga.get_chromosome_fitness(0) > 0 and ga.get_chromosome_fitness(-1) >= 0:
|
if ga.get_chromosome_fitness(0) > 0 and ga.get_chromosome_fitness(-1) >= 0:
|
||||||
selection_method(ga)
|
selection_method(ga)
|
||||||
else:
|
else:
|
||||||
raise Exception("Converted fitness values must be all positive. Consider using rank selection instead.")
|
raise Exception("Converted fitness values can't have negative values or be all 0. Consider using rank selection or stochastic selection instead.")
|
||||||
|
|
||||||
return new_method
|
return new_method
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ def compute_parent_amount(selection_method):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def new_method(ga):
|
def new_method(ga):
|
||||||
parent_amount = max(2, len(ga.population)*ga.parent_ratio)
|
parent_amount = max(2, round(len(ga.population)*ga.parent_ratio))
|
||||||
selection_method(ga, parent_amount)
|
selection_method(ga, parent_amount)
|
||||||
|
|
||||||
return new_method
|
return new_method
|
||||||
@ -65,6 +65,9 @@ class Parent_Selection:
|
|||||||
|
|
||||||
|
|
||||||
class Rank:
|
class Rank:
|
||||||
|
"""Methods for selecting parents based on their rankings in the population
|
||||||
|
i.e. the n-th best chromosome has a fixed probability of being selected,
|
||||||
|
regardless of their chances"""
|
||||||
|
|
||||||
@check_selection_probability
|
@check_selection_probability
|
||||||
@ensure_sorted
|
@ensure_sorted
|
||||||
@ -107,6 +110,25 @@ class Parent_Selection:
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@check_selection_probability
|
||||||
|
@ensure_sorted
|
||||||
|
@compute_parent_amount
|
||||||
|
def stochastic(ga, parent_amount):
|
||||||
|
"""
|
||||||
|
Selects parents using the same probability approach as tournament selection,
|
||||||
|
but doesn't create tournaments. Uses random.choices with weighted values to
|
||||||
|
select parents and may produce duplicate parents.
|
||||||
|
"""
|
||||||
|
|
||||||
|
weights = [
|
||||||
|
(1-ga.selection_probability) ** i
|
||||||
|
for i
|
||||||
|
in range(len(ga.population))
|
||||||
|
]
|
||||||
|
|
||||||
|
ga.population.mating_pool = random.choices(ga.population, weights, k = parent_amount)
|
||||||
|
|
||||||
|
|
||||||
class Fitness:
|
class Fitness:
|
||||||
|
|
||||||
@check_selection_probability
|
@check_selection_probability
|
||||||
@ -153,24 +175,25 @@ class Parent_Selection:
|
|||||||
|
|
||||||
@check_selection_probability
|
@check_selection_probability
|
||||||
@ensure_sorted
|
@ensure_sorted
|
||||||
@check_positive_fitness
|
|
||||||
@compute_parent_amount
|
@compute_parent_amount
|
||||||
def stochastic(ga, parent_amount):
|
def stochastic(ga, parent_amount):
|
||||||
"""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
|
Selects parents using the same probability approach as roulette selection,
|
||||||
that it will be selected. Instead of dividing the fitness by the sum of all fitnesses
|
but doesn't spin a roulette for every selection. Uses random.choices with
|
||||||
and incrementally increasing the chance something is selected, the stochastic method
|
weighted values to select parents and may produce duplicate parents.
|
||||||
just divides by the highest fitness and selects randomly.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
max_fitness = ga.get_chromosome_fitness(0)
|
if ga.get_chromosome_fitness(-1) == ga.get_chromosome_fitness(0):
|
||||||
|
offset = 1-ga.get_chromosome_fitness(-1)
|
||||||
|
elif ga.get_chromosome_fitness(-1) < 0:
|
||||||
|
offset = -ga.get_chromosome_fitness(-1)
|
||||||
|
else:
|
||||||
|
offset = 0
|
||||||
|
|
||||||
# Loops until it reaches a desired mating pool size
|
weights = [
|
||||||
while len(ga.population.mating_pool) < parent_amount:
|
ga.get_chromosome_fitness(index) + offset
|
||||||
|
for index
|
||||||
|
in range(len(ga.population))
|
||||||
|
]
|
||||||
|
|
||||||
# Selected chromosome
|
ga.population.mating_pool = random.choices(ga.population, weights, k = parent_amount)
|
||||||
index = random.randrange(len(ga.population))
|
|
||||||
|
|
||||||
# Probability of becoming a parent is fitness/max_fitness
|
|
||||||
if random.uniform(ga.selection_probability, 1) < ga.get_chromosome_fitness(index)/max_fitness:
|
|
||||||
ga.population.set_parent(index)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user