Guide to use model

In this phase, the main task is to find out the global optimal - in this project, we call it named model for simple. We designed the classical as well as the state-of-the-art population-based meta-heuristics models: Evolutionary-based, Swarm-based, Physics-based, Human-based, Biology-based, Mathematical-based, Musical-based

All of this methods are used in the same way. So, in this guide, we’ll demo with a specific method such as Genetic Algorithm in Evolutionary-based.

Installation

Dependencies

To use the library, your computer must installed all of these packages first:

  • Python (>= 3.6)

  • Numpy (>= 1.15.1)

  • Matplotlib (>=3.1.3)

  • Scipy (>= 1.5.2)

User Installation

$ pip uninstall mealpy
$ pip install mealpy==2.3.0
  • Or install the development version from GitHub:

$ pip install git+https://github.com/thieu1995/mealpy

I accidentally deleted version 2.1.1 on Pypi since it’s not synced with version 2.1.1 on Github Release. If you still want to use version 2.1.1. Please use this command:

$ pip install -e git+https://github.com/thieu1995/mealpy@ead414d2d9aa5317864e779fa5d4ad7b65159181#egg=mealpy

Getting started in 30s

Tutorial
  • Import libraries

  • Define your fitness function

  • Define a problem dictionary

  • Training and get the results

from mealpy.evolutionary_based import GA
import numpy as np

def fitness_func(solution):
    return np.sum(solution**2)

problem_dict = {
    "fit_func": fitness_func,
    "lb": [-100, ] * 30,
    "ub": [100, ] * 30,
    "minmax": "min",
    "verbose": True,
}

ga_model = GA.BaseGA(problem_dict, epoch=100, pop_size=50, pc=0.85, pm=0.1)
best_position, best_fitness_value = ga_model.solve()

print(best_position)
print(best_fitness_value)

You can see the error after each iteration which is found by GA:

Fitness Function Preparation

Make sure that your designed Fitness Function take an solution (a numpy vector) and return the fitness value (single real value or list of real value)

We have already included the library opfunu which is a framework of benchmark functions for optimization problems. You can use it in the very easy way by:

from opfunu.type_based.uni_modal import Functions           # or
from opfunu.cec.cec2014 import Fucntion                     # or
from opfunu.dimension_based.benchmarknd import Functions

# Then you need to create an object of Function to get the functions
type_based = Functions()
F1 = type_based._sum_squres__
F2 = type_based.__dixon_price__
....

But if you don’t want to use it, you want to design your own fitness functions. It is ok, all you need to do is write your own function with input is a numpy vector (the solution) and output is the single objective value or list of multiple objective values.

import numpy as np

## This is normal fitness function
def fitness_normal(solution=None):
        return np.sqrt(solution**2)         # Single value


## This is how you design multi-objective function
#### Link: https://en.wikipedia.org/wiki/Test_functions_for_optimization
def fitness_multi(solution):
    def booth(x, y):
        return (x + 2*y - 7)**2 + (2*x + y - 5)**2
    def bukin(x, y):
        return 100 * np.sqrt(np.abs(y - 0.01 * x**2)) + 0.01 * np.abs(x + 10)
    def matyas(x, y):
        return 0.26 * (x**2 + y**2) - 0.48 * x * y
    return [booth(solution[0], solution[1]), bukin(solution[0], solution[1]), matyas(solution[0], solution[1])]


## This is how you design Constrained Benchmark Function (G01)
#### Link: https://onlinelibrary.wiley.com/doi/pdf/10.1002/9781119136507.app2
def fitness_constrained(solution):
        def g1(x):
        return 2 * x[0] + 2 * x[1] + x[9] + x[10] - 10
    def g2(x):
        return 2 * x[0] + 2 * x[2] + x[9] + x[10] - 10
    def g3(x):
        return 2 * x[1] + 2 * x[2] + x[10] + x[11] - 10
    def g4(x):
        return -8 * x[0] + x[9]
    def g5(x):
        return -8 * x[1] + x[10]
    def g6(x):
        return -8 * x[2] + x[11]
    def g7(x):
        return -2 * x[3] - x[4] + x[9]
    def g8(x):
        return -2 * x[5] - x[6] + x[10]
    def g9(x):
        return -2 * x[7] - x[8] + x[11]

    def violate(value):
        return 0 if value <= 0 else value

    fx = 5 * np.sum(solution[:4]) - 5 * np.sum(solution[:4] ** 2) - np.sum(solution[4:13])

    ## Increase the punishment for g1 and g4 to boost the algorithm (You can choice any constraint instead of g1 and g4)
    fx += violate(g1(solution)) ** 2 + violate(g2(solution)) + violate(g3(solution)) + \
        2 * violate(g4(solution)) + violate(g5(solution)) + violate(g6(solution)) + \
        violate(g7(solution)) + violate(g8(solution)) + violate(g9(solution))
    return fx

