forked from JCarlosR/Algoritmo-Genetico-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfirst_program.py
More file actions
408 lines (309 loc) · 9.28 KB
/
first_program.py
File metadata and controls
408 lines (309 loc) · 9.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
#coding:windows-1252
# Permite escribir usando tildes
from __future__ import unicode_literals
# Permite generar aleatorios
import random
# Variables globales definidas inicialmente
M = 6
A = 11
B = 7
limInferior = 1
probC = 0.5
probM = 0.35
iteraciones = 20
# Variables globales por definir
longC = 0
longC_X = 0
longC_Y = 0
# Variables que permiten encontrar el óptimo global
desviaciones = []
mejoresCromosomas = []
# Genera dos poblaciones, evitando el par (1, 1)
def generarPoblacion(pX, pY):
i = 0
while i < M:
pX += [ random.randrange(limInferior, B/2) ]
pY += [ random.randrange(limInferior, A/2) ]
# Basta que uno sea diferente de 1 para continuar
if pX[i] == 1 and pY[i] == 1:
pX.pop()
pY.pop()
else:
i += 1
# Cálculo de la longitud de cromosoma
def calcularLongitud():
global longC
global longC_X
global longC_Y
longC_X = len(toBinary(B/2))
longC_Y = len(toBinary(A/2))
longC = longC_X + longC_Y
# Devuelve el área no utilizada luego de los cortes
def evaluar(x, y):
# Longitud sobrante en la Altura
Sa = A % y
# Longitud sobrante en la Base
Sb = B % x
# Lo que desea calcular
sobranteTotal = 0
# Se usará _A y _B para calcular el área sobrante del sobrante
# Importante para no alterar el valor original de A y B
# Según la forma del retazo se intenta hacer más cortes
if x > y:
# El sobrante es el bloque 1
B1 = (B - Sb) * Sa
# Reasignación de A y B
_B = A
_A = Sb
# Calculamos las sobras de las sobras
Sa = _A % y
Sb = _B % x
sobranteMenor = _B * Sa + (_A - Sa) * Sb
# El total es
sobranteTotal = sobranteMenor + B1
elif y > x:
# El sobrante es el bloque 3
B3 = (A - Sa) * Sb
# Reasignación de A y B
_A = B
_B = Sa
# Calculamos las sobras de las sobras
Sa = _A % y
Sb = _B % x
sobranteMenor = _B * Sa + (_A - Sa) * Sb
# El total es
sobranteTotal = sobranteMenor + B3
else:
sobranteTotal = B * Sa + (A - Sa) * Sb
return sobranteTotal
# Cantidad de retazos útiles
def utiles(x, y):
if x > y:
return (B/x) * (A/y) + ((B%x)/y) * (A/x)
elif y > x:
return (B/x) * (A/y) + (B/y) * ((A%y)/x)
else:
return (B/x) * (A/y)
# Devuelve en un arreglo la conversión a binario
def toBinary(n, longitud=0):
arreglo = []
while n >= 2:
arreglo += [ n % 2 ]
n = n / 2
arreglo += [ n ]
if longitud == 0:
relleno = []
else:
relleno = [0] * (longitud-len(arreglo))
return arreglo + relleno
# Cruza la cantidad de genes indicada entre los cromosomas
def cruzar(cromosoma1, cromosoma2, genes):
for i in range(genes):
temporal = cromosoma1[i]
cromosoma1[i] = cromosoma2[i]
cromosoma2[i] = temporal
# Devuelve en decimal la conversión de un arreglo binario
def toDecimal(cromosoma):
resultado = 0
for i in range(len(cromosoma)):
resultado += cromosoma[i] * pow(2, i)
return resultado
# Clase para manejar los intervalos
class Intervalo:
def __init__(self, min, max):
self.min = min
self.max = max
def pertenece(self, valor):
return self.min<=valor and valor<=self.max
def toString(self):
return '[' + '{:.2f}'.format(self.min) + ' - ' + '{:.2f}'.format(self.max) + ']'
# Imprime un cromosoma con formato adecuado
def imprimirCromosoma(cromosoma):
cadena = ''
for gen in cromosoma:
cadena = str(gen) + cadena
numCeros = longC - len(cromosoma)
ceros = '0' * numCeros
print ceros, cadena
# Imprimir matriz con título
def imprimirMt(matriz):
for fila in matriz:
imprimirCromosoma(fila)
# Función principal
def main():
print "Bienvenido - Algoritmo genético de 2 variables"
# Calculamos la longitud de cromosoma total
calcularLongitud()
# Para cálculos posteriores
cromosomas = []
evaluaciones = []
columnaK = []
desviaciones = []
mejoresCromosomas = []
aleatorios = []
seleccion = []
posicionesCruce = []
cruzamiento = []
mutacion = []
# Primera población de individuos X e Y
poblacionX = []
poblacionY = []
generarPoblacion(poblacionX, poblacionY)
for ite in range(iteraciones):
print "Población X:", poblacionX
print "Población Y:", poblacionY
print 'Longitud de X: ', longC_X
print 'Longitud de Y: ', longC_Y
print 'Longitud total: ', longC
# Convertimos la primera población a cromosomas
for i in range(M):
# Se antepone Y y luego X, porque al imprimir se gira
cromosomas += [ toBinary(poblacionY[i], longC_Y) + toBinary(poblacionX[i], longC_X) ]
print 'Cromosomas: '
imprimirMt(cromosomas)
# Evaluamos
sumaEvaluaciones = 0
for i in range(M):
evaluacion = evaluar(poblacionX[i], poblacionY[i])
evaluaciones += [ evaluacion ]
sumaEvaluaciones += evaluacion
print 'Evaluaciones: ', evaluaciones
# Promedio de las evaluaciones (para la desviación estándar)
promedio = sumaEvaluaciones / M
##################################################
##### Desviación estándar
# Suma de cuadrados
sumaCuadrados = 0
for e in evaluaciones:
sumaCuadrados += pow(e - promedio, 2)
interno = sumaCuadrados / (M-1)
dS = pow(interno, 0.5)
# Guardamos la ds de la iteración actual
desviaciones += [ dS ]
#### Mejor individuo
# Posición del mejor cromosoma
minIndex = evaluaciones.index(min(evaluaciones))
# Guardamos el mejor cromosoma de la iteración actual
mejoresCromosomas += [ cromosomas[minIndex] ]
##################################################
# Cálculo de la columna K
for e in evaluaciones:
columnaK += [ float(e) / sumaEvaluaciones ]
print 'Columna K: ', columnaK
# Definición de los intervalos
intervalos = [ Intervalo(0, columnaK[0]) ]
inferior = columnaK[0] + 0.01
for i in range(1, M):
superior = intervalos[i-1].max + columnaK[i]
intervalos += [ Intervalo(inferior, superior) ]
inferior = superior + 0.01
# Listado de intervalos
print 'Intervalos: '
for intervalo in intervalos:
print intervalo.toString()
# Aleatorios para la selección
for i in range(M):
aleatorios += [ random.uniform(0, 1) ]
# Selección
for i in range(M):
seleccion += [0]
for j in range(M):
if intervalos[i].pertenece( aleatorios[j] ):
seleccion[i] += 1
print 'Selección: ', seleccion
# Reproducción
reproduccion = cromosomas[:]
for i in range(len(seleccion)):
for j in range(seleccion[i]-1):
for k in range(M):
if seleccion[k] == 0:
reproduccion[k] = cromosomas[i]
seleccion[k] += 1
break
print 'Reproducción: '
imprimirMt(reproduccion)
# Punto de cruce
ptoCruce = random.randrange(1, longC-1)
# Elegidos para cruzarse
for i in range(M):
if random.uniform(0, 1) <= probC:
posicionesCruce += [i]
print 'Fila escogida para el cruzamiento: ', i
# Cruzamiento
cruzamiento = reproduccion[:]
genesCruzar = longC - ptoCruce
print 'Genes a cruzar: ', genesCruzar
for i in range(0, len(posicionesCruce), 2):
if i+1 < len(posicionesCruce):
print 'Se cruzarán los cromosomas ', posicionesCruce[i], 'con ', posicionesCruce[i+1]
cruzar(cruzamiento[posicionesCruce[i]], cruzamiento[posicionesCruce[i+1]], genesCruzar)
print 'Cruzamiento: '
imprimirMt(cruzamiento)
# Mutación
mutacion = cruzamiento[:]
for i in range(M):
for j in range(len(cruzamiento[i])):
if random.uniform(0, 1) <= probM:
mutacion[i][j] = 1 if cruzamiento[i][j] == 0 else 0
print 'Mutó el cromosoma ', i, ' su gen ', j
print 'Mutación: '
imprimirMt(mutacion)
print 'Fin de la iteracion ', ite
# Luego de la mutación se corrigen los valores imposibles
i = 0
while i < M:
print 'Parte corresponde al x: ', mutacion[i][longC_Y:]
poblacionX[i] = toDecimal(mutacion[i][longC_Y:])
print 'Elem x de la mutacion en decimal es ', poblacionX[i]
if poblacionX[i] < 1 or poblacionX[i] > B/2:
poblacionX[i] = random.randrange(limInferior, B/2)
print 'Este elem x se cambio por ', poblacionX[i]
print 'Parte corresponde al y: ', mutacion[i][:longC_Y]
poblacionY[i] = toDecimal(mutacion[i][:longC_Y])
print 'Elem y de la mutacion en decimal es ', poblacionY[i]
if poblacionY[i] < 1 or poblacionY[i] > A/2:
poblacionY[i] = random.randrange(limInferior, A/2)
print 'Este elem y se cambio por ', poblacionY[i]
if poblacionX[i] == 1 and poblacionY[i] == 1:
x = random.randrange(limInferior, B/2)
y = random.randrange(limInferior, A/2)
mutacion[i] = toBinary(y) + toBinary(x)
else:
i = i + 1
cromosomas[:] = []
evaluaciones[:] = []
columnaK[:] = []
intervalos[:] = []
aleatorios[:] = []
seleccion[:] = []
reproduccion[:] = []
posicionesCruce[:] = []
cruzamiento[:] = []
mutacion[:] = []
# raw_input('Presione <ENTER> para continuar')
raw_input('Presione <ENTER> para ver resultados')
menorDS = 0;
for i in range(1, M):
if desviaciones[i] < desviaciones[menorDS]:
menorDS = i;
print 'La mejor población es la población: ', menorDS
mejorCromosoma = mejoresCromosomas[menorDS]
print 'El mejor cromosoma de la mejor generación es: '
imprimirCromosoma(mejorCromosoma)
print 'Parte X: ', mejorCromosoma[longC_Y:]
xOptimo = toDecimal(mejorCromosoma[longC_Y:])
print 'Valor X: ', xOptimo
print 'Parte Y: ', mejorCromosoma[:longC_Y]
yOptimo = toDecimal(mejorCromosoma[:longC_Y])
print 'Valor Y: ', yOptimo
print 'Retazos útiles: ', utiles(xOptimo, yOptimo)
print 'Área sobrante: ', evaluar(xOptimo, yOptimo)
# Sección de test
def test():
global A
global B
A = 10
B = 7
print utiles(4, 3)
print "funca" if utiles(4, 3) == 5 else "dada"
main()