Metadata-Version: 2.4
Name: pygenalgo
Version: 2.1.0
Summary: Genetic Algorithms toolbox in Python3
Home-page: https://github.com/vrettasm/PyGeneticAlgorithms
Author: Michalis Vrettas, PhD
Author-email: "Michalis Vrettas, PhD" <michail.vrettas@gmail.com>
License: GPL-3.0
Project-URL: Homepage, https://github.com/vrettasm/PyGeneticAlgorithms
Keywords: optimization,genetic algorithms,island model
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: joblib
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# PyGenAlgo: A simple and powerful toolkit for genetic algorithms.

![Logo](./logo/pga_logo.png)

[![DOI](https://zenodo.org/badge/311952715.svg)](https://doi.org/10.5281/zenodo.18171837)

[![linting: pylint](https://img.shields.io/badge/linting-pylint-yellowgreen)](https://github.com/pylint-dev/pylint)

**Pylint score: 9.81 / 10**

This repository implements a genetic algorithm toolbox in Python3 programming language, using only *Numpy* and *Joblib*
as additional libraries. The toolbox offers the following implementations (as engines):

- A **StandardGA** class, where the whole population of chromosomes is replaced by a new one at the end of each
iteration (or epoch).
- An **IslandModelGA** class offers a new genetic operator (MigrationOperator), which allows for periodic migration
of the best individuals among the (co-evolving) different island populations. The island populations are coevolving
in parallel using separate CPUs.
- A brand new **MultiObjectiveGA** class is added that allows the user to solve more complex multiobjective optimization
problems. The major difference in the new class is that the fitness function is expected to return a tuple with all the
objective function values, e.g. (fx1, fx2, ..., fxn) rather a single function value fx. Note, that if the problems has
additional constraints to satisfy, as is usually the case, they should be summed in one 'penalty' variable and included
in the tuple _before_ any other objective value i.e. (sum_penalty, fx1, fx2, ..., fxn). This way, when the chromosomes
are sorted those that minimize all constraints (sum_penalty == 0) will be placed higher in the rank.

For computationally expensive fitness functions the StandardGA and MultiObjectiveGA classes provide the option of
parallel evaluation (of the individual chromosomes), by setting in the method run(..., parallel=True). However, for
fast fitness functions this will actually cause the algorithm to execute slower (due to the time required to open and
close the parallel pool). So the default setting here is "parallel=False". Regarding the IslandModelGA this is running
in parallel mode by definition.

  > **NEWS**:
  > In this new release two additional selection operators have been implemented (i.e. ParetoFrontSelector and
  > ParetoTournamentSelector) that are used exclusively with the 'MultiObjectiveGA' and select the new parents
  > using pareto-front selection techniques. Note that both of these classes provide a base for the development
  > of possible new selection methodologies for multi-objective problems. Examples that use the new techniques
  > have also been added to demonstrate their use.
  > 

The current implementation provides (out of the box) a wide variety of genetic operators, including:

- **Selection operators**:
  - [Linear Rank Selector](pygenalgo/operators/selection/linear_rank_selector.py)
  - [Neighborhood Selector](pygenalgo/operators/selection/neighborhood_selector.py)
  - [Random Selector](pygenalgo/operators/selection/random_selector.py)
  - [Roulette Wheel Selector](pygenalgo/operators/selection/roulette_wheel_selector.py)
  - [Stochastic Universal Selector](pygenalgo/operators/selection/stochastic_universal_selector.py)
  - [Tournament Selector](pygenalgo/operators/selection/tournament_selector.py)
  - [Truncation Selector](pygenalgo/operators/selection/truncation_selector.py)
  - [Boltzmann Selector](pygenalgo/operators/selection/boltzmann_selector.py)
  - [Pareto Front Selector](pygenalgo/operators/selection/pareto_front_selector.py)
  - [Pareto Tournament Selector](pygenalgo/operators/selection/pareto_tournament_selector.py)

- **Crossover operators**:
  - [Single-Point Crossover*](pygenalgo/operators/crossover/single_point_crossover.py)
  - [Multi-Point Crossover*](pygenalgo/operators/crossover/multi_point_crossover.py)
  - [Uniform Crossover*](pygenalgo/operators/crossover/uniform_crossover.py)
  - [Order Crossover (OX1)](pygenalgo/operators/crossover/order_crossover.py)
  - [Partially Mapped Crossover (PMX)](pygenalgo/operators/crossover/partially_mapped_crossover.py)
  - [Position Based Crossover (POS)](pygenalgo/operators/crossover/position_based_crossover.py)
  - [Blend-α Crossover (BLX-α)*](pygenalgo/operators/crossover/blend_crossover.py)
  - [Simulated Binary Crossover (SBX)*](pygenalgo/operators/crossover/simulated_binary_crossover.py)

- **Mutation operators**:
  - [Random Mutator](pygenalgo/operators/mutation/random_mutator.py)
  - [Shuffle Mutator](pygenalgo/operators/mutation/shuffle_mutator.py)
  - [Inverse Mutator](pygenalgo/operators/mutation/inverse_mutator.py)
  - [Gaussian Mutator](pygenalgo/operators/mutation/gaussian_mutator.py)
  - [Swap Mutator](pygenalgo/operators/mutation/swap_mutator.py)
  - [Flip Mutator](pygenalgo/operators/mutation/flip_mutator.py)
  - [Polynomial Mutator](pygenalgo/operators/mutation/polynomial_mutator.py)

- **Migration operators**
  - [Clockwise Migrator](pygenalgo/operators/migration/clockwise_migration.py)
  - [Random Migrator](pygenalgo/operators/migration/random_migration.py)

- **Meta operators**
  - [Meta Selector](pygenalgo/operators/selection/meta_selector.py)
  - [Meta Crossover](pygenalgo/operators/crossover/meta_crossover.py)
  - [Meta Mutator](pygenalgo/operators/mutation/meta_mutator.py)
  - [Meta Migration](pygenalgo/operators/migration/meta_migration.py)

**NOTE(1):** Meta operators call randomly other compatible operators (selection/crossover/mutation/migration)
from a predefined set, with equal probability.

**NOTE(2):** Crossover operators marked by '*' support variable chromosome lengths (VLC). By definition all
mutation operators support VCL too, because they operate on a single chromosome at a time.

Incorporating additional genetic operators is easily facilitated by inheriting from the base classes:
- [SelectionOperator](pygenalgo/operators/selection/select_operator.py)
- [CrossoverOperator](pygenalgo/operators/crossover/crossover_operator.py)
- [MutationOperator](pygenalgo/operators/mutation/mutate_operator.py)
- [MigrationOperator](pygenalgo/operators/migration/migration_operator.py)

and implementing the basic interface as described therein. In the examples that follow I show how one can use this code
to run a GA for optimization problems (maximization/minimization) with and without constraints. The project is ongoing
so new things might come along the way.

### Installation

There are two options to install the software.

The easiest way is to download it from PyPI. Simply run the following command on a terminal:
    
    pip install pygenalgo

Alternatively one can clone directly the latest version using git as follows:

    git clone https://github.com/vrettasm/PyGeneticAlgorithms.git

After the download of the code (or the git clone), one can use the following commands:

    cd PyGeneticAlgorithms
    pip install .

This will install the latest PyGenAlgo version in the package management system.

### Required packages

The recommended version is Python 3.10 (and above). To simplify the required packages just use:

    pip install -r requirements.txt

### Fitness function

The most important thing the user has to do is to define the fitness function. A template for single objective function
is provided here in addition to the examples below. The cost_function decorator is used to indicate whether the function
will be maximized (default), or minimized. The second output parameter ("solution_found") is optional; only in the cases
where we can evaluate if a termination condition is satisfied.

```python
from pygenalgo.genome.chromosome import Chromosome
from pygenalgo.utils.utilities import cost_function


# Fitness function <template>.
@cost_function(minimize=True)
def fitness_func(individual: Chromosome):
    """
    This is how a fitness function should look like. The whole
    evaluation should be implemented (or wrapped around) this
    function.
    
    :param individual: Individual chromosome to be evaluated.
    
    :return: the function value evaluated at the individual.
    """

    # Extract gene values from the chromosome.
    x = individual.values()
    
    # ... CODE TO IMPLEMENT ...

    # Compute the function value.
    f_value = ...

    # Condition for termination.
    # We set it to True / False.
    solution_found = ...

    # Return the solution.
    return f_value, solution_found
# _end_def_
```
Once the fitness function is defined correctly the next steps are straightforward as described in the examples.

### Examples

Some optimization examples on how to use these algorithms:

| **Problem**                                                   | **Variables** | **Objectives** | **Constraints** | **Optima** |
|:--------------------------------------------------------------|:-------------:|:--------------:|:---------------:|:----------:|
| [Sphere](examples/sphere.ipynb)                               |    M (=5)     |       1        |       no        |   single   |
| [Rastrigin](examples/rastrigin.ipynb)                         |    M (=5)     |       1        |       no        |   single   |
| [Rosenbrock](examples/rosenbrock_on_a_disk.ipynb)             |    M (=2)     |       1        |        1        |   single   |
| [Binh & Korn](examples/binh_and_korn_multiobjective.ipynb)    |    M (=2)     |       2        |        2        |   Pareto   |
| [Sphere (parallel)](examples/sphere_in_parallel.ipynb)        |    M (=10)    |       1        |       no        |   single   |
| [Easom (parallel)](examples/easom_in_parallel.ipynb)          |    M (=2)     |       1        |       no        |   single   |
| [Traveling Salesman](examples/tsp.ipynb)                      |    M (=10)    |       1        |       yes       |   single   |
| [N-Queens](examples/queens_puzzle.ipynb)                      |    M (=8)     |       1        |       yes       |   single   |
| [OneMax](examples/one_max.ipynb)                              |    M (=50)    |       1        |       no        |   single   |
| [Zakharov](examples/zakharov.ipynb)                           |    M (=8)     |       1        |       no        |   single   |
| [Shubert](examples/shubert_2D.ipynb)                          |       2       |       1        |       no        |  multiple  |
| [Gaussian Mixture](examples/gaussian_mixture_2D.ipynb)        |       2       |       1        |       no        |  multiple  |
| [Multi-Depot VRP](examples/mdvrp/mdvrp_with_clustering.ipynb) |       M       |       1        |       yes       |  multiple  |
| [MOO: Binh & Korn](examples/moo_binh_and_korn.ipynb)          |    M (=2)     |       2        |        2        |   Pareto   |
| [MOO: Tanaka](examples/moo_tanaka.ipynb)                      |    M (=2)     |       2        |        2        |   Pareto   |
| [MOO: Osyczka & Kundu](examples/moo_osyczka_kundu.ipynb)      |       6       |       2        |        6        |   Pareto   |
| [MOO: DTLZ3](examples/moo_dtlz3.ipynb)                        |       N       |       3        |       no        |   Pareto   |

Constraint optimization problems can be easily addressed using the [Penalty Method](https://en.wikipedia.org/wiki/Penalty_method).

## References and Documentation

This work is described in:

- [Michail D. Vrettas and Stefano Silvestri (2025)](https://www.sciencedirect.com/science/article/pii/S2352711025000949)
"PyGenAlgo: a simple and powerful toolkit for genetic algorithms". SoftwareX, vol. 30. DOI: 10.1016/j.softx.2025.102127.

You can find the latest documentation [here](https://pygeneticalgorithms.readthedocs.io/en/latest/).

### Contact

For any questions/comments (**regarding this code**) please contact me at: vrettasm@gmail.com
