Completed
Push — master ( fc4c38...3e2db1 )
by Grega
11s
created

DifferentialEvolutionAlgorithm   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 94
Duplicated Lines 17.02 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 16
loc 94
rs 10
wmc 16

5 Methods

Rating   Name   Duplication   Size   Complexity  
A evalPopulation() 0 5 3
B __init__() 0 33 1
A run() 0 8 2
D generationStep() 5 26 8
A initPopulation() 0 3 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
import random as rnd
2
import copy
3
from NiaPy.benchmarks.utility import Utility
4
5
__all__ = ['DifferentialEvolutionAlgorithm']
6
7
8
class SolutionDE(object):
9
    def __init__(self, D, LB, UB):
10
        self.D = D
11
        self.LB = LB
12
        self.UB = UB
13
14
        self.Solution = []
15
        self.Fitness = float('inf')
16
        self.generateSolution()
17
18
    def generateSolution(self):
19
        self.Solution = [self.LB + (self.UB - self.LB) * rnd.random() for _i in range(self.D)]
20
21 View Code Duplication
    def evaluate(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
22
        self.Fitness = SolutionDE.FuncEval(self.D, self.Solution)
23
24
    def repair(self):
25
        for i in range(self.D):
26
            if self.Solution[i] > self.UB:
27
                self.Solution[i] = self.UB
28
            if self.Solution[i] < self.LB:
29
                self.Solution[i] = self.LB
30
31
    def __eq__(self, other):
32
        return self.Solution == other.Solution and self.Fitness == other.Fitness
33
34
35
class DifferentialEvolutionAlgorithm(object):
36
    """Differential evolution algorithm.
37
38
    Date: 7. 2. 2018
39
40
    Authors : Uros Mlakar
41
42
    License: MIT
43
44
    Reference paper: Storn, Rainer, and Kenneth Price. "Differential evolution - a simple and
45
    efficient heuristic for global optimization over continuous spaces." Journal of global
46
    optimization 11.4 (1997): 341-359.
47
    """
48
49
    # pylint: disable=too-many-instance-attributes
50
    def __init__(self, D, NP, nFES, F, CR, benchmark):
51
        """**__init__(self, D, NP, nFES, F, CR, benchmark)**.
52
53
        Arguments:
54
            D {integer} -- dimension of problem
55
56
            NP {integer} -- population size
57
58
            nFES {integer} -- number of function evaluations
59
60
            F {decimal} -- scaling factor
61
62
            CR {decimal} -- crossover rate
63
64
            benchmark {object} -- benchmark implementation object
65
66
        Raises:
67
            TypeError -- Raised when given benchmark function which does not exists.
68
69
        """
70
71
        self.benchmark = Utility().get_benchmark(benchmark)
72
        self.D = D  # dimension of problem
73
        self.Np = NP  # population size
74
        self.nFES = nFES  # number of function evaluations
75
        self.F = F  # scaling factor
76
        self.CR = CR  # crossover rate
77
        self.Lower = self.benchmark.Lower  # lower bound
78
        self.Upper = self.benchmark.Upper  # upper bound
79
80
        SolutionDE.FuncEval = staticmethod(self.benchmark.function())
81
        self.Population = []
82
        self.bestSolution = SolutionDE(self.D, self.Lower, self.Upper)
83
84
    def evalPopulation(self):
85
        for p in self.Population:
86
            p.evaluate()
87
            if p.Fitness < self.bestSolution.Fitness:
88
                self.bestSolution = copy.deepcopy(p)
89
90
    def initPopulation(self):
91
        for _i in range(self.Np):
92
            self.Population.append(SolutionDE(self.D, self.Lower, self.Upper))
93
94
    def generationStep(self, Population):
95
        newPopulation = []
96
        for i in range(self.Np):
97
            newSolution = SolutionDE(self.D, self.Lower, self.Upper)
98
99
            r = rnd.sample(range(0, self.Np), 3)
100
            while i in r:
101
                r = rnd.sample(range(0, self.Np), 3)
102
            jrand = int(rnd.random() * self.Np)
103
104
            for j in range(self.D):
105 View Code Duplication
                if rnd.random() < self.CR or j == jrand:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
106
                    newSolution.Solution[j] = Population[r[0]].Solution[j] + \
107
                        self.F * (Population[r[1]].Solution[j] - Population[r[2]].Solution[j])
108
                else:
109
                    newSolution.Solution[j] = Population[i].Solution[j]
110
            newSolution.repair()
111
            newSolution.evaluate()
112
113
            if newSolution.Fitness < self.bestSolution.Fitness:
114
                self.bestSolution = copy.deepcopy(newSolution)
115
            if newSolution.Fitness < self.Population[i].Fitness:
116
                newPopulation.append(newSolution)
117
            else:
118
                newPopulation.append(Population[i])
119
        return newPopulation
120
121
    def run(self):
122
        self.initPopulation()
123
        self.evalPopulation()
124
        FEs = self.Np
125
        while FEs <= self.nFES:
126
            self.Population = self.generationStep(self.Population)
127
            FEs += self.Np
128
        return self.bestSolution.Fitness
129