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

BatAlgorithm   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 117
Duplicated Lines 19.66 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 35
dl 23
loc 117
rs 9
c 1
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
F move_bat() 0 44 14
A init_bat() 1 14 4
F __init__() 11 37 10
A best_bat() 9 9 4
A simplebounds() 0 7 3

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
"""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