Metadata-Version: 2.4
Name: lonkit
Version: 0.3.0
Summary: Local Optima Networks (LONs) for continuous and discrete optimization - Python implementation
Project-URL: Homepage, https://helix-agh.github.io/lonkit
Project-URL: Documentation, https://helix-agh.github.io/lonkit
Project-URL: Repository, https://github.com/helix-agh/lonkit
Project-URL: Issues, https://github.com/helix-agh/lonkit/issues
Author: HELIX AGH
License: MIT
Keywords: basin-hopping,continuous-optimization,discrete-optimization,evolutionary-algorithms,fitness-landscape,fitness-landscape-analysis,local-optima-networks,metaheuristics,multi-dimensional,optimization,visualization
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.10
Requires-Dist: igraph>=0.11.0
Requires-Dist: imageio>=2.31.0
Requires-Dist: joblib>=1.3.0
Requires-Dist: kaleido>=0.2.1
Requires-Dist: matplotlib>=3.7.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: pandas>=2.0.0
Requires-Dist: plotly>=5.15.0
Requires-Dist: scipy>=1.10.0
Requires-Dist: tqdm>=4.67.3
Provides-Extra: dev
Requires-Dist: ioh>=0.3.22; extra == 'dev'
Requires-Dist: mkdocs-material>=9.7.0; extra == 'dev'
Requires-Dist: mkdocs>=1.6.1; extra == 'dev'
Requires-Dist: mkdocstrings-python>=1.0.0; extra == 'dev'
Requires-Dist: mkdocstrings>=1.0.0; extra == 'dev'
Requires-Dist: mypy>=1.13.0; extra == 'dev'
Requires-Dist: pre-commit>=4.0.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">
    <img src="https://raw.githubusercontent.com/helix-agh/lonkit/main/docs/assets/icon.png" alt="lonkit" width="800">
</div>

[![PyPI version](https://badge.fury.io/py/lonkit.svg)](https://pypi.org/project/lonkit/)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1Ujl48ffgHg9ck1Hueh59s65OR3Q3BG99?usp=sharing)

**Local Optima Networks**

lonkit is a Python library for constructing, analyzing, and visualizing Local Optima Networks (LONs) for both continuous and discrete optimization problems. LONs provide a powerful way to understand the structure of fitness landscapes, revealing how local optima are connected and how difficult it may be to find global optima.

## Features

- **Basin-Hopping Sampling**: Efficient exploration of continuous fitness landscapes using configurable Basin-Hopping
- **Iterated Local Search**: Discrete LON construction via ILS with built-in problems (Number Partitioning, OneMax)
- **LON Construction**: Automatic construction of Local Optima Networks from sampling data
- **CMLON Support**: Compressed Monotonic LONs for cleaner landscape analysis
- **Rich Metrics**: Compute landscape metrics including funnel analysis and neutrality
- **Beautiful Visualizations**: 2D and 3D plots with support for animated GIFs

## Installation

```bash
pip install lonkit
```

Or install from source:

```bash
git clone https://github.com/helix-agh/lonkit.git
cd lonkit
pip install -e .
```

## Quick Start

```python
import numpy as np
from lonkit import compute_lon, LONVisualizer, BasinHoppingSamplerConfig

# Define an objective function
def rastrigin(x: np.ndarray) -> float:
    return 10 * len(x) + np.sum(x**2 - 10 * np.cos(2 * np.pi * x))

# Construct the LON
config = BasinHoppingSamplerConfig(
    n_runs=20,
    n_iter_no_change=500,
    seed=42
)
lon = compute_lon(
    rastrigin,
    dim=2,
    lower_bound=-5.12,
    upper_bound=5.12,
    config=config
)

metrics = lon.compute_metrics()
print(f"Number of funnels: {metrics['n_funnels']}")
print(f"Global funnels: {metrics['n_global_funnels']}")

# Visualize
viz = LONVisualizer()
viz.plot_2d(lon, output_path="lon_2d.png")
viz.plot_3d(lon, output_path="lon_3d.png")
```

### Compressed Monotonic LONs (CMLONs)

CMLONs are a compressed representation where nodes with equal fitness that are connected get merged. This provides a cleaner view of the landscape's funnel structure.

```python
# Convert LON to CMLON
cmlon = lon.to_cmlon()

# Analyze CMLON-specific metrics
cmlon_metrics = cmlon.compute_metrics()
```

### Custom Sampling Configuration

```python
from lonkit import BasinHoppingSampler, BasinHoppingSamplerConfig

config = BasinHoppingSamplerConfig(
    n_runs=50,                   # Number of independent runs
    n_iter_no_change=1000,       # Stop after this many consecutive non-improving perturbations
    step_size=0.05,              # Perturbation size
    step_mode="percentage",      # "percentage" or "fixed"
    coordinate_precision=4,      # Precision for identifying optima
    fitness_precision=None,      # Precision for fitness values (None = full double)
    seed=42                      # For reproducibility
)

sampler = BasinHoppingSampler(config)

# Define search domain
domain = [(-5.12, 5.12), (-5.12, 5.12)]

# Run sampling
result = sampler.sample(rastrigin, domain)
lon = sampler.sample_to_lon(result)
```

## Discrete Optimization Problems

lonkit also supports Local Optima Networks for discrete optimization problems using Iterated Local Search (ILS).

### Quick Start (Discrete)

```python
from lonkit import NumberPartitioning, ILSSampler, ILSSamplerConfig, LONVisualizer

# Define problem instance
problem = NumberPartitioning(n=20, k=0.5, instance_seed=1)

# Configure and run ILS sampling
config = ILSSamplerConfig(n_runs=50, n_iter_no_change=100, seed=42)
sampler = ILSSampler(config)
result = sampler.sample(problem)

# Build LON and CMLON
lon = sampler.sample_to_lon(result)
cmlon = lon.to_cmlon()

# Compute metrics
print(lon.compute_metrics())
print(cmlon.compute_metrics())

# Visualize
viz = LONVisualizer()
viz.plot_2d(cmlon, output_path="npp_cmlon.png")
```

### Custom Discrete Problems

You can define your own discrete problem by subclassing `DiscreteProblem`. For bitstring problems, inherit from `BitstringProblem` instead it provides `random_solution()`, `local_search()`, `perturb()`, and `solution_id()` out of the box. You only need to implement `evaluate()`.

## Documentation

For full documentation, visit: [https://helix-agh.github.io/lonkit](https://helix-agh.github.io/lonkit)

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
