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

CoralReefsOptimization.asexualReprodution()   A

Complexity

Conditions 1

Size

Total Lines 22
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nop 6
dl 0
loc 22
rs 10
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, redefined-builtin, unused-argument, consider-using-enumerate, expression-not-assigned
3
import logging
4
from scipy.spatial.distance import euclidean
5
from numpy import apply_along_axis, argsort, where, random as rand, asarray, delete, sqrt, sum, unique, append
6
from NiaPy.algorithms.algorithm import Algorithm
7
8
logging.basicConfig()
9
logger = logging.getLogger('NiaPy.algorithms.basic')
10
logger.setLevel('INFO')
11
12
__all__ = ['CoralReefsOptimization']
13
14
def SexualCrossoverSimple(pop, p, task, rnd=rand, **kwargs):
15
	r"""Sexual reproduction of corals.
16
17
	Args:
18
		pop (numpy.ndarray): Current population.
19
		p (float): Probability in range [0, 1].
20
		task (Task): Optimization task.
21
		rnd (mtrand.RandomState): Random generator.
22
		**kwargs (Dict[str, Any]): Additional arguments.
23
24
	Returns:
25
		Tuple[numpy.ndarray, numpy.ndarray]:
26
			1. New population.
27
			2. New population function/fitness values.
28
	"""
