Passed
Pull Request — master (#202)
by
unknown
01:02
created

NiaPy.algorithms.basic.cro.MoveCorals()   A

Complexity

Conditions 3

Size

Total Lines 18
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 3
nop 6
dl 0
loc 18
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[float]]:
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[float]]:
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[float]]:
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[float]]]): 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[float]]]): 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[float]]]): 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
		Algorithm.setParameters(self, NP=N)
151
		self.phi, self.k, self.P_Cr, self.P_F = phi, k, P_Cr, P_F
152
		self.Fa, self.Fb, self.Fd = int(self.NP * Fa), int(self.NP * Fb), int(self.NP * Fd)
153
		self.SexualCrossover, self.Brooding, self.Distance = SexualCrossover, Brooding, Distance
154
		if ukwargs: logger.info('Unused arguments: %s' % (ukwargs))
155
156
	def asexualReprodution(self, Reef, Reef_f, task):
157
		r"""Asexual reproduction of corals.
158
159
		Args:
160
			Reef (numpy.ndarray): Current population of reefs.
161
			Reef_f (numpy.ndarray[float]): Current populations function/fitness values.
162
			task (Task): Optimization task.
163
164
		Returns:
165
			Tuple[numpy.ndarray, numpy.ndarray[float]]:
166
				1. New population.
167
				2. New population fitness/funciton values.
168
169
		See Also:
170
			* :func:`NiaPy.algorithms.basic.CoralReefsOptimization.setting`
171
			* :func:`NiaPy.algorithms.basic.BroodingSimple`
172
		"""
173
		I = argsort(Reef_f)[:self.Fa]
174
		Reefn, Reefn_f = self.Brooding(Reef[I], self.P_F, task, rnd=self.Rand)
175
		Reef, Reef_f = self.setting(Reef, Reef_f, Reefn, Reefn_f, task)
176
		return Reef, Reef_f
177
178
	def depredation(self, Reef, Reef_f):
179
		r"""Depredation operator for reefs.
180
181
		Args:
182
			Reef (numpy.ndarray): Current reefs.
183
			Reef_f (numpy.ndarray[float]): Current reefs function/fitness values.
184
185
		Returns:
186
			Tuple[numpy.ndarray, numpy.ndarray[float]]:
187
				1. Best individual
188
				2. Best individual fitness/function value
189
		"""
190
		I = argsort(Reef_f)[::-1][:self.Fd]
191
		return delete(Reef, I), delete(Reef_f, I)
192
193
	def setting(self, X, X_f, Xn, Xn_f, task):
194
		r"""Operator for setting reefs.
195
196
		New reefs try to seatle to selected position in search space.
197
		New reefs are successful if theyr fitness values is better or if they have no reef ocupying same search space.
198
199
		Args:
200
			X (numpy.ndarray): Current population of reefs.
201
			X_f (numpy.ndarray[float]): Current populations function/fitness values.
202
			Xn (numpy.ndarray): New population of reefs.
203
			Xn_f (array of float): New populations function/fitness values.
204
			task (Task): Optimization task.
205
206
		Returns:
207
			Tuple[numpy.ndarray, numpy.ndarray[float]]:
208
				1. New seatled population.
209
				2. New seatled population fitness/function values.
210
		"""
211
		def update(A, phi):
212
			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...
213
			I = unique(where(D < phi)[0])
214
			if I.any(): Xn[I], Xn_f[I] = MoveCorals(Xn[I], self.P_F, self.P_F, task, rnd=self.Rand)
215
		for i in range(self.k): update(X, self.phi), update(Xn, self.phi)
216
		D = asarray([sqrt(sum((X - e) ** 2, axis=1)) for e in Xn])
217
		I = unique(where(D >= self.phi)[0])
218
		return append(X, Xn[I], 0), append(X_f, Xn_f[I], 0)
219
220
	def runIteration(self, task, Reef, Reef_f, xb, fxb, **dparams):
221
		r"""Core function of Coral Reefs Optimization algorithm.
222
223
		Args:
224
			task (Task): Optimization task.
225
			Reef (numpy.ndarray): Current population.
226
			Reef_f (numpy.ndarray[float]): Current population fitness/function value.
227
			xb (numpy.ndarray): Global best solution.
228
			fxb (float): Global best solution fitness/function value.
229
			**dparams: Additional arguments
230
231
		Returns:
232
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
233
				1. New population.
234
				2. New population fitness/function values.
235
				3. Additional arguments:
236
237
		See Also:
238
			* :func:`NiaPy.algorithms.basic.CoralReefsOptimization.SexualCrossover`
239
			* :func:`NiaPy.algorithms.basic.CoralReefsOptimization.Brooding`
240
		"""
241
		I = self.Rand.choice(len(Reef), size=self.Fb, replace=False)
242
		Reefn_s, Reefn_s_f = self.SexualCrossover(Reef[I], self.P_Cr, task, rnd=self.Rand)
243
		Reefn_b, Reffn_b_f = self.Brooding(delete(Reef, I, 0), self.P_F, task, rnd=self.Rand)
244
		Reefn, Reefn_f = self.setting(Reef, Reef_f, append(Reefn_s, Reefn_b, 0), append(Reefn_s_f, Reffn_b_f, 0), task)
245
		Reef, Reef_f = self.asexualReprodution(Reefn, Reefn_f, task)
246
		if task.Iters % self.k == 0: Reef, Reef_f = self.depredation(Reef, Reef_f)
247
		return Reef, Reef_f, {}
248
249
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
250