Passed
Push — master ( 3d8385...545ed9 )
by Grega
01:00
created

FlowerPollinationAlgorithm   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 118
Duplicated Lines 37.29 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 44
loc 118
rs 8.8
wmc 36

7 Methods

Rating   Name   Duplication   Size   Complexity  
B __init__() 22 22 5
A run() 0 2 1
F move_flower() 0 41 13
A init_flower() 12 13 4
A best_flower() 8 9 4
B Levy() 0 16 6
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
"""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 View Code Duplication
    def __init__(self, D, NP, nFES, p, benchmark):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
28
        self.benchmark = Utility.get_benchmark(benchmark)
29
        self.D = D  # dimension
30
        self.NP = NP  # population size
31
        self.nFES = nFES  # number of function evaluations
32
        self.p = p  # probability switch
33
        self.Lower = self.benchmark.Lower  # lower bound
34
        self.Upper = self.benchmark.Upper  # upper bound
35
        self.Fun = self.benchmark.function()  # function
36
37
        self.f_min = 0.0  # minimum fitness
38
39
        self.Lb = [0] * self.D  # lower bound
40
        self.Ub = [0] * self.D  # upper bound
41
42
        self.dS = [[0 for _i in range(self.D)]
43
                   for _j in range(self.NP)]  # differential
44
        self.Sol = [[0 for _i in range(self.D)]
45
                    for _j in range(self.NP)]  # population of solutions
46
        self.Fitness = [0] * self.NP  # fitness
47
        self.best = [0] * self.D  # best solution
48
        self.evaluations = 0  # evaluations counter
49 View Code Duplication
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
50
    def best_flower(self):
51
        i = 0
52
        j = 0
53
        for i in range(self.NP):
54
            if self.Fitness[i] < self.Fitness[j]:
55
                j = i
56
        for i in range(self.D):
57
            self.best[i] = self.Sol[j][i]
58
        self.f_min = self.Fitness[j]
59
60
    @classmethod
61
    def simplebounds(cls, val, lower, upper):
62
        if val < lower:
63
            val = lower
64
        if val > upper:
65
            val = upper
66
        return val
67 View Code Duplication
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
68
    def init_flower(self):
69
        for i in range(self.D):
70
            self.Lb[i] = self.Lower
71
            self.Ub[i] = self.Upper
72
73
        for i in range(self.NP):
74
            for j in range(self.D):
75
                rnd = random.uniform(0, 1)
76
                self.dS[i][j] = 0.0
77
                self.Sol[i][j] = self.Lb[j] + (self.Ub[j] - self.Lb[j]) * rnd
78
            self.Fitness[i] = self.Fun(self.D, self.Sol[i])
79
            self.evaluations = self.evaluations + 1
80
        self.best_flower()
81
82
    def move_flower(self):
83
        S = [[0.0 for i in range(self.D)] for j in range(self.NP)]
84
        self.init_flower()
85
86
        while True:
87
            if self.evaluations == self.nFES:
88
                break
89
90
            for i in range(self.NP):
91
                if random.uniform(0, 1) > self.p:  # probability switch
92
                    L = self.Levy()
93
                    for j in range(self.D):
94
                        self.dS[i][j] = L[j] * (self.Sol[i][j] - self.best[j])
95
                        S[i][j] = self.Sol[i][j] + self.dS[i][j]
96
97
                        S[i][j] = self.simplebounds(
98
                            S[i][j], self.Lb[j], self.Ub[j])
99
                else:
100
                    epsilon = random.uniform(0, 1)
101
                    JK = np.random.permutation(self.NP)
102
103
                    for j in range(self.D):
104
                        S[i][j] = S[i][j] + epsilon * \
105
                            (self.Sol[JK[0]][j] - self.Sol[JK[1]][j])
106
                        S[i][j] = self.simplebounds(
107
                            S[i][j], self.Lb[j], self.Ub[j])
108
109
                Fnew = self.Fun(self.D, S[i])
110
                self.evaluations = self.evaluations + 1
111
112
                if Fnew <= self.Fitness[i]:
113
                    for j in range(self.D):
114
                        self.Sol[i][j] = S[i][j]
115
                    self.Fitness[i] = Fnew
116
117
                if Fnew <= self.f_min:
118
                    for j in range(self.D):
119
                        self.best[j] = S[i][j]
120
                    self.f_min = Fnew
121
122
        return self.f_min
123
124
    def Levy(self):
125
        beta = 1.5
126
        sigma = (Gamma(1 + beta) * np.sin(np.pi * beta / 2) /
127
                 (Gamma((1 + beta) / 2) * beta * 2**((beta - 1) / 2)))**(1 / beta)
128
        u = [[0] for j in range(self.D)]
129
        v = [[0] for j in range(self.D)]
130
        step = [[0] for j in range(self.D)]
131
        L = [[0] for j in range(self.D)]
132
133
        for j in range(self.D):
134
            u[j] = np.random.normal(0, 1) * sigma
135
            v[j] = np.random.normal(0, 1)
136
            step[j] = u[j] / abs(v[j])**(1 / beta)
137
            L[j] = 0.01 * step[j]
138
139
        return L
140
141
    def run(self):
142
        return self.move_flower()
143