Skip to main content

BSO — Binary Snake Optimizer

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

CI PyPI Python License: MIT


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 helperbsopt.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 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

pip install bsopt

With the optional scikit-learn feature-selection helper:

pip install "bsopt[sklearn]"

Quickstart

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

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 for the exact fitness formula and 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.

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.

Development

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). Releases are published to PyPI automatically via trusted publishing when a GitHub Release is cut (see .github/workflows/publish.yml).

Contributions, issues, and feature requests are welcome — please open an issue or a pull request.

Citation

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

@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:

@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. 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.

Release files for bsopt 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bsopt 0.1.0
File Size Uploaded
bsopt-0.1.0.tar.gz 13.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bsopt 0.1.0
File Interpreter ABI Platform
bsopt-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 25.7 kB

Release files / bsopt-0.1.0.tar.gz

Download URL bsopt-0.1.0.tar.gz
Size 13.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e905888a472c6776a848109c3e5fa299bda9c4aaa8785018b4b9f082e33f7159
BLAKE2b-256 checksum
How to use checksums
154974662431eec3f969be5531e36c1bb9c9e99b42cfc758b64781135babaa42
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release files / bsopt-0.1.0-py3-none-any.whl

Download URL bsopt-0.1.0-py3-none-any.whl
Size 12.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c9313eeae8458fdad087da4098dfb13db87e208ecb7a33b2468d713a53f28bad
BLAKE2b-256 checksum
How to use checksums
5341cc565bb07e85f2eb125c58dff78dad208ad8bf5dafa79ef30cb090fa08db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page