Repository navigation
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
examples/example_initial_population.pydemonstrates generated and supplied populations. -
Gene-type validation and conversion share methods for scalar values, candidate arrays, and populations. Columns with matching types and precisions are converted together. Floating-point values are rounded before casting, including narrow NumPy types, and extreme decimal scaling preserves finite values before the cast. Additive mutation computes the sum before conversion, preserving fractional offsets and exact integer addition. Finite spaces keep large integers exact during conversion, and integer ranges use exact Python values for NumPy scalar bounds. Custom operators and their callbacks apply gene types whether duplicates are allowed or not. Permutation mutation applies each destination gene's type and precision, and saved best solutions preserve mixed scalar types and large integers across repeated runs. The new
examples/example_gene_type_conversion.pydemonstrates these rules. Thepygad.helperandpygad.utilssubmodule versions are1.4.3and1.5.5. -
Constructor validation shares checks for integer counts, finite numeric settings, ranges, callable signatures, and operator selection. NumPy counts become Python integers before arithmetic, preventing narrow-integer overflow in mutation percentages and repeated runs. Tournament sizes are validated for ordinary, NSGA-II, and NSGA-III tournaments. Stop criteria share one parser, accept scientific notation, preserve large integer counts, and reject zero, negative, or fractional saturation/evaluation counts. Zero worker counts consistently disable parallel processing.
-
Only the active mutation control is validated, in the order probability, count, percentage. Permutation and polynomial mutation apply explicit controls, including zero probability. Zero crossover probability preserves parents even when a random draw is exactly zero. Permutations check complete proposals against destination spaces, types, constraints, and duplicates, retrying compatible alternatives before retaining the original solution. SBX and polynomial mutation resolve bounds from gene spaces or initialization ranges, sort reversed bounds, and clip supplied values before calculation. Converted results stay within the permitted space, including excluded continuous upper bounds.
-
Each GA owns NumPy and Python random generators. NumPy integer seeds are accepted, separate instances and global generators do not interfere, and checkpoints preserve generator states. Custom operators and callbacks can use
numpy_random_generatorandpython_random_generatorfor reproducible choices. Built-in seeded results may differ from earlier versions. -
Ranges and stepped dictionaries are sampled by index instead of being materialized for ordinary generation and constraint sampling. Inspection snapshots remain compact for large domains; duplicate repair still searches complete finite domains from the original settings. Constructor containers are copied, existing logger handlers are retained, invalid loggers report the original validation error, and adaptive replacement no longer emits an incorrect warning. Parameter checks precede population generation and constraint execution. The new
examples/example_constructor_parameters.pydemonstrates callable signatures, NumPy counts, and independent seeded instances. Thepygad.helperandpygad.utilssubmodule versions are1.4.4and1.5.6. -
The new best_solutions_generations and solutions_generations attributes record actual generation numbers across repeated
run()calls, with one entry per best-fitness snapshot and saved population, respectively. Existing histories retain all starting and final snapshots, including both snapshots at a run boundary.best_solution_generationuses actual generation numbers and the same single-objective or NSGA-II ordering asbest_solution(), without changing the current population's Pareto fronts. Population history records each snapshot's size, including NSGA-III growth. Fitness plots, best-solution gene plots, population diagnostics, and PDF reports use this metadata. New-solution-rate plots use the latest population once per generation and exclude the final population; Pareto evolution selects actual generation intervals and includes the final population. Checkpoints preserve the metadata. Older single-run checkpoints recover their generation numbers; unavailable numbers in older repeated-run histories becomeNone, withbest_solution_generation=-1when the winning snapshot's generation is unknown. The newexamples/example_repeated_runs.pydemonstrates continuing from a checkpoint. -
saturate_N checks consecutive unchanged generations, including the current population and the initial baseline. Changes between matching endpoints reset the count,
saturate_1no longer stops improving runs, and everyrun()resets its saturation count. Multi-objective comparisons use the whole best-fitness vector. -
Returned and in-place
on_fitnesschanges are validated before selection. The best solution is recomputed after the callback, keeping saved solutions and fitness aligned. Saved population fitness and best-fitness vectors are copied to prevent later callback edits from changing earlier snapshots, and saved genes retain their configured NumPy scalar types. Callback order and call counts are preserved, including the absence of an additionalon_fitnesscall for the final population. Callbacks continue to receive fitness after cache reuse. -
Fitness validation is shared by sequential, threaded, process, batch, cached, and adaptive evaluation. Empty or nested objective vectors, non-numeric values, inconsistent objective counts, and NaN values fail with descriptive errors before selection. Single-objective infinities remain accepted; objective vectors require finite values for Pareto calculations. Explicit fitness passed to
best_solution()is validated too. -
Saved fitness uses indexes of complete solutions instead of repeated linear history searches, keeping large integer gene values exact. Built-in evolution indexes newly saved snapshots incrementally. Cache precedence remains saved solutions, saved best solutions, retained elites, then retained parents, using the first matching entry in each source. Unsaved duplicate solutions are still evaluated independently. Indexes are rebuilt around direct evaluations, repeated runs, user operators, and callbacks to honor history edits, and are omitted from checkpoints and worker snapshots. No additional user configuration is required.
-
The NSGA-III DTLZ2 custom mutation uses the GA's random generator, making its quality tests independent of global random draws without relaxing their thresholds. A regression test checks reproducibility despite changes to the global random state.
-
Regression tests cover zero-generation runs, early stopping, repeated runs, checkpoint continuation and older checkpoints, manually cleared histories, callback edits, NumPy gene types, multi-objective history and Pareto fronts, NSGA-III population growth, history plots and PDF reports, malformed fitness in sequential/thread/process and batch modes, adaptive objective counts, cache precedence, and incremental indexing. Documentation covers the new attributes, stopping rules, fitness validation, cache behavior, plots, and checkpoint compatibility. The
pygad.utilsandpygad.visualizesubmodule versions are1.5.7and1.2.2. -
Release history is ordered from newest to oldest, with Unreleased first and the latest 10 entries visible initially. Readers can show 10 more entries at a time, show the complete history, or jump directly to a selected release on the same page. Existing release links automatically reveal their target, the table of contents follows the visible entries, and keyboard focus moves to newly revealed notes. All release content remains available to documentation search, printing, and readers without JavaScript. Feature links use standard Markdown paths and heading anchors so they work in repository views and built documentation.
-
The generation guide explains instance-owned random generators with a custom mutation example, precise saturation counting, and generation metadata across repeated runs and checkpoints. The seeded example output is refreshed, and the guide clarifies that best-fitness history is collected even when best-solution gene values are not saved.
-
A new Examples index connects all 81 repository Python scripts and the TSP notebook to their documentation guides. Shared Python example cards link scripts beside the relevant explanations, use compact tables for larger groups, and provide expandable run instructions, requirements, and working directories. Self-contained scripts can be downloaded directly from the built documentation; examples needing data link to their folders and dataset setup instructions. One catalog and shared templates keep descriptions and links consistent, and the documentation build rejects missing scripts, uncataloged Python files, unknown example references, and missing guides. GitHub links match the documentation checkout. The TSP notebook's Colab-specific CSV path and local adaptation requirements are clarified. Earlier entries describe the regression tests and runnable examples added with the library changes.
-
Documentation guides also render directly on GitHub and in compatible Markdown previews. Internal references use Markdown links; parameter descriptions use expandable details; navigation lists and PNG diagrams remain visible; and Sphinx-only labels, toctrees, and video embeds are hidden from previews. All Python example sections and the Examples index include checked-in Markdown generated from the shared catalog and templates, with script links, requirements, dataset setup, and run instructions. A Python-only command updates these sections, and builds reject stale content or incomplete section comments. Built documentation retains its cards, dropdowns, figures, downloads, navigation, and published anchors.
-
Package metadata declares Python 3.8 or newer, matching the minimum version in the test matrix. Documentation reads the package version from
pygad/_version.py. Release tags must match that version, and publication requires the Python 3.8 through 3.14 test matrix and a documentation build with warnings treated as errors. The matrix imports the installed wheel from outside the checkout. A GitHub Release is created only after PyPI publication succeeds, using the documented release notes and the published PyPI source distribution and wheel after verifying their SHA-256 hashes against the checked build.
The operators consume different random draws from earlier versions. Runs with the same random_seed remain reproducible within the same version and environment, but can produce different results from earlier versions.