Skip to content

Commit

Permalink
Add option to show stats at the end
Browse files Browse the repository at this point in the history
  • Loading branch information
diogomatoschaves committed Jun 25, 2020
1 parent 5d5ebb5 commit a28ab1d
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 9 deletions.
3 changes: 3 additions & 0 deletions geneal/genetic_algorithms/_binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def __init__(
selection_rate: float = 0.5,
selection_strategy: str = "roulette_wheel",
verbose: bool = True,
show_stats: bool = True,
plot_results: bool = True,
excluded_genes: Sequence = None,
n_crossover_points: int = 1,
Expand All @@ -33,6 +34,7 @@ def __init__(
:param selection_rate: percentage of the population to be selected for crossover
:param selection_strategy: strategy to use for selection
:param verbose: whether to print iterations status
:param show_stats: whether to print stats at the end
:param plot_results: whether to plot results of the run at the end
"""

Expand All @@ -46,6 +48,7 @@ def __init__(
selection_rate=selection_rate,
selection_strategy=selection_strategy,
verbose=verbose,
show_stats=show_stats,
plot_results=plot_results,
excluded_genes=excluded_genes,
n_crossover_points=n_crossover_points,
Expand Down
3 changes: 3 additions & 0 deletions geneal/genetic_algorithms/_continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def __init__(
selection_rate: float = 0.5,
selection_strategy: str = "roulette_wheel",
verbose: bool = True,
show_stats: bool = True,
plot_results: bool = True,
excluded_genes: Sequence = None,
variables_limits=(-10, 10),
Expand All @@ -35,6 +36,7 @@ def __init__(
:param selection_rate: percentage of the population to be selected for crossover
:param selection_strategy: strategy to use for selection
:param verbose: whether to print iterations status
:param show_stats: whether to print stats at the end
:param plot_results: whether to plot results of the run at the end
:param variables_limits: limits for each variable [(x1_min, x1_max), (x2_min, x2_max), ...].
If only one tuple is provided, then it is assumed the same for every variable
Expand All @@ -51,6 +53,7 @@ def __init__(
selection_rate=selection_rate,
selection_strategy=selection_strategy,
verbose=verbose,
show_stats=show_stats,
plot_results=plot_results,
excluded_genes=excluded_genes,
n_crossover_points=n_crossover_points,
Expand Down
60 changes: 51 additions & 9 deletions geneal/genetic_algorithms/genetic_algorithm_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def __init__(
selection_rate: float = 0.5,
selection_strategy: str = "roulette_wheel",
verbose: bool = True,
show_stats: bool = True,
plot_results: bool = True,
excluded_genes: Sequence = None,
n_crossover_points: int = 1,
Expand All @@ -43,6 +44,7 @@ def __init__(
:param selection_rate: percentage of the population to be selected for crossover
:param selection_strategy: strategy to use for selection
:param verbose: whether to print iterations status
:param show_stats: whether to print stats at the end
:param plot_results: whether to plot results of the run at the end
:param n_crossover_points: number of slices to make for the crossover
:param random_state: optional. whether the random seed should be set
Expand All @@ -68,6 +70,7 @@ def __init__(
self.selection_rate = selection_rate
self.n_crossover_points = n_crossover_points
self.verbose = verbose
self.show_stats = show_stats
self.plot_results = plot_results

self.pop_keep = math.floor(selection_rate * pop_size)
Expand All @@ -81,9 +84,10 @@ def __init__(
self.n_mutations = self.get_number_mutations()

self.generations_ = 0
self.best_fitness_ = 0
self.best_individual_ = None
self.best_fitness_ = 0
self.population_ = None
self.fitness_ = None

def check_input_base(
self, fitness_function, selection_strategy, pop_size, excluded_genes
Expand Down Expand Up @@ -185,14 +189,15 @@ def solve(self):
break

self.generations_ = gen_n
self.best_fitness_ = fitness[0]
self.best_individual_ = population[0, :]
self.best_fitness_ = fitness[0]
self.population_ = population
self.fitness_ = fitness

if self.plot_results:
self.plot_fitness_results(mean_fitness, max_fitness, gen_n)

if self.verbose:
if self.show_stats:
end_time = datetime.datetime.now()

time_str = get_elapsed_time(start_time, end_time)
Expand All @@ -211,7 +216,17 @@ def calculate_fitness(self, population):
def select_parents(self, fitness):
"""
Selects the parents according to a given selection strategy.
Options are
Options are:
roulette_wheel: Selects individuals from mating pool giving
higher probabilities to fitter individuals.
two_by_two: Pairs fittest individuals two by two
random: Selects individuals from mating pool randomly.
tournament: Selects individuals by choosing groups of 3 candidate
individuals and then selecting the fittest one from the 3.
:param fitness: the fitness values of the population at a given iteration
:return: a tuple containing the selected 2 parents for each mating
Expand Down Expand Up @@ -257,12 +272,31 @@ def select_parents(self, fitness):
return ma, pa

def roulette_wheel_selection(self, value):
"""
Performs roulette wheel selection
:param value: random value defining which individual is selected
:return: the selected individual
"""
return np.argmin(value > self.prob_intervals) - 1

def random_selection(self, value):
"""
Performs random selection
:param value: random value defining which individual is selected
:return: the selected individual
"""
return np.argmin(value > self.prob_intervals) - 1

def tournament_selection(self, fitness, range_max):
"""
Performs tournament selection.
:param fitness: the fitness values of the population at a given iteration
:param range_max: range of individuals that can be selected for the tournament
:return: the selected individuals
"""

selected_individuals = np.random.choice(range_max, size=(self.n_matings, 3))

Expand All @@ -275,7 +309,17 @@ def tournament_selection(self, fitness, range_max):
)
)

def tournament_selection_helper(self, selected_individuals, fitness):
@staticmethod
def tournament_selection_helper(selected_individuals, fitness):
"""
Helper for tournament selection method. Selects the fittest individual
from a pool of candidate individuals
:param selected_individuals: group of candidate individuals for
tournament selection
:param fitness: the fitness values of the population at a given iteration
:return: the selected individual
"""

individuals_fitness = fitness[selected_individuals]

Expand All @@ -295,9 +339,7 @@ def get_selection_probabilities(self):
return np.linspace(0, 1, self.pop_keep + 1)

def get_number_mutations(self):
return math.ceil(
(self.pop_size - 1) * self.n_genes * self.mutation_rate
)
return math.ceil((self.pop_size - 1) * self.n_genes * self.mutation_rate)

@staticmethod
def sort_by_fitness(fitness, population):
Expand Down Expand Up @@ -414,4 +456,4 @@ def mutate_population(self, population, n_mutations):
self.allowed_mutation_genes, n_mutations, replace=True
)

return [mutation_rows, mutation_cols]
return mutation_rows, mutation_cols

0 comments on commit a28ab1d

Please sign in to comment.