Passed
Pull Request — master (#233)
by Grega
01:17
created

CamelAlgorithm.getParameters()   A

Complexity

Conditions 1

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nop 1
dl 0
loc 17
rs 9.85
c 0
b 0
f 0
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