Skip to content

PyGAD 3.5.0 #334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/md/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ Release Date 08 July 2025
15. More examples are created.
16. Edited the `sort_solutions_nsga2()` method in the `pygad/utils/nsga2.py` script to accept an optional parameter called `find_best_solution` when calling this method just to find the best solution.
17. Fixed a bug while applying the non-dominated sorting in the `get_non_dominated_set()` method inside the `pygad/utils/nsga2.py` script. It was swapping the non-dominated and dominated sets. In other words, it used the non-dominated set as if it is the dominated set and vice versa. All the calls to this method were edited accordingly. https://github.com/ahmedfgad/GeneticAlgorithmPython/issues/320.
18. Fix a bug retrieving in the `best_solution()` method when retrieving the best solution for multi-objective problems. https://github.com/ahmedfgad/GeneticAlgorithmPython/pull/331

# PyGAD Projects at GitHub

Expand Down
15 changes: 12 additions & 3 deletions docs/source/pygad_more.rst
Original file line number Diff line number Diff line change
Expand Up @@ -530,14 +530,23 @@ assigning a larger value for the ``sample_size`` parameter.
PyGAD does not yet handle the **dependencies** among the genes in the
``gene_constraint`` parameter.

For example, gene 0 might depend on gene 1. To efficiently enforce
the constraints, the constraint for gene 1 must be enforced first (if
not ``None``) then the constraint for gene 0.
This is an example where gene 0 depends on gene 1. To efficiently
enforce the constraints, the constraint for gene 1 must be enforced
first (if not ``None``) then the constraint for gene 0.

.. code:: python

gene_constraint=
[
lambda solution,values: [val for val in values if val<solution[1]],
lambda solution,values: [val for val in values if val>10]
]

PyGAD applies constraints sequentially, starting from the first gene
to the last. To ensure correct behavior when genes depend on each
other, structure your GA problem so that if gene X depends on gene Y,
then gene Y appears earlier in the chromosome (solution) than gene X.
As a result, its gene constraint will be earlier in the list.

Full Example
------------
Expand Down
23 changes: 21 additions & 2 deletions docs/source/releases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1593,7 +1593,7 @@ Release Date 07 January 2025
8. Refactoring the ``pygad/helper/unique.py`` script to remove
duplicate codes and reformatting the docstrings.

9. The plot_pareto_front_curve() method added to the
9. The ``plot_pareto_front_curve()`` method added to the
pygad.visualize.plot.Plot class to visualize the Pareto front for
multi-objective problems. It only supports 2 objectives.
https://github.com/ahmedfgad/GeneticAlgorithmPython/issues/279
Expand Down Expand Up @@ -1630,11 +1630,12 @@ Release Date 07 January 2025
PyGAD 3.5.0
-----------

Release Date 07 July 2025
Release Date 08 July 2025

1. Fix a bug when minus sign (-) is used inside the ``stop_criteria``
parameter for multi-objective problems.
https://github.com/ahmedfgad/GeneticAlgorithmPython/issues/314
https://github.com/ahmedfgad/GeneticAlgorithmPython/issues/323

2. Fix a bug when the ``stop_criteria`` parameter is passed as an
iterable (e.g. list) for multi-objective problems (e.g.
Expand Down Expand Up @@ -1726,6 +1727,7 @@ Release Date 07 July 2025
called to ensure the candidate value is valid. Check the `Gene
Constraint <https://pygad.readthedocs.io/en/latest/pygad_more.html#gene-constraint>`__
section for more information.
https://github.com/ahmedfgad/GeneticAlgorithmPython/issues/119

11. A new parameter called ``sample_size`` is added. To select a gene
value that respects a constraint, this variable defines the size of
Expand Down Expand Up @@ -1755,6 +1757,23 @@ Release Date 07 July 2025

15. More examples are created.

16. Edited the ``sort_solutions_nsga2()`` method in the
``pygad/utils/nsga2.py`` script to accept an optional parameter
called ``find_best_solution`` when calling this method just to find
the best solution.

17. Fixed a bug while applying the non-dominated sorting in the
``get_non_dominated_set()`` method inside the
``pygad/utils/nsga2.py`` script. It was swapping the non-dominated
and dominated sets. In other words, it used the non-dominated set as
if it is the dominated set and vice versa. All the calls to this
method were edited accordingly.
https://github.com/ahmedfgad/GeneticAlgorithmPython/issues/320.

18. Fix a bug retrieving in the ``best_solution()`` method when
retrieving the best solution for multi-objective problems.
https://github.com/ahmedfgad/GeneticAlgorithmPython/pull/331

PyGAD Projects at GitHub
========================

Expand Down
65 changes: 0 additions & 65 deletions example_multi_objective.py

This file was deleted.

16 changes: 6 additions & 10 deletions pygad/pygad.py
Original file line number Diff line number Diff line change
Expand Up @@ -2237,17 +2237,13 @@ def best_solution(self, pop_fitness=None):
pop_fitness == numpy.max(pop_fitness))[0][0]
elif pop_fitness_arr.ndim == 2:
# Multi-objective optimization.
# Sort by all objectives in descending order.
# The first objective is the most important, then the second, etc.
sorted_indices = numpy.lexsort([ -pop_fitness_arr[:,i] for i in reversed(range(pop_fitness_arr.shape[1])) ])
best_match_idx = sorted_indices[0]
maximum_fitness_value = pop_fitness_arr[best_match_idx]

best_match_list = numpy.where(
pop_fitness == maximum_fitness_value)

best_match_idx = best_match_list[0][0] # Get the first index of the best match.
# Use NSGA-2 to sort the solutions using the fitness.
# Set find_best_solution=True to avoid overriding the pareto_fronts instance attribute.
best_match_list = self.sort_solutions_nsga2(fitness=pop_fitness,
find_best_solution=True)

# Get the first index of the best match.
best_match_idx = best_match_list[0]

best_solution = self.population[best_match_idx, :].copy()
best_solution_fitness = pop_fitness[best_match_idx]
Expand Down