Completed
Pull Request — master (#21)
by Grega
01:03
created

BatAlgorithm.run()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 2
rs 10
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.utility import Utility
16
17
__all__ = ['BatAlgorithm']
18
19
20
class BatAlgorithm(object):
21
    """Bat Algorithm implementation."""
22
23
    # pylint: disable=too-many-instance-attributes
24 View Code Duplication
    def __init__(self, D, NP, nFES, A, r, Qmin, Qmax, benchmark):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
25
        """Initialize algorithm.
26
27
        Arguments:
28
            D {integer} -- dimension of problem
29
            NP {integer} -- population size
30
            nFES {integer} -- number of function evaluations
31
            A {decimal} -- loudness
32
            r {decimal} -- pulse rate
33
            Qmin {decimal} -- minimum frequency
34
            Qmax {decimal } -- maximum frequency
35
            benchmark {object} -- benchmark implementation object
36
37
        Raises:
38
            TypeError -- Raised when given benchmark function which does not exists.
39
40
        """
41
42
        self.benchmark = Utility.get_benchmark(benchmark)
43
        self.D = D  # dimension
44
        self.NP = NP  # population size
45
        self.nFES = nFES  # number of function evaluations
46
        self.A = A  # loudness
47
        self.r = r  # pulse rate
48
        self.Qmin = Qmin  # frequency min
49
        self.Qmax = Qmax  # frequency max
50
        self.Lower = self.benchmark.Lower  # lower bound
51
        self.Upper = self.benchmark.Upper  # upper bound
52
53
        self.f_min = 0.0  # minimum fitness
54
55
        self.Lb = [0] * self.D  # lower bound
56
        self.Ub = [0] * self.D  # upper bound
57
        self.Q = [0] * self.NP  # frequency
58
59
        self.v = [[0 for _i in range(self.D)]
60
                  for _j in range(self.NP)]  # velocity
61
        self.Sol = [[0 for _i in range(self.D)] for _j in range(
62
            self.NP)]  # population of solutions
63
        self.Fitness = [0] * self.NP  # fitness
64
        self.best = [0] * self.D  # best solution
65
        self.evaluations = 0  # evaluations counter
66
        self.Fun = self.benchmark.function()
67
68
    def best_bat(self):
69 View Code Duplication
        """Find best bat."""
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
70
71
        i = 0
72
        j = 0
73
        for i in range(self.NP):
74
            if self.Fitness[i] < self.Fitness[j]:
75
                j = i
76
        for i in range(self.D):
77
            self.best[i] = self.Sol[j][i]
78
        self.f_min = self.Fitness[j]
79
80
    def init_bat(self):
81 View Code Duplication
        """Initialize bat."""
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
82
83
        for i in range(self.D):
84
            self.Lb[i] = self.Lower
85
            self.Ub[i] = self.Upper
86
87
        for i in range(self.NP):
88
            self.Q[i] = 0
89
            for j in range(self.D):
90
                rnd = random.uniform(0, 1)
91
                self.v[i][j] = 0.0
92
                self.Sol[i][j] = self.Lb[j] + (self.Ub[j] - self.Lb[j]) * rnd
93
            self.Fitness[i] = self.Fun(self.D, self.Sol[i])
94
            self.evaluations = self.evaluations + 1
95
        self.best_bat()
96
97
    @classmethod
98
    def simplebounds(cls, val, lower, upper):
99
        if val < lower:
100
            val = lower
101
        if val > upper:
102
            val = upper
103
        return val
104
105
    def move_bat(self):
106
        S = [[0.0 for i in range(self.D)] for j in range(self.NP)]
107
108
        self.init_bat()
109
110
        while True:
111
            if self.evaluations == self.nFES:
112
                break
113
114
            for i in range(self.NP):
115
                rnd = random.uniform(0, 1)
116
                self.Q[i] = self.Qmin + (self.Qmin - self.Qmax) * rnd
117
                for j in range(self.D):
118
                    self.v[i][j] = self.v[i][j] + (self.Sol[i][j] -
119
                                                   self.best[j]) * self.Q[i]
120
                    S[i][j] = self.Sol[i][j] + self.v[i][j]
121
122
                    S[i][j] = self.simplebounds(S[i][j], self.Lb[j],
123
                                                self.Ub[j])
124
125
                rnd = random.random()
126
127
                if rnd > self.r:
128
                    for j in range(self.D):
129
                        S[i][j] = self.best[j] + 0.001 * random.gauss(0, 1)
130
                        S[i][j] = self.simplebounds(S[i][j], self.Lb[j],
131
                                                    self.Ub[j])
132
133
                Fnew = self.Fun(self.D, S[i])
134
                self.evaluations = self.evaluations + 1
135
136
                rnd = random.random()
137
138
                if (Fnew <= self.Fitness[i]) and (rnd < self.A):
139
                    for j in range(self.D):
140
                        self.Sol[i][j] = S[i][j]
141
                    self.Fitness[i] = Fnew
142
143
                if Fnew <= self.f_min:
144
                    for j in range(self.D):
145
                        self.best[j] = S[i][j]
146
                    self.f_min = Fnew
147
148
        return self.f_min
149
150
    def run(self):
151
        return self.move_bat()
152