1#    This file is part of DEAP.
2#
3#    DEAP is free software: you can redistribute it and/or modify
4#    it under the terms of the GNU Lesser General Public License as
5#    published by the Free Software Foundation, either version 3 of
6#    the License, or (at your option) any later version.
7#
8#    DEAP is distributed in the hope that it will be useful,
9#    but WITHOUT ANY WARRANTY; without even the implied warranty of
10#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11#    GNU Lesser General Public License for more details.
12#
13#    You should have received a copy of the GNU Lesser General Public
14#    License along with DEAP. If not, see <http://www.gnu.org/licenses/>.
15
16import operator
17import random
18
19import numpy
20
21from deap import base
22from deap import benchmarks
23from deap import creator
24from deap import tools
25
26creator.create("FitnessMax", base.Fitness, weights=(1.0,))
27creator.create("Particle", numpy.ndarray, fitness=creator.FitnessMax, speed=list,
28    smin=None, smax=None, best=None)
29
30def generate(size, pmin, pmax, smin, smax):
31    part = creator.Particle(numpy.random.uniform(pmin, pmax, size))
32    part.speed = numpy.random.uniform(smin, smax, size)
33    part.smin = smin
34    part.smax = smax
35    return part
36
37def updateParticle(part, best, phi1, phi2):
38    u1 = numpy.random.uniform(0, phi1, len(part))
39    u2 = numpy.random.uniform(0, phi2, len(part))
40    v_u1 = u1 * (part.best - part)
41    v_u2 = u2 * (best - part)
42    part.speed += v_u1 + v_u2
43    for i, speed in enumerate(part.speed):
44        if abs(speed) < part.smin:
45            part.speed[i] = math.copysign(part.smin, speed)
46        elif abs(speed) > part.smax:
47            part.speed[i] = math.copysign(part.smax, speed)
48    part += part.speed
49
50toolbox = base.Toolbox()
51toolbox.register("particle", generate, size=2, pmin=-6, pmax=6, smin=-3, smax=3)
52toolbox.register("population", tools.initRepeat, list, toolbox.particle)
53toolbox.register("update", updateParticle, phi1=2.0, phi2=2.0)
54toolbox.register("evaluate", benchmarks.h1)
55
56def main():
57    pop = toolbox.population(n=5)
58    stats = tools.Statistics(lambda ind: ind.fitness.values)
59    stats.register("avg", numpy.mean)
60    stats.register("std", numpy.std)
61    stats.register("min", numpy.min)
62    stats.register("max", numpy.max)
63
64    logbook = tools.Logbook()
65    logbook.header = ["gen", "evals"] + stats.fields
66
67    GEN = 1000
68    best = None
69
70    for g in range(GEN):
71        for part in pop:
72            part.fitness.values = toolbox.evaluate(part)
73            if part.best is None or part.best.fitness < part.fitness:
74                part.best = creator.Particle(part)
75                part.best.fitness.values = part.fitness.values
76            if best is None or best.fitness < part.fitness:
77                best = creator.Particle(part)
78                best.fitness.values = part.fitness.values
79        for part in pop:
80            toolbox.update(part, best)
81
82        # Gather all the fitnesses in one list and print the stats
83        logbook.record(gen=g, evals=len(pop), **stats.compile(pop))
84        print(logbook.stream)
85
86    return pop, logbook, best
87
88if __name__ == "__main__":
89    main()
90
91