Skip to content

Single-Swarm

Using Builtins

import math
import operator

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

tools.rng.seed(1234)  # disables randomization

NGEN = 1000


def generate(size, pmin, pmax, smin, smax):
    p_list = [tools.rng.uniform(pmin, pmax) for _ in range(size)]
    s_list = [tools.rng.uniform(smin, smax) for _ in range(size)]
    part = creator.Particle(p_list)
    part.speed = s_list
    part.smin = smin
    part.smax = smax
    return part


def update(part, best, phi1, phi2):
    u1 = (tools.rng.uniform(0, phi1) for _ in range(len(part)))
    u2 = (tools.rng.uniform(0, phi2) for _ in range(len(part)))
    v_u1 = map(operator.mul, u1, map(operator.sub, part.best, part))
    v_u2 = map(operator.mul, u2, map(operator.sub, best, part))
    part.speed = list(map(operator.add, part.speed, map(operator.add, v_u1, v_u2)))
    for i, speed in enumerate(part.speed):
        if abs(speed) < part.smin:
            part.speed[i] = math.copysign(part.smin, speed)
        elif abs(speed) > part.smax:
            part.speed[i] = math.copysign(part.smax, speed)
    part[:] = list(map(operator.add, part, part.speed))


def setup():
    creator.create_type("FitnessMax", Fitness, weights=(1.0,))
    creator.create_type(
        "Particle", list, fitness=creator.FitnessMax, speed=list, smin=None, smax=None, best=None
    )

    toolbox = Toolbox()
    toolbox.register("particle", generate, size=2, pmin=-6, pmax=6, smin=-3, smax=3)
    toolbox.register("population", tools.init_repeat, list, toolbox.particle)
    toolbox.register("update", update, phi1=2.0, phi2=2.0)
    toolbox.register("evaluate", tools.bm_h1)

    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)

    logbook = tools.Logbook()
    logbook.header = ["gen", "evals"] + stats.fields

    return toolbox, stats, logbook


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


def main():
    toolbox, stats, logbook = setup()
    pop = toolbox.population(size=5)

    best = None
    for generation in range(NGEN):
        for part in pop:
            part.fitness.values = toolbox.evaluate(part)
            if not part.best or part.best.fitness < part.fitness:
                part.best = creator.Particle(part)
                part.best.fitness.values = part.fitness.values
            if not best or best.fitness < part.fitness:
                best = creator.Particle(part)
                best.fitness.values = part.fitness.values
        for part in pop:
            toolbox.update(part, best)
        logbook.record(gen=generation, evals=len(pop), **stats.compile(pop))
        print(logbook.stream)

    print_results(best)


if __name__ == "__main__":
    main()

Using Numpy

import math

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

tools.rng.seed(1234)  # disables randomization

NGEN = 1000


def generate(size, pmin, pmax, smin, smax):
    p_list = numpy.array([tools.rng.uniform(pmin, pmax) for _ in range(size)])
    s_list = numpy.array([tools.rng.uniform(smin, smax) for _ in range(size)])
    part = creator.Particle(p_list)
    part.speed = s_list
    part.smin = smin
    part.smax = smax
    return part


def update(part, best, phi1, phi2):
    u1 = numpy.array([tools.rng.uniform(0, phi1) for _ in range(len(part))])
    u2 = numpy.array([tools.rng.uniform(0, phi2) for _ in range(len(part))])
    v_u1 = u1 * (part.best - part)
    v_u2 = u2 * (best - part)
    part.speed += v_u1 + v_u2
    for i, speed in enumerate(part.speed):
        if abs(speed) < part.smin:
            part.speed[i] = math.copysign(part.smin, speed)
        elif abs(speed) > part.smax:
            part.speed[i] = math.copysign(part.smax, speed)
    part += part.speed


def setup():
    creator.create_type("FitnessMax", Fitness, weights=(1.0,))
    creator.create_type(
        "Particle",
        numpy.ndarray,
        fitness=creator.FitnessMax,
        speed=list,
        smin=None,
        smax=None,
        best=None,
    )

    toolbox = Toolbox()
    toolbox.register("particle", generate, size=2, pmin=-6, pmax=6, smin=-3, smax=3)
    toolbox.register("population", tools.init_repeat, list, toolbox.particle)
    toolbox.register("update", update, phi1=2.0, phi2=2.0)
    toolbox.register("evaluate", tools.bm_h1)

    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)

    logbook = tools.Logbook()
    logbook.header = ["gen", "evals"] + stats.fields

    return toolbox, stats, logbook


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


def main():
    toolbox, stats, logbook = setup()
    pop = toolbox.population(size=5)

    best = None
    for g in range(NGEN):
        for part in pop:
            part.fitness.values = toolbox.evaluate(part)
            if part.best is None or part.best.fitness < part.fitness:
                part.best = creator.Particle(part)
                part.best.fitness.values = part.fitness.values
            if best is None or best.fitness < part.fitness:
                best = creator.Particle(part)
                best.fitness.values = part.fitness.values
        for part in pop:
            toolbox.update(part, best)
        logbook.record(gen=g, evals=len(pop), **stats.compile(pop))
        print(logbook.stream)

    print_results(best)


if __name__ == "__main__":
    main()