Passed
Push — master ( 4fbe02...684e9e )
by
unknown
57s
created

FireflyAlgorithm.FindLimits()   A

Complexity

Conditions 4

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
c 0
b 0
f 0
dl 0
loc 6
rs 9.2
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
21
    """Firefly Algorithm implementation."""
22
23
    # pylint: disable=too-many-instance-attributes
24
25
    def __init__(self, D, NP, nFES, alpha, betamin, gamma, benchmark):
26
        self.benchmark = Utility().get_benchmark(benchmark)
27
        self.D = D  # dimension of the problem
28
        self.NP = NP  # population size
29
        self.nFES = nFES  # number of function evaluations
30
        self.alpha = alpha  # alpha parameter
31
        self.betamin = betamin  # beta parameter
32
        self.gamma = gamma  # gamma parameter
33
        # sort of fireflies according to fitness value
34
        self.Index = [0] * self.NP
35
        self.Fireflies = [[0 for _i in range(self.D)]
36
                          for _j in range(self.NP)]  # firefly agents
37
        self.Fireflies_tmp = [[0 for _i in range(self.D)] for _j in range(
38
            self.NP)]  # intermediate pop
39
        self.Fitness = [0.0] * self.NP  # fitness values
40
        self.Intensity = [0.0] * self.NP  # light intensity
41
        self.nbest = [0.0] * self.NP  # the best solution found so far
42
        self.Lower = self.benchmark.Lower  # lower bound
43
        self.Upper = self.benchmark.Upper  # upper bound
44
        self.fbest = None  # the best
45
        self.evaluations = 0
46
        self.eval_flag = True  # evaluations flag
47
        self.Fun = self.benchmark.function()
48
49
    def init_ffa(self):
50
        for i in range(self.NP):
51
            for j in range(self.D):
52
                self.Fireflies[i][j] = random.uniform(
53
                    0, 1) * (self.Upper - self.Lower) + self.Lower
54
            self.Fitness[i] = 1.0  # initialize attractiveness
55
            self.Intensity[i] = self.Fitness[i]
56
57
    def alpha_new(self, a):
58
        delta = 1.0 - math.pow((math.pow(10.0, -4.0) / 0.9), 1.0 / float(a))
59
        return (1 - delta) * self.alpha
60
61
    def eval_true(self):
62
        """Check evaluations."""
63
64
        if self.evaluations == self.nFES:
65
            self.eval_flag = False
66
67
    def sort_ffa(self):  # implementation of bubble sort
68
        for i in range(self.NP):
69
            self.Index[i] = i
70
71
        for i in range(0, (self.NP - 1)):
72
            j = i + 1
73
            for j in range(j, self.NP):
74
                if self.Intensity[i] > self.Intensity[j]:
75
                    z = self.Intensity[i]  # exchange attractiveness
76
                    self.Intensity[i] = self.Intensity[j]
77
                    self.Intensity[j] = z
78
                    z = self.Fitness[i]  # exchange fitness
79
                    self.Fitness[i] = self.Fitness[j]
80
                    self.Fitness[j] = z
81
                    z = self.Index[i]  # exchange indexes
82
                    self.Index[i] = self.Index[j]
83
                    self.Index[j] = z
84
85
    def replace_ffa(self):  # replace the old population according to the new Index values
86
        # copy original population to a temporary area
87
        for i in range(self.NP):
88
            for j in range(self.D):
89
                self.Fireflies_tmp[i][j] = self.Fireflies[i][j]
90
91
        # generational selection in the sense of an EA
92
        for i in range(self.NP):
93
            for j in range(self.D):
94
                self.Fireflies[i][j] = self.Fireflies_tmp[self.Index[i]][j]
95
96
    def FindLimits(self, k):
97
        for i in range(self.D):
98
            if self.Fireflies[k][i] < self.Lower:
99
                self.Fireflies[k][i] = self.Lower
100
            if self.Fireflies[k][i] > self.Upper:
101
                self.Fireflies[k][i] = self.Upper
102
103
    def move_ffa(self):
104
        for i in range(self.NP):
105
            scale = abs(self.Upper - self.Lower)
106
            for j in range(self.NP):
107
                r = 0.0
108
                for k in range(self.D):
109
                    r += (self.Fireflies[i][k] - self.Fireflies[j][k]) * \
110
                        (self.Fireflies[i][k] - self.Fireflies[j][k])
111
                r = math.sqrt(r)
112
                if self.Intensity[i] > self.Intensity[j]:  # brighter and more attractive
113
                    beta0 = 1.0
114
                    beta = (beta0 - self.betamin) * \
115
                        math.exp(-self.gamma * math.pow(r, 2.0)) + self.betamin
116
                    for k in range(self.D):
117
                        r = random.uniform(0, 1)
118
                        tmpf = self.alpha * (r - 0.5) * scale
119
                        self.Fireflies[i][k] = self.Fireflies[i][
120
                            k] * (1.0 - beta) + self.Fireflies_tmp[j][k] * beta + tmpf
121
            self.FindLimits(i)
122
123
    def run(self):
124
        self.init_ffa()
125
126
        while self.eval_flag is not False:
127
128
            # optional reducing of alpha
129
            self.alpha = self.alpha_new(self.nFES / self.NP)
130
131
            # evaluate new solutions
132
            for i in range(self.NP):
133
134
                self.eval_true()
135
                if self.eval_flag is not True:
136
                    break
137
138
                self.Fitness[i] = self.Fun(self.D, self.Fireflies[i])
139
                self.evaluations = self.evaluations + 1
140
                self.Intensity[i] = self.Fitness[i]
141
142
            # ranking fireflies by their light intensity
143
            self.sort_ffa()
144
            # replace old population
145
            self.replace_ffa()
146
            # find the current best
147
            self.fbest = self.Intensity[0]
148
            # move all fireflies to the better locations
149
            self.move_ffa()
150
151
        return self.fbest
152