Repository navigation
Releases
PyGAD 3.9.2
PyGAD 3.9.2
Release Date: October 16, 2026.
- Roulette wheel selection and stochastic universal selection no longer fail with fitness values near the float limits. In PyGAD 3.9.1, a fitness of
-sys.float_info.max, which some libraries give a rejected solution, made the shifted values overflow, and parent selection raisedIndexError. The values are now scaled before they are shifted or added.-infandNaNget no chance, solutions with+inffitness share every chance equally, and a population with no finite fitness raises a clearValueError. Ordinary non-negative fitness keeps exactly the same probabilities. - Regression tests cover the most negative float, huge values of both signs, huge positive values, infinite and missing values, and full runs with both selectors. The
pygad.utilssubmodule version is1.5.12.
PyGAD 3.9.1
PyGAD 3.9.1
Release Date: October 16, 2026.
- Roulette wheel selection and stochastic universal selection favor the better solutions when fitness values are negative. Before this change, each share was the fitness divided by the total, which flips the order for negative values: the fitness values
-1and-9gave the worse solution 90% of the selections. Negative fitness values are now shifted by the smallest fitness first, so-1and-9become8and0. This also covers mixed positive and negative values, and equal negative values give every solution the same chance. Fitness values that are all zero or above keep their exact previous behavior. - Regression tests cover negative, mixed-sign, equal negative, multi-objective, and large Python integer fitness, and a minimization run with each selector. The
pygad.utilssubmodule version is1.5.11.
PyGAD 3.9.0
PyGAD 3.9.0
Release Date: October 16, 2026.
- Roulette wheel selection and stochastic universal selection sum fitness values in a floating-point type wide enough for the input. Large
int64,uint64,float16, andfloat32fitness values no longer overflow and raiseZeroDivisionError. Object arrays of Python integers keep exact values. See PR #381. - SBX crossover and polynomial mutation round integer results to the nearest integer instead of truncating them. For a gene with a finite gene space, the result moves to the nearest allowed value. Before this change, the highest value of an integer gene was almost never produced, values were pulled toward zero, and SBX could not keep a parent's highest value. Results for integer genes change for the same random seed. Float genes are not affected. See Conversion and Rounding Rules.
- A new
gene_categoricalparameter marks genes whose values are categories with no order. For these genes, polynomial mutation picks one of the other allowed values at random and SBX crossover copies the value of one parent. The defaultNonekeeps the previous behavior. See Categorical Genes. - Regression tests cover reaching both ends of integer and finite gene spaces, balanced steps up and down, negative ranges, stepped and uneven spaces, and every
gene_categoricalvalidation rule and operator behavior. Thepygad.helperandpygad.utilssubmodule versions are1.4.7and1.5.10.
PyGAD 3.8.1
PyGAD 3.8.1
Release Date: October 11, 2026.
- Random and adaptive mutation clip generated values to NumPy integer type limits before casting, fixing overflow errors and wraparound with types such as
numpy.uint8andnumpy.int8. The same rule covers additive and replacement mutation,Nonegene-space entries, constraint candidates, and duplicate repair. Clipping applies only to explicitly requested NumPy integer types. See issue #379 and Conversion and Rounding Rules. - Python
intconversion of candidate arrays and population columns uses explicit signed 64-bit storage across NumPy versions and platforms, fixing large-integer conversion and initialization failures on Windows with NumPy 1.x. Integer range sampling and bounded operators use the same storage limits. Parent selection and crossover share array allocation, preserving large integers throughout the lifecycle. Per-gene Pythonintelements keep their scalar type, and explicitly requested NumPy types keep their widths. Supplied Pythonintpopulation values must fit in signed 64-bit storage; usegene_type=objectfor larger supplied integers. See Conversion and Rounding Rules. - Regression tests cover integer mutation limits, exact large-integer storage, initialization, constraints, duplicate repair, parent selection, crossover, and NSGA-III population growth. Windows CI checks both NumPy 1.24.4 and the latest NumPy release without version-specific implementation branches. The 16 pre-existing Windows failures with NumPy 1.24.4 are fixed, and no higher NumPy minimum is required. The
pygad.helperandpygad.utilssubmodule versions are1.4.6and1.5.8.
PyGAD 3.8.0
PyGAD 3.8.0
Release Date: October 9, 2026.
Watch the release video on YouTube.
-
Two-point crossover selects two distinct random cut points from
0throughnum_genes, with every pair equally likely. The segment length can vary from one to all genes, and the single-gene case no longer raises a slicing error. See PR #371. -
Swap mutation can select any pair of distinct gene positions, matching its documentation. Single-gene offspring are returned unchanged. See PR #375.
-
SBX crossover selects the lower or upper child with equal probability, removing the bias toward lower gene values. See PR #376.
-
Random and adaptive mutation can change permutations when
allow_duplicate_genes=Falseleaves no unused replacement value. The fallback swaps compatible genes while preserving their numeric values, destination types, gene spaces, uniqueness, and constraints. Swapped genes are tracked within each mutation pass to prevent immediately undoing a swap. See PR #373. -
Regression tests cover single-gene behavior, cut-point and swap-pair coverage, SBX symmetry and bounds, mixed gene types, constrained permutations, both adaptive mutation controls, and reproducibility. The
pygad.utilssubmodule version is1.5.2. -
Parallel fitness evaluation now reuses its executor within each
run()call, including adaptive offspring evaluation. Workers are shut down after normal completion, early stopping, and exceptions. Executors are excluded from checkpoints and worker snapshots. -
Serial, thread, and process modes use the same fitness-cache rules and result validation. Adaptive mutation evaluates the actual offspring, supplies
Nonefor their not-yet-assigned population indices, preserves fractional fitness, and uses the correct retained-parent or elite fitness. These evaluations are included innum_fitness_evaluationsand theevaluations_<N>stop criterion. See issues #195 and #201. -
Process workers use cloudpickle payloads for callable and GA state, supporting local functions and continuation after loading a checkpoint. Current state is sent for each evaluation round; grouped tasks reduce repeated state transfers. No new dependency is required. See issues #121 and #250.
-
pygad.kerasga.predict() synchronizes calls sharing a model across threads and restores the model's original weights even after prediction errors. See issue #150.
-
Stochastic universal selection uses the requested
num_parentsfor pointer spacing, so direct calls can select a different number of parents fromnum_parents_mating. Regression tests cover smaller and larger counts, equal-fitness sampling, objective vectors, and mixed gene types. See issue #85. -
Scramble mutation shuffles the selected segment's values directly, removing the separate index shuffle and reversal. Every permutation of that segment is possible; its values, array dtype, and unselected genes are preserved. Seeded results can differ from earlier versions. See issue #76.
-
New examples explain replacing a loaded fitness function, starting fresh when the objective changes, and handling short final fitness batches. The lifecycle guide also explains progress reporting and the order of fitness evaluation and callbacks. See issues #263, #217, and #154.
-
Rank selection assigns descending selection weights to the best-to-worst sorted solutions, correcting a bias that gave worse solutions higher selection probabilities. Regression tests verify exact probabilities, original population indices, negative fitness, objective vectors, crowding distance, ties, and parent copies. See issue #120. Seeded rank-selection results can differ from earlier versions.
-
A new plot_lifecycle() method draws the lifecycle configured for a GA instance, including operators, callbacks, population replacement, generation loops, and stopping decisions. Stage annotations and a configuration panel show relevant settings, including gene types, batching, and offspring shapes. Use
show_parameters=Falsefor a compact view,save_dirto export SVG, PNG, or PDF, andshow=Falseto create a chart without displaying it. Usetransparent=Truefor a transparent background. Charts fit their labels and connectors with small outer margins. The method works before or afterrun()without executing user functions or changing GA state. A new example is available atexamples/plots/example_plot_lifecycle.py. Thepygad.visualizesubmodule version is1.2.1. -
Duplicate-gene repair now uses one shared implementation for generated and manual initial populations, crossover, mutation, and NSGA-III population growth. Custom crossover and mutation outputs and their callbacks are also repaired when
allow_duplicate_genes=False. Finite domains are searched completely through replacement chains, including changes to earlier duplicate occurrences. Continuous candidates and additional searches for dependent constraints usesample_size. -
Repair uses each destination gene's type, precision, and range, and validates constraints against complete candidate solutions. Mixed types are compared by their exact stored numeric values. Mixed types,
sample_size=1, stepped spaces, per-gene ranges, andNoneentries are handled consistently. Impossible initialization spaces warn instead of accessing uninitialized attributes. Equal and reversed integer bounds are handled consistently. Swap fallback uses original continuous andNonebounds instead of membership in cached samples. SBX and polynomial mutation convert and round generated values before repair and use their own bounds. Thepygad.helperandpygad.utilssubmodule versions are1.4.2and1.5.4. -
A new
examples/example_duplicate_gene_repair.pydemonstrates repair through several genes. Regression tests compare small finite spaces with exhaustive search and cover long chains, impossible spaces, constraints, callbacks, mixed types, and reproducible runs. -
Initial population creation and NSGA-III population growth share column sampling and preparation methods. Integer ranges are sampled directly instead of being allocated for each gene value. Generated range values remain within their bounds after conversion and rounding, with a descriptive error when the type and precision cannot represent any valid value. Supplied population dimensions are inferred before per-gene validation, overriding explicit dimensions. Supplied populations also apply gene constraints, and mixed numeric values retain their exact values during conversion. Empty and malformed populations are rejected early; tuple and NumPy gene-type specifications are accepted without modifying caller-owned inputs. The new `example...
PyGAD-3.7.0
- Validation logic is applied to validate the
num_generationsparameter. - The
num_generationsparameter must be assigned a positive integer. Previously, any number (positive/negative, int/float) was accepted. - A new script called
activation.pyis added into thepygad.helpermodule to include the activation function used by thecnnandnnmodules. - In the
pygad.parent_selection.ParentSelectionclass, thestochastic_universal_selection()method now calls thewheel_cumulative_probs()method instead of repeating the code of calculating the probabilities used for parent selection. - The
wheel_cumulative_probs()method in thepygad.parent_selection.ParentSelectionclass is refactored to reduce its computational time. - Use
numpy.where()to decide which the source parent of each gene within theuniform_crossover()method in theutils/crossover.pyscript. The same was already applied to thescattered_crossover()method. - Add tests for the following modules:
nncnngacnnkerasgatorchga
- Fix a bug in the
visualize/plot.pyscript where thelabelsparameter ofboxplot()has been renamedtick_labelsin Matplotlib. - Fix a bug where the
best_solutions_fitnesslist (instance attribute topygad.GA) has the fitness of the last generation duplicated when an early stop happens inside theon_generation()callback. This made its size incompatible with thebest_solutionslist. - 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.
- 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
NSGA3class lives in the newpygad/utils/nsga3.pyscript and is mixed into thepygad.GAclass the same wayNSGA2is. - 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 settingparent_selection_typeto'nsga3'or'tournament_nsga3'. - A new parameter
nsga3_num_divisionsis added to thepygad.GAconstructor. It is required whenparent_selection_typeis'nsga3'or'tournament_nsga3'and sets the number of divisions per objective axis used to build the structured reference points (thepparameter from Deb & Jain 2014). The total number of reference points isC(M + p - 1, p)whereMis the number of objectives. - When
sol_per_popis smaller than the number of NSGA-III reference points, PyGAD raises a warning and grows the population to match before the generational loop starts. - A new crossover operator: Simulated Binary Crossover (SBX). Use it by setting
crossover_type='sbx'. The shape of the spread is controlled by the newsbx_crossover_etaparameter (default 30). - A new mutation operator: polynomial mutation. Use it by setting
mutation_type='polynomial'. The size of the change is controlled by the newpolynomial_mutation_etaparameter (default 20). - Two new stop criteria:
time_<seconds>stops the run when the time insiderun()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 attributenum_fitness_evaluationscounts the calls. - A new submodule
pygad.utils.quality_indicatorswith four functions to measure the quality of a Pareto front:hypervolume,inverted_generational_distance,generational_distance, andspacing. - A new submodule
pygad.benchmarkswith built-in benchmark problems.pygad.benchmarks.classichas Sphere, Rastrigin, Rosenbrock, Griewank, Schwefel, Ackley, and Himmelblau.pygad.benchmarks.zdthas the ZDT family (ZDT1, ZDT2, ZDT3, ZDT4, ZDT6).pygad.benchmarks.dtlzhas DTLZ1, DTLZ2, DTLZ3, and DTLZ4.pygad.benchmarks.knapsackhas 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. - Update the documentation to reflect the recent additions and changes to the library structure.
- A new benchmark
pygad.benchmarks.tspwith aTSPclass for the Travelling Salesman Problem. The class accepts either 2Dcoordinatesor a precomputeddistance_matrix, exposesgene_space,gene_type, andallow_duplicate_genesfor the permutation encoding, and returns the negative tour length as the fitness. - Two new example folders under
/examples:examples/benchmarks/has one runnable example per benchmark (classic, ZDT, DTLZ, knapsack, and TSP), andexamples/quality_indicators/has one runnable example per quality indicator (hypervolume, IGD, GD, and spacing). plot_pareto_front_curve()now also supports 3 objectives (3D scatter). M >= 4 still raises and points to the new high-dimensional plots.- 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), andplot_pareto_front_heatmap()(solutions-by-objectives heatmap). The other four requiresave_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), andplot_pareto_front_evolution()(non-dominated set overlaid every k generations). - Fix a latent divide-by-zero in
NSGA3.nsga3_normalize_fitness(). The safeguard for near-zero denominators used to collapse to0for tiny negative values (the realistic case under PyGAD-max), which silently produced wrong normalized values. The safeguard now keeps the negative sign. - Refactor the NSGA classes to keep each script focused. A new module
pygad/utils/nsga.pyhosts theNSGAmixin withnon_dominated_sorting()andget_non_dominated_set(), which are shared between NSGA-II and NSGA-III.nsga2.pynow only carries NSGA-II specific code (crowding_distance,sort_solutions_nsga2).nsga3.pynow only carries the NSGA-III algorithm primitives. Thensga3_selection()andtournament_selection_nsga3()methods have moved topygad/utils/parent_selection.pynext 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 inpygad/utils/engine.py. - Rename NSGA-III novel names to start with
nsga3_so the algorithm-specific surface is easy to spot. Algorithm primitives becomensga3_generate_reference_points,nsga3_compute_ideal_point,nsga3_find_extreme_points,nsga3_compute_intercepts,nsga3_normalize_fitness,nsga3_associate_to_reference_points, andnsga3_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 renamedNSGA3_ASF_EPSILONandNSGA3_INTERCEPT_NEAR_ZERO. Names that already had NSGA-II parallels (tournament_selection_nsga3,pareto_fronts,non_dominated_sorting) keep their original spelling. - Spell every name and docstring in American English (
normalize,maximize,behavior,color,optimization, ...) so the library stays consistent. - Expand abbreviated names introduced by the NSGA-III refactor:
fl_indicestocritical_front_indices,fl_assoctocritical_front_associations,fl_disttocritical_front_distances,st_indicestoselection_pool_indices,st_fitnesstoselection_pool_fitness,accepted_assoctoaccepted_associations,Ktonum_to_select(innsga3_niching_select). - 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, andallow_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. - A new
Reportmixin inpygad/utils/report.pyaddsga_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 usesreportlabandmatplotlib, both available through the new optional dependency extrapip install pygad[report]. - A new example
examples/example_generate_report.pyshows how to build a PDF report after running a multi-objective GA. - The
pygad.md,releases.md,visualize.md, andutils.mddocumentation pages were updated to reflect the new module layout, the renamed methods, the newgenerate_report()entry point, and the new NSGA-III instance attributes (nsga3_num_divisions,nsga3_reference_points). The "Other Instance Attributes & Methods" section inpygad.mdis 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 ...
PyGAD-3.6.0
-
Support passing a class to the fitness, crossover, and mutation. #342
-
A new class called
Validationis created in the newpygad/utils/validation.pyscript. It has a method calledvalidate_parameters()to validate all the parameters passed while instantiating thepygad.GAclass. -
Refactoring the
pygad.pyscript by moving a lot of functions and methods to other classes in other scripts. -
The
summary()method was moved toHelperclass in thepygad/helper/misc.pyscript. -
The validation code in the
__init__()method of thepygad.GAclass is moved to the newvalidate_parameters()method in the newValidationclass in the newpygad/utils/validation.pyscript. Moreover, thevalidate_multi_stop_criteria()method is also moved to the same class. -
The GA main workflow is moved into the new
GAEngineclass in the newpygad/utils/engine.pyscript. Specifically, these methods are moved from thepygad.GAclass to the newGAEngineclass:
1.run()
1.run_loop_head()
2.run_select_parents()
3.run_crossover()
4.run_mutation()
5.run_update_population()
2.initialize_population()
3.cal_pop_fitness()
4.best_solution()
5.round_genes() -
The
pygad.GAclass now extends the two new classesutils.validation.Validationandutils.engine.GAEngine. -
The version of the
pygad.utilssubmodule is upgraded from1.3.0to1.4.0. -
The version of the
pygad.helpersubmodule is upgraded from1.2.0to1.3.0. -
The version of the
pygad.visualizesubmodule is upgraded from1.1.0to1.1.1. -
The version of the
pygad.nnsubmodule is upgraded from1.2.1to1.2.2. -
The version of the
pygad.cnnsubmodule is upgraded from1.1.0to1.1.1. -
The version of the
pygad.torchgasubmodule is upgraded from1.4.0to1.4.1. -
The version of the
pygad.kerasgasubmodule is upgraded from1.3.0to1.3.1. -
Update the elitism after the evolution ends to fix issue where the best solution returned by the
best_solution()method is not correct. #337 -
Fix a bug in calling the
numpy.reshape()function. The parameternewshapeis removed since it is no longer supported started from NumPy2.4.0. https://numpy.org/doc/stable/release/2.4.0-notes.html#removed-newshape-parameter-from-numpy-reshape -
A minor change in the documentation is made to replace the
newshapeparameter when callingnumpy.reshape(). -
Fix a bug in the
visualize/plot.pyscript that causes a warning to be given when the plot leged is used with single-objective problems. -
A new method called
initialize_parents_array()is added to theHelperclass in thepygad/helper/misc.pyscript. It is usually called from the methods in theParentSelectionclass in thepygad/utils/parent_selection.pyscript to initialize the parents array. -
Add more tests about:
1. Operators (crossover, mutation, and parent selection).
2. Thebest_solution()method.
3. Parallel processing.
4. TheGANNmodule.
5. The plots created by thevisualize. -
Instead of using repeated code for converting the data type and rounding the genes during crossover and mutation, the
change_gene_dtype_and_round()method is called from thepygad.helper.misc.Helperclass. -
Fix some documentation issues. #336
-
Update the documentation to reflect the recent additions and changes to the library structure.
PyGAD-3.5.0
- Fix a bug when minus sign (-) is used inside the
stop_criteriaparameter for multi-objective problems. #314 #323 - Fix a bug when the
stop_criteriaparameter is passed as an iterable (e.g. list) for multi-objective problems (e.g.['reach_50_60', 'reach_20, 40']). #314 - Call the
get_matplotlib()function from theplot_genes()method inside thepygad.visualize.plot.Plotclass to import the matplotlib library. #315 - Create a new helper method called
select_unique_value()inside thepygad/helper/unique.pyscript to select a unique gene from an array of values. - Create a new helper method called
get_random_mutation_range()inside thepygad/utils/mutation.pyscript that returns the random mutation range (min and max) for a single gene by its index. - Create a new helper method called
change_random_mutation_value_dtypeinside thepygad/utils/mutation.pyscript that changes the data type of the value used to apply random mutation. - Create a new helper method called
round_random_mutation_value()inside thepygad/utils/mutation.pyscript that rounds the value used to apply random mutation. - Create the
pygad/helper/misc.pyscript with a class calledHelperthat has the following helper methods:change_population_dtype_and_round(): For each gene in the population, round the gene value and change the data type.change_gene_dtype_and_round(): Round the change the data type of a single gene.mutation_change_gene_dtype_and_round(): Decides whether mutation is done by replacement or not. Then it rounds and change the data type of the new gene value.validate_gene_constraint_callable_output(): Validates the output of the user-defined callable/function that checks whether the gene constraint defined in thegene_constraintparameter is satisfied or not.get_gene_dtype(): Returns the gene data type from thegene_typeinstance attribute.get_random_mutation_range(): Returns the random mutation range using therandom_mutation_min_valandrandom_mutation_min_valinstance attributes.get_initial_population_range(): Returns the initial population values range using theinit_range_lowandinit_range_highinstance attributes.generate_gene_value_from_space(): Generates/selects a value for a gene using thegene_spaceinstance attribute.generate_gene_value_randomly(): Generates a random value for the gene. Only used ifgene_spaceisNone.generate_gene_value(): Generates a value for the gene. It checks whethergene_spaceisNoneand calls eithergenerate_gene_value_randomly()orgenerate_gene_value_from_space().filter_gene_values_by_constraint(): Receives a list of values for a gene. Then it filters such values using the gene constraint.get_valid_gene_constraint_values(): Selects one valid gene value that satisfy the gene constraint. It simply callsgenerate_gene_value()to generate some gene values then it filters such values usingfilter_gene_values_by_constraint().
- Create a new helper method called
mutation_process_random_value()inside thepygad/utils/mutation.pyscript that generates constrained random values for mutation. It calls eithergenerate_gene_value()orget_valid_gene_constraint_values()based on whether thegene_constraintparameter is used or not. - A new parameter called
gene_constraintis added. It accepts a list of callables (i.e. functions) acting as constraints for the gene values. Before selecting a value for a gene, the callable is 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. #119 - A new parameter called
sample_sizeis added. To select a gene value that respects a constraint, this variable defines the size of the sample from which a value is selected randomly. Useful if eitherallow_duplicate_genesorgene_constraintis used. An instance attribute of the same name is created in the instances of thepygad.GAclass. Check the [sample_size Parameter](https://pygad.readthedocs.io/en/latest/pygad_more.html#sample-size-parameter) section for more information. - Use the
sample_sizeparameter instead ofnum_trialsin the methodssolve_duplicate_genes_randomly()andunique_float_gene_from_range()inside thepygad/helper/unique.pyscript. It is the maximum number of values to generate as the search space when looking for a unique float value out of a range. - Fixed a bug in population initialization when
allow_duplicate_genes=False. Previously, gene values were checked for duplicates before rounding, which could allow near-duplicates like 7.61 and 7.62 to pass. After rounding (e.g., both becoming 7.6), this resulted in unintended duplicates. The fix ensures gene values are now rounded before duplicate checks, preventing such cases. - More tests are created.
- More examples are created.
- Edited the
sort_solutions_nsga2()method in thepygad/utils/nsga2.pyscript to accept an optional parameter calledfind_best_solutionwhen calling this method just to find the best solution. - Fixed a bug while applying the non-dominated sorting in the
get_non_dominated_set()method inside thepygad/utils/nsga2.pyscript. 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. #320. - Fix a bug retrieving in the
best_solution()method when retrieving the best solution for multi-objective problems. #331
PyGAD-3.4.0
- The
delay_after_genparameter is removed from thepygad.GAclass constructor. As a result, it is no longer an attribute of thepygad.GAclass instances. To add a delay after each generation, apply it inside theon_generationcallback. #283 - In the
single_point_crossover()method of thepygad.utils.crossover.Crossoverclass, all the random crossover points are returned before theforloop. This is by calling thenumpy.random.randint()function only once before the loop to generate all the K points (where K is the offspring size). This is compared to calling thenumpy.random.randint()function inside theforloop K times, once for each individual offspring. - Bug fix in the
examples/example_custom_operators.pyscript. #285 - While making prediction using the
pygad.torchga.predict()function, no gradients are calculated. - The
gene_typeparameter of thepygad.helper.unique.Unique.unique_int_gene_from_range()method accepts the type of the current gene only instead of the full gene_type list. - Created a new method called
unique_float_gene_from_range()inside thepygad.helper.unique.Uniqueclass to find a unique floating-point number from a range. - Fix a bug in the
pygad.helper.unique.Unique.unique_gene_by_space()method to return the numeric value only instead of a NumPy array. - Refactoring the
pygad/helper/unique.pyscript to remove duplicate codes and reformatting the docstrings. - 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. #279
- Fix a bug converting a nested NumPy array to a nested list. #300
- The
Matplotliblibrary is only imported when a method inside thepygad/visualize/plot.pyscript is used. This is more efficient than usingimport matplotlib.pyplotat the module level as this causes it to be imported whenpygadis imported even when it is not needed. #292 - Fix a bug when minus sign (-) is used inside the
stop_criteriaparameter (e.g.stop_criteria=["saturate_10", "reach_-0.5"]). #296 - Make sure
self.best_solutionsis a list of lists inside thecal_pop_fitnessmethod. #293 - Fix a bug where the
cal_pop_fitness()method was using theprevious_generation_fitnessattribute to return the parents fitness. This instance attribute was not using the fitness of the latest population, instead the fitness of the population before the last one. The issue is solved by updating theprevious_generation_fitnessattribute to the latest population fitness before the GA completes. #291
PyGAD 3.3.1
- After the last generation and before the
run()method completes, update the 2 instance attributes: 1)last_generation_parents2)last_generation_parents_indices. This is to keep the list of parents up-to-date with the latest population fitnesslast_generation_fitness. #275 - 4 methods with names starting with
run_. Their purpose is to keep the main loop inside therun()method clean. Check the [Other Methods](https://pygad.readthedocs.io/en/latest/pygad.html#other-methods) section for more information.