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