[1113] | 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): |
---|
[1139] | 7 | def __init__(self, maxsize, similar=operator.eq, fitness_field="fitness", *args, **kwargs): |
---|
| 8 | super(HallOfFameCustom, self).__init__(maxsize, similar, *args, **kwargs) |
---|
[1113] | 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 | |
---|