USE(7.1)
USE(7.1)
AbEC - Adding a New Optimizer
<< >>
< [ Home ] < 1. [ Use ] > 2. [ Configuration files ] > 3. [ Fitness function ] > 4. [ Running ] > 5. [ Results ] > 6. [ Example ] > 7. [ Adding new components ] >> 7.1. [ Adding a New Optimizer ] >>>> 7.1.1. [ Example of a New Optimizer ] >> 7.2. [ Adding a New Component ] >>>> 7.2.1. [ Example of a New Component ] >> 7.3. [ Adding a New Metric File ] >>>> 7.3.1. [ Example of a New Metric ]

> AbEC/abec/optimizers/optimizer.py

This is the file where we are going to implement the optimizer. First of all, lets talk about some requirements.

The template of a new optimizer can be downloaded in the link: [ Optimizer template ].

> Hyper-parameters

In order to set the hyper-parameters of the component, inside of the file it is necessary to be defined one list, named params, where each element of this list we put the hyper-parameters of our new component. Below a generic example of this list.

params = ["HYPER-PARAMETER-1", "HYPER-PARAMETER-2", ..., "HYPER-PARAMETER-N"]


With the hyper-parameters defined, There are two methods that are mandatory, they are cp and optimizer.




> Confirmation of hyper-parameters (cp)

This method is used to confirm that all the values of the hyper-parameters are within the allowed range. A generic example of this method is showed below:

from aux.aux import errorWarning
import sys

def cp(parameters):
    if not (MIN <= parameters["<NAME-OF-OPTIMIZER>_<HYPER-PARAMETER-1>"] <= MAX):
       errorWarning("3.X.1", "algoConfig.ini", "<NAME-OF-THE-OPTIMIZER>_<HYPER-PARAMETER-1>", "The <HYPER-PARAMETER-1> should be in the interval [MIN, MAX]")
       sys.exit()

    if not (MIN <= parameters["<NAME-OF-OPTIMIZER>_<HYPER-PARAMETER-2>"] <= MAX):
       errorWarning("3.X.2", "algoConfig.ini", "<NAME-OF-THE-OPTIMIZER>_<HYPER-PARAMETER-2>", "The <HYPER-PARAMETER-2> should be in the interval [MIN, MAX]")
       sys.exit()

    if not (MIN <= parameters["<NAME-OF-OPTIMIZER>_<HYPER-PARAMETER-N>"] <= MAX):
       errorWarning("3.X.N", "algoConfig.ini", "<NAME-OF-THE-OPTIMIZER>_<HYPER-PARAMETER-N>", "The <HYPER-PARAMETER-N> should be in the interval [MIN, MAX]")
       sys.exit()

    return 1





> The optimizer (optimizer)

This method is the implementation of the optimizer itself, hence, this is the most important method and need to be carefully writen.

def optimizer(pop, best, runVars, parameters):
    .
    .
    .
    return pop, runVars





> optimizer.py

And then the complete file will be something like:

from aux.aux import errorWarning
import sys

params = ["HYPER-PARAMETER-1", "HYPER-PARAMETER-2", ..., "HYPER-PARAMETER-N"]

def cp(parameters):
    if not (MIN <= parameters["<NAME-OF-OPTIMIZER>_<HYPER-PARAMETER-1>"] <= MAX):
       errorWarning("3.X.1", "algoConfig.ini", "<NAME-OF-THE-OPTIMIZER>_<HYPER-PARAMETER-1>", "The <HYPER-PARAMETER-1> should be in the interval [MIN, MAX]")
       sys.exit()

    if not (MIN <= parameters["<NAME-OF-OPTIMIZER>_<HYPER-PARAMETER-2>"] <= MAX):
       errorWarning("3.X.2", "algoConfig.ini", "<NAME-OF-THE-OPTIMIZER>_<HYPER-PARAMETER-2>", "The <HYPER-PARAMETER-2> should be in the interval [MIN, MAX]")
       sys.exit()

    if not (MIN <= parameters["<NAME-OF-OPTIMIZER>_<HYPER-PARAMETER-N>"] <= MAX):
       errorWarning("3.X.N", "algoConfig.ini", "<NAME-OF-THE-OPTIMIZER>_<HYPER-PARAMETER-N>", "The <HYPER-PARAMETER-N> should be in the interval [MIN, MAX]")
       sys.exit()

    return 1

