Passed
Push — master ( b4d881...21cb52 )
by Simon
02:57
created

gradient_free_optimizers.optimizers.pop_opt.differential_evolution   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 8
eloc 56
dl 0
loc 81
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A DifferentialEvolutionOptimizer.mutation() 0 5 1
A DifferentialEvolutionOptimizer._constraint_loop() 0 5 3
A DifferentialEvolutionOptimizer.iterate() 0 19 1
A DifferentialEvolutionOptimizer.evaluate() 0 3 1
A DifferentialEvolutionOptimizer.init_pos() 0 6 1
A DifferentialEvolutionOptimizer.__init__() 0 18 1
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
import random
6
import numpy as np
7
8
from ._evolutionary_algorithm import EvolutionaryAlgorithmOptimizer
9
from ._individual import Individual
10
11
12
class DifferentialEvolutionOptimizer(EvolutionaryAlgorithmOptimizer):
13
    name = "Differential Evolution"
14
    _name_ = "differential_evolution"
15
    __name__ = "DifferentialEvolutionOptimizer"
16
17
    optimizer_type = "population"
18
    computationally_expensive = False
19
20
    def __init__(
21
        self,
22
        *args,
23
        population=10,
24
        mutation_rate=0.9,
25
        crossover_rate=0.9,
26
        **kwargs
27
    ):
28
        super().__init__(*args, **kwargs)
29
30
        self.population = population
31
        self.mutation_rate = mutation_rate
32
        self.crossover_rate = crossover_rate
33
34
        self.individuals = self._create_population(Individual)
35
        self.optimizers = self.individuals
36
37
        self.offspring_l = []
38
39
    def mutation(self, f=1):
40
        ind_selected = random.sample(self.individuals, 3)
41
42
        x_1, x_2, x_3 = [ind.pos_best for ind in ind_selected]
43
        return x_1 + self.mutation_rate * np.subtract(x_2, x_3)
44
45
    def _constraint_loop(self, position):
46
        while True:
47
            if self.conv.not_in_constraint(position):
48
                return position
49
            position = self.p_current.move_climb(position, epsilon_mod=0.3)
50
51
    @EvolutionaryAlgorithmOptimizer.track_new_pos
52
    def init_pos(self):
53
        nth_pop = self.nth_trial % len(self.individuals)
54
55
        self.p_current = self.individuals[nth_pop]
56
        return self.p_current.init_pos()
57
58
    @EvolutionaryAlgorithmOptimizer.track_new_pos
59
    def iterate(self):
60
        self.p_current = self.individuals[
61
            self.nth_trial % len(self.individuals)
62
        ]
63
        target_vector = self.p_current.pos_new
64
65
        mutant_vector = self.mutation()
66
67
        crossover_rates = [1 - self.crossover_rate, self.crossover_rate]
68
        pos_new = self.discrete_recombination(
69
            [target_vector, mutant_vector],
70
            crossover_rates,
71
        )
72
        pos_new = self.conv2pos(pos_new)
73
        pos_new = self._constraint_loop(pos_new)
74
75
        self.p_current.pos_new = self.conv2pos(pos_new)
76
        return self.p_current.pos_new
77
78
    @EvolutionaryAlgorithmOptimizer.track_new_score
79
    def evaluate(self, score_new):
80
        self.p_current.evaluate(score_new)  # selection
81