BeesAlgorithm.runIteration()   C
last analyzed

Complexity

Conditions 10

Size

Total Lines 49
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 29
nop 8
dl 0
loc 49
rs 5.9999
c 0
b 0
f 0

How to fix   Complexity    Many Parameters   

Complexity

Complex classes like NiaPy.algorithms.basic.bea.BeesAlgorithm.runIteration() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
# coding=utf-8
2
import logging
3
from numpy import array, argsort, where
4
from NiaPy.algorithms.algorithm import Algorithm
5
6
__all__ = ['BeesAlgorithm']
7
8
logging.basicConfig()
9
logger = logging.getLogger('NiaPy.algorithms.basic')
10
logger.setLevel('INFO')
11
12
13
class BeesAlgorithm(Algorithm):
14
	r"""Implementation of Bees algorithm.
15
16
	Algorithm:
17
		 The Bees algorithm
18
19
	Date:
20
		 2019
21
22
	Authors:
23
		 Rok Potočnik
24
25
	License:
26
		 MIT
27
28
	Reference paper:
29
		 DT Pham, A Ghanbarzadeh, E Koc, S Otri, S Rahim, and M Zaidi. The bees algorithm-a novel tool for complex optimisation problems. In Proceedings of the 2nd Virtual International Conference on Intelligent Production Machines and Systems (IPROMS 2006), pages 454–459, 2006
30
31
	Attributes:
32
		 NP (Optional[int]): Number of scout bees parameter.
33
		 m (Optional[int]): Number of sites selected out of n visited sites parameter.
34
		 e (Optional[int]): Number of best sites out of m selected sitest parameter.
35
		 nep (Optional[int]): Number of bees recruited for best e sites parameter.
36
		 nsp (Optional[int]): Number of bees recruited for the other selected sites parameter.
37
		 ngh (Optional[float]): Initial size of patches parameter.
38
		 ukwargs (Dict[str, Any]): Additional arguments.
39
40
	See Also:
41
		 * :func:`NiaPy.algorithms.Algorithm.setParameters`
42
43
	"""
44
	Name = ['BeesAlgorithm', 'BEA']
45
46
	@staticmethod
47
	def algorithmInfo():
48
		r"""Get information about algorithm.
49
50
		Returns:
51
			str: Algorithm information
52
53
		See Also:
54
			* :func:`NiaPy.algorithms.Algorithm.algorithmInfo`
55
		"""
56
		return r"""DT Pham, A Ghanbarzadeh, E Koc, S Otri, S Rahim, and M Zaidi. The bees algorithm-a novel tool for complex optimisation problems. In Proceedings of the 2nd Virtual International Conference on Intelligent Production Machines and Systems (IPROMS 2006), pages 454–459, 2006"""
57
58 View Code Duplication
	@staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
59
	def typeParameters():
60
		r"""Get dictionary with functions for checking values of parameters.
61
62
		Returns:
63
			 Dict[str, Callable]:
64
				  * NP (Callable[[int], bool]): Checks if number of bees parameter has a proper value.
65
				  * m (Callable[[int], bool]): Checks if number of selected sites parameter has a proper value.
66
				  * e (Callable[[int], bool]): Checks if number of elite selected sites parameter has a proper value.
67
				  * nep (Callable[[int], bool]): Checks if number of elite bees parameter has a proper value.
68
				  * nsp (Callable[[int], bool]): Checks if number of other bees parameter has a proper value.
69
				  * ngh (Callable[[float], bool]): Checks if size of patches parameter has a proper value.
70
71
		See Also:
72
			 * :func:`NiaPy.algorithms.algorithm.Algorithm.typeParameters`
73
		"""
74
		d = Algorithm.typeParameters()
75
		d.update({
76
			'NP': lambda x: isinstance(x, int) and x > 0,
77
			'm': lambda x: isinstance(x, int) and x > 0,
78
			'e': lambda x: isinstance(x, int) and x > 0,
79
			'nep': lambda x: isinstance(x, int) and x > 0,
80
			'nsp': lambda x: isinstance(x, int) and x > 0,
81
			'ngh': lambda x: isinstance(x, float) and x > 0
82
		})
83
		return d
84
85
	def setParameters(self, NP=40, m=5, e=4, ngh=1, nep=4, nsp=2, **ukwargs):
86
		r"""Set the parameters of the algorithm.
87
88
		Args:
89
			 NP (Optional[int]): Number of scout bees parameter.
90
			 m (Optional[int]): Number of sites selected out of n visited sites parameter.
91
			 e (Optional[int]): Number of best sites out of m selected sitest parameter.
92
			 nep (Optional[int]): Number of bees recruited for best e sites parameter.
93
			 nsp (Optional[int]): Number of bees recruited for the other selected sites parameter.
94
			 ngh (Optional[float]): Initial size of patches parameter.
95
			 ukwargs (Dict[str, Any]): Additional arguments.
96
97
		See Also:
98
			 * :func:`NiaPy.algorithms.Algorithm.setParameters`
99
		"""
100
		Algorithm.setParameters(self, NP=NP, **ukwargs)
101
		self.n, self.m, self.e, self.nep, self.nsp, self.ngh = NP, m, e, nep, nsp, ngh
102
103
	def getParameters(self):