Problem Preparation

You will need to define a problem dictionary with must has keywords (“fit_func”, “lb”, “ub”, “minmax”, “verbose”). For special case, when you are trying to solve multiple objective functions, you need another keyword “obj_weight”:

  • fit_func: Your fitness function

  • lb: Lower bound of variables, it should be list of values

  • ub: Upper bound of variables, it should be list of values

  • minmax: The problem you are trying to solve is minimum or maximum, value can be “min” or “max”

  • verbose: Print the training process, value can be True or False

  • obj_weight: list weights for all your objectives (Optional, default = [1, 1, …1])

## Design a problem dictionary for normal function
problem_normal = {
    "fit_func": fitness_normal,
    "lb": [-100, ] * 30,
    "ub": [100, ] * 30,
    "minmax": "min",
    "verbose": True,
}

## Design a problem dictionary for multiple objective functions above
problem_multi = {
    "fit_func": fitness_multi,
    "lb": [-10, -10],
    "ub": [10, 10],
    "minmax": "min",
    "verbose": True,
    "obj_weight": [0.4, 0.1, 0.5]               # Define it or default value will be [1, 1, 1]
}

## Design a problem dictionary for constrained objective function above
problem_constrained = {
  "fit_func": fitness_constrained,
  "lb": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  "ub": [1, 1, 1, 1, 1, 1, 1, 1, 1, 100, 100, 100, 1],
  "minmax": "min",
  "verbose": True,
}

Training

Start learning by call function solve(). There are 3 different training modes include:

  • sequential: Using single core to run (default for all algorithm)

  • thread: Create multiple threading depend on your chip and OS

  • process: Create multiple cores to run your algorithm.

## Need to import the algorithm that will be used
from mealpy.bio_based import SMA
from mealpy.evolutionary_based import GA
from mealpy.swarm_based import PSO

sma_model = SMA.BaseSMA(problem_normal, epoch=100, pop_size=50, pr=0.03)
best_position, best_fitness_value = sma_model.solve()

ga_model = GA.BaseGA(problem_multi, epoch=1000, pop_size=100, pc=0.9, pm=0.05)
best_position, best_fitness_value = ga_model.solve(mode="thread")

pso_model = PSO.BasePSO(problem_constrained, epoch=500, pop_size=80, c1=2.0, c2=1.8, w_min=0.3, w_max=0.8)
best_position, best_fitness_value = pso_model.solve(mode="process")

The returned results are 2 values :

  • best_position: the global best position it found on training process

  • best_fitness_value: the global best fitness value

Advances

Lower/Upper Bound

There are a few ways to set up the lower bound (LB) and upper bound (UB). It is also depend on the values of LB and UB

1. When you have different lower bound and upper bound for each parameters

problem_dict1 = {
   "fit_func": F5,
   "lb": [-3, -5, 1, -10, ],
   "ub": [5, 10, 100, 30, ],
   "minmax": "min",
   "verbose": True,
}

2. When you have same lower bound and upper bound for each variable, then you can use:

## 2.1 number: then you need to specify your problem size / number of dimensions (n_dims)
problem_dict2 = {
   "fit_func": F5,
   "lb": -10,
   "ub": 30,
   "minmax": "min",
   "verbose": True,
   "n_dims": 30,  # Remember the keyword "n_dims"
}

## 2.2 array: Then there are 2 ways
problem_dict3 = {
   "fit_func": F5,
   "lb": [-5],
   "ub": [10],
   "minmax": "min",
   "verbose": True,
   "n_dims": 30,  # Remember the keyword "n_dims"
}

## or
n_dims = 100
problem_dict4 = {
   "fit_func": F5,
   "lb": [-5] * n_dims,
   "ub": [10] * n_dims,
   "minmax": "min",
   "verbose": True,
}

Stopping Condition (Termination)

By default, when create an optimizer, the default stopping condition (termination) is epochs (generations, iterations) But there are different stopping condition you can try by creating an Termination dictionary. There are 4 termination cases:

1. FE (Number of Function Evaluation)

term_dict1 = {
   "mode": "FE",
   "quantity": 100000    # 100000 number of function evaluation
}

2. MG (Maximum Generations / Epochs): This is default in all algorithms

