Passed
Pull Request — master (#233)
by
unknown
01:19
created

CamelAlgorithm.setParameters()   A

Complexity

Conditions 1

Size

Total Lines 17
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 10
dl 0
loc 17
rs 10
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, singleton-comparison, multiple-statements, attribute-defined-outside-init, no-self-use, logging-not-lazy, unused-variable, arguments-differ, bad-continuation, unused-argument, no-else-return
3
import logging
4
5
from numpy import exp, random as rand, asarray
6
7
from NiaPy.algorithms.algorithm import Algorithm, Individual
8
from NiaPy.util.utility import objects2array
9
10
logging.basicConfig()
11
logger = logging.getLogger('NiaPy.algorithms.basic')
12
logger.setLevel('INFO')
13
14
__all__ = ['CamelAlgorithm']
15
16
class Camel(Individual):
17
	r"""Implementation of population individual that is a camel for Camel algorithm.
18
19
	Algorithm:
20
		Camel algorithm
21
22
	Date:
23
		2018
24
25
	Authors:
26
		Klemen Berkovič
27
28
	License:
29
		MIT
30
31
	Attributes:
32
		E (float): Camel endurance.
33
		S (float): Camel supply.
34
		x_past (numpy.ndarray): Camel's past position.
35
		f_past (float): Camel's past funciton/fitness value.
36
		steps (int): Age of camel.
37
38
	See Also:
39
		* :class:`NiaPy.algorithms.Individual`
40
	"""
41
	def __init__(self, E_init=None, S_init=None, **kwargs):
42
		r"""Initialize the Camel.
43
44
		Args:
45
			E_init (Optional[float]): Starting endurance of Camel.
46
			S_init (Optional[float]): Stating supply of Camel.
47
			**kwargs (Dict[str, Any]): Additional arguments.
48
49
		See Also:
50
			* :func:`NiaPy.algorithms.Individual.__init__`
51
		"""
52
		Individual.__init__(self, **kwargs)
53
		self.E, self.E_past = E_init, E_init
54
		self.S, self.S_past = S_init, S_init
55
		self.x_past, self.f_past = self.x, self.f
56
		self.steps = 0
57
58
	def nextT(self, T_min, T_max, rnd=rand):
59
		r"""Apply nextT function on Camel.
60
61
		Args:
62
			T_min (float): TODO
63
			T_max (float): TODO
64
			rnd (Optional[mtrand.RandomState]): Random number generator.
65
		"""
66
		self.T = (T_max - T_min) * rnd.rand() + T_min
67
68
	def nextS(self, omega, n_gens):
69
		r"""Apply nextS on Camel.
70
71
		Args:
72
			omega (float): TODO.
73
			n_gens (int): Number of Camel Algorithm iterations/generations.
74
		"""
75
		self.S = self.S_past * (1 - omega * self.steps / n_gens)
76
77
	def nextE(self, n_gens, T_max):
78
		r"""Apply function nextE on function on Camel.
79
80
		Args:
81
			n_gens (int): Number of Camel Algorithm iterations/generations
82
			T_max (float): Maximum temperature of environment
83
		"""
84
		self.E = self.E_past * (1 - self.T / T_max) * (1 - self.steps / n_gens)
85
86
	def nextX(self, cb, E_init, S_init, task, rnd=rand):
87
		r"""Apply function nextX on Camel.
88
89
		This method/function move this Camel to new position in search space.
90
91
		Args:
92
			cb (Camel): Best Camel in population.
93
			E_init (float): Starting endurance of camel.
94
			S_init (float): Starting supply of camel.
95
			task (Task): Optimization task.
96
			rnd (Optional[mtrand.RandomState]): Random number generator.
97
		"""
98
		delta = -1 + rnd.rand() * 2
99
		self.x = self.x_past + delta * (1 - (self.E / E_init)) * exp(1 - self.S / S_init) * (cb - self.x_past)
100
		if not task.isFeasible(self.x): self.x = self.x_past
101
		else: self.f = task.eval(self.x)
102
103
	def next(self):
104
		r"""Save new position of Camel to old position."""
105
		self.x_past, self.f_past, self.E_past, self.S_past = self.x.copy(), self.f, self.E, self.S
106
		self.steps += 1
107
		return self
108
109
	def refill(self, S=None, E=None):
110
		r"""Apply this function to Camel.
111
112
		Args:
113
			S (float): New value of Camel supply.
114
			E (float): New value of Camel endurance.
115
		"""
116
		self.S, self.E = S, E
117
118
class CamelAlgorithm(Algorithm):
119
	r"""Implementation of Camel traveling behavior.
120
121
	Algorithm:
122
		Camel algorithm
123
124
	Date:
125
		2018
126
127
	Authors:
128
		Klemen Berkovič
129
130
	License:
131
		MIT
132
133
	Reference URL:
134
		https://www.iasj.net/iasj?func=fulltext&aId=118375
135
136
	Reference paper:
137
		Ali, Ramzy. (2016). Novel Optimization Algorithm Inspired by Camel Traveling Behavior. Iraq J. Electrical and Electronic Engineering. 12. 167-177.
138
139
	Attributes:
140
		Name (List[str]): List of strings representing name of the algorithm.
141
		T_min (float): Minimal temperature of environment.
142
		T_max (float): Maximal temperature of environment.
143
		E_init (float): Starting value of energy.
144
		S_init (float): Starting value of supplys.
145
146
	See Also:
147
		* :class:`NiaPy.algorithms.Algorithm`
148
	"""
149
	Name = ['CamelAlgorithm', 'CA']
150
151
	@staticmethod
152
	def algorithmInfo():
153
		r"""Get information about algorithm.
154
155
		Returns:
156
			str: Algorithm information
157
		"""
158
		return r'''Ali, Ramzy. (2016). Novel Optimization Algorithm Inspired by Camel Traveling Behavior. Iraq J. Electrical and Electronic Engineering. 12. 167-177.'''
159
160
	@staticmethod
161
	def typeParameters():
162
		r"""Get dictionary with functions for checking values of parameters.
163
164
		Returns:
165
			Dict[str, Callable]:
166
				* omega (Callable[[Union[int, float]], bool])
167
				* mu (Callable[[float], bool])
168
				* alpha (Callable[[float], bool])
169
				* S_init (Callable[[Union[float, int]], bool])
170
				* E_init (Callable[[Union[float, int]], bool])
171
				* T_min (Callable[[Union[float, int], bool])
172
				* T_max (Callable[[Union[float, int], bool])
173
174
		See Also:
175
			* :func:`NiaPy.algorithms.Algorithm.typeParameters`
176
		"""
177
		d = Algorithm.typeParameters()
178
		d.update({
179
			'omega': lambda x: isinstance(x, (float, int)),
180
			'mu': lambda x: isinstance(x, float) and 0 <= x <= 1,
181
			'alpha': lambda x: isinstance(x, float) and 0 <= x <= 1,
182
			'S_init': lambda x: isinstance(x, (float, int)) and x > 0,
183
			'E_init': lambda x: isinstance(x, (float, int)) and x > 0,
184
			'T_min': lambda x: isinstance(x, (float, int)) and x > 0,
185
			'T_max': lambda x: isinstance(x, (float, int)) and x > 0
186
		})
187
		return d
188
189
	def setParameters(self, NP=50, omega=0.25, mu=0.5, alpha=0.5, S_init=10, E_init=10, T_min=-10, T_max=10, **ukwargs):
190
		r"""Set the arguments of an algorithm.
191
192
		Arguments:
193
			NP (Optional[int]): Population size :math:`\in [1, \infty)`.
194
			T_min (Optional[float]): Minimum temperature, must be true :math:`$T_{min} < T_{max}`.
195
			T_max (Optional[float]): Maximum temperature, must be true :math:`T_{min} < T_{max}`.
196
			omega (Optional[float]): Burden factor :math:`\in [0, 1]`.
197
			mu (Optional[float]): Dying rate :math:`\in [0, 1]`.
198
			S_init (Optional[float]): Initial supply :math:`\in (0, \infty)`.
199
			E_init (Optional[float]): Initial endurance :math:`\in (0, \infty)`.
200
201
		See Also:
202
			* :func:`NiaPy.algorithms.Algorithm.setParameters`
203
		"""
204
		Algorithm.setParameters(self, NP=NP, itype=Camel, InitPopFunc=ukwargs.pop('InitPopFunc', self.initPop), **ukwargs)
205
		self.omega, self.mu, self.alpha, self.S_init, self.E_init, self.T_min, self.T_max = omega, mu, alpha, S_init, E_init, T_min, T_max
206
207
	def getParameters(self):
208
		r"""Get parameters of the algorithm.
209
210
		Returns:
211
			Dict[str, Any]:
212
		"""
213
		d = Algorithm.getParameters(self)
214
		d.update({
215
			'omega': self.omega,
216
			'mu': self.mu,
217
			'alpha': self.alpha,
218
			'S_init': self.S_init,
219
			'E_init': self.E_init,
220
			'T_min': self.T_min,
221
			'T_max': self.T_max
222
		})
223
		return d
224
225
	def initPop(self, task, NP, rnd, itype, **kwargs):
226
		r"""Initialize starting population.
227
228
		Args:
229
			task (Task): Optimization task.
230
			NP (int): Number of camels in population.
231
			rnd (mtrand.RandomState): Random number generator.
232
			itype (Individual): Individual type.
233
			**kwargs (Dict[str, Any]): Additional arguments.
234
235
		Returns:
236
			Tuple[numpy.ndarray[Camel], numpy.ndarray[float]]:
237
				1. Initialize population of camels.
238
				2. Initialized populations function/fitness values.
239
		"""
240
		caravan = objects2array([itype(E_init=self.E_init, S_init=self.S_init, task=task, rnd=rnd, e=True) for _ in range(NP)])
241
		return caravan, asarray([c.f for c in caravan])
242
243
	def walk(self, c, cb, task):
244
		r"""Move the camel in search space.
245
246
		Args:
247
			c (Camel): Camel that we want to move.
248
			cb (Camel): Best know camel.
249
			task (Task): Optimization task.
250
251
		Returns:
252
			Camel: Camel that moved in the search space.
253
		"""
254
		c.nextT(self.T_min, self.T_max, self.Rand)
255
		c.nextS(self.omega, task.nGEN)
256
		c.nextE(task.nGEN, self.T_max)
257
		c.nextX(cb, self.E_init, self.S_init, task, self.Rand)
258
		return c
259
260
	def oasis(self, c, rn, alpha):
261
		r"""Apply oasis function to camel.
262
263
		Args:
264
			c (Camel): Camel to apply oasis on.
265
			rn (float): Random number.
266
			alpha (float): View range of Camel.
267
268
		Returns:
269
			Camel: Camel with appliyed oasis on.
270
		"""
271
		if rn > 1 - alpha and c.f < c.f_past: c.refill(self.S_init, self.E_init)
272
		return c
273
274
	def lifeCycle(self, c, mu, task):
275
		r"""Apply life cycle to Camel.
276
277
		Args:
278
			c (Camel): Camel to apply life cycle.
279
			mu (float): Vision range of camel.
280
			task (Task): Optimization task.
281
282
		Returns:
283
			Camel: Camel with life cycle applyed to it.
284
		"""
285
		if c.f_past < mu * c.f: return Camel(self.E_init, self.S_init, rnd=self.Rand, task=task)
286
		else: return c.next()
287
288
	def initPopulation(self, task):
289
		r"""Initialize population.
290
291
		Args:
292
			task (Task): Optimization taks.
293
294
		Returns:
295
			Tuple[numpy.ndarray[Camel], numpy.ndarray[float], dict]:
296
				1. New population of Camels.
297
				2. New population fitness/function values.
298
				3. Additional arguments.
299
300
		See Also:
301
			* :func:`NiaPy.algorithms.Algorithm.initPopulation`
302
		"""
303
		caravan, fcaravan, _ = Algorithm.initPopulation(self, task)
304
		return caravan, fcaravan, {}
305
306
	def runIteration(self, task, caravan, fcaravan, cb, fcb, **dparams):
307
		r"""Core function of Camel Algorithm.
308
309
		Args:
310
			task (Task): Optimization task.
311
			caravan (numpy.ndarray[Camel]): Current population of Camels.
312
			fcaravan (numpy.ndarray[float]): Current population fitness/function values.
313
			cb (Camel): Current best Camel.
314
			fcb (float): Current best Camel fitness/function value.
315
			**dparams (Dict[str, Any]): Additional arguments.
316
317
		Returns:
318
			Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, folat, dict]:
319
				1. New population
320
				2. New population function/fitness value
321
				3. New global best solution
322
				4. New global best fitness/objective value
323
				5. Additional arguments
324
		"""
325
		ncaravan = objects2array([self.walk(c, cb, task) for c in caravan])
326
		ncaravan = objects2array([self.oasis(c, self.rand(), self.alpha) for c in ncaravan])
327
		ncaravan = objects2array([self.lifeCycle(c, self.mu, task) for c in ncaravan])
328
		fncaravan = asarray([c.f for c in ncaravan])
329
		cb, fcb = self.getBest(ncaravan, fncaravan, cb, fcb)
330
		return ncaravan, fncaravan, cb, fcb, {}
331
332
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
333