Introduction
MEALPY is the largest python library in the world for most of the cutting-edge meta-heuristic algorithms (nature-inspired algorithms, black-box optimization, global search optimizers, iterative learning algorithms, continuous optimization, derivative free optimization, gradient free optimization, zeroth order optimization, stochastic search optimization, random search optimization). These algorithms belong to population-based algorithms (PMA), which are the most popular algorithms in the field of approximate optimization.
- Free software: GNU General Public License (GPL) V3 license
- Total algorithms: 215 (190 official (original, hybrid, variants), 25 developed)
- Documentation: https://mealpy.readthedocs.io/en/latest/
- Python versions: >=3.7x
- Dependencies: numpy, scipy, pandas, matplotlib
Citation Request
Please include these citations if you plan to use this library:
@article{van2023mealpy,
title={MEALPY: An open-source library for latest meta-heuristic algorithms in Python},
author={Van Thieu, Nguyen and Mirjalili, Seyedali},
journal={Journal of Systems Architecture},
year={2023},
publisher={Elsevier},
doi={10.1016/j.sysarc.2023.102871}
}
@article{van2023groundwater,
title={Groundwater level modeling using Augmented Artificial Ecosystem Optimization},
author={Van Thieu, Nguyen and Barma, Surajit Deb and Van Lam, To and Kisi, Ozgur and Mahesha, Amai},
journal={Journal of Hydrology},
volume={617},
pages={129034},
year={2023},
publisher={Elsevier},
doi={https://doi.org/10.1016/j.jhydrol.2022.129034}
}
@article{ahmed2021comprehensive,
title={A comprehensive comparison of recent developed meta-heuristic algorithms for streamflow time series forecasting problem},
author={Ahmed, Ali Najah and Van Lam, To and Hung, Nguyen Duy and Van Thieu, Nguyen and Kisi, Ozgur and El-Shafie, Ahmed},
journal={Applied Soft Computing},
volume={105},
pages={107282},
year={2021},
publisher={Elsevier},
doi={10.1016/j.asoc.2021.107282}
}
Usage
Goals
Our goals are to implement all classical as well as the state-of-the-art nature-inspired algorithms, create a simple interface that helps researchers access optimization algorithms as quickly as possible, and share knowledge of the optimization field with everyone without a fee. What you can do with mealpy:
- Analyse parameters of meta-heuristic algorithms.
- Perform Qualitative and Quantitative Analysis of algorithms.
- Analyse rate of convergence of algorithms.
- Test and Analyse the scalability and the robustness of algorithms.
- Save results in various formats (csv, json, pickle, png, pdf, jpeg)
- Export and import models can also be done with Mealpy.
- Solve any optimization problem
Installation
- Install the stable (latest) version from PyPI release:
$ pip install mealpy==3.0.1
- Install the alpha/beta version from PyPi
$ pip install mealpy==2.5.4a6
- Install the pre-release version directly from the source code:
$ git clone https://github.com/thieu1995/mealpy.git
$ cd mealpy
$ python setup.py install
- In case, you want to install the development version from Github:
$ pip install git+https://github.com/thieu1995/permetrics
After installation, you can import Mealpy as any other Python module:
$ python
>>> import mealpy
>>> mealpy.__version__
>>> print(mealpy.get_all_optimizers())
>>> model = mealpy.get_optimizer_by_name("OriginalWOA")(epoch=100, pop_size=50)
Examples
Before dive into some examples, let me ask you a question. What type of problem are you trying to solve? Additionally, what would be the solution for your specific problem? Based on the table below, you can select an appropriate type of decision variables to use.
Class | Syntax | Problem Types |
---|---|---|
FloatVar | FloatVar(lb=(-10., )*7, ub=(10., )*7, name="delta") | Continuous Problem |
IntegerVar | IntegerVar(lb=(-10., )*7, ub=(10., )*7, name="delta") | LP, IP, NLP, QP, MIP |
StringVar | StringVar(valid_sets=(("auto", "backward", "forward"), ("leaf", "branch", "root")), name="delta") | ML, AI-optimize |
BinaryVar | BinaryVar(n_vars=11, name="delta") | Networks |
BoolVar | BoolVar(n_vars=11, name="delta") | ML, AI-optimize |
PermutationVar | PermutationVar(valid_set=(-10, -4, 10, 6, -2), name="delta") | Combinatorial Optimization |
MixedSetVar | MixedSetVar(valid_sets=(("auto", 2, 3, "backward", True), (0, "tournament", "round-robin")), name="delta") | MIP, MILP |
TransferBoolVar | TransferBoolVar(n_vars=11, name="delta", tf_func="sstf_02") | ML, AI-optimize, Feature |
TransferBinaryVar | TransferBinaryVar(n_vars=11, name="delta", tf_func="vstf_04") | Networks, Feature Selection |
Let's go through a basic and advanced example.
Simple Benchmark Function
Using Problem dict
from mealpy import FloatVar, SMA
import numpy as np
def objective_function(solution):
return np.sum(solution**2)
problem = {
"obj_func": objective_function,
"bounds": FloatVar(lb=(-100., )*30, ub=(100., )*30),
"minmax": "min",
"log_to": None,
}
## Run the algorithm
model = SMA.OriginalSMA(epoch=100, pop_size=50, pr=0.03)
g_best = model.solve(problem)
print(f"Best solution: {g_best.solution}, Best fitness: {g_best.target.fitness}")
Define a custom Problem class
Please note that, there is no more generate_position
, amend_solution
, and fitness_function
in Problem class.
We take care everything under the DataType Class above. Just choose which one fit for your problem.
We recommend you define a custom class that inherit Problem
class if your decision variable is not FloatVar
from mealpy import Problem, FloatVar, BBO
import numpy as np
# Our custom problem class
class Squared(Problem):
def __init__(self, bounds=None, minmax="min", data=None, **kwargs):
self.data = data
super().__init__(bounds, minmax, **kwargs)
def obj_func(self, solution):
x = self.decode_solution(solution)["my_var"]
return np.sum(x ** 2)
## Now, we define an algorithm, and pass an instance of our *Squared* class as the problem argument.
bound = FloatVar(lb=(-10., )*20, ub=(10., )*20, name="my_var")
problem = Squared(bounds=bound, minmax="min", name="Squared", data="Amazing")
model = BBO.OriginalBBO(epoch=100, pop_size=20)
g_best = model.solve(problem)
Set Seed for Optimizer (So many people asking for this feature)
You can set random seed number for each run of single optimizer.
model = SMA.OriginalSMA(epoch=100, pop_size=50, pr=0.03)
g_best = model.solve(problem=problem, seed=10) # Default seed=None
Large-Scale Optimization
from mealpy import FloatVar, SHADE
import numpy as np
def objective_function(solution):
return np.sum(solution**2)
problem = {
"obj_func": objective_function,
"bounds": FloatVar(lb=(-1000., )*10000, ub=(1000.,)*10000), # 10000 dimensions
"minmax": "min",
"log_to": "console",
}
## Run the algorithm
optimizer = SHADE.OriginalSHADE(epoch=10000, pop_size=100)
g_best = optimizer.solve(problem)
print(f"Best solution: {g_best.solution}, Best fitness: {g_best.target.fitness}")
Distributed Optimization / Parallelization Optimization
Please read the article titled MEALPY: An open-source library for latest meta-heuristic algorithms in Python to gain a clear understanding of the concept of parallelization (distributed optimization) in metaheuristics. Not all metaheuristics can be run in parallel.
from mealpy import FloatVar, SMA
import numpy as np
def objective_function(solution):
return np.sum(solution**2)
problem = {
"obj_func": objective_function,
"bounds": FloatVar(lb=(-100., )*100, ub=(100., )*100),
"minmax": "min",
"log_to": "console",
}
## Run distributed SMA algorithm using 10 threads
optimizer = SMA.OriginalSMA(epoch=10000, pop_size=100, pr=0.03)
optimizer.solve(problem, mode="thread", n_workers=10) # Distributed to 10 threads
print(f"Best solution: {optimizer.g_best.solution}, Best fitness: {optimizer.g_best.target.fitness}")
## Run distributed SMA algorithm using 8 CPUs (cores)
optimizer.solve(problem, mode="process", n_workers=8) # Distributed to 8 cores
print(f"Best solution: {optimizer.g_best.solution}, Best fitness: {optimizer.g_best.target.fitness}")
The Benefit Of Using Custom Problem Class (BEST PRACTICE)
Optimize Machine Learning model
In this example, we use SMA optimize to optimize the hyper-parameters of SVC model.
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn import datasets, metrics
from mealpy import FloatVar, StringVar, IntegerVar, BoolVar, MixedSetVar, SMA, Problem
# Load the data set; In this example, the breast cancer dataset is loaded.
X, y = datasets.load_breast_cancer(return_X_y=True)
# Create training and test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1, stratify=y)
sc = StandardScaler()
X_train_std = sc.fit_transform(X_train)
X_test_std = sc.transform(X_test)
data = {
"X_train": X_train_std,
"X_test": X_test_std,
"y_train": y_train,
"y_test": y_test
}
class SvmOptimizedProblem(Problem):
def __init__(self, bounds=None, minmax="max", data=None, **kwargs):
self.data = data
super().__init__(bounds, minmax, **kwargs)
def obj_func(self, x):
x_decoded = self.decode_solution(x)
C_paras, kernel_paras = x_decoded["C_paras"], x_decoded["kernel_paras"]
degree, gamma, probability = x_decoded["degree_paras"], x_decoded["gamma_paras"], x_decoded["probability_paras"]
svc = SVC(C=C_paras, kernel=kernel_paras, degree=degree,
gamma=gamma, probability=probability, random_state=1)
# Fit the model
svc.fit(self.data["X_train"], self.data["y_train"])
# Make the predictions
y_predict = svc.predict(self.data["X_test"])
# Measure the performance
return metrics.accuracy_score(self.data["y_test"], y_predict)
my_bounds = [
FloatVar(lb=0.01, ub=1000., name="C_paras"),
StringVar(valid_sets=('linear', 'poly', 'rbf', 'sigmoid'), name="kernel_paras"),
IntegerVar(lb=1, ub=5, name="degree_paras"),
MixedSetVar(valid_sets=('scale', 'auto', 0.01, 0.05, 0.1, 0.5, 1.0), name="gamma_paras"),
BoolVar(n_vars=1, name="probability_paras"),
]
problem = SvmOptimizedProblem(bounds=my_bounds, minmax="max", data=data)
model = SMA.OriginalSMA(epoch=100, pop_size=20)
model.solve(problem)
print(f"Best agent: {model.g_best}")
print(f"Best solution: {model.g_best.solution}")
print(f"Best accuracy: {model.g_best.target.fitness}")
print(f"Best parameters: {model.problem.decode_solution(model.g_best.solution)}")
Solving Combinatorial Problems
Traveling Salesman Problem (TSP)
In the context of the Mealpy for the Traveling Salesman Problem (TSP), a solution is a possible route that represents a tour of visiting all the cities exactly once and returning to the starting city. The solution is typically represented as a permutation of the cities, where each city appears exactly once in the permutation.
For example, let's consider a TSP instance with 5 cities labeled as A, B, C, D, and E. A possible solution could be
represented as the permutation [A, B, D, E, C]
, which indicates the order in which the cities are visited. This
solution suggests that the tour starts at city A, then moves to city B, then D, E, and finally C before returning to city A.
import numpy as np
from mealpy import PermutationVar, WOA, Problem
# Define the positions of the cities
city_positions = np.array([[60, 200], [180, 200], [80, 180], [140, 180], [20, 160],
[100, 160], [200, 160], [140, 140], [40, 120], [100, 120],
[180, 100], [60, 80], [120, 80], [180, 60], [20, 40],
[100, 40], [200, 40], [20, 20], [60, 20], [160, 20]])
num_cities = len(city_positions)
data = {
"city_positions": city_positions,
"num_cities": num_cities,
}
class