NiaPy.algorithms.basic.ga.CrossoverUros()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 17
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nop 4
dl 0
loc 17
rs 10
c 0
b 0
f 0
1
# encoding=utf8
2
import logging
3
4
from numpy import argmin, sort, random as rand, asarray, fmin, fmax, sum, empty
5
6
from NiaPy.algorithms.algorithm import Algorithm, Individual, defaultIndividualInit
7
8
logging.basicConfig()
9
logger = logging.getLogger('NiaPy.algorithms.basic')
10
logger.setLevel('INFO')
11
12
__all__ = ['GeneticAlgorithm', 'TournamentSelection', 'RouletteSelection', 'TwoPointCrossover', 'MultiPointCrossover', 'UniformCrossover', 'UniformMutation', 'CreepMutation', 'CrossoverUros', 'MutationUros']
13
14
def TournamentSelection(pop, ic, ts, x_b, rnd=rand):
15
	r"""Tournament selection method.
16
17
	Args:
18
		pop (numpy.ndarray[Individual]): Current population.
19
		ic (int): Index of current individual in population.
20
		ts (int): Tournament size.
21
		x_b (Individual): Global best individual.
22
		rnd (mtrand.RandomState): Random generator.
23
24
	Returns:
25
		Individual: Winner of the tournament.
26
	"""
27
	comps = [pop[i] for i in rand.choice(len(pop), ts, replace=False)]
28
	return comps[argmin([c.f for c in comps])]
29
30
def RouletteSelection(pop, ic, ts, x_b, rnd=rand):
31
	r"""Roulette selection method.
32
33
	Args:
34
		pop (numpy.ndarray[Individual]): Current population.
35
		ic (int): Index of current individual in population.
36
		ts (int): Unused argument.
37
		x_b (Individual): Global best individual.
38
		rnd (mtrand.RandomState): Random generator.
39
40
	Returns:
41
		Individual: selected individual.
42
	"""
43
	f = sum([x.f for x in pop])
44
	qi = sum([pop[i].f / f for i in range(ic + 1)])
45
	return pop[ic].x if rnd.rand() < qi else x_b
46
47
def TwoPointCrossover(pop, ic, cr, rnd=rand):
48
	r"""Two point crossover method.
49
50
	Args:
51
		pop (numpy.ndarray[Individual]): Current population.
52
		ic (int): Index of current individual.
53
		cr (float): Crossover probability.
54
		rnd (mtrand.RandomState): Random generator.
55
56
	Returns:
57
		numpy.ndarray: New genotype.
58
	"""
59
	io = ic
60
	while io != ic: io = rnd.randint(len(pop))
61
	r = sort(rnd.choice(len(pop[ic]), 2))
62
	x = pop[ic].x
63
	x[r[0]:r[1]] = pop[io].x[r[0]:r[1]]
64
	return asarray(x)
65
66
def MultiPointCrossover(pop, ic, n, rnd=rand):
67
	r"""Multi point crossover method.
68
69
	Args:
70
		pop (numpy.ndarray[Individual]): Current population.
71
		ic (int): Index of current individual.
72
		n (flat): TODO.
73
		rnd (mtrand.RandomState): Random generator.
74
75
	Returns:
76
		numpy.ndarray: New genotype.
77
	"""
78
	io = ic
79
	while io != ic: io = rnd.randint(len(pop))
80
	r, x = sort(rnd.choice(len(pop[ic]), 2 * n)), pop[ic].x
81
	for i in range(n): x[r[2 * i]:r[2 * i + 1]] = pop[io].x[r[2 * i]:r[2 * i + 1]]
82
	return asarray(x)
83
84
def UniformCrossover(pop, ic, cr, rnd=rand):
85
	r"""Uniform crossover method.
86
87
	Args:
88
		pop (numpy.ndarray[Individual]): Current population.
89
		ic (int): Index of current individual.
90
		cr (float): Crossover probability.
91
		rnd (mtrand.RandomState): Random generator.
92
93
	Returns:
94
		numpy.ndarray: New genotype.
95
	"""
96
	io = ic
97
	while io != ic: io = rnd.randint(len(pop))
98
	j = rnd.randint(len(pop[ic]))
99
	x = [pop[io][i] if rnd.rand() < cr or i == j else pop[ic][i] for i in range(len(pop[ic]))]
100
	return asarray(x)
