Passed
Push — master ( aae147...fb8817 )
by Grega
02:11 queued 43s
created

__init__()   B

Complexity

Conditions 1

Size

Total Lines 43

Duplication

Lines 4
Ratio 9.3 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 1
c 2
b 1
f 0
dl 4
loc 43
rs 8.8571
1
import random as rnd
2
import copy
3
from NiaPy.benchmarks.utility import Utility
4
5
__all__ = ['SelfAdaptiveDifferentialEvolutionAlgorithm']
6
7 View Code Duplication
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
8
class SolutionjDE(object):
9
10
    def __init__(self, D, LB, UB, F, CR):
11
        self.D = D
12
        self.LB = LB
13
        self.UB = UB
14
        self.F = F
15
        self.CR = CR
16
        self.Solution = []
17
        self.Fitness = float('inf')
18
        self.generateSolution()
19
20
    def generateSolution(self):
21
        """Generate solution."""
22
23
        self.Solution = [self.LB + (self.UB - self.LB) * rnd.random()
24
                         for _i in range(self.D)]
25
26
    def evaluate(self):
27
        """Evaluate solution."""
28
29
        self.Fitness = SolutionjDE.FuncEval(self.D, self.Solution)
30
31
    def repair(self):
32
        for i in range(self.D):
33
            if self.Solution[i] > self.UB:
34
                self.Solution[i] = self.UB
35
            if self.Solution[i] < self.LB:
36
                self.Solution[i] = self.LB
37
38
    def __eq__(self, other):
39
        return self.Solution == other.Solution and self.Fitness == other.Fitness
40
41
42
class SelfAdaptiveDifferentialEvolutionAlgorithm(object):
43
    r"""Implementation of Self-adaptive differential evolution algorithm.
44
45
    **Algorithm:** Self-adaptive differential evolution algorithm
46
47
    **Date:** 2018
48
49
    **Author:** Uros Mlakar
50
51
    **License:** MIT
52
53
    **Reference paper:**
54
        Brest, J., Greiner, S., Boskovic, B., Mernik, M., Zumer, V.
55
        Self-adapting control parameters in differential evolution:
56
        A comparative study on numerical benchmark problems.
57
        IEEE transactions on evolutionary computation, 10(6), 646-657, 2006.
58
    """
59
60
    def __init__(self, D, NP, nFES, F, CR, Tao, benchmark):
61
        r"""**__init__(self, D, NP, nFES, F, CR, Tao, benchmark)**.
62
63
        Arguments:
64
            D {integer} -- dimension of problem
65
66
            NP {integer} -- population size
67
68
            nFES {integer} -- number of function evaluations
69
70
            F {decimal} -- scaling factor
71
72
            CR {decimal} -- crossover rate
73
74
            Tao {decimal}
75
76
            benchmark {object} -- benchmark implementation object
77
78
        Raises:
79
            TypeError -- Raised when given benchmark function which does not exists.
80
81
        """
82
83
        self.benchmark = Utility().get_benchmark(benchmark)
84
        self.D = D  # dimension of problem
85
        self.Np = NP  # population size
86
        self.nFES = nFES  # number of function evaluations
87
        self.F = F  # scaling factor
88
        self.CR = CR  # crossover rate
89
        self.Tao = Tao
90
        self.Lower = self.benchmark.Lower  # lower bound
91
        self.Upper = self.benchmark.Upper  # upper bound
92
93
        SolutionjDE.FuncEval = staticmethod(self.benchmark.function())
94
        self.Population = []
95
        self.FEs = 0
96
        self.Done = False
97
        self.bestSolution = SolutionjDE(
98
            self.D,
99 View Code Duplication
            self.Lower,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
100
            self.Upper,
101
            self.F,
102
            self.CR)
103
104
    def evalPopulation(self):
105
        """Evaluate population."""
106
107
        for p in self.Population:
108
            p.evaluate()
109
            if p.Fitness < self.bestSolution.Fitness:
110
                self.bestSolution = copy.deepcopy(p)
111
112
    def initPopulation(self):
113
        """Initialize population."""
114
115
        for _i in range(self.Np):
116
            self.Population.append(
117
                SolutionjDE(self.D,
118
                            self.Lower,
119
                            self.Upper,
120
                            self.F,
121
                            self.CR))
122
123
    def tryEval(self, v):
124
        if self.FEs <= self.nFES:
125
            v.evaluate()
126
            self.FEs += 1
127
        else:
128
            self.Done = True
129
130
    def generationStep(self, Population):
131
        """Implement main DE/jDE step."""
132
133
        newPopulation = []
134
        for i in range(self.Np):
135
            newSolution = SolutionjDE(
136
                self.D,
137
                self.Lower,
138
                self.Upper,
139
                self.F,
140
                self.CR)
141
142
            if rnd.random() < self.Tao:
143
                newSolution.F = rnd.random()
144
            else:
145
                newSolution.F = Population[i].F
146
147
            if rnd.random() < self.Tao:
148
                newSolution.CR = rnd.random()
149
            else:
150
                newSolution.CR = Population[i].CR
151
152
            r = rnd.sample(range(0, self.Np), 3)
153
            while i in r:
154
                r = rnd.sample(range(0, self.Np), 3)
155
            jrand = int(rnd.random() * self.Np)
156
157
            for j in range(self.D):
158
                if rnd.random() < newSolution.CR or j == jrand:
159
                    newSolution.Solution[j] = Population[r[0]].Solution[j] + newSolution.F * (
160
                        Population[r[1]].Solution[j] - Population[r[2]].Solution[j])
161
                else:
162
                    newSolution.Solution[j] = Population[i].Solution[j]
163
            newSolution.repair()
164
            self.tryEval(newSolution)
165
166
            if newSolution.Fitness < self.bestSolution.Fitness:
167
                self.bestSolution = copy.deepcopy(newSolution)
168
            if newSolution.Fitness < self.Population[i].Fitness:
169
                newPopulation.append(newSolution)
170
            else:
171
                newPopulation.append(Population[i])
172
        return newPopulation
173
174
    def run(self):
175
        self.initPopulation()
176
        self.evalPopulation()
177
        self.FEs = self.Np
178
        while not self.Done:
179
            self.Population = self.generationStep(self.Population)
180
        return self.bestSolution.Fitness
181