Completed
Pull Request — master (#17)
by Grega
02:07
created

BatAlgorithm.__init__()   F

Complexity

Conditions 10

Size

Total Lines 37

Duplication

Lines 11
Ratio 29.73 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 11
loc 37
rs 3.1304
c 1
b 0
f 0
cc 10

How to fix   Complexity   

Complexity

Complex classes like BatAlgorithm.__init__() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""Bat algorithm.
2
3
Date: 2015
4
5
Authors : Iztok Fister Jr. and Marko Burjek
6
7
License: MIT
8
9
Reference paper: Yang, Xin-She. "A new metaheuristic bat-inspired algorithm."
10
Nature inspired cooperative strategies for optimization (NICSO 2010).
11
Springer, Berlin, Heidelberg, 2010. 65-74.
12
"""
13
14
import random
15
from NiaPy.benchmarks import Rastrigin, Rosenbrock, Griewank, Sphere
16
17
__all__ = ['BatAlgorithm']
18
19
20
class BatAlgorithm(object):
21
    # pylint: disable=too-many-instance-attributes
22
    def __init__(self, D, NP, nFES, A, r, Qmin, Qmax, Lower, Upper, function):
23
        self.D = D  # dimension
24
        self.NP = NP  # population size
25
        self.nFES = nFES  # number of function evaluations
26
        self.A = A  # loudness
27
        self.r = r  # pulse rate
28
        self.Qmin = Qmin  # frequency min
29
        self.Qmax = Qmax  # frequency max
30
        self.Lower = Lower  # lower bound
31
        self.Upper = Upper  # upper bound
32
33
        self.f_min = 0.0  # minimum fitness
34
35
        self.Lb = [0] * self.D  # lower bound
36
        self.Ub = [0] * self.D  # upper bound
37
        self.Q = [0] * self.NP  # frequency
38
39
        self.v = [[0 for _i in range(self.D)]
40
                  for _j in range(self.NP)]  # velocity
41
        self.Sol = [[0 for _i in range(self.D)] for _j in range(
42
            self.NP)]  # population of solutions
43
        self.Fitness = [0] * self.NP  # fitness
44
        self.best = [0] * self.D  # best solution
45
        self.evaluations = 0  # evaluations counter
46
        if callable(function):
47 View Code Duplication
            self.Fun = function
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
48
        else:
49
            if function == 'rastrigin':
50
                self.Fun = Rastrigin().function()
51
            elif function == 'rosenbrock':
52
                self.Fun = Rosenbrock().function()
53
            elif function == 'griewank':
54
                self.Fun = Griewank().function()
55
            elif function == 'sphere':
56
                self.Fun = Sphere().function()
57 View Code Duplication
            else:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
58
                raise TypeError('Passed benchmark is not defined!')
59
60
    def best_bat(self):
61
        i = 0
62
        j = 0
63
        for i in range(self.NP):
64
            if self.Fitness[i] < self.Fitness[j]:
65
                j = i
66
        for i in range(self.D):
67
            self.best[i] = self.Sol[j][i]
68
        self.f_min = self.Fitness[j]
69
70
    def init_bat(self):
71
        for i in range(self.D):
72
            self.Lb[i] = self.Lower
73
            self.Ub[i] = self.Upper
74
75
        for i in range(self.NP):
76
            self.Q[i] = 0
77
            for j in range(self.D):
78
                rnd = random.uniform(0, 1)
79
                self.v[i][j] = 0.0
80
                self.Sol[i][j] = self.Lb[j] + (self.Ub[j] - self.Lb[j]) * rnd
81
            self.Fitness[i] = self.Fun(self.D, self.Sol[i])
82
            self.evaluations = self.evaluations + 1
83
        self.best_bat()
84
85
    @classmethod
86
    def simplebounds(cls, val, lower, upper):
87
        if val < lower:
88
            val = lower
89
        if val > upper:
90
            val = upper
91
        return val
92
93
    def move_bat(self):
94
        S = [[0.0 for i in range(self.D)] for j in range(self.NP)]
95
96
        self.init_bat()
97
98
        while True:
99
            if self.evaluations == self.nFES:
100
                break
101
102
            for i in range(self.NP):
103
                rnd = random.uniform(0, 1)
104
                self.Q[i] = self.Qmin + (self.Qmin - self.Qmax) * rnd
105
                for j in range(self.D):
106
                    self.v[i][j] = self.v[i][j] + (self.Sol[i][j] -
107
                                                   self.best[j]) * self.Q[i]
108
                    S[i][j] = self.Sol[i][j] + self.v[i][j]
109
110
                    S[i][j] = self.simplebounds(S[i][j], self.Lb[j],
111
                                                self.Ub[j])
112
113
                rnd = random.random()
114
115
                if rnd > self.r:
116
                    for j in range(self.D):
117
                        S[i][j] = self.best[j] + 0.001 * random.gauss(0, 1)
118
                        S[i][j] = self.simplebounds(S[i][j], self.Lb[j],
119
                                                    self.Ub[j])
120
121
                Fnew = self.Fun(self.D, S[i])
122
                self.evaluations = self.evaluations + 1
123
124
                rnd = random.random()
125
126
                if (Fnew <= self.Fitness[i]) and (rnd < self.A):
127
                    for j in range(self.D):
128
                        self.Sol[i][j] = S[i][j]
129
                    self.Fitness[i] = Fnew
130
131
                if Fnew <= self.f_min:
132
                    for j in range(self.D):
133
                        self.best[j] = S[i][j]
134
                    self.f_min = Fnew
135
136
        return self.f_min
137