104
		r"""Get parameters of the algorithm.
105
106
		Returns:
107
			 Dict[str, Any]:
108
		"""
109
		d = Algorithm.getParameters(self)
110
		d.update({
111
			'm': self.m,
112
			'e': self.e,
113
			'ngh': self.ngh,
114
			'nep': self.nep,
115
			'nsp': self.nsp
116
		})
117
		return d
118
119
	def beeDance(self, x, task, ngh):
120
		r"""Bees Dance. Search for new positions.
121
122
		Args:
123
			 x (numpy.ndarray): One instance from the population.
124
			 task (Task): Optimization task.
125
			 ngh (float): A small value for patch search.
126
127
		Returns:
128
			 Tuple[numpy.ndarray, float]:
129
				  1. New population.
130
				  2. New population fitness/function values.
131
132
		See Also:
133
			 * :func:`NiaPy.algorithms.Algorithm.initPopulation`
134
		"""
135
		ind = self.randint(task.D)
136
		y = array(x, copy=True)
137
		y[ind] = x[ind] + self.uniform(-ngh, ngh)
138
		y = self.repair(y, task.Lower, task.Upper)
139
		res = task.eval(y)
140
		return y, res
141
142
	def initPopulation(self, task):
143
		r"""Initialize the starting population.
144
145
		Args:
146
			 task (Task): Optimization task
147
148
		Returns:
149
			 Tuple[numpy.ndarray, numpy.ndarray, Dict[str, Any]]:
150
				  1. New population.
151
				  2. New population fitness/function values.
152
153
		See Also:
154
			 * :func:`NiaPy.algorithms.Algorithm.initPopulation`
155
		"""
156
		BeesPosition, BeesCost, _ = Algorithm.initPopulation(self, task)
157
158
		idxs = argsort(BeesCost)
159
		BeesCost = BeesCost[idxs]
160
		BeesPosition = BeesPosition[idxs, :]
161
162
		return BeesPosition, BeesCost, {'ngh': self.ngh}
163
164 View Code Duplication
	def repair(self, x, lower, upper):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
165
		r"""Truncate exceeded dimensions to the limits.
166
167
		Args:
168
			 x (numpy.ndarray): Individual to repair.
169
			 lower (numpy.ndarray): Lower limits for dimensions.
170
			 upper (numpy.ndarray): Upper limits for dimensions.
171
172
		Returns:
173
			 numpy.ndarray: Repaired individual.
174
		"""
175
		ir = where(x < lower)
176
		x[ir] = lower[ir]
177
		ir = where(x > upper)
178
		x[ir] = upper[ir]
179
		return x
180
181
	def runIteration(self, task, BeesPosition, BeesCost, xb, fxb, ngh, **dparams):
182
		r"""Core function of Forest Optimization Algorithm.
183
184
		Args:
185
			 task (Task): Optimization task.
186
			 BeesPosition (numpy.ndarray[float]): Current population.
187
			 BeesCost (numpy.ndarray[float]): Current population function/fitness values.
188
			 xb (numpy.ndarray): Global best individual.
189
			 fxb (float): Global best individual fitness/function value.
190
			 ngh (float): A small value used for patches.
191
			 **dparams (Dict[str, Any]): Additional arguments.
192
193
		Returns:
194
			 Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
195
				  1. New population.
196
				  2. New population fitness/function values.
197
				  3. New global best solution.
198
				  4. New global best fitness/objective value.
199
				  5. Additional arguments:
200
						* ngh (float): A small value used for patches.
201
		"""
202
		for ies in range(self.e):
203
			BestBeeCost = float('inf')
204
			for ieb in range(self.nep):
205
				NewBeePos, NewBeeCost = self.beeDance(BeesPosition[ies, :], task, ngh)
206
				if NewBeeCost < BestBeeCost:
207
					BestBeeCost = NewBeeCost
208
					BestBeePos = NewBeePos
209
			if BestBeeCost < BeesCost[ies]:
210
				BeesPosition[ies, :] = BestBeePos
0 ignored issues
show
introduced by
The variable BestBeePos does not seem to be defined for all execution paths.
Loading history...
211
				BeesCost[ies] = BestBeeCost
212
		for ies in range(self.e, self.m):
213
			BestBeeCost = float('inf')
214
			for ieb in range(self.nsp):
215
				NewBeePos, NewBeeCost = self.beeDance(BeesPosition[ies, :], task, ngh)
216
				if NewBeeCost < BestBeeCost:
217
					BestBeeCost = NewBeeCost
218
					BestBeePos = NewBeePos
219
			if BestBeeCost < BeesCost[ies]:
220
				BeesPosition[ies, :] = BestBeePos
221
				BeesCost[ies] = BestBeeCost
222
		for ies in range(self.m, self.n):
223
			BeesPosition[ies, :] = array(self.uniform(task.Lower, task.Upper, task.D))
224
			BeesCost[ies] = task.eval(BeesPosition[ies, :])
225
		idxs = argsort(BeesCost)
226
		BeesCost = BeesCost[idxs]
227
		BeesPosition = BeesPosition[idxs, :]
228
		ngh = ngh * 0.95
229
		return BeesPosition, BeesCost, BeesPosition[0].copy(), BeesCost[0], {'ngh': ngh}
230
231
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
232