Skip to content

Commit faeec77

Browse files
authored
PyGAD 2.16.3
PyGAD 2.16.2 1. A new instance attribute called `previous_generation_fitness` added in the `pygad.GA` class. It holds the fitness values of one generation before the fitness values saved in the `last_generation_fitness`. 2. Issue in the `cal_pop_fitness()` method in getting the correct indices of the previous parents. This is solved by using the previous generation's fitness saved in the new attribute `previous_generation_fitness` to return the parents' fitness values. Thanks to Tobias Tischhauser (M.Sc. - [Mitarbeiter Institut EMS, Departement Technik, OST – Ostschweizer Fachhochschule, Switzerland](https://www.ost.ch/de/forschung-und-dienstleistungen/technik/systemtechnik/ems/team)) for detecting this bug. PyGAD 2.16.3 1. Validate the fitness value returned from the fitness function. An exception is raised if something is wrong. #67
1 parent 4ad007e commit faeec77

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
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.1"
3+
__version__ = "2.16.3"

pygad.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ def __init__(self,
899899
self.last_generation_parents = None # A list holding the parents of the last generation.
900900
self.last_generation_offspring_crossover = None # A list holding the offspring after applying crossover in the last generation.
901901
self.last_generation_offspring_mutation = None # A list holding the offspring after applying mutation in the last generation.
902+
self.previous_generation_fitness = None # Holds the fitness values of one generation before the fitness values saved in the last_generation_fitness attribute. Added in PyGAD 2.26.2
902903

903904
def round_genes(self, solutions):
904905
for gene_idx in range(self.num_genes):
@@ -1146,16 +1147,20 @@ def cal_pop_fitness(self):
11461147
# Calculating the fitness value of each solution in the current population.
11471148
for sol_idx, sol in enumerate(self.population):
11481149

1149-
# Check if the parent's fitness value is already calculated. If so, use it instead of calling the fitness function.
1150-
if not (self.last_generation_parents is None) and len(numpy.where(numpy.all(self.last_generation_parents == sol, axis=1))[0] > 0):
1150+
# Check if this solution is a parent from the previous generation and its fitness value is already calculated. If so, use the fitness value instead of calling the fitness function.
1151+
if (self.last_generation_parents is not None) and len(numpy.where(numpy.all(self.last_generation_parents == sol, axis=1))[0] > 0):
11511152
# Index of the parent in the parents array (self.last_generation_parents). This is not its index within the population.
11521153
parent_idx = numpy.where(numpy.all(self.last_generation_parents == sol, axis=1))[0][0]
11531154
# Index of the parent in the population.
11541155
parent_idx = self.last_generation_parents_indices[parent_idx]
11551156
# Use the parent's index to return its pre-calculated fitness value.
1156-
fitness = self.last_generation_fitness[parent_idx]
1157+
fitness = self.previous_generation_fitness[parent_idx]
11571158
else:
11581159
fitness = self.fitness_func(sol, sol_idx)
1160+
if type(fitness) in GA.supported_int_float_types:
1161+
pass
1162+
else:
1163+
raise ValueError("The fitness function should return a number but the value {fit_val} of type {fit_type} found.".format(fit_val=fitness, fit_type=type(fitness)))
11591164
pop_fitness.append(fitness)
11601165

11611166
pop_fitness = numpy.array(pop_fitness)
@@ -1244,6 +1249,7 @@ def run(self):
12441249
if not (self.on_mutation is None):
12451250
self.on_mutation(self, self.last_generation_offspring_mutation)
12461251

1252+
# Update the population attribute according to the offspring generated.
12471253
if (self.keep_parents == 0):
12481254
self.population = self.last_generation_offspring_mutation
12491255
elif (self.keep_parents == -1):
@@ -1257,6 +1263,7 @@ def run(self):
12571263

12581264
self.generations_completed = generation + 1 # The generations_completed attribute holds the number of the last completed generation.
12591265

1266+
self.previous_generation_fitness = self.last_generation_fitness.copy()
12601267
# Measuring the fitness of each chromosome in the population. Save the fitness in the last_generation_fitness attribute.
12611268
self.last_generation_fitness = self.cal_pop_fitness()
12621269

0 commit comments

Comments
 (0)