Passed
Push — master ( 4b817d...f6ac83 )
by Grega
54s
created

FireflyAlgorithm.run()   B

Complexity

Conditions 4

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
c 0
b 0
f 0
dl 0
loc 26
rs 8.5806
1
"""Firefly algorithm.
2
3
Date: 2016
4
5
Authors : Iztok Fister Jr. and Iztok Fister
6
License: MIT
7
8
Reference paper: Fister, I., Fister Jr, I., Yang, X. S., & Brest, J. (2013).
9
A comprehensive review of firefly algorithms. Swarm and Evolutionary Computation, 13, 34-46.
10
"""
11
12
import random
13
import math
14
from NiaPy.benchmarks.utility import Utility
15
16
__all__ = ['FireflyAlgorithm']
17
18
19
class FireflyAlgorithm(object):
20
    """Firefly Algorithm implementation."""
21
22
    # pylint: disable=too-many-instance-attributes
23 View Code Duplication
    def __init__(self, D, NP, nFES, alpha, betamin, gamma, Lower, Upper, function):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
24
        self.D = D  # dimension of the problem
25
        self.NP = NP  # population size
26
        self.nFES = nFES  # number of function evaluations
27
        self.alpha = alpha  # alpha parameter
28
        self.betamin = betamin  # beta parameter
29
        self.gamma = gamma  # gamma parameter
30
        # sort of fireflies according to fitness value
31
        self.Index = [0] * self.NP
32
        self.Fireflies = [[0 for _i in range(self.D)]
33
                          for _j in range(self.NP)]  # firefly agents
34
        self.Fireflies_tmp = [[0 for _i in range(self.D)] for _j in range(
35
            self.NP)]  # intermediate pop
36
        self.Fitness = [0.0] * self.NP  # fitness values
37
        self.Intensity = [0.0] * self.NP  # light intensity
38
        self.nbest = [0.0] * self.NP  # the best solution found so far
39
        self.Lower = Lower  # lower bound
40
        self.Upper = Upper  # upper bound
41
        self.fbest = None  # the best
42
        self.evaluations = 0
43
        self.Fun = Utility.itialize_benchmark(function)
44
45
    def init_ffa(self):
46
        for i in range(self.NP):
47
            for j in range(self.D):
48
                self.Fireflies[i][j] = random.uniform(
49
                    0, 1) * (self.Upper - self.Lower) + self.Lower
50
            self.Fitness[i] = 1.0  # initialize attractiveness
51
            self.Intensity[i] = self.Fitness[i]
52
53
    def alpha_new(self, a):
54
        delta = 1.0 - math.pow((math.pow(10.0, -4.0) / 0.9), 1.0 / float(a))
55
        return (1 - delta) * self.alpha
56
57
    def sort_ffa(self):  # implementation of bubble sort
58
        for i in range(self.NP):
59
            self.Index[i] = i
60
61
        for i in range(0, (self.NP - 1)):
62
            j = i + 1
63
            for j in range(j, self.NP):
64
                if self.Intensity[i] > self.Intensity[j]:
65
                    z = self.Intensity[i]  # exchange attractiveness
66
                    self.Intensity[i] = self.Intensity[j]
67
                    self.Intensity[j] = z
68
                    z = self.Fitness[i]  # exchange fitness
69
                    self.Fitness[i] = self.Fitness[j]
70
                    self.Fitness[j] = z
71
                    z = self.Index[i]  # exchange indexes
72
                    self.Index[i] = self.Index[j]
73
                    self.Index[j] = z
74
75
    def replace_ffa(self):  # replace the old population according to the new Index values
76
        # copy original population to a temporary area
77
        for i in range(self.NP):
78
            for j in range(self.D):
79
                self.Fireflies_tmp[i][j] = self.Fireflies[i][j]
80
81
        # generational selection in the sense of an EA
82
        for i in range(self.NP):
83
            for j in range(self.D):
84
                self.Fireflies[i][j] = self.Fireflies_tmp[self.Index[i]][j]
85
86
    def FindLimits(self, k):
87
        for i in range(self.D):
88
            if self.Fireflies[k][i] < self.Lower:
89
                self.Fireflies[k][i] = self.Lower
90
            if self.Fireflies[k][i] > self.Upper:
91
                self.Fireflies[k][i] = self.Upper
92
93
    def move_ffa(self):
94
        for i in range(self.NP):
95
            scale = abs(self.Upper - self.Lower)
96
            for j in range(self.NP):
97
                r = 0.0
98
                for k in range(self.D):
99
                    r += (self.Fireflies[i][k] - self.Fireflies[j][k]) * \
100
                        (self.Fireflies[i][k] - self.Fireflies[j][k])
101
                r = math.sqrt(r)
102
                if self.Intensity[i] > self.Intensity[j]:  # brighter and more attractive
103
                    beta0 = 1.0
104
                    beta = (beta0 - self.betamin) * \
105
                        math.exp(-self.gamma * math.pow(r, 2.0)) + self.betamin
106
                    for k in range(self.D):
107
                        r = random.uniform(0, 1)
108
                        tmpf = self.alpha * (r - 0.5) * scale
109
                        self.Fireflies[i][k] = self.Fireflies[i][
110
                            k] * (1.0 - beta) + self.Fireflies_tmp[j][k] * beta + tmpf
111
            self.FindLimits(i)
112
113
    def run(self):
114
        self.init_ffa()
115
116
        while True:
117
            if self.evaluations == self.nFES:
118
                break
119
120
            # optional reducing of alpha
121
            self.alpha = self.alpha_new(self.nFES / self.NP)
122
123
            # evaluate new solutions
124
            for i in range(self.NP):
125
                self.Fitness[i] = self.Fun(self.D, self.Fireflies[i])
126
                self.evaluations = self.evaluations + 1
127
                self.Intensity[i] = self.Fitness[i]
128
129
            # ranking fireflies by their light intensity
130
            self.sort_ffa()
131
            # replace old population
132
            self.replace_ffa()
133
            # find the current best
134
            self.fbest = self.Intensity[0]
135
            # move all fireflies to the better locations
136
            self.move_ffa()
137
138
        return self.fbest
139