Skip to content

Custom Strategy

import array

import numpy
from deap_er import Fitness, Toolbox, creator, tools

tools.rng.seed(1234)  # disables randomization

IND_SIZE = 30
MIN_VALUE = 4
MAX_VALUE = 5
MIN_STRATEGY = 0.5
MAX_STRATEGY = 3


def gen_evo_strat(icls, scls):
    ind = icls(tools.rng.uniform(MIN_VALUE, MAX_VALUE) for _ in range(IND_SIZE))
    ind.strategy = scls(tools.rng.uniform(MIN_STRATEGY, MAX_STRATEGY) for _ in range(IND_SIZE))
    return ind


def check_strategy(strat):
    def wrapper(func):
        def wrapped(*args, **kwargs):
            children = func(*args, **kwargs)
            for child in children:
                for i, s in enumerate(child.strategy):
                    if s < strat:
                        child.strategy[i] = strat
            return children

        return wrapped

    return wrapper


def setup():
    creator.create_type("FitnessMin", Fitness, weights=(-1.0,))
    creator.create_type(
        "Individual", array.array, typecode="d", fitness=creator.FitnessMin, strategy=None
    )
    creator.create_type("Strategy", array.array, typecode="d")

    toolbox = Toolbox()
    toolbox.register("individual", gen_evo_strat, creator.Individual, creator.Strategy)
    toolbox.register("population", tools.init_repeat, list, toolbox.individual)
    toolbox.register("mate", tools.cx_es_blend, alpha=0.1)
    toolbox.register("mutate", tools.mut_es_log_normal, learn_rate=1.0, mut_prob=0.03)
    toolbox.register("select", tools.sel_tournament, contestants=3)
    toolbox.register("evaluate", tools.bm_sphere)
    toolbox.decorate("mate", check_strategy(MIN_STRATEGY))
    toolbox.decorate("mutate", check_strategy(MIN_STRATEGY))

    stats = tools.Statistics(lambda ind: ind.fitness.values)
    stats.register("avg", numpy.mean)
    stats.register("std", numpy.std)
    stats.register("min", numpy.min)
    stats.register("max", numpy.max)

    return toolbox, stats


def print_results(best_ind):
    if best_ind.fitness.values >= (0.5,):
        raise RuntimeError("Evolution failed to converge.")
    print("\nEvolution converged correctly.")


def main():
    toolbox, stats = setup()
    pop = toolbox.population(size=100)
    hof = tools.HallOfFame(1)
    args = {
        "toolbox": toolbox,
        "population": pop,
        "generations": 500,
        "offsprings": 100,
        "survivors": 10,
        "cx_prob": 0.6,
        "mut_prob": 0.3,
        "hof": hof,
        "stats": stats,
        "verbose": True,  # prints stats
    }
    tools.ea_mu_comma_lambda(**args)
    print_results(hof[0])


if __name__ == "__main__":
    main()