Customization

In this section, we present more complicated examples.

Principle

If you aspire to create a novel algorithm that differs from genetic algorithms (GAs), it is advisable to derive from the mixin classe and use the metaclass :ref:api-design. The base classes have been crafted specifically for GA-style algorithms, yet they offer flexibility. There is no compulsion to adhere strictly to their implementation; you have the freedom to override the methods within the base classes to suit your novel algorithm’s requirements.

Customization Tricks

Take Partical Swarm Optimization(PSO) as an example for a quick look at the tricks of customization. First of all, define class ParticleSwarm(PopulationMixin):..., as subclass of PopulationMixin. PopulationMixin is a mixin class where you have to define method transition to implement the PSO algorithm. Then assign element_class to be the type of particles, and set default_size as the number of the particles.

Since the package has provide a practical class for PSO, you only need set the attribute element_class to be your own particle class in most cases. See example-pso.py in examples.

class _Particle(BaseParticle):
    ...

class MyParticleSwarm(ParticleSwarm, metaclass=MetaContainer):

    element_class = _Particle
    default_size = 20
    ...

In the standard definition, as an individual, a particle has two “chromosomes”, one represents the current position, the other represents the current velocity. While, you can define three or more chromosomes, to include the acceleration. It also has an important attribute, memory storing the best position that the particle passed-by.

Evolution Strategy

Evolution Strategy is indeed a special type of GA. Hence we inherit it from BasePopulation.

Here we mainly redefine the method mate and remove mutate.

#!/usr/bin/env python

"""
(mu + lambda) - Evolution Strategy

*References*
Rechenberg, I. 1973. Evolutionsstrategie – Optimierung technischer Systeme nach Prinzipien der biologischen Evolution, Frommann-Holzboog.
"""


from .base import BasePopulation
from .utils import randint2


class EvolutionStrategy(BasePopulation):
    # Evolution Strategy

    params ={
        "mu" : 10,
        "lambda_": 20,
    }

    def init(self):
        super().init()
        if 'mu' not in self.params:
            self.set_params(mu=self.default_size) 

    def transition(self, *args, **kwargs):
        offspring = self.mate()
        self.extend(offspring)
        self.mate()
        self.select_best_individuals(self.mu)

    def mate(self, lambda_=None):
        lambda_ = lambda_ or self.lambda_
        offspring = []
        n = len(self)
        for _ in range(lambda_):
            i, j = randint2(0, n-1)
            child = self[i].cross(self[j])
            offspring.append(child)
        return offspring

    def select_best_individuals(self, mu=None):
        mu = mu or self.mu
        self.individuals = self.get_best_individuals(mu)

Differential Evolution

The standard DE is a global searching algorithm. The class DifferentialEvolution for DE is inherited from PopulationMixin.

class DifferentialEvolution(PopulationMixin):

    params ={
    "factor" : 0.25,
    "cross_prob": 0.75,
    }

    test_individuals = []

    def init(self):
        self.dimension = len(self.individuals[0][0])
        self.test = self.clone()

    def transition(self, *args, **kwargs):
        self.move()
        for k, (test_individual, individual) in enumerate(zip(self.test, self)):
            if test_individual.fitness > individual.fitness:
                self.individuals[k] = test_individual

    def move(self):
        for t in self.test:
            x0, x1, x2 = choice(self.individuals, size=3, replace=False)

            jrand = np.random.randint(0, self.dimension)
            xx = x0.chromosome + self.factor * (x1.chromosome - x2.chromosome)
            for j in range(self.dimension):
                if random()<self.cross_prob or j == jrand:
                    t.chromosomes[0][j] = xx[j]

After running comparison-de.py, we get the following fitness curves.

Hacking

Will be filled in future.