Skip to content

Commit 19bac06

Browse files
authored
PyGAD 2.16.1
1. Reuse the fitness of previously explored solutions rather than recalculating them. This feature only works if `save_solutions=True`. 2. The user can use the `tqdm` library to show a progress bar. #50 ```python import pygad import numpy import tqdm equation_inputs = [4,-2,3.5] desired_output = 44 def fitness_func(solution, solution_idx): output = numpy.sum(solution * equation_inputs) fitness = 1.0 / (numpy.abs(output - desired_output) + 0.000001) return fitness num_generations = 10000 with tqdm.tqdm(total=num_generations) as pbar: ga_instance = pygad.GA(num_generations=num_generations, sol_per_pop=5, num_parents_mating=2, num_genes=len(equation_inputs), fitness_func=fitness_func, on_generation=lambda _: pbar.update(1)) ga_instance.run() ga_instance.plot_result() ``` 3. Solved the issue of unequal length between the `solutions` and `solutions_fitness` when the `save_solutions` parameter is set to `True`. Now, the fitness of the last population is appended to the `solutions_fitness` array. #64 4. There was an issue of getting the length of these 4 variables (`solutions`, `solutions_fitness`, `best_solutions`, and `best_solutions_fitness`) doubled after each call of the `run()` method. This is solved by resetting these variables at the beginning of the `run()` method. #62 5. Bug fixes when adaptive mutation is used (`mutation_type="adaptive"`). #65
1 parent c87641b commit 19bac06

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from .pygad import * # Relative import.
22

3-
__version__ = "2.16.0"
3+
__version__ = "2.16.1"

pygad.py

+29-9
Original file line numberDiff line numberDiff line change
@@ -1169,7 +1169,14 @@ def run(self):
11691169
"""
11701170

11711171
if self.valid_parameters == False:
1172-
raise ValueError("ERROR calling the run() method: \nThe run() method cannot be executed with invalid parameters. Please check the parameters passed while creating an instance of the GA class.\n")
1172+
raise ValueError("Error calling the run() method: \nThe run() method cannot be executed with invalid parameters. Please check the parameters passed while creating an instance of the GA class.\n")
1173+
1174+
# Reset the variables that store the solutions and their fitness after each generation. If not reset, then for each call to the run() method the new solutions and their fitness values will be appended to the old variables and their length double. Some errors arise if not reset.
1175+
# If, in the future, new variables are created that get appended after each generation, please consider resetting them here.
1176+
self.best_solutions = [] # Holds the best solution in each generation.
1177+
self.best_solutions_fitness = [] # A list holding the fitness value of the best solution for each generation.
1178+
self.solutions = [] # Holds the solutions in each generation.
1179+
self.solutions_fitness = [] # Holds the fitness of the solutions in each generation.
11731180

11741181
if not (self.on_start is None):
11751182
self.on_start(self)
@@ -1290,6 +1297,10 @@ def run(self):
12901297

12911298
time.sleep(self.delay_after_gen)
12921299

1300+
# Save the fitness of the last generation.
1301+
if self.save_solutions:
1302+
self.solutions_fitness.extend(self.last_generation_fitness)
1303+
12931304
# Save the fitness value of the best solution.
12941305
_, best_solution_fitness, _ = self.best_solution(pop_fitness=self.last_generation_fitness)
12951306
self.best_solutions_fitness.append(best_solution_fitness)
@@ -1316,7 +1327,7 @@ def steady_state_selection(self, fitness, num_parents):
13161327
-num_parents: The number of parents to be selected.
13171328
It returns an array of the selected parents.
13181329
"""
1319-
1330+
13201331
fitness_sorted = sorted(range(len(fitness)), key=lambda k: fitness[k])
13211332
fitness_sorted.reverse()
13221333
# Selecting the best individuals in the current generation as parents for producing the offspring of the next generation.
@@ -2075,16 +2086,25 @@ def adaptive_mutation_population_fitness(self, offspring):
20752086

20762087
fitness = self.last_generation_fitness.copy()
20772088
temp_population = numpy.zeros_like(self.population)
2078-
temp_population[0:self.last_generation_parents.shape[0], :] = self.last_generation_parents.copy()
2079-
temp_population[self.last_generation_parents.shape[0]:, :] = offspring
2080-
2089+
2090+
if (self.keep_parents == 0):
2091+
parents_to_keep = []
2092+
elif (self.keep_parents == -1):
2093+
parents_to_keep = self.last_generation_parents.copy()
2094+
temp_population[0:len(parents_to_keep), :] = parents_to_keep
2095+
elif (self.keep_parents > 0):
2096+
parents_to_keep, _ = self.steady_state_selection(self.last_generation_fitness, num_parents=self.keep_parents)
2097+
temp_population[0:len(parents_to_keep), :] = parents_to_keep
2098+
2099+
temp_population[len(parents_to_keep):, :] = offspring
2100+
20812101
fitness[:self.last_generation_parents.shape[0]] = self.last_generation_fitness[self.last_generation_parents_indices]
20822102

2083-
for idx in range(self.last_generation_parents.shape[0], fitness.shape[0]):
2103+
for idx in range(len(parents_to_keep), fitness.shape[0]):
20842104
fitness[idx] = self.fitness_func(temp_population[idx], None)
20852105
average_fitness = numpy.mean(fitness)
20862106

2087-
return average_fitness, fitness[self.last_generation_parents.shape[0]:]
2107+
return average_fitness, fitness[len(parents_to_keep):]
20882108

20892109
def adaptive_mutation(self, offspring):
20902110

@@ -3433,7 +3453,7 @@ def plot_genes(self,
34333453
bbox_inches='tight')
34343454

34353455
matplotlib.pyplot.show()
3436-
3456+
34373457
return fig
34383458

34393459
def save(self, filename):
@@ -3460,5 +3480,5 @@ def load(filename):
34603480
except FileNotFoundError:
34613481
raise FileNotFoundError("Error reading the file {filename}. Please check your inputs.".format(filename=filename))
34623482
except:
3463-
raise BaseException("Error loading the file. Please check if the file exists.")
3483+
raise BaseException("Error loading the file. If the file already exists, please reload all the functions previously used (e.g. fitness function).")
34643484
return ga_in

0 commit comments

Comments
 (0)