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

GeneticAlgorithm.__init__()   B

Complexity

Conditions 1

Size

Total Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
cc 1
c 3
b 2
f 0
dl 0
loc 37
rs 8.8571
1
import random as rnd
2
import copy
3
from NiaPy.benchmarks.utility import Utility
4
5
__all__ = ['GeneticAlgorithm']
6
7
8 View Code Duplication
class Chromosome(object):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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()
20
                         for _i in range(self.D)]
21
22
    def evaluate(self):
23
        self.Fitness = Chromosome.FuncEval(self.D, self.Solution)
24
25
    def repair(self):
26
        for i in range(self.D):
27
            if self.Solution[i] > self.UB:
28
                self.Solution[i] = self.UB
29
            if self.Solution[i] < self.LB:
30
                self.Solution[i] = self.LB
31
32
    def __eq__(self, other):
33
        return self.Solution == other.Solution and self.Fitness == other.Fitness
34
35
    def toString(self):
36
        print([i for i in self.Solution])
37
38
39
class GeneticAlgorithm(object):
40
    r"""Implementation of Genetic algorithm.
41
42
    **Algorithm:** Genetic algorithm
43
44
    **Date:** 2018
45
46
    **Author:** Uros Mlakar
47
48
    **License:** MIT
49
    """
50
51
    def __init__(self, D, NP, nFES, Ts, Mr, gamma, benchmark):
52
        r"""**__init__(self, D, NP, nFES, Ts, Mr, gamma, benchmark)**.
53
54
        Arguments:
55
            D {integer} -- dimension of problem
56
57
            NP {integer} -- population size
58
59
            nFES {integer} -- number of function evaluations
60
61
            Ts {decimal} -- tournament selection
62
63
            Mr {decimal} -- mutation rate
64
65
            gamma {decimal} -- minimum frequency
66
67
            benchmark {object} -- benchmark implementation object
68
69
        Raises:
70
            TypeError -- Raised when given benchmark function which does not exists.
71
72
        """
73
        self.benchmark = Utility().get_benchmark(benchmark)
74
        self.NP = NP
75
        self.D = D
76
        self.Ts = Ts
77
        self.Mr = Mr
78
        self.gamma = gamma
79
        self.Lower = self.benchmark.Lower
80
        self.Upper = self.benchmark.Upper
81
        self.Population = []
82
        self.nFES = nFES
83
        self.FEs = 0
84
        self.Done = False
85
        Chromosome.FuncEval = staticmethod(self.benchmark.function())
86
87
        self.Best = Chromosome(self.D, self.Lower, self.Upper)
88
89
    def checkForBest(self, pChromosome):
90
        if pChromosome.Fitness <= self.Best.Fitness:
91
            self.Best = copy.deepcopy(pChromosome)
92
93
    def TournamentSelection(self):
94
        indices = list(range(self.NP))
95
        rnd.shuffle(indices)
96
        tPop = []
97
        for i in range(self.Ts):
98
            tPop.append(self.Population[i])
99
        tPop.sort(key=lambda x: x.Fitness)
100
101
        self.Population.remove(tPop[0])
102
        self.Population.remove(tPop[1])
103
        return tPop[0], tPop[1]
104
105
    def CrossOver(self, parent1, parent2):
106
        alpha = [-self.gamma + (1 + 2 * self.gamma) * rnd.random()
107
                 for i in range(self.D)]
108
        child1 = Chromosome(self.D, self.Lower, self.Upper)
109
        child2 = Chromosome(self.D, self.Lower, self.Upper)
110
        child1.Solution = [alpha[i] * parent1.Solution[i] +
111
                           (1 - alpha[i]) * parent2.Solution[i] for i in range(self.D)]
112
        child2.Solution = [alpha[i] * parent2.Solution[i] +
113
                           (1 - alpha[i]) * parent1.Solution[i] for i in range(self.D)]
114
        return child1, child2
115
116
    def Mutate(self, child):
117
        for i in range(self.D):
118
            if rnd.random() < self.Mr:
119
                sigma = 0.20 * float(child.UB - child.LB)
120
                child.Solution[i] = min(
121
                    max(rnd.gauss(child.Solution[i], sigma), child.LB), child.UB)
122
123
    def init(self):
124
        for i in range(self.NP):
125
            self.Population.append(Chromosome(self.D, self.Lower, self.Upper))
126
            self.Population[i].evaluate()
127
            self.checkForBest(self.Population[i])
128
129
    def tryEval(self, c):
130
        if self.FEs < self.nFES:
131
            self.FEs += 1
132
            c.evaluate()
133
        else:
134
            self.Done = True
135
136
    def run(self):
137
        self.init()
138
        self.FEs = self.NP
139
        while not self.Done:
140
            for _k in range(int(self.NP / 2)):
141
                parent1, parent2 = self.TournamentSelection()
142
                child1, child2 = self.CrossOver(parent1, parent2)
143
144
                self.Mutate(child1)
145
                self.Mutate(child2)
146
147
                child1.repair()
148
                child2.repair()
149
150
                self.tryEval(child1)
151
                self.tryEval(child2)
152
153
                tPop = [parent1, parent2, child1, child2]
154
                tPop.sort(key=lambda x: x.Fitness)
155
                self.Population.append(tPop[0])
156
                self.Population.append(tPop[1])
157
158
            for i in range(self.NP):
159
                self.checkForBest(self.Population[i])
160
        return self.Best.Fitness
161