Metadata-Version: 2.5
Name: bsopt
Version: 0.1.0
Summary: Binary Snake Optimizer (BSO): a sigmoid-binarized Snake Optimizer metaheuristic for feature selection and binary combinatorial optimization.
Project-URL: Homepage, https://github.com/InquietoPartho/bsopt
Project-URL: Repository, https://github.com/InquietoPartho/bsopt
Project-URL: Documentation, https://github.com/InquietoPartho/bsopt#readme
Project-URL: Issues, https://github.com/InquietoPartho/bsopt/issues
Author: Pijush Kanti Roy Partho
License: MIT
License-File: LICENSE
Keywords: feature-selection,machine-learning,metaheuristic,optimization,snake-optimizer,swarm-intelligence
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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
Requires-Python: >=3.9
Requires-Dist: numpy>=1.21
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: scikit-learn>=1.0; extra == 'dev'
Provides-Extra: sklearn
Requires-Dist: scikit-learn>=1.0; extra == 'sklearn'
Description-Content-Type: text/markdown

<div align="center">

# BSO — Binary Snake Optimizer

**A sigmoid-binarized adaptation of the Snake Optimizer metaheuristic for feature selection and binary combinatorial optimization.**

[![CI](https://github.com/InquietoPartho/bsopt/actions/workflows/ci.yml/badge.svg)](https://github.com/InquietoPartho/bsopt/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/bsopt)](https://pypi.org/project/bsopt/)
[![Python](https://img.shields.io/pypi/pyversions/bsopt)](https://pypi.org/project/bsopt/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

</div>

---

> **Note on the name.** The bare name `BSO` is taken on PyPI by an
> unrelated package, so this is published as the short form
> **`bsopt`**. The Python import path matches: `import bsopt`.

## Overview

Snake Optimizer (SO) is a population-based metaheuristic proposed by
Hashim & Hussien (2022), inspired by snake mating behavior. It splits
its population into two cooperating sub-swarms and alternates between
**exploration** and **exploitation** phases based on a temperature
signal and a food-quantity signal — with dedicated "fight," "mate," and
"egg-laying" dynamics during exploitation.

`bsopt` binarizes that search via a sigmoid transfer function,
so the same population dynamics can operate directly on **binary
decision vectors** — most commonly, "which of N candidate features to
keep." The optimizer itself is fully agnostic to what the mask
represents: it only needs a function that scores a binary vector.

## Features

- **Pure NumPy core** — no heavy dependencies for the optimizer itself.
- **Pluggable fitness function** — works for feature selection, or any
  other binary combinatorial problem you can score.
- **Reproducible by design** — all randomness is drawn from a local,
  seeded `numpy.random.Generator`; no mutation of global NumPy state.
- **Optional scikit-learn helper** — `bsopt.sklearn_selector.select_features`
  wraps the optimizer for the common case of wrapper-based feature
  selection against any sklearn-compatible classifier.
- **Fully documented algorithm** — see [`docs/pseudocode.md`](docs/pseudocode.md)
  for line-by-line pseudocode and notes on where this implementation
  deviates from the published continuous algorithm (including a fix for
  an index-out-of-bounds edge case in the original mating step when the
  population size is odd).
- **Tested** — unit tests cover the transfer function, convergence
  behavior, reproducibility, and edge cases; run in CI across Python
  3.9–3.12 on every push.

## Installation

```bash
pip install bsopt
```

With the optional scikit-learn feature-selection helper:

```bash
pip install "bsopt[sklearn]"
```

## Quickstart

```python
import numpy as np
from bsopt import binary_snake_optimizer

def fitness(mask: np.ndarray) -> float:
    """Toy example: minimize the number of selected bits, unless
    none are selected (which is disallowed)."""
    return mask.sum() if mask.sum() > 0 else len(mask)

result = binary_snake_optimizer(
    fitness_fn=fitness,
    dim=20,
    n_agents=30,
    n_iter=50,
    seed=42,
)

print(result.best_mask)      # binary array, shape (20,)
print(result.best_fitness)   # scalar fitness of best_mask
print(result.history)        # best-so-far fitness per iteration
```

## Feature selection with scikit-learn

```python
from sklearn.ensemble import RandomForestClassifier
from bsopt.sklearn_selector import select_features

result = select_features(
    estimator=RandomForestClassifier(n_estimators=50, random_state=42),
    X=X_train,          # DataFrame or array, shape (n_samples, n_features)
    y=y_train,
    n_agents=30,
    n_iter=50,
    random_state=42,
)

print(result.selected_features)   # list of selected feature names
print(result.mask)                # binary mask over all input features
```

`select_features` scores each candidate mask by fitting a clone of your
estimator on a held-out split and combining validation error with a
sparsity penalty, so the search favors compact, accurate feature
subsets. See [`docs/pseudocode.md`](docs/pseudocode.md) for the exact
fitness formula and [`examples/`](examples/) for a runnable end-to-end
script.

## API reference

| Symbol | Description |
|---|---|
| `bsopt.binary_snake_optimizer(fitness_fn, dim, n_agents=30, n_iter=50, lb=-3.0, ub=3.0, threshold=0.25, threshold2=0.6, c1=0.5, c2=0.05, c3=2.0, seed=None, verbose=False)` | Core optimizer. Returns a `BSOResult`. |
| `bsopt.BSOResult` | Dataclass with `best_mask`, `best_fitness`, `history`. |
| `bsopt.sigmoid`, `bsopt.binarize` | The transfer function and stochastic binarization step, exposed for reuse/testing. |
| `bsopt.sklearn_selector.select_features(...)` | Convenience wrapper for sklearn-based feature selection. Requires the `sklearn` extra. Returns a `FeatureSelectionResult`. |

Every public function has a complete NumPy/Google-style docstring —
see `help(binary_snake_optimizer)` or browse
[`src/bsopt/core.py`](src/bsopt/core.py).

## Algorithm

The population is split into two equal sub-swarms (male/female). Each
iteration:

1. A temperature term `Temp` and food-quantity term `Q` are computed
   for the current iteration.
2. If `Q` is below a threshold, snakes **explore**: random walks around
   a randomly chosen leader in their own sub-swarm.
3. Otherwise, snakes **exploit**:
   - If `Temp` is high ("hot"), snakes move directly toward the current
     best-known position ("food").
   - If `Temp` is low ("cold"), snakes either **fight** (move toward
     the opposite sub-swarm's best individual) or **mate** (move toward
     a paired individual in the opposite sub-swarm), which can also
     trigger an **egg-laying** reset of the worst individual in each
     sub-swarm.
4. Every proposed position is clipped to bounds, passed through a
   **sigmoid transfer function** to get an inclusion probability per
   bit, stochastically binarized, scored with `fitness_fn`, and
   greedily accepted if it improves on the snake's current fitness.

Full pseudocode, equation references back to the original paper, and a
list of every place this implementation deviates from it (with
justification) live in [`docs/pseudocode.md`](docs/pseudocode.md).

## Development

```bash
git clone https://github.com/InquietoPartho/bsopt
cd bsopt
pip install -e ".[dev,sklearn]"
pytest -v
```

Continuous integration runs the test suite on Python 3.9–3.12 for
every push and pull request (see [`.github/workflows/ci.yml`](.github/workflows/ci.yml)).
Releases are published to PyPI automatically via
[trusted publishing](https://docs.pypi.org/trusted-publishers/) when a
GitHub Release is cut (see [`.github/workflows/publish.yml`](.github/workflows/publish.yml)).

Contributions, issues, and feature requests are welcome — please open
an [issue](https://github.com/InquietoPartho/bsopt/issues)
or a pull request.

## Citation

If you use this package in academic work, please cite the original
Snake Optimizer paper:

```bibtex
@article{hashim2022snake,
  title   = {Snake Optimizer: A novel meta-heuristic optimization algorithm},
  author  = {Hashim, Fatma A. and Hussien, Abdelazim G.},
  journal = {Knowledge-Based Systems},
  year    = {2022},
  doi     = {10.1016/j.knosys.2022.108320}
}
```

and, if useful, this package:

```bibtex
@software{bsopt,
  title  = {bsopt: A Python implementation of the Binary Snake Optimizer},
  author = {Roy Partho, Pijush Kanti},
  year   = {2026},
  url    = {https://github.com/InquietoPartho/bsopt}
}
```

## License

Released under the [MIT License](LICENSE). This is an independent
reimplementation of a published algorithm — the algorithm itself is
not owned by this package, but please credit the original authors'
work (linked above) appropriately, and check the license of the
original MATLAB reference code if you redistribute code derived from
it directly.