29
	for i in range(len(pop) // 2): pop[i] = asarray([pop[i, d] if rnd.rand() < p else pop[i * 2, d] for d in range(task.D)])
30
	return pop, apply_along_axis(task.eval, 1, pop)
31
32
def BroodingSimple(pop, p, task, rnd=rand, **kwargs):
33
	r"""Brooding or internal sexual reproduction of corals.
34
35
	Args:
36
		pop (numpy.ndarray): Current population.
37
		p (float): Probability in range [0, 1].
38
		task (Task): Optimization task.
39
		rnd (mtrand.RandomState): Random generator.
40
		**kwargs (Dict[str, Any]): Additional arguments.
41
42
	Returns:
43
		Tuple[numpy.ndarray, numpy.ndarray]:
44
			1. New population.
45
			2. New population function/fitness values.
46
	"""
47
	for i in range(len(pop)): pop[i] = task.repair(asarray([pop[i, d] if rnd.rand() < p else task.Lower[d] + task.bRange[d] * rnd.rand() for d in range(task.D)]), rnd=rnd)
48
	return pop, apply_along_axis(task.eval, 1, pop)
49
50
def MoveCorals(pop, p, F, task, rnd=rand, **kwargs):
51
	r"""Move corals.
52
53
	Args:
54
		pop (numpy.ndarray): Current population.
55
		p (float): Probability in range [0, 1].
56
		F (float): Factor.
57
		task (Task): Optimization task.
58
		rnd (mtrand.RandomState): Random generator.
59
		**kwargs (Dict[str, Any]): Additional arguments.
60
61
	Returns:
62
		Tuple[numpy.ndarray, numpy.ndarray]:
63
			1. New population.
64
			2. New population function/fitness values.
65
	"""
66
	for i in range(len(pop)): pop[i] = task.repair(asarray([pop[i, d] if rnd.rand() < p else pop[i, d] + F * rnd.rand() for d in range(task.D)]), rnd=rnd)
67
	return pop, apply_along_axis(task.eval, 1, pop)
68
69
class CoralReefsOptimization(Algorithm):
70
	r"""Implementation of Coral Reefs Optimization Algorithm.
71
72
	Algorithm:
73
		Coral Reefs Optimization Algorithm
74
75
	Date:
76
		2018
77
78
	Authors:
79
		Klemen Berkovič
80
81
	License:
82
		MIT
83
84
	Reference Paper:
85
		S. Salcedo-Sanz, J. Del Ser, I. Landa-Torres, S. Gil-López, and J. A. Portilla-Figueras, “The Coral Reefs Optimization Algorithm: A Novel Metaheuristic for Efficiently Solving Optimization Problems,” The Scientific World Journal, vol. 2014, Article ID 739768, 15 pages, 2014.
86
87
	Reference URL:
88
		https://doi.org/10.1155/2014/739768.
89
90
	Attributes:
91
		Name (List[str]): List of strings representing algorithm name.
92
		phi (float): Range of neighborhood.
93
		Fa (int): Number of corals used in asexsual reproduction.
94
		Fb (int): Number of corals used in brooding.
95
		Fd (int): Number of corals used in depredation.
96
		k (int): Nomber of trys for larva setting.
97
		P_F (float): Mutation variable :math:`\in [0, \infty]`.
98
		P_Cr(float): Crossover rate in [0, 1].
99
		Distance (Callable[[numpy.ndarray, numpy.ndarray], float]): Funciton for calculating distance between corals.
100
		SexualCrossover (Callable[[numpy.ndarray, float, Task, mtrand.RandomState, Dict[str, Any]], Tuple[numpy.ndarray, numpy.ndarray[float]]]): Crossover function.
101
		Brooding (Callable[[numpy.ndarray, float, Task, mtrand.RandomState, Dict[str, Any]], Tuple[numpy.ndarray, numpy.ndarray]]): Brooding function.
102
103
	See Also:
104
		* :class:`NiaPy.algorithms.Algorithm`
105
	"""
106
	Name = ['CoralReefsOptimization', 'CRO']
107
108
	@staticmethod
109
	def typeParameters():
110
		r"""Get dictionary with functions for checking values of parameters.
111
112
		Returns:
113
			Dict[str, Callable]:
114
				* N (func): TODO
115
				* phi (func): TODO
116
				* Fa (func): TODO
117
				* Fb (func): TODO
118
				* Fd (func): TODO
119
				* k (func): TODO
120
		"""
121
		return {
122
			# TODO funkcije za testiranje
123
			'N': False,
124
			'phi': False,
125
			'Fa': False,
126
			'Fb': False,
127
			'Fd': False,
128
			'k': False
129
		}
130
131
	def setParameters(self, N=25, phi=0.4, Fa=0.5, Fb=0.5, Fd=0.3, k=25, P_Cr=0.5, P_F=0.36, SexualCrossover=SexualCrossoverSimple, Brooding=BroodingSimple, Distance=euclidean, **ukwargs):
132
		r"""Set the parameters of the algorithm.
133
134
		Arguments:
135
			N (int): population size for population initialization.
136
			phi (int): TODO.
137
			Fa (float): Value $\in [0, 1]$ for Asexual reproduction size.
138
			Fb (float): Value $\in [0, 1]$ for Brooding size.
139
			Fd (float): Value $\in [0, 1]$ for Depredation size.
140
			k (int): Trys for larvae setting.
141
			SexualCrossover (Callable[[numpy.ndarray, float, Task, mtrand.RandomState, Dict[str, Any]], Tuple[numpy.ndarray, numpy.ndarray]]): Crossover function.
142
			P_Cr (float): Crossover rate $\in [0, 1]$.
143
			Brooding (Callable[[numpy.ndarray, float, Task, mtrand.RandomState, Dict[str, Any]], Tuple[numpy.ndarray, numpy.ndarray]]): Brooding function.
144
			P_F (float): Crossover rate $\in [0, 1]$.
145
			Distance (Callable[[numpy.ndarray, numpy.ndarray], float]): Funciton for calculating distance between corals.
146
147
		See Also:
148
			* :func:`NiaPy.algorithms.Algorithm.setParameters`
149
		"""
150
		ukwargs.pop('NP', None)
151
		Algorithm.setParameters(self, NP=N, **ukwargs)
152
		self.phi, self.k, self.P_Cr, self.P_F = phi, k, P_Cr, P_F
153
		self.Fa, self.Fb, self.Fd = int(self.NP * Fa), int(self.NP * Fb), int(self.NP * Fd)
154
		self.SexualCrossover, self.Brooding, self.Distance = SexualCrossover, Brooding, Distance
155
156
	def getParameters(self):
157
		r"""Get parameters values of the algorithm.
158
159
		Returns:
160
			Dict[str, Any]: TODO.
161
		"""
162
		d = Algorithm.getParameters(self)
163
		d.update({
164
			'phi': self.phi,
165
			'k': self.k,
166
			'P_Cr': self.P_Cr,
167
			'P_F': self.P_F,
168
			'Fa': self.Fa,
169
			'Fd': self.Fd,
170
			'Fb': self.Fb
171
		})
172
		return d
173
174
	def asexualReprodution(self, Reef, Reef_f, xb, fxb, task):
175
		r"""Asexual reproduction of corals.
176
177
		Args:
178
			Reef (numpy.ndarray): Current population of reefs.
179
			Reef_f (numpy.ndarray): Current populations function/fitness values.
180
			task (Task): Optimization task.
181
182
		Returns:
183
			Tuple[numpy.ndarray, numpy.ndarray]:
184
				1. New population.
185
				2. New population fitness/funciton values.
186
187
		See Also:
188
			* :func:`NiaPy.algorithms.basic.CoralReefsOptimization.setting`
189
			* :func:`NiaPy.algorithms.basic.BroodingSimple`
190
		"""
191
		I = argsort(Reef_f)[:self.Fa]
192
		Reefn, Reefn_f = self.Brooding(Reef[I], self.P_F, task, rnd=self.Rand)
193
		xb, fxb = self.getBest(Reefn, Reefn_f, xb, fxb)
194
		Reef, Reef_f, xb, fxb = self.setting(Reef, Reef_f, Reefn, Reefn_f, xb, fxb, task)
195
		return Reef, Reef_f, xb, fxb
196
197
	def depredation(self, Reef, Reef_f):
198
		r"""Depredation operator for reefs.
199
200
		Args:
201
			Reef (numpy.ndarray): Current reefs.
202
			Reef_f (numpy.ndarray): Current reefs function/fitness values.
203
204
		Returns:
205
			Tuple[numpy.ndarray, numpy.ndarray]:
206
				1. Best individual
207
				2. Best individual fitness/function value
208
		"""
209
		I = argsort(Reef_f)[::-1][:self.Fd]
210
		return delete(Reef, I), delete(Reef_f, I)
211
212
	def setting(self, X, X_f, Xn, Xn_f, xb, fxb, task):
213
		r"""Operator for setting reefs.
214
215
		New reefs try to seatle to selected position in search space.
216
		New reefs are successful if theyr fitness values is better or if they have no reef ocupying same search space.
217
218
		Args:
219
			X (numpy.ndarray): Current population of reefs.
220
			X_f (numpy.ndarray): Current populations function/fitness values.
221
			Xn (numpy.ndarray): New population of reefs.
222
			Xn_f (array of float): New populations function/fitness values.
223
			xb (numpy.ndarray): Global best solution.
224
			fxb (float): Global best solutions fitness/objective value.
225
			task (Task): Optimization task.
226
227
		Returns:
228
			Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float]:
229
				1. New seatled population.
230
				2. New seatled population fitness/function values.
231
		"""
232
		def update(A, phi, xb, fxb):
233
			D = asarray([sqrt(sum((A - e) ** 2, axis=1)) for e in Xn])
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Xn does not seem to be defined.
Loading history...
234
			I = unique(where(D < phi)[0])
235
			if I.any():
236
				Xn[I], Xn_f[I] = MoveCorals(Xn[I], self.P_F, self.P_F, task, rnd=self.Rand)
237
				xb, fxb = self.getBest(Xn[I], Xn_f[I], xb, fxb)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Xn_f does not seem to be defined.
Loading history...
238
			return xb, fxb
239
		for i in range(self.k):
240
			xb, fxb = update(X, self.phi, xb, fxb)
241
			xb, fxb = update(Xn, self.phi, xb, fxb)
242
		D = asarray([sqrt(sum((X - e) ** 2, axis=1)) for e in Xn])
243
		I = unique(where(D >= self.phi)[0])
244
		return append(X, Xn[I], 0), append(X_f, Xn_f[I], 0), xb, fxb
245
246
	def runIteration(self, task, Reef, Reef_f, xb, fxb, **dparams):
247
		r"""Core function of Coral Reefs Optimization algorithm.
248
249
		Args:
250
			task (Task): Optimization task.
251
			Reef (numpy.ndarray): Current population.
252
			Reef_f (numpy.ndarray): Current population fitness/function value.
253
			xb (numpy.ndarray): Global best solution.
254
			fxb (float): Global best solution fitness/function value.
255
			**dparams: Additional arguments
256
257
		Returns:
258
			Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
259
				1. New population.
260
				2. New population fitness/function values.
261
				3. New global bset solution
262
				4. New global best solutions fitness/objective value
263
				5. Additional arguments:
264
265
		See Also:
266
			* :func:`NiaPy.algorithms.basic.CoralReefsOptimization.SexualCrossover`
267
			* :func:`NiaPy.algorithms.basic.CoralReefsOptimization.Brooding`
268
		"""
269
		I = self.Rand.choice(len(Reef), size=self.Fb, replace=False)
270
		Reefn_s, Reefn_s_f = self.SexualCrossover(Reef[I], self.P_Cr, task, rnd=self.Rand)
271
		xb, fxb = self.getBest(Reefn_s, Reefn_s_f, xb, fxb)
272
		Reefn_b, Reffn_b_f = self.Brooding(delete(Reef, I, 0), self.P_F, task, rnd=self.Rand)
273
		xb, fxb = self.getBest(Reefn_s, Reefn_s_f, xb, fxb)
274
		Reefn, Reefn_f, xb, fxb = self.setting(Reef, Reef_f, append(Reefn_s, Reefn_b, 0), append(Reefn_s_f, Reffn_b_f, 0), xb, fxb, task)
275
		Reef, Reef_f, xb, fxb = self.asexualReprodution(Reefn, Reefn_f, xb, fxb, task)
276
		if task.Iters % self.k == 0: Reef, Reef_f = self.depredation(Reef, Reef_f)
277
		return Reef, Reef_f, xb, fxb, {}
278
279
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
280