def optimizer(pop, best, runVars, parameters):
    .
    .
    .
    return pop, runVars





> algoConfig.ini

Once you have added the optimizer script in the respective folder, you will be able to configure this component in the configuration file "algoConfig.ini". The component will appers in the file as follows:


{
"<NAME-OF-THE-OPTIMIZER>_POP_PERC": 1 -> This is the percentage of the individuals in the population that will perform this optimizer; 0 is turned off and 1 is 100% of the individuals. (float) in [0, 1]
}

The optimizer parameters:

{
"<NAME-OF-THE-OPTIMIZER>_POP_PERC": 1, -> This is the percentage of the individuals in the population that will perform this optimizer; 0 is turned off and 1 is 100% of the individuals. (float) in [0, 1]
"<NAME-OF-THE-OPTIMIZER>_<HYPER-PARAMETER-1>": value, -> range permitted for the value (type)
"<NAME-OF-THE-OPTIMIZER>_<HYPER-PARAMETER-2>": value, -> range permitted for the value (type)
.
.
"<NAME-OF-THE-OPTIMIZER>_<HYPER-PARAMETER-N>": value -> range permitted for the value (type)
}

[~]$ Example of a new Optimizer
As an example, we are going now to add an optimizer, the Differential Evolution (DE).

> AbEC/abec/optimizers/de.py


$ nano abec/optimizers/de.py


> [ file ]

import sys
import copy
import abec
import aux.globalVar as globalVar
from aux.aux import errorWarning

params = ["F", "CR"]

def cp(parameters):
    if not (0 < parameters["DE_F"] <= 10):
       errorWarning("3.3.1", "algoConfig.ini", "DE_F", "The F parameters should be in the interval ]0, 10]")
       sys.exit()

    if not (0 < parameters["DE_CR"] <= 10):
       errorWarning("3.3.2", "algoConfig.ini", "DE_CR", "The CR parameter should be in the interval ]0, 10]")
       sys.exit()

    return 1

def optimizer(pop, best, runVars, parameters):
    tempPop = copy.deepcopy(pop)
    tempPop.ind = sorted(tempPop.ind, key = lambda x:x["id"])
    dePop = [d for d in tempPop.ind if d["type"]=="DE"]
    for ind in dePop:
       x = []
       candidates = [c for c in dePop if c["id"] != ind["id"]]
       a, b, c = globalVar.rng.choice(candidates, 3, replace=False)

       for d in range(parameters["NDIM"]):
          x.append(a["pos"][d] + parameters["DE_F"]*(b["pos"][d] - c["pos"][d]))
          if x[d] > parameters["MAX_POS"]:
             x[d] = parameters["MAX_POS"]
          elif x[d] > parameters["MIN_POS"]:
             x[d] = parameters["MIN_POS"]

       for d in range(parameters["NDIM"]):
          if globalVar.rng.random() < parameters["DE_CR"]:
             ind["pos"][d] = x[d]

    for ind in dePop:
       ind = abec.evaluate(ind, parameters)
       for i in range(len(pop.ind)):
          if ind["id"] == pop.ind[i]["id"]:
             if ind["fit"] < pop.ind[i]["fit"]:
                pop.ind[i] = ind.copy()
                ind, globalVar.best = abec.updateBest(pop.ind[i], globalVar.best)
             else ind["fit"] < pop.ind[i]["fit"]:
                pop.ind[i]["ae"] = 1


    return pop, runVars


And then to use it in the algorithm, we set it up in the configuration file algoConfig.ini, just like this:

$ nano abec/algoConfig.ini


> [ file ]

{
"ALGORITHM": "DE",
"POPSIZE": 50,
"MIN_POS": -10,
"MAX_POS": 10,
"DE_POP_PERC": 1,
"DE_F": 0.5,
"DE_CR": 0.7
}

Be free to use this framework.
AbEC © 2023.