ArtificialBeeColonyAlgorithm.runIteration()   D
last analyzed

Complexity

Conditions 12

Size

Total Lines 54
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 32
nop 9
dl 0
loc 54
rs 4.8
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like NiaPy.algorithms.basic.abc.ArtificialBeeColonyAlgorithm.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
# encoding=utf8
2
import copy
3
import logging
4
5
from numpy import asarray, full, argmax
6
7
from NiaPy.algorithms.algorithm import Algorithm, Individual, defaultIndividualInit
8
9
logging.basicConfig()
10
logger = logging.getLogger('NiaPy.algorithms.basic')
11
logger.setLevel('INFO')
12
13
__all__ = ['ArtificialBeeColonyAlgorithm']
14
15
class SolutionABC(Individual):
16
	r"""Representation of solution for Artificial Bee Colony Algorithm.
17
18
	Date:
19
		2018
20
21
	Author:
22
		Klemen Berkovič
23
24
	See Also:
25
		* :class:`NiaPy.algorithms.Individual`
26
	"""
27
	def __init__(self, **kargs):
28
		r"""Initialize individual.
29
30
		Args:
31
			kargs (Dict[str, Any]): Additional arguments.
32
33
		See Also:
34
			* :func:`NiaPy.algorithms.Individual.__init__`
35
		"""
36
		Individual.__init__(self, **kargs)
37
38
class ArtificialBeeColonyAlgorithm(Algorithm):
39
	r"""Implementation of Artificial Bee Colony algorithm.
40
41
	Algorithm:
42
		Artificial Bee Colony algorithm
43
44
	Date:
45
		2018
46
47
	Author:
48
		Uros Mlakar and Klemen Berkovič
49
50
	License:
51
		MIT
52
53
	Reference paper:
54
		Karaboga, D., and Bahriye B. "A powerful and efficient algorithm for numerical function optimization: artificial bee colony (ABC) algorithm." Journal of global optimization 39.3 (2007): 459-471.
55
56
	Arguments
57
		Name (List[str]): List containing strings that represent algorithm names
58
		Limit (Union[float, numpy.ndarray[float]]): Limt
59
60
	See Also:
61
		* :class:`NiaPy.algorithms.Algorithm`
62
	"""
63
	Name = ['ArtificialBeeColonyAlgorithm', 'ABC']
64
65
	@staticmethod
66
	def algorithmInfo():
67
		r"""Get algorithms information.
68
69
		Returns:
70
			str: Algorithm information.
71
72
		See Also:
73
			* :func:`NiaPy.algorithms.Algorithm.algorithmInfo`
74
		"""
75
		return r"""Karaboga, D., and Bahriye B. "A powerful and efficient algorithm for numerical function optimization: artificial bee colony (ABC) algorithm." Journal of global optimization 39.3 (2007): 459-471."""
76
77
	@staticmethod
78
	def typeParameters():
79
		r"""Return functions for checking values of parameters.
80
81
		Returns:
82
			Dict[str, Callable]:
83
				* Limit (Callable[Union[float, numpy.ndarray[float]]]): TODO
84
85
		See Also:
86
			* :func:`NiaPy.algorithms.Algorithm.typeParameters`
87
		"""
88
		d = Algorithm.typeParameters()
89
		d.update({'Limit': lambda x: isinstance(x, int) and x > 0})
90
		return d
91
92
	def setParameters(self, NP=10, Limit=100, **ukwargs):
93
		r"""Set the parameters of Artificial Bee Colony Algorithm.
94
95
		Parameters:
96
			Limit (Optional[Union[float, numpy.ndarray[float]]]): Limt
97
			**ukwargs (Dict[str, Any]): Additional arguments
98
99
		See Also:
100
			* :func:`NiaPy.algorithms.Algorithm.setParameters`
101
		"""
102
		Algorithm.setParameters(self, NP=NP, InitPopFunc=defaultIndividualInit, itype=SolutionABC, **ukwargs)
103
		self.FoodNumber, self.Limit = int(self.NP / 2), Limit
104
105
	def CalculateProbs(self, Foods, Probs):
106
		r"""Calculate the probes.
107
108
		Parameters:
109
			Foods (numpy.ndarray): TODO
110
			Probs (numpy.ndarray): TODO
111
112
		Returns:
113
			numpy.ndarray: TODO
114
		"""
