Skip to content

Prepare PyGAD 3.7.0 release#358

Merged
ahmedfgad merged 20 commits into
masterfrom
github-actions
Jun 3, 2026
Merged

Prepare PyGAD 3.7.0 release#358
ahmedfgad merged 20 commits into
masterfrom
github-actions

Conversation

@ahmedfgad
Copy link
Copy Markdown
Owner

These are the changes yet applied to be released in PyGAD 3.7.0. The changes are not published yet in the PyPI package.

  1. Validation logic is applied to validate the num_generations parameter.
  2. The num_generations parameter must be assigned a positive integer. Previously, any number (positive/negative, int/float) was accepted.
  3. A new script called activation.py is added into the pygad.helper module to include the activation function used by the cnn and nn modules.
  4. In the pygad.parent_selection.ParentSelection class, the stochastic_universal_selection() method now calls the wheel_cumulative_probs() method instead of repeating the code of calculating the probabilities used for parent selection.
  5. The wheel_cumulative_probs() method in the pygad.parent_selection.ParentSelection class is refactored to reduce its computational time.
  6. Use numpy.where() to decide which the source parent of each gene within the uniform_crossover() method in the utils/crossover.py script. The same was already applied to the scattered_crossover() method.
  7. Add tests for the following modules:
    nn
    cnn
    gacnn
    kerasga
    torchga
  8. Fix a bug in the visualize/plot.py script where the labels parameter of boxplot() has been renamed tick_labels in Matplotlib.
  9. Fix a bug where the best_solutions_fitness list (instance attribute to pygad.GA) has the fitness of the last generation duplicated when an early stop happens inside the on_generation() callback. This made its size incompatible with the best_solutions list.
  10. The documentation is refactored to solve many language issues and the Furo theme is applied. For easy navigation, the index is reformatted to only show the main sections. At each page, its index is shown at the right side. A new theme toggle button to change theme between light and dark.
  11. Support of multi-objective optimization using the Non-Dominated Sorting Genetic Algorithm III (NSGA-III). NSGA-III replaces the crowding distance of NSGA-II with niching against a structured grid of reference points, so it scales better to problems with 4 or more objectives. The new NSGA3 class lives in the new pygad/utils/nsga3.py script and is mixed into the pygad.GA class the same way NSGA2 is.
  12. Two new parent selection methods are added to support NSGA-III: 1) nsga3_selection() for plain NSGA-III selection, and 2) tournament_selection_nsga3() for the tournament variant. Use them by setting parent_selection_type to 'nsga3' or 'tournament_nsga3'.
  13. A new parameter nsga3_num_divisions is added to the pygad.GA constructor. It is required when parent_selection_type is 'nsga3' or 'tournament_nsga3' and sets the number of divisions per objective axis used to build the structured reference points (the p parameter from Deb & Jain 2014). The total number of reference points is C(M + p - 1, p) where M is the number of objectives.
  14. When sol_per_pop is smaller than the number of NSGA-III reference points, PyGAD raises a warning and grows the population to match before the generational loop starts.
  15. A new crossover operator: Simulated Binary Crossover (SBX). Use it by setting crossover_type='sbx'. The shape of the spread is controlled by the new sbx_crossover_eta parameter (default 30).
  16. A new mutation operator: polynomial mutation. Use it by setting mutation_type='polynomial'. The size of the change is controlled by the new polynomial_mutation_eta parameter (default 20).
  17. Two new stop criteria: time_<seconds> stops the run when the time inside run() is at least the given number of seconds; evaluations_<N> stops the run when the number of fitness function calls reaches the given count. New instance attribute num_fitness_evaluations counts the calls.
  18. A new submodule pygad.utils.quality_indicators with four functions to measure the quality of a Pareto front: hypervolume, inverted_generational_distance, generational_distance, and spacing.
  19. A new submodule pygad.benchmarks with built-in benchmark problems. pygad.benchmarks.classic has Sphere, Rastrigin, Rosenbrock, Griewank, Schwefel, Ackley, and Himmelblau. pygad.benchmarks.zdt has the ZDT family (ZDT1, ZDT2, ZDT3, ZDT4, ZDT6). pygad.benchmarks.dtlz has DTLZ1, DTLZ2, DTLZ3, and DTLZ4. pygad.benchmarks.knapsack has the 0/1 Knapsack problem. Each class is callable with the PyGAD fitness signature and returns negated values (for the minimization-style problems) so PyGAD can maximize toward the original minimum.
  20. Update the documentation to reflect the recent additions and changes to the library structure.
  21. A new benchmark pygad.benchmarks.tsp with a TSP class for the Travelling Salesman Problem. The class accepts either 2D coordinates or a precomputed distance_matrix, exposes gene_space, gene_type, and allow_duplicate_genes for the permutation encoding, and returns the negative tour length as the fitness.
  22. Two new example folders under /examples: examples/benchmarks/ has one runnable example per benchmark (classic, ZDT, DTLZ, knapsack, and TSP), and examples/quality_indicators/ has one runnable example per quality indicator (hypervolume, IGD, GD, and spacing).
  23. plot_pareto_front_curve() now also supports 3 objectives (3D scatter). M >= 4 still raises and points to the new high-dimensional plots.
  24. Seven new plot methods on pygad.GA. The first three work on the final population (no extra flag needed): plot_pareto_front_pcp() (parallel coordinates, any M >= 2), plot_pareto_front_scatter_matrix() (M-by-M pairwise scatter, best for M >= 4), and plot_pareto_front_heatmap() (solutions-by-objectives heatmap). The other four require save_solutions=True: plot_fitness_band() (per-generation min / mean / max with a shaded band), plot_non_dominated_hypervolume() (hypervolume of the non-dominated set per generation), plot_population_diversity() (mean pairwise distance per generation), and plot_pareto_front_evolution() (non-dominated set overlaid every k generations).
  25. Fix a latent divide-by-zero in NSGA3.nsga3_normalize_fitness(). The safeguard for near-zero denominators used to collapse to 0 for tiny negative values (the realistic case under PyGAD-max), which silently produced wrong normalized values. The safeguard now keeps the negative sign.
  26. Refactor the NSGA classes to keep each script focused. A new module pygad/utils/nsga.py hosts the NSGA mixin with non_dominated_sorting() and get_non_dominated_set(), which are shared between NSGA-II and NSGA-III. nsga2.py now only carries NSGA-II specific code (crowding_distance, sort_solutions_nsga2). nsga3.py now only carries the NSGA-III algorithm primitives. The nsga3_selection() and tournament_selection_nsga3() methods have moved to pygad/utils/parent_selection.py next to their NSGA-II counterparts. The engine-time helpers _bootstrap_nsga3_reference_points(), _nsga3_grow_population(), _nsga3_generate_extra_random_solutions(), and _nsga3_generate_single_random_gene() now live in pygad/utils/engine.py.
  27. Rename NSGA-III novel names to start with nsga3_ so the algorithm-specific surface is easy to spot. Algorithm primitives become nsga3_generate_reference_points, nsga3_compute_ideal_point, nsga3_find_extreme_points, nsga3_compute_intercepts, nsga3_normalize_fitness, nsga3_associate_to_reference_points, and nsga3_niching_select. Module-level helpers gain the same prefix (_nsga3_pick_target_reference_point, _nsga3_pick_candidate_at_reference, _nsga3_enumerate_compositions, _nsga3_validate_multi_objective_fitness, _nsga3_accumulate_fronts). The constants are renamed NSGA3_ASF_EPSILON and NSGA3_INTERCEPT_NEAR_ZERO. Names that already had NSGA-II parallels (tournament_selection_nsga3, pareto_fronts, non_dominated_sorting) keep their original spelling.
  28. Spell every name and docstring in American English (normalize, maximize, behavior, color, optimization, ...) so the library stays consistent.
  29. Expand abbreviated names introduced by the NSGA-III refactor: fl_indices to critical_front_indices, fl_assoc to critical_front_associations, fl_dist to critical_front_distances, st_indices to selection_pool_indices, st_fitness to selection_pool_fitness, accepted_assoc to accepted_associations, K to num_to_select (in nsga3_niching_select).
  30. The NSGA-III population auto-growth path now respects every initial-population rule: init_range_low/init_range_high, gene_space, gene_type (single dtype or nested per-gene [type, precision]), gene_constraint, and allow_duplicate_genes=False. Previously, only the gene-space / init-range sampling step was applied; gene constraints and duplicate resolution were skipped, which could leave the grown rows in an invalid state.
  31. A new Report mixin in pygad/utils/report.py adds ga_instance.generate_report(filename, ...) to build a PDF report of the run. The report bundles a configuration table, a run-summary table, the best solution, and every applicable plot (auto-selected based on the run's properties: SOO vs MOO, number of objectives, save_solutions, save_best_solutions). The report uses reportlab and matplotlib, both available through the new optional dependency extra pip install pygad[report].
  32. A new example examples/example_generate_report.py shows how to build a PDF report after running a multi-objective GA.
  33. The pygad.md, releases.md, visualize.md, and utils.md documentation pages were updated to reflect the new module layout, the renamed methods, the new generate_report() entry point, and the new NSGA-III instance attributes (nsga3_num_divisions, nsga3_reference_points). The "Other Instance Attributes & Methods" section in pygad.md is now grouped by area (Lifecycle, Population, Fitness, Parent Selection, NSGA-II, NSGA-III, Crossover, Mutation, Elitism, Gene Constraints, Saving) so each method or attribute appears under its topic.
  34. Fix issue gene_constraint parameter documentation needs to be clarified #351 by updating the documentation to clarify what the solution has.

@ahmedfgad ahmedfgad merged commit 5709795 into master Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant