Passed
Push — master ( d39371...69bf6f )
by Simon
03:38
created

EvolutionStrategyOptimizer._mutate()   A

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
import numpy as np
6
7
from math import floor, ceil
8
from .base_population_optimizer import BasePopulationOptimizer
9
from ...search import Search
10
from ..local import HillClimbingOptimizer
11
12
13
class EvolutionStrategyOptimizer(BasePopulationOptimizer, Search):
14
    def __init__(self, search_space, mutation_rate=0.5, crossover_rate=0.5):
15
        super().__init__(search_space)
16
17
        self.mutation_rate = mutation_rate
18
        self.crossover_rate = crossover_rate
19
20
        self.individuals = []
21
22
    def _mutate(self):
23
        nth_iter = self._iterations(self.individuals)
24
        p_current = self.individuals[nth_iter % len(self.individuals)]
25
26
        return p_current._move_climb(self.p_current.pos_current)
27
28
    def _random_cross(self, array_list):
29
        n_arrays = len(array_list)
30
        size = array_list[0].size
31
        shape = array_list[0].shape
32
33
        choice = np.random.randint(n_arrays, size=size).reshape(shape).astype(bool)
34
        return np.choose(choice, array_list)
35
36
    def _sort_best(self):
37
        scores_list = []
38
        for ind in self.individuals:
39
            scores_list.append(ind.score_current)
40
41
        scores_np = np.array(scores_list)
42
        idx_sorted_ind = list(scores_np.argsort()[::-1])
43
44
        return [self.individuals[idx] for idx in idx_sorted_ind]
45
46
    def _cross(self):
47
        ind_sorted = self._sort_best()
48
49
        p_best = ind_sorted[0]
50
        p_sec_best = ind_sorted[1]
51
52
        two_best_pos = [p_best.pos_current, p_sec_best.pos_current]
53
        pos_new = self._random_cross(two_best_pos)
54
55
        p_worst = ind_sorted[-1]
56
        p_worst.pos_new = pos_new
57
58
        self.p_current = p_worst
59
60
        return pos_new
61
62
    def _evo_iterate(self):
63
        total_rate = self.mutation_rate + self.crossover_rate
64
        rand = np.random.uniform(low=0, high=total_rate)
65
66
        if len(self.individuals) == 1 or rand <= self.mutation_rate:
67
            return self._mutate()
68
        else:
69
            return self._cross()
70
71
    def init_pos(self, pos):
72
        individual = HillClimbingOptimizer(self.space_dim)
73
        self.individuals.append(individual)
74
        individual.init_pos(pos)
75
76
        self.p_current = individual
77
78
    def iterate(self):
79
        return self._evo_iterate()
80
81
    def evaluate(self, score_new):
82
        self.p_current.score_new = score_new
83
84
        self.p_current._evaluate_new2current(score_new)
85
        self.p_current._evaluate_current2best()
86
87