1 | from deap.tools import HallOfFame |
---|
2 | import operator |
---|
3 | from copy import deepcopy |
---|
4 | from bisect import bisect_right |
---|
5 | |
---|
6 | class HallOfFameCustom(HallOfFame): |
---|
7 | def __init__(self, maxsize, similar=operator.eq, fitness_field="fitness", *args, **kwargs): |
---|
8 | super(HallOfFameCustom, self).__init__(maxsize, similar, *args, **kwargs) |
---|
9 | print("HOF_size =",self.maxsize) |
---|
10 | self._fitness_field = fitness_field |
---|
11 | |
---|
12 | def extract_fitness(self, ind): |
---|
13 | return getattr(ind, self._fitness_field) |
---|
14 | |
---|
15 | def update(self, population): |
---|
16 | """Update the hall of fame with the *population* by replacing the |
---|
17 | worst individuals in it by the best individuals present in |
---|
18 | *population* (if they are better). The size of the hall of fame is |
---|
19 | kept constant. |
---|
20 | |
---|
21 | :param population: A list of individual with a fitness attribute to |
---|
22 | update the hall of fame with. |
---|
23 | """ |
---|
24 | for ind in population: |
---|
25 | if len(self) == 0 and self.maxsize != 0: |
---|
26 | # Working on an empty hall of fame is problematic for the |
---|
27 | # "for else" |
---|
28 | for hofer in self: |
---|
29 | if self.similar(ind, hofer): |
---|
30 | break |
---|
31 | else: |
---|
32 | self.insert(population[0]) |
---|
33 | |
---|
34 | continue |
---|
35 | if self.extract_fitness(ind) >= self.extract_fitness(self[-1]) or len(self) < self.maxsize: |
---|
36 | for hofer in self: |
---|
37 | # Loop through the hall of fame to check for any |
---|
38 | # similar individual |
---|
39 | if self.similar(ind, hofer): |
---|
40 | break |
---|
41 | else: |
---|
42 | # The individual is unique and strictly better than |
---|
43 | # the worst |
---|
44 | if len(self) >= self.maxsize: |
---|
45 | self.remove(-1) |
---|
46 | self.insert(ind) |
---|
47 | |
---|
48 | def insert(self, item): |
---|
49 | """Insert a new individual in the hall of fame using the |
---|
50 | :func:`~bisect.bisect_right` function. The inserted individual is |
---|
51 | inserted on the right side of an equal individual. Inserting a new |
---|
52 | individual in the hall of fame also preserve the hall of fame's order. |
---|
53 | This method **does not** check for the size of the hall of fame, in a |
---|
54 | way that inserting a new individual in a full hall of fame will not |
---|
55 | remove the worst individual to maintain a constant size. |
---|
56 | |
---|
57 | :param item: The individual with a fitness attribute to insert in the |
---|
58 | hall of fame. |
---|
59 | """ |
---|
60 | item = deepcopy(item) |
---|
61 | i = bisect_right(self.keys, self.extract_fitness(item)) |
---|
62 | self.items.insert(len(self) - i, item) |
---|
63 | self.keys.insert(i, self.extract_fitness(item)) |
---|
64 | |
---|