Passed
Branch master (13db34)
by Grega
02:16
created

ArtificialBeeColonyAlgorithm.runIteration()   C

Complexity

Conditions 9

Size

Total Lines 46
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 26
nop 9
dl 0
loc 46
rs 6.6666
c 0
b 0
f 0

How to fix   Many Parameters   

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