whalepy
whalepy is a research-oriented Python toolbox for the Whale Optimization Algorithm (WOA) family.
The project now includes working implementations of plain/basic WOA, Adaptive WOA, Chaotic WOA, Mutation-Based WOA, Modified Spiral WOA, Levy Walk WOA, Gaussian Mutation WOA, Opposition-Based WOA, Single-Dimensional WOA, Worst-Individual-Disturbance WOA, and Exponential Decay WOA for continuous benchmark problems.
The following variants have been implemented:
| No. | Algorithm | Year | Publication |
|---|---|---|---|
| 1 | WOA (Whale Optimization Algorithm) | 2016 | Mirjalili & Lewis [1] |
| 2 | AdaptiveWOA (Adaptive Whale Optimization Algorithm) | 2016 | Trivedi et al. [2], Chen et al. [3], Sun et al. [4] |
| 3 | CWOA (Chaotic WOA) | 2018 | Kaur & Arora [5] |
| 4 | MutationWOA (Mutation-Based WOA, DE/rand/1) | 2019 | Mostafa Bozorgi & Yazdani [6] |
| 5 | ModifiedSpiralWOA (Modified Spiral WOA) | 2018 | Sun et al. [7] |
| 6 | LevyWalkWOA (Levy Flight WOA) | 2017 | Ling et al. [8] |
| 7 | GaussianWOA (Gaussian Mutation WOA, GM-WOA) | 2019 | Luo et al. [9] |
| 8 | OppositionBasedWOA (Opposition-Based WOA) | 2018 | Alamri et al. [10] |
| 9 | SingleDimensionalWOA (WOA with Single-Dimensional Swimming) | 2020 | Du et al. [11] |
| 10 | WorstIndividualDisturbanceWOA (Individual Disturbance WOA) | 2022 | Qiao et al. [12] |
| 11 | ExponentialDecayWOA (WOA with Exponential Convergence Factor) | 2022 | Sun et al. [4] |
The scaffold uses a WOA-specific domain model built around Whale objects rather than generic evolutionary
abstractions.
Adaptive WOA extends the plain WOA loop with adaptive control schedules. In this project, the adaptive variant
supports nonlinear decay of the convergence coefficient a, an optional inertia-like weight in the leader
attraction step, and an optional adaptive spiral probability that increasingly favors exploitation later in the
run.
Chaotic WOA replaces selected random draws in WOA with deterministic chaotic sequences. In this project, the
chaotic variant supports logistic, tent, and sine maps, optional chaotic population initialization, chaotic
coefficient generation, chaotic branch probability, chaotic spiral values, and optional chaotic modulation of
the convergence coefficient a.
Modified Spiral WOA keeps the standard WOA exploration behavior and changes only the exploitation spiral around the leader (the best solution found so far). In this project, the variant supports both the standard logarithmic spiral and a practical Archimedean-style spiral that shrinks more gradually and covers the local neighborhood more evenly.
Mutation-Based WOA augments the standard WOA movement with DE-inspired mutation. In this project, the mutation
variant keeps the normal WOA candidate, optionally creates a mutation candidate with DE/rand/1, evaluates both,
and keeps the better one according to the optimization mode.
Levy Walk WOA modifies the exploration phase with Levy-flight-based random walks. In this project, the Levy variant uses Mantegna-style heavy-tailed steps during exploration while keeping standard WOA-like exploitation around the leader (the best solution found so far).
Gaussian Mutation WOA (GM-WOA) runs the standard WOA update unchanged, then applies a multiplicative
Gaussian mutation X' = X^A * (1 + G) (element-wise) with G ~ N(0, I) to every whale, where X^A is
the position produced by the base WOA step. The mutated candidate replaces the current position only if it
improves the fitness (greedy selection). Because the perturbation is proportional to |X^A_i|, coordinates
near zero are barely changed while coordinates far from the origin can move substantially. Implementation
follows Luo et al. (2019).
Opposition-Based WOA reuses the base WOA main loop unchanged and only modifies population initialization.
A random population of size N is generated, an opposite candidate x_opp = lb + ub - x is produced for
each whale, both sets are evaluated, and the best N individuals from the resulting pool of 2N candidates
form the starting population.
Single-Dimensional WOA replaces the classical encircling-prey step with the single-dimensional swimming
mechanism from Du et al. (2020). Instead of updating the full position vector, a single randomly
selected coordinate d is updated via X_d(t+1) = X*_d(t) - A * |C * X*_d(t) - X_d(t)|, while all
other coordinates stay unchanged. The exploration branch and the spiral branch are inherited from the
base WOA without modification.
Worst-Individual-Disturbance WOA disturbs the classical encircling step with information about the
worst individual in the population, following the individual-disturbance strategy from Qiao et al.
(2022). The encircling update X_new = X_best - A*D is replaced with
X_new = r_4 * X_best - A*D + (1 - r_4) * X_worst, where r_4 is drawn uniformly from [0, 1]
.This introduces information about the worst individual into the encircling update while retaining the best individual as a reference point.
The exploration branch and the spiral branch stay identical to the base WOA.
Exponential WOA replaces the standard linear schedule of the convergence coefficient a with a nonlinear schedule based on an exponential function. The remaining WOA movement mechanisms are unchanged.
Installation
Basic installation:
pip install .
Usage
Common usage pattern:
config = VariantData(...)
algorithm = Variant(config)
result = algorithm.run()
Top-level imports are available for all implemented variants:
from whalepy import (
AdaptiveWOA,
AdaptiveWOAData,
BoundaryConstraint,
CWOA,
CWOAData,
ExponentialDecayWOA,
ExponentialDecayWOAData,
FunctionLoader,
GaussianWOA,
GaussianWOAData,
LevyWalkWOA,
LevyWalkWOAData,
ModifiedSpiralWOA,
ModifiedSpiralWOAData,
MutationWOA,
MutationWOAData,
OppositionBasedWOA,
OppositionWOAData,
OptimizationType,
SingleDimensionalWOA,
SingleDimensionalWOAData,
WOA,
WOAData,
WorstIndividualDisturbanceWOA,
WorstIndividualDisturbanceWOAData,
run_algorithm,
)
Basic WOA example:
from whalepy import FunctionLoader, WOA, WOAData
loader = FunctionLoader()
config = WOAData(
population_size=25,
max_iter=80,
max_nfe=2200,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("sphere"),
seed=7,
)
algorithm = WOA(config)
result = algorithm.run()
print(result.best_fitness_value)
Stopping rule:
max_iteris the primary loop budgetmax_nfeis an additional evaluation cap- if both are provided, the algorithm stops when either limit is reached first
- most variants spend one evaluation per whale per iteration, but GM-WOA and Opposition-Based WOA
spend more, so they use up
max_nfefaster — see their notes below
Result:
result.best_whaleandresult.best_fitness_valuedescribe the best solution found during the whole run; this solution is also the leaderX*used in the position updatesresult.historycontains the best fitness value found so far after the initialization and after each iterationresult.worst_whale,result.mean_fitness_valueandresult.std_fitness_valuedescribe the final population
Function handling:
- use
FunctionLoader().load_callable("sphere")for built-in benchmarks - or pass a plain Python callable with
function=my_objective
Boundary handling:
- all variants accept
boundary_constraints_fun - built-in choices include
BoundaryConstraint.CLIP,BoundaryConstraint.REFLECT, andBoundaryConstraint.RANDOM_RESET
Adaptive WOA usage:
from whalepy import AdaptiveWOA, AdaptiveWOAData, FunctionLoader
loader = FunctionLoader()
config = AdaptiveWOAData(
population_size=25,
max_iter=80,
max_nfe=2200,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("ackley"),
seed=7,
a_strategy="cosine",
use_inertia_weight=True,
adaptive_probability=True,
p_start=0.5,
p_end=0.9,
)
result = AdaptiveWOA(config).run()
print(result.best_fitness_value)
Adaptive WOA notes:
a_strategy="cosine"uses a cosine decay for the convergence coefficienta_strategy="logarithmic"uses a logarithmic decay for the convergence coefficientuse_inertia_weight=Trueenables a growing weight on the best-whale attraction termadaptive_probability=Truegradually shifts more updates toward the spiral exploitation branch
Chaotic WOA usage:
from whalepy import CWOA, CWOAData, FunctionLoader
loader = FunctionLoader()
config = CWOAData(
population_size=25,
max_iter=100,
max_nfe=2600,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("ackley"),
seed=7,
chaotic_map="logistic",
chaotic_seed=0.37,
use_chaotic_initialization=True,
use_chaotic_probability=True,
use_chaotic_coefficients=True,
use_chaotic_spiral=True,
)
result = CWOA(config).run()
print(result.best_fitness_value)
Chaotic WOA notes:
chaotic_map="logistic"uses the logistic map withlogistic_a=4.0by defaultchaotic_map="tent"uses the tent map with the built-in0.7 / 1.4286schedulechaotic_map="sine"uses the sine map withsine_a=4.0by default- chaotic values can replace standard random draws for initialization,
r,p, andl use_chaotic_a=Trueoptionally modulates the base convergence coefficient with chaos
Mutation-Based WOA usage:
from whalepy import FunctionLoader, MutationWOA, MutationWOAData
loader = FunctionLoader()
config = MutationWOAData(
population_size=30,
max_iter=100,
max_nfe=3500,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("rastrigin"),
seed=7,
mutation_strategy="de_rand_1",
mutation_factor=0.6,
mutation_probability=0.35,
use_mutation_selection=True,
)
result = MutationWOA(config).run()
print(result.best_fitness_value)
Modified Spiral WOA usage:
from whalepy import FunctionLoader, ModifiedSpiralWOA, ModifiedSpiralWOAData
loader = FunctionLoader()
config = ModifiedSpiralWOAData(
population_size=30,
max_iter=120,
max_nfe=3800,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("ackley"),
seed=7,
spiral_mode="archimedean",
spiral_b=1.0,
spiral_step=0.25,
spiral_shrink_factor=0.75,
)
result = ModifiedSpiralWOA(config).run()
print(result.best_fitness_value)
Levy Walk WOA usage:
from whalepy import FunctionLoader, LevyWalkWOA, LevyWalkWOAData
loader = FunctionLoader()
config = LevyWalkWOAData(
population_size=30,
max_iter=120,
max_nfe=3800,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("ackley"),
seed=7,
levy_beta=1.5,
levy_scale=0.05,
use_levy_exploration=True,
levy_mode="exploration_only",
)
result = LevyWalkWOA(config).run()
print(result.best_fitness_value)
Levy Walk WOA notes:
levy_betacontrols the heaviness of the Levy taillevy_scalecontrols the overall exploration step sizeuse_levy_exploration=Trueenables Levy-flight exploration when|A| >= 1levy_mode="exploration_only"uses only the Levy move in the exploration branchlevy_mode="hybrid"blends a standard WOA exploration candidate with a Levy-flight perturbation
Gaussian WOA usage:
from whalepy import FunctionLoader, GaussianWOA, GaussianWOAData
loader = FunctionLoader()
config = GaussianWOAData(
population_size=30,
max_iter=120,
max_nfe=3800,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("ackley"),
seed=7,
)
result = GaussianWOA(config).run()
print(result.best_fitness_value)
Gaussian Mutation WOA (GM-WOA) notes:
- runs the standard WOA update on the whole population, producing positions
X^A - then applies a multiplicative Gaussian mutation
X' = X^A * (1 + G)(element-wise,G ~ N(0, I)) to every whale, following Luo et al. (2019) - the mutated candidate is accepted only if it improves the fitness (greedy selection); otherwise the
standard WOA position
X^Ais kept - the perturbation scale on coordinate
iis proportional to|X^A_i|, so points near the origin are perturbed only slightly and points far from it can move substantially - the base WOA operators (encircling, spiral update, random exploration) are unchanged; there are no
additional parameters beyond those inherited from
WOAData - one iteration costs two evaluations per whale (the WOA step plus the mutated candidate), so with the
settings above the run completes 62 full iterations and may enter a partial 63rd one before
reaching
max_nfe=3800 - to allow the same number of full iterations as the other variants, GM-WOA requires approximately twice the evaluation budget, since each iteration evaluates both the standard WOA candidate and the Gaussian-mutated candidate
Opposition-Based WOA usage:
from whalepy import FunctionLoader, OppositionBasedWOA, OppositionWOAData
loader = FunctionLoader()
config = OppositionWOAData(
population_size=30,
max_iter=120,
max_nfe=3800,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("ackley"),
seed=7,
use_obl_initialization=True,
)
result = OppositionBasedWOA(config).run()
print(result.best_fitness_value)
Opposition-Based WOA notes:
use_obl_initialization=True(default) generates an opposite candidatex_opp = lb + ub - xfor every random whale and keeps the best N individuals from the combined pool of 2N candidates as the starting populationuse_obl_initialization=Falsedisables the OBL step and makes the algorithm behave exactly like base WOA- the main loop is inherited from base WOA without modification
- initialization costs
2 * population_sizeevaluations instead ofpopulation_size, somax_nfemust be at least that large or the algorithm raises aValueError
Single-Dimensional WOA usage:
from whalepy import FunctionLoader, SingleDimensionalWOA, SingleDimensionalWOAData
loader = FunctionLoader()
config = SingleDimensionalWOAData(
population_size=30,
max_iter=120,
max_nfe=3800,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("ackley"),
seed=7,
)
result = SingleDimensionalWOA(config).run()
print(result.best_fitness_value)
Single-Dimensional WOA notes:
- implements only the single-dimensional swimming mechanism from Du et al. (2020, Symmetry 12(11), 1892)
- whenever the base WOA would run its encircling-prey update (
p < 0.5and|A| < 1), a single randomly selected coordinatedis updated viaX_d(t+1) = X*_d(t) - A * |C * X*_d(t) - X_d(t)| - all other coordinates keep their current values
- the exploration branch and the spiral update are identical to the base WOA
- there are no additional configuration parameters beyond those inherited from
WOAData
Worst-Individual-Disturbance WOA usage:
from whalepy import (
FunctionLoader,
WorstIndividualDisturbanceWOA,
WorstIndividualDisturbanceWOAData,
)
loader = FunctionLoader()
config = WorstIndividualDisturbanceWOAData(
population_size=30,
max_iter=120,
max_nfe=3800,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("ackley"),
seed=7,
)
result = WorstIndividualDisturbanceWOA(config).run()
print(result.best_fitness_value)
Worst-Individual-Disturbance WOA notes:
- implements the individual-disturbance strategy from Qiao et al. (2022), eq. 9
- the classical encircling formula
X_new = X_best - A*Dis replaced withX_new = r_4 * X_best - A*D + (1 - r_4) * X_worst, wherer_4is drawn uniformly from[0, 1] - only the individual-disturbance component is retained; the neighborhood mutation search proposed alongside it in the same paper is not applied
- the exploration branch and the spiral update are identical to the base WOA
- there are no additional configuration parameters beyond those inherited from
WOAData
Exponential Decay WOA usage:
from whalepy import ExponentialDecayWOA, ExponentialDecayWOAData, FunctionLoader
loader = FunctionLoader()
config = ExponentialDecayWOAData(
population_size=30,
max_iter=120,
max_nfe=3800,
dimension=5,
lb=[-5.0] * 5,
ub=[5.0] * 5,
function=loader.load_callable("ackley"),
seed=7,
a_initial=2.0,
a_final=0.0,
k=0.5,
)
result = ExponentialDecayWOA(config).run()
print(result.best_fitness_value)
Exponential Decay WOA notes:
- implements the nonlinear convergence coefficient from Sun et al. (2022, eq. 12):
a(t) = a_initial - (a_initial - a_final) * (exp(tau^k) - 1) / (e - 1) - if
Tdenotes the total number of scheduled iterations, thentau = t / (T - 1)fort = 0, ..., T - 1 - boundary conditions are exact:
a(0) == a_initialanda(T - 1) == a_final k > 0shapes the curve: smaller values makeadrop quickly early in the run, larger values keep it high for longer (at the halfway point,k=0.3givesa ≈ 0.54whilek=0.9givesa ≈ 1.18)- the useful range is problem-dependent, so
kis exposed as a configuration parameter - the example above uses
k=0.5for demonstration; the benchmark experiments run for this project usedk=0.7 - only the update rule for
ais taken from Sun et al.; the rest of the algorithm (encircling, spiral update, random exploration) is identical to the base WOA
Optional convenience helper:
from whalepy import WOA, WOAData, run_algorithm
result = run_algorithm(WOA, WOAData(...))
Benchmarking
The repository includes a simple benchmark runner for comparing all implemented variants on the same benchmark setup.
Run the full benchmark suite:
python benchmarks/benchmark_runner.py
Run a smaller smoke benchmark:
python benchmarks/benchmark_runner.py --smoke
Write per-run results to CSV:
python benchmarks/benchmark_runner.py --csv benchmarks/results/benchmark_results.csv
The benchmark runner compares:
- WOA
- AdaptiveWOA
- CWOA
- MutationWOA
- ModifiedSpiralWOA
- LevyWalkWOA
- GaussianWOA
- OppositionBasedWOA
- SingleDimensionalWOA
- WorstIndividualDisturbanceWOA
- ExponentialDecayWOA
The default registry includes these benchmark functions:
- Ackley
- Schwefel
- Griewank
- Michalewicz
- Rastrigin
- Rana
- EggHolder
- Rosenbrock
Reported metrics include:
- algorithm name
- function name
- dimension
- run count
- best fitness across runs
- mean best fitness across runs
- standard deviation of best fitness
- average runtime
- average completed epochs
- average function evaluations
Project Layout
benchmarks/
whalepy/
WOAAlgs/
models/
functions/
helpers/
examples/
doc/
Status
Implemented now:
- plain/basic WOA
- adaptive WOA with nonlinear
a, adaptive inertia weight, and optional adaptive spiral probability - chaotic WOA with logistic, tent, and sine maps plus optional chaotic initialization and parameter draws
- mutation-based WOA with DE/rand/1 candidate generation and fitness-based selection
- modified spiral WOA with configurable logarithmic and Archimedean-style exploitation spirals
- Levy walk WOA with Levy-flight exploration using Mantegna's algorithm
- Gaussian Mutation WOA (GM-WOA) that appends a multiplicative Gaussian perturbation
X^A * (1 + G)with greedy selection after each standard WOA update - opposition-based WOA that seeds the population with the best N individuals from N random whales and their opposite counterparts
- single-dimensional WOA that replaces the encircling-prey step with a single-coordinate update from Du et al. (2020)
- worst-individual-disturbance WOA that perturbs the encircling step with information from the worst individual, following Qiao et al. (2022)
- exponential decay WOA with an exponential decay schedule for the convergence coefficient
- built-in Ackley, Schwefel, Griewank, Michalewicz, Rastrigin, Rana, EggHolder, and Rosenbrock benchmark callables, with Sphere still available for compatibility
- WOA-specific
WhaleandPopulationmodels
References
- Mirjalili, S., Lewis, A., 2016. The Whale Optimization Algorithm. Advances in Engineering Software 95, 51–67. https://doi.org/10.1016/j.advengsoft.2016.01.008
- Trivedi, I.N., Pradeep, J., Narottam, J., Arvind, K., Dilip, L., 2016. Novel Adaptive Whale Optimization Algorithm for Global Optimization. Indian Journal of Science and Technology 9. https://doi.org/10.17485/ijst/2016/v9i38/101939
- Chen, H., Yang, C., Heidari, A.A., Zhao, X., 2020. An efficient double adaptive random spare reinforced whale optimization algorithm. Expert Systems with Applications 154, 113018. https://doi.org/10.1016/j.eswa.2019.113018
- Sun, G., Shang, Y., Yuan, K., Gao, H., 2022. An Improved Whale Optimization Algorithm Based on Nonlinear Parameters and Feedback Mechanism. Int J Comput Intell Syst 15. https://doi.org/10.1007/s44196-022-00092-7
- Kaur, G., Arora, S., 2018. Chaotic whale optimization algorithm. Journal of Computational Design and Engineering 5, 275–284. https://doi.org/10.1016/j.jcde.2017.12.006
- Mostafa Bozorgi, S., Yazdani, S., 2019. IWOA: An improved whale optimization algorithm for optimization problems. Journal of Computational Design and Engineering 6, 243–259. https://doi.org/10.1016/j.jcde.2019.02.002
- Sun, W., Wang, J., Wei, X., 2018. An Improved Whale Optimization Algorithm Based on Different Searching Paths and Perceptual Disturbance. Symmetry 10, 210. https://doi.org/10.3390/sym10060210
- Ling, Y., Zhou, Y., Luo, Q., 2017. Lévy Flight Trajectory-Based Whale Optimization Algorithm for Global Optimization. IEEE Access 5, 6168–6186. https://doi.org/10.1109/access.2017.2695498
- Luo, J., Chen, H., Heidari, A.A., Xu, Y., Zhang, Q., Li, C., 2019. Multi-strategy boosted mutative whale-inspired optimization approaches. Applied Mathematical Modelling 73, 109–123. https://doi.org/10.1016/j.apm.2019.03.046
- Alamri, H.S., Alsariera, Y.A., Zamli, K.Z., 2018. Opposition-Based Whale Optimization Algorithm. adv sci lett 24, 7461–7464. https://doi.org/10.1166/asl.2018.12959
- Du, P., Cheng, W., Liu, N., Zhang, H., Lu, J., 2020. A Modified Whale Optimization Algorithm with Single-Dimensional Swimming for Global Optimization Problems. Symmetry 12, 1892. https://doi.org/10.3390/sym12111892
- Qiao, S., Yu, H., Heidari, A.A., El-Saleh, A.A., Cai, Z., Xu, X., Mafarja, M., Chen, H., 2022. Individual disturbance and neighborhood mutation search enhanced whale optimization: performance design for engineering problems. Journal of Computational Design and Engineering 9, 1817–1851. https://doi.org/10.1093/jcde/qwac081
Metadata
Release files for whalepy 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| whalepy-1.0.0.tar.gz | 47.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| whalepy-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 100.3 kB
Release files / whalepy-1.0.0.tar.gz
| Download URL | whalepy-1.0.0.tar.gz |
|---|---|
| Size | 47.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6e81521ff965f73f3d5d54c4414b703a38ad4c281efde0af06d2aa787092f5ef
|
|
BLAKE2b-256 checksum How to use checksums |
1789eaf025e01369d3575e3466b749f3d0cf1c7d282f7d0d46cd847003bac22f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / whalepy-1.0.0-py3-none-any.whl
| Download URL | whalepy-1.0.0-py3-none-any.whl |
|---|---|
| Size | 52.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
51e5b42e83886cce0e2c843cff0eca3b24fcbc0b9c67d3edf52015b007bc2552
|
|
BLAKE2b-256 checksum How to use checksums |
7a284a6fc9336f0274cce45aaa568721cb4d0f575524448ba7b938dcaf6c044b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|