term_dict2 = {  # When creating this object, it will override the default epoch you define in your model
   "mode": "MG",
   "quantity": 1000  # 1000 epochs
}

3. ES (Early Stopping): Same idea in training neural network (If the global best solution not better an epsilon after K epoch then stop the program

term_dict3 = {
   "mode": "ES",
   "quantity": 30  # after 30 epochs, if the global best doesn't improve then we stop the program
}

4. TB (Time Bound): You just want your algorithm run in K seconds. Especially when comparing different algorithms

term_dict4 = {
   "mode": "ES",
   "quantity": 60  # 60 seconds = 1 minute to run this algorithm only
}

After import and create a termination object, you need to pass it to your optimizer as a additional parameter with the keyword “termination”

model3 = SMA.BaseSMA(problem_dict1, epoch=100, pop_size=50, pr=0.03, termination=term_dict4)
model3.solve()

Import All Models

from mealpy.bio_based import BBO, EOA, IWO, SBO, SMA, TPO, VCS, WHO
from mealpy.evolutionary_based import CRO, DE, EP, ES, FPA, GA, MA
from mealpy.human_based import BRO, BSO, CA, CHIO, FBIO, GSKA, ICA, LCO, QSA, SARO, SSDO, TLO
from mealpy.math_based import AOA, CGO, GBO, HC, SCA
from mealpy.music_based import HS
from mealpy.physics_based import ArchOA, ASO, EFO, EO, HGSO, MVO, NRO, SA, TWO, WDO
from mealpy.probabilistic_based import CEM
from mealpy.system_based import AEO, GCO, WCA
from mealpy.swarm_based import ABC, ACOR, ALO, AO, BA, BeesA, BES, BFO, BSA, COA, CSA, CSO, DO, EHO, FA, FFA, FOA, GOA, GWO, HGS
from mealpy.swarm_based import HHO, JA, MFO, MRFO, MSA, NMRA, PFA, PSO, SFO, SHO, SLO, SRSR, SSA, SSO, SSpiderA, SSpiderO, WOA

problem = {
    "fit_func": fitness_function,
    "lb": LB,
    "ub": UB,
    "minmax": "min",
    "verbose": True,
}

model = BBO.OriginalBBO(problem, epoch=10, pop_size=50)
# model = BBO.BaseBBO(problem, epoch=10, pop_size=50)
# model = EOA.BaseEOA(problem, epoch=10, pop_size=50)
# model = IWO.OriginalIWO(problem, epoch=10, pop_size=50)
# model = SBO.BaseSBO(problem, epoch=10, pop_size=50)
# model = SBO.OriginalSBO(problem, epoch=10, pop_size=50)
# model = SMA.OriginalSMA(problem, epoch=10, pop_size=50)
# model = SMA.BaseSMA(problem, epoch=10, pop_size=50)
# model = VCS.OriginalVCS(problem, epoch=100, pop_size=50)
# model = VCS.BaseVCS(problem, epoch=10, pop_size=50)
# model = WHO.BaseWHO(problem, epoch=10, pop_size=50)

# model = CRO.BaseCRO(problem, epoch=10, pop_size=50)
# model = CRO.OCRO(problem, epoch=10, pop_size=50)
# model = DE.BaseDE(problem, epoch=10, pop_size=50)
# model = DE.JADE(problem, epoch=10, pop_size=50)
# model = DE.SADE(problem, epoch=10, pop_size=50)
# model = DE.SHADE(problem, epoch=10, pop_size=50)
# model = DE.L_SHADE(problem, epoch=10, pop_size=50)
# model = DE.SAP_DE(problem, epoch=10, pop_size=50)
# model = EP.BaseEP(problem, epoch=10, pop_size=50)
# model = EP.LevyEP(problem, epoch=10, pop_size=50)
# model = ES.BaseES(problem, epoch=10, pop_size=50)
# model = ES.LevyES(problem, epoch=10, pop_size=50)
# model = FPA.BaseFPA(problem, epoch=10, pop_size=50)
# model = GA.BaseGA(problem, epoch=10, pop_size=50)
# model = MA.BaseMA(problem, epoch=10, pop_size=50)

# model = BRO.OriginalBRO(problem, epoch=10, pop_size=50)
# model = BRO.BaseBRO(problem, epoch=10, pop_size=50, pr=0.03)
# model = BSO.BaseBSO(problem, epoch=10, pop_size=50)
# model = BSO.ImprovedBSO(problem, epoch=10, pop_size=50)
# model = CA.OriginalCA(problem, epoch=10, pop_size=50)
# model = CHIO.BaseCHIO(problem, epoch=10, pop_size=50)
# model = CHIO.OriginalCHIO(problem, epoch=10, pop_size=50, pr=0.03)
# model = GSKA.BaseGSKA(problem, epoch=10, pop_size=50)
# model = GSKA.OriginalGSKA(problem, epoch=10, pop_size=50)
# model = FBIO.OriginalFBIO(problem, epoch=10, pop_size=50)
# model = FBIO.BaseFBIO(problem, epoch=10, pop_size=50)
# model = ICA.BaseICA(problem, epoch=10, pop_size=50)
# model = LCO.BaseLCO(problem, epoch=10, pop_size=50)
# model = LCO.ImprovedLCO(problem, epoch=10, pop_size=50, pr=0.03)
# model = LCO.OriginalLCO(problem, epoch=10, pop_size=50)
# model = QSA.BaseQSA(problem, epoch=10, pop_size=50)
# model = QSA.OppoQSA(problem, epoch=10, pop_size=50)
# model = QSA.LevyQSA(problem, epoch=10, pop_size=50)
# model = QSA.ImprovedQSA(problem, epoch=10, pop_size=50, pr=0.03)
# model = QSA.OriginalQSA(problem, epoch=10, pop_size=50)
# model = SARO.BaseSARO(problem, epoch=10, pop_size=50)
# model = SARO.OriginalSARO(problem, epoch=10, pop_size=50)
# model = SSDO.BaseSSDO(problem, epoch=10, pop_size=50)
# model = TLO.BaseTLO(problem, epoch=10, pop_size=50)
# model = TLO.OriginalTLO(problem, epoch=10, pop_size=50)
# model = TLO.ITLO(problem, epoch=10, pop_size=50)

# model = AOA.OriginalAOA(problem, epoch=10, pop_size=50)
# model = CGO.OriginalCGO(problem, epoch=100, pop_size=50)
# model = GBO.OriginalGBO(problem, epoch=10, pop_size=50, pr=0.03)
# model = HC.OriginalHC(problem, epoch=10, pop_size=50)
# model = HC.BaseHC(problem, epoch=10, pop_size=50)
# model = SCA.OriginalSCA(problem, epoch=10, pop_size=50)
# model = SCA.BaseSCA(problem, epoch=10, pop_size=50)

# model = HS.OriginalHS(problem, epoch=10, pop_size=50)
# model = HS.BaseHS(problem, epoch=10, pop_size=50)

# model = ArchOA.OriginalArchOA(problem, epoch=10, pop_size=50)
# model = ASO.BaseASO(problem, epoch=10, pop_size=50)
# model = EFO.OriginalEFO(problem, epoch=10, pop_size=50)
# model = EFO.BaseEFO(problem, epoch=10, pop_size=50)
# model = EO.BaseEO(problem, epoch=10, pop_size=50)
# model = EO.ModifiedEO(problem, epoch=10, pop_size=50)
# model = EO.AdaptiveEO(problem, epoch=10, pop_size=50)
# model = HGSO.BaseHGSO(problem, epoch=10, pop_size=50)
# model = MVO.OriginalMVO(problem, epoch=10, pop_size=50)
# model = MVO.BaseMVO(problem, epoch=10, pop_size=50)
# model = NRO.BaseNRO(problem, epoch=10, pop_size=50)
# model = SA.BaseSA(problem, epoch=10, pop_size=50)
# model = TWO.BaseTWO(problem, epoch=10, pop_size=50)
# model = TWO.OppoTWO(problem, epoch=10, pop_size=50)
# model = TWO.LevyTWO(problem, epoch=10, pop_size=50)
# model = TWO.EnhancedTWO(problem, epoch=10, pop_size=50)
# model = WDO.BaseWDO(problem, epoch=10, pop_size=50)

# model = CEM.BaseCEM(problem, epoch=10, pop_size=50)

# model = AEO.OriginalAEO(problem, epoch=10, pop_size=50)
# model = AEO.ModifiedAEO(problem, epoch=10, pop_size=50)
# model = AEO.AdaptiveAEO(problem, epoch=10, pop_size=50)
# model = AEO.EnhancedAEO(problem, epoch=10, pop_size=50)
# model = AEO.IAEO(problem, epoch=10, pop_size=50)
# model = GCO.OriginalGCO(problem, epoch=10, pop_size=50)
# model = GCO.BaseGCO(problem, epoch=10, pop_size=50)
# model = WCA.BaseWCA(problem, epoch=10, pop_size=50)

# model = ABC.BaseABC(problem, epoch=10, pop_size=50)
# model = ACOR.BaseACOR(problem, epoch=10, pop_size=50)
# model = ALO.OriginalALO(problem, epoch=10, pop_size=50)
# model = ALO.BaseALO(problem, epoch=10, pop_size=50)
# model = AO.OriginalAO(problem, epoch=10, pop_size=50)
# model = BA.BaseBA(problem, epoch=10, pop_size=50)
# model = BA.OriginalBA(problem, epoch=10, pop_size=50)
# model = BA.ModifiedBA(problem, epoch=10, pop_size=50)
# model = BeesA.BaseBeesA(problem, epoch=10, pop_size=50)
# model = BeesA.ProbBeesA(problem, epoch=10, pop_size=50)
# model = BES.BaseBES(problem, epoch=10, pop_size=50)
# model = BFO.OriginalBFO(problem, epoch=10, pop_size=50)
# model = BFO.ABFO(problem, epoch=10, pop_size=50)
# model = BSA.BaseBSA(problem, epoch=10, pop_size=50)
# model = COA.BaseCOA(problem, epoch=10, pop_size=50)
# model = CSA.BaseCSA(problem, epoch=10, pop_size=50)
# model = CSO.BaseCSO(problem, epoch=10, pop_size=50)
# model = DO.BaseDO(problem, epoch=10, pop_size=50)
# model = EHO.BaseEHO(problem, epoch=10, pop_size=50)
# model = FA.BaseFA(problem, epoch=10, pop_size=50)
# model = FFA.BaseFFA(problem, epoch=10, pop_size=50)
# model = FOA.OriginalFOA(problem, epoch=10, pop_size=50)
# model = FOA.BaseFOA(problem, epoch=10, pop_size=50)
# model = FOA.WhaleFOA(problem, epoch=10, pop_size=50)
# model = GOA.BaseGOA(problem, epoch=10, pop_size=50)
# model = GWO.BaseGWO(problem, epoch=10, pop_size=50)
# model = GWO.RW_GWO(problem, epoch=10, pop_size=50)
# model = HGS.OriginalHGS(problem, epoch=10, pop_size=50)
# model = HHO.BaseHHO(problem, epoch=10, pop_size=50)
# model = JA.OriginalJA(problem, epoch=10, pop_size=50)
# model = JA.BaseJA(problem, epoch=10, pop_size=50)
# model = JA.LevyJA(problem, epoch=10, pop_size=50)
# model = MFO.OriginalMFO(problem, epoch=10, pop_size=50)
# model = MFO.BaseMFO(problem, epoch=10, pop_size=50)
# model = MRFO.BaseMRFO(problem, epoch=10, pop_size=50)
# model = MSA.BaseMSA(problem, epoch=10, pop_size=50)
# model = NMRA.BaseNMRA(problem, epoch=10, pop_size=50)
# model = NMRA.ImprovedNMRA(problem, epoch=10, pop_size=50)
# model = PFA.BasePFA(problem, epoch=10, pop_size=50)
# model = PSO.BasePSO(problem, epoch=10, pop_size=50)
# model = PSO.C_PSO(problem, epoch=10, pop_size=50)
# model = PSO.CL_PSO(problem, epoch=10, pop_size=50)
# model = PSO.PPSO(problem, epoch=10, pop_size=50)
# model = PSO.HPSO_TVAC(problem, epoch=10, pop_size=50)
# model = SFO.BaseSFO(problem, epoch=10, pop_size=50)
# model = SFO.ImprovedSFO(problem, epoch=10, pop_size=50)
# model = SHO.BaseSHO(problem, epoch=10, pop_size=50)
# model = SLO.BaseSLO(problem, epoch=10, pop_size=50)
# model = SLO.ModifiedSLO(problem, epoch=10, pop_size=50)
# model = SLO.ISLO(problem, epoch=10, pop_size=50)
# model = SRSR.BaseSRSR(problem, epoch=10, pop_size=50)
# model = SSA.OriginalSSA(problem, epoch=10, pop_size=50)
# model = SSA.BaseSSA(problem, epoch=10, pop_size=50)
# model = SSO.BaseSSO(problem, epoch=10, pop_size=50)
# model = SSpiderA.BaseSSpiderA(problem, epoch=10, pop_size=50)
# model = SSpiderO.BaseSSpiderO(problem, epoch=10, pop_size=50)
# model = WOA.BaseWOA(problem, epoch=10, pop_size=50)
# model = WOA.HI_WOA(problem, epoch=10, pop_size=50)

best_position, best_fitness = model.solve()
print(f"Best position: {best_position}, Best fit: {best_fitness}")