101
102
def CrossoverUros(pop, ic, cr, rnd=rand):
103
	r"""Crossover made by Uros Mlakar.
104
105
	Args:
106
		pop (numpy.ndarray[Individual]): Current population.
107
		ic (int): Index of current individual.
108
		cr (float): Crossover probability.
109
		rnd (mtrand.RandomState): Random generator.
110
111
	Returns:
112
		numpy.ndarray: New genotype.
113
	"""
114
	io = ic
115
	while io != ic: io = rnd.randint(len(pop))
116
	alpha = cr + (1 + 2 * cr) * rnd.rand(len(pop[ic]))
117
	x = alpha * pop[ic] + (1 - alpha) * pop[io]
118
	return x
119
120 View Code Duplication
def UniformMutation(pop, ic, mr, task, rnd=rand):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
121
	r"""Uniform mutation method.
122
123
	Args:
124
		pop (numpy.ndarray[Individual]): Current population.
125
		ic (int): Index of current individual.
126
		mr (float): Mutation probability.
127
		task (Task): Optimization task.
128
		rnd (mtrand.RandomState): Random generator.
129
130
	Returns:
131
		numpy.ndarray: New genotype.
132
	"""
133
	j = rnd.randint(task.D)
134
	nx = [rnd.uniform(task.Lower[i], task.Upper[i]) if rnd.rand() < mr or i == j else pop[ic][i] for i in range(task.D)]
135
	return asarray(nx)
136
137
def MutationUros(pop, ic, mr, task, rnd=rand):
138
	r"""Mutation method made by Uros Mlakar.
139
140
	Args:
141
		pop (numpy.ndarray[Individual]): Current population.
142
		ic (int): Index of individual.
143
		mr (float): Mutation rate.
144
		task (Task): Optimization task.
145
		rnd (mtrand.RandomState): Random generator.
146
147
	Returns:
148
		numpy.ndarray: New genotype.
149
	"""
150
	return fmin(fmax(rnd.normal(pop[ic], mr * task.bRange), task.Lower), task.Upper)
151
152 View Code Duplication
def CreepMutation(pop, ic, mr, task, rnd=rand):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
153
	r"""Creep mutation method.
154
155
	Args:
156
		pop (numpy.ndarray[Individual]): Current population.
157
		ic (int): Index of current individual.
158
		mr (float): Mutation probability.
159
		task (Task): Optimization task.
160
		rnd (mtrand.RandomState): Random generator.
161
162
	Returns:
163
		numpy.ndarray: New genotype.
164
	"""
165
	ic, j = rnd.randint(len(pop)), rnd.randint(task.D)
166
	nx = [rnd.uniform(task.Lower[i], task.Upper[i]) if rnd.rand() < mr or i == j else pop[ic][i] for i in range(task.D)]
167
	return asarray(nx)
168
169
class GeneticAlgorithm(Algorithm):
170
	r"""Implementation of Genetic Algorithm.
171
172
	Algorithm:
173
		Genetic algorithm
174
175
	Date:
176
		2018
177
178
	Author:
179
		Klemen Berkovič
180
181
	Reference paper:
182
		Goldberg, David (1989). Genetic Algorithms in Search, Optimization and Machine Learning. Reading, MA: Addison-Wesley Professional.
183
184
	License:
185
		MIT
186
187
	Attributes:
188
		Name (List[str]): List of strings representing algorithm name.
189
		Ts (int): Tournament size.
190
		Mr (float): Mutation rate.
191
		Cr (float): Crossover rate.
192
		Selection (Callable[[numpy.ndarray[Individual], int, int, Individual, mtrand.RandomState], Individual]): Selection operator.
193
		Crossover (Callable[[numpy.ndarray[Individual], int, float, mtrand.RandomState], Individual]): Crossover operator.
194
		Mutation (Callable[[numpy.ndarray[Individual], int, float, Task, mtrand.RandomState], Individual]): Mutation operator.
195
196
	See Also:
197
		* :class:`NiaPy.algorithms.Algorithm`
198
	"""
199
	Name = ['GeneticAlgorithm', 'GA']
200
201
	@staticmethod
202
	def algorithmInfo():
203
		r"""Get basic information of algorithm.
204
205
		Returns:
206
			str: Basic information of algorithm.
207
208
		See Also:
209
			* :func:`NiaPy.algorithms.Algorithm.algorithmInfo`
210
		"""
211
		return r"""On info"""
212
213
	@staticmethod
214
	def typeParameters():
215
		r"""Get dictionary with functions for checking values of parameters.
216
217
		Returns:
218
			Dict[str, Callable]:
219
				* Ts (Callable[[int], bool]): Tournament size.
220
				* Mr (Callable[[float], bool]): Probability of mutation.
221
				* Cr (Callable[[float], bool]): Probability of crossover.
222
223
		See Also:
224
			* :func:`NiaPy.algorithms.Algorithm.typeParameters`
225
		"""
226
		d = Algorithm.typeParameters()
227
		d.update({
228
			'Ts': lambda x: isinstance(x, int) and x > 1,
229
			'Mr': lambda x: isinstance(x, float) and 0 <= x <= 1,
230
			'Cr': lambda x: isinstance(x, float) and 0 <= x <= 1
231
		})
232
		return d
233
234
	def setParameters(self, NP=25, Ts=5, Mr=0.25, Cr=0.25, Selection=TournamentSelection, Crossover=UniformCrossover, Mutation=UniformMutation, **ukwargs):
235
		r"""Set the parameters of the algorithm.
236
237
		Arguments:
238
			NP (Optional[int]): Population size.
239
			Ts (Optional[int]): Tournament selection.
240
			Mr (Optional[int]): Mutation rate.
241
			Cr (Optional[float]): Crossover rate.
242
			Selection (Optional[Callable[[numpy.ndarray[Individual], int, int, Individual, mtrand.RandomState], Individual]]): Selection operator.
243
			Crossover (Optional[Callable[[numpy.ndarray[Individual], int, float, mtrand.RandomState], Individual]]): Crossover operator.
244
			Mutation (Optional[Callable[[numpy.ndarray[Individual], int, float, Task, mtrand.RandomState], Individual]]): Mutation operator.
245
246
		See Also:
247
			* :func:`NiaPy.algorithms.Algorithm.setParameters`
248
			* Selection:
249
				* :func:`NiaPy.algorithms.basic.TournamentSelection`
250
				* :func:`NiaPy.algorithms.basic.RouletteSelection`
251
			* Crossover:
252
				* :func:`NiaPy.algorithms.basic.UniformCrossover`
253
				* :func:`NiaPy.algorithms.basic.TwoPointCrossover`
254
				* :func:`NiaPy.algorithms.basic.MultiPointCrossover`
255
				* :func:`NiaPy.algorithms.basic.CrossoverUros`
256
			* Mutations:
257
				* :func:`NiaPy.algorithms.basic.UniformMutation`
258
				* :func:`NiaPy.algorithms.basic.CreepMutation`
259
				* :func:`NiaPy.algorithms.basic.MutationUros`
260
		"""
261
		Algorithm.setParameters(self, NP=NP, itype=ukwargs.pop('itype', Individual), InitPopFunc=ukwargs.pop('InitPopFunc', defaultIndividualInit), **ukwargs)
262
		self.Ts, self.Mr, self.Cr = Ts, Mr, Cr
263
		self.Selection, self.Crossover, self.Mutation = Selection, Crossover, Mutation
264
265
	def runIteration(self, task, pop, fpop, xb, fxb, **dparams):
266
		r"""Core function of GeneticAlgorithm algorithm.
267
268
		Args:
269
			task (Task): Optimization task.
270
			pop (numpy.ndarray): Current population.
271
			fpop (numpy.ndarray): Current populations fitness/function values.
272
			xb (numpy.ndarray): Global best individual.
273
			fxb (float): Global best individuals function/fitness value.
274
			**dparams (Dict[str, Any]): Additional arguments.
275
276
		Returns:
277
			Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
278
				1. New population.
279
				2. New populations function/fitness values.
280
				3. New global best solution
281
				4. New global best solutions fitness/objective value
282
				5. Additional arguments.
283
		"""
284
		npop = empty(self.NP, dtype=object)
285
		for i in range(self.NP):
286
			ind = self.itype(x=self.Selection(pop, i, self.Ts, xb, self.Rand), e=False)
287
			ind.x = self.Crossover(pop, i, self.Cr, self.Rand)
288
			ind.x = self.Mutation(pop, i, self.Mr, task, self.Rand)
289
			ind.evaluate(task, rnd=self.Rand)
290
			npop[i] = ind
291
			if npop[i].f < fxb: xb, fxb = self.getBest(npop[i], npop[i].f, xb, fxb)
292
		return npop, asarray([i.f for i in npop]), xb, fxb, {}
293
294
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
295