Passed
Push — master ( 7dc8c7...0f59c2 )
by Simon
03:25
created

EvolutionStrategyOptimizer._random_cross()   A

Complexity

Conditions 1

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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