Metadata-Version: 2.5
Name: pymetaheuristics
Version: 0.3.0
Summary: Metaheuristics solvers in Python
Project-URL: Homepage, https://github.com/igormcsouza/pymetaheuristics
Project-URL: Repository, https://github.com/igormcsouza/pymetaheuristics
Project-URL: Documentation, https://igormcsouza.github.io/pymetaheuristics/
Author-email: Igor Souza <igormcsouza@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: metaheuristics,python,solver
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# pymetaheuristics

[![Continuous Integration](https://github.com/igormcsouza/pymetaheuristics/actions/workflows/integration.yml/badge.svg)](https://github.com/igormcsouza/pymetaheuristics/actions/workflows/integration.yml)
[![Coverage Status](https://coveralls.io/repos/github/igormcsouza/pymetaheuristics/badge.svg?branch=main)](https://coveralls.io/github/igormcsouza/pymetaheuristics?branch=main)
[![PyPI version](https://badge.fury.io/py/pymetaheuristics.svg)](https://badge.fury.io/py/pymetaheuristics)

Metaheuristics for optimization problems in plain Python, with no
dependencies. Describe the problem as a `Problem`: how to generate a
solution, how to evaluate it, which solutions are feasible, and whether to
minimize or maximize. Then pass it to a heuristic: a Genetic Algorithm or
Simulated Annealing. Every heuristic returns the same `OptimizationResult`.

Documentation: <https://igormcsouza.github.io/pymetaheuristics/>
([changelog](CHANGELOG.md)).

## Install

Requires Python 3.12+.

```sh
pip install pymetaheuristics
# or
uv add pymetaheuristics
```

## Quickstart

```python
from pymetaheuristics.core import Direction, Problem, max_iterations
from pymetaheuristics.genetic_algorithm import genetic_algorithm
from pymetaheuristics.simulated_annealing import (
    bit_flip_neighbor, simulated_annealing)

VALUES, WEIGHTS, CAPACITY = [60, 100, 120], [10, 20, 30], 50

knapsack = Problem(
    generate=lambda rng: [rng.randint(0, 1) for _ in VALUES],
    evaluate=lambda s: sum(v for v, bit in zip(VALUES, s) if bit),
    feasible=lambda s: sum(w for w, bit in zip(WEIGHTS, s) if bit)
    <= CAPACITY,
    direction=Direction.MAXIMIZE,
)

ga = genetic_algorithm(knapsack, stop=max_iterations(20), rng=42)
sa = simulated_annealing(knapsack, stop=max_iterations(200), rng=42,
                         neighbor=bit_flip_neighbor)
print(ga.best_solution, ga.best_value)  # [0, 1, 1] 220
print(sa.best_solution, sa.best_value)  # [0, 1, 1] 220
```

## How well does it work?

Every heuristic against random search on the [benchmark suite](docs/benchmarks.md), with
the same budget of 2000 evaluations over 20 seeds
([details](docs/experiments.md)):

![Gap closed versus random search](docs/img/overview-gap.png)
![Time per run](docs/img/overview-time.png)

On TSP all three heuristics find the optimum on every seed and on the
sphere the GA and SA close over 99.7% of random search's gap, while random
search stays far off. Rastrigin is hard for all of them with this budget. A full run takes
about 10-30 ms.

## Documentation

The documentation lives in [docs/](docs/). Start with [docs/index.md](docs/index.md),
or build the site locally with `uv run --group docs mkdocs serve`. It
covers:

- [Tutorial](docs/tutorial/index.md): problems, directions, constraints, both
  heuristics, results and history.
- [Worked examples](docs/examples.md): Knapsack and TSP.
- [Extending](docs/extending.md): custom operators and heuristics, plus
  the runnable [examples/](examples/).
- [Architecture](docs/architecture.md), [benchmarks](docs/benchmarks.md),
  [experiments](docs/experiments.md).
- [Release notes](docs/release-notes.md): what changed between versions.

## Development

```sh
uv sync                    # dev tools
uv run pre-commit install
uv run ruff check .
sh scripts/test.sh         # pytest with coverage, including the doc snippets
uv run --group docs mkdocs build --strict
```

Contributions are welcome. Open an issue or a pull request.