115
		Probs = [1.0 / (Foods[i].f + 0.01) for i in range(self.FoodNumber)]
116
		s = sum(Probs)
117
		Probs = [Probs[i] / s for i in range(self.FoodNumber)]
118
		return Probs
119
120
	def initPopulation(self, task):
121
		r"""Initialize the starting population.
122
123
		Parameters:
124
			task (Task): Optimization task
125
126
		Returns:
127
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
128
				1. New population
129
				2. New population fitness/function values
130
				3. Additional arguments:
131
					* Probes (numpy.ndarray): TODO
132
					* Trial (numpy.ndarray): TODO
133
134
		See Also:
135
			* :func:`NiaPy.algorithms.Algorithm.initPopulation`
136
		"""
137
		Foods, fpop, _ = Algorithm.initPopulation(self, task)
138
		Probs, Trial = full(self.FoodNumber, 0.0), full(self.FoodNumber, 0.0)
139
		return Foods, fpop, {'Probs': Probs, 'Trial': Trial}
140
141
	def runIteration(self, task, Foods, fpop, xb, fxb, Probs, Trial, **dparams):
142
		r"""Core funciton of  the algorithm.
143
144
		Parameters:
145
			task (Task): Optimization task
146
			Foods (numpy.ndarray): Current population
147
			fpop (numpy.ndarray[float]): Function/fitness values of current population
148
			xb (numpy.ndarray): Current best individual
149
			fxb (float): Current best individual fitness/function value
150
			Probs (numpy.ndarray): TODO
151
			Trial (numpy.ndarray): TODO
152
			dparams (Dict[str, Any]): Additional parameters
153
154
		Returns:
155
			Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
156
				1. New population
157
				2. New population fitness/function values
158
				3. New global best solution
159
				4. New global best fitness/objecive value
160
				5. Additional arguments:
161
					* Probes (numpy.ndarray): TODO
162
					* Trial (numpy.ndarray): TODO
163
		"""
164
		for i in range(self.FoodNumber):
165
			newSolution = copy.deepcopy(Foods[i])
166
			param2change = int(self.rand() * task.D)
167
			neighbor = int(self.FoodNumber * self.rand())
168
			newSolution.x[param2change] = Foods[i].x[param2change] + (-1 + 2 * self.rand()) * (Foods[i].x[param2change] - Foods[neighbor].x[param2change])
169
			newSolution.evaluate(task, rnd=self.Rand)
170
			if newSolution.f < Foods[i].f:
171
				Foods[i], Trial[i] = newSolution, 0
172
				if newSolution.f < fxb: xb, fxb = newSolution.x.copy(), newSolution.f
173
			else: Trial[i] += 1
174
		Probs, t, s = self.CalculateProbs(Foods, Probs), 0, 0
175
		while t < self.FoodNumber:
176
			if self.rand() < Probs[s]:
177
				t += 1
178
				Solution = copy.deepcopy(Foods[s])
179
				param2change = int(self.rand() * task.D)
180
				neighbor = int(self.FoodNumber * self.rand())
181
				while neighbor == s: neighbor = int(self.FoodNumber * self.rand())
182
				Solution.x[param2change] = Foods[s].x[param2change] + (-1 + 2 * self.rand()) * (Foods[s].x[param2change] - Foods[neighbor].x[param2change])
183
				Solution.evaluate(task, rnd=self.Rand)
184
				if Solution.f < Foods[s].f:
185
					Foods[s], Trial[s] = Solution, 0
186
					if Solution.f < fxb: xb, fxb = Solution.x.copy(), Solution.f
187
				else: Trial[s] += 1
188
			s += 1
189
			if s == self.FoodNumber: s = 0
190
		mi = argmax(Trial)
191
		if Trial[mi] >= self.Limit:
192
			Foods[mi], Trial[mi] = SolutionABC(task=task, rnd=self.Rand), 0
193
			if Foods[mi].f < fxb: xb, fxb = Foods[mi].x.copy(), Foods[mi].f
194
		return Foods, asarray([f.f for f in Foods]), xb, fxb, {'Probs': Probs, 'Trial': Trial}
195
196
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
197