Passed
Push — master ( 246d84...6c9f44 )
by
unknown
01:06
created

FlowerPollinationAlgorithm.eval_true()   A

Complexity

Conditions 2

Size

Total Lines 5

Duplication

Lines 4
Ratio 80 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
dl 4
loc 5
rs 9.4285
1
"""Flower Pollination algorithm.
2
3
Date: February 2018
4
5
Authors : Dusan Fister & Iztok Fister Jr.
6
7
License: MIT
8
9
Reference paper: Yang, Xin-She. "Flower pollination algorithm for
10
global optimization." International conference on unconventional
11
computing and natural computation. Springer, Berlin, Heidelberg, 2012.
12
13
Implementation is based on the following MATLAB code:
14
https://www.mathworks.com/matlabcentral/fileexchange/45112-flower-pollination-algorithm?requestedDomain=true
15
"""
16
17
import random
18
import numpy as np
19
from scipy.special import gamma as Gamma
20
from NiaPy.benchmarks.utility import Utility
21
22
__all__ = ['FlowerPollinationAlgorithm']
23
24
25
class FlowerPollinationAlgorithm(object):
26
    # pylint: disable=too-many-instance-attributes
27
28
    def __init__(self, D, NP, nFES, p, benchmark):
29
        """Initialize algorithm.
30
31
        Arguments:
32
            D {integer} -- dimension of problem
33
            NP {integer} -- population size
34
            nFES {integer} -- number of function evaluations
35
            p {decimal} -- probability switch
36
            benchmark {object} -- benchmark implementation object
37
38
        Raises:
39
            TypeError -- Raised when given benchmark function which does not exists.
40
41
        """
42
43
        self.benchmark = Utility().get_benchmark(benchmark)
44
        self.D = D  # dimension
45
        self.NP = NP  # population size
46
        self.nFES = nFES  # number of function evaluations
47
        self.p = p  # probability switch
48
        self.Lower = self.benchmark.Lower  # lower bound
49
        self.Upper = self.benchmark.Upper  # upper bound
50
        self.Fun = self.benchmark.function()  # function
51
52
        self.f_min = 0.0  # minimum fitness
53
54
        self.Lb = [0] * self.D  # lower bound
55
        self.Ub = [0] * self.D  # upper bound
56
57
        self.dS = [[0 for _i in range(self.D)]
58
                   for _j in range(self.NP)]  # differential
59
        self.Sol = [[0 for _i in range(self.D)]
60
                    for _j in range(self.NP)]  # population of solutions
61
        self.Fitness = [0] * self.NP  # fitness
62
        self.best = [0] * self.D  # best solution
63
        self.eval_flag = True  # evaluations flag
64
        self.evaluations = 0  # evaluations counter
65
66
    def best_flower(self):
67 View Code Duplication
        i = 0
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
68
        j = 0
69
        for i in range(self.NP):
70
            if self.Fitness[i] < self.Fitness[j]:
71
                j = i
72
        for i in range(self.D):
73
            self.best[i] = self.Sol[j][i]
74
        self.f_min = self.Fitness[j]
75
76
    def eval_true(self):
77
        """Check evaluations."""
78
79
        if self.evaluations == self.nFES:
80
            self.eval_flag = False
81
82
    @classmethod
83
    def simplebounds(cls, val, lower, upper):
84
        if val < lower:
85
            val = lower
86
        if val > upper:
87
            val = upper
88
        return val
89
90
    def init_flower(self):
91
        for i in range(self.D):
92
            self.Lb[i] = self.Lower
93
            self.Ub[i] = self.Upper
94
95
        for i in range(self.NP):
96
            for j in range(self.D):
97
                rnd = random.uniform(0, 1)
98
                self.dS[i][j] = 0.0
99
                self.Sol[i][j] = self.Lb[j] + (self.Ub[j] - self.Lb[j]) * rnd
100
            self.Fitness[i] = self.Fun(self.D, self.Sol[i])
101
            self.evaluations = self.evaluations + 1
102
        self.best_flower()
103
104
    def move_flower(self):
105
        S = [[0.0 for i in range(self.D)] for j in range(self.NP)]
106
        self.init_flower()
107
108
        while self.eval_flag is not False:
109
            for i in range(self.NP):
110
                if random.uniform(0, 1) > self.p:  # probability switch
111
                    L = self.Levy()
112
                    for j in range(self.D):
113
                        self.dS[i][j] = L[j] * (self.Sol[i][j] - self.best[j])
114
                        S[i][j] = self.Sol[i][j] + self.dS[i][j]
115
116
                        S[i][j] = self.simplebounds(
117
                            S[i][j], self.Lb[j], self.Ub[j])
118
                else:
119
                    epsilon = random.uniform(0, 1)
120
                    JK = np.random.permutation(self.NP)
121
122
                    for j in range(self.D):
123
                        S[i][j] = S[i][j] + epsilon * \
124
                            (self.Sol[JK[0]][j] - self.Sol[JK[1]][j])
125
                        S[i][j] = self.simplebounds(
126
                            S[i][j], self.Lb[j], self.Ub[j])
127
128
                self.eval_true()
129
                if self.eval_flag is not True:
130
                    break
131
132
                Fnew = self.Fun(self.D, S[i])
133
                self.evaluations = self.evaluations + 1
134
135
                if Fnew <= self.Fitness[i]:
136
                    for j in range(self.D):
137
                        self.Sol[i][j] = S[i][j]
138
                    self.Fitness[i] = Fnew
139
140
                if Fnew <= self.f_min:
141
                    for j in range(self.D):
142
                        self.best[j] = S[i][j]
143
                    self.f_min = Fnew
144
        print self.evaluations
0 ignored issues
show
introduced by
invalid syntax (<string>, line 144)
Loading history...
145
        return self.f_min
146
147
    def Levy(self):
148
        beta = 1.5
149
        sigma = (Gamma(1 + beta) * np.sin(np.pi * beta / 2) /
150
                 (Gamma((1 + beta) / 2) * beta * 2**((beta - 1) / 2)))**(1 / beta)
151
        u = [[0] for j in range(self.D)]
152
        v = [[0] for j in range(self.D)]
153
        step = [[0] for j in range(self.D)]
154
        L = [[0] for j in range(self.D)]
155
156
        for j in range(self.D):
157
            u[j] = np.random.normal(0, 1) * sigma
158
            v[j] = np.random.normal(0, 1)
159
            step[j] = u[j] / abs(v[j])**(1 / beta)
160
            L[j] = 0.01 * step[j]
161
162
        return L
163
164
    def run(self):
165
        return self.move_flower()
166