Documentos de Académico
Documentos de Profesional
Documentos de Cultura
2163047829
Introducción
El presente trabajo presenta un análisis al problema de minimizar una función 𝑓(𝑥, 𝑦) usando algoritmos geneticos, en este caso
usando el algoritmo evolución diferencial. Se analiza a detalle el modelo propuesto, así como se observan variaciones en los
parámetros posibles del algoritmo, analizando varias ejecuciones del algoritmo.
El problema de minimizar una función 𝑓(𝑥, 𝑦) consiste en evaluar una solución de dos coordenadas que al evaluar sus
componentes nos dé el mínimo global.
La función dada para este problema es la función de Easom, tiene varios mínimos locales. Es unimodal, y el mínimo global tiene
un área pequeña en relación con el espacio de búsqueda.
A) Función de aptitud
B) Población inicial
La población inicial puede elegirse en el código modificando el tam_poblacion, y se uso una estructura de datos matriz para
guardar las coordenadas en binario que genera el método
Siguiendo los apuntes se decide usar binarios, para ello utilizamos nuestro rango de posibles soluciones −100 ≤ 𝑥, 𝑦 ≤ 100
Contreras Villanueva Israel
2163047829
Seleccionamos la precisión del binario
𝑃𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛 = 103
200(103 ) = 200000
2𝑥 ≥ 200000
𝑥 = 18
v1 = (100110100000001111111010011011111)
.
.
vn = (100110100000001111111010011011111)
Para obtener el valor decimal de una coordenada binaria utilizamos la siguiente formula:
x=-100+a*(100-(-100))/((2**18)-1)
y=-100+b*(100-(-100))/((2**18)-1)
Para esto se implementó la función nex_generacion esta función contiene los dos modos de cruza.
Para el torneo mínimo se necesita que la población sea de 4 ya que se generan 2 parejas de la matriz, estas 4 parejas
son seleccionada al azar y distintas entre sí.
La primera pareja se mide en una “pelea” de la cual la victoria la definirá la aptitud de ese cromosoma
Para casi terminar definimos la “pelea final” con los ganadores de la primera y segunda pelea.
Para la ruleta necesitamos el vector aptitud que contiene la aptitud de cada cromosoma
Un punto:
Intercambiamos los bits que entraron en el corte con x y y, es decir, el corte en x a partir de la posición de corte intercambiamos
los valores con los de y en el mismo punto de corte, y caso contrario con y, a partir del corte intercambiamos los valores de y
por los de x en el mismo corte.
Dos puntos:
Generamos un aleatorio entre 0 y 17 para saber cuales van a ser los puntos de corte
Intercambiamos los bits que están dentro del rango de corte, si cortamos en x intercambiamos con los de y, y viceversa.
F) Mutación
Recorremos todos los cromosomas y definimos una probabilidad de muta, generamos un aleatorio entre 0 y 1
Si el aleatorio es menor que la probabilidad de mutación entonces se genera un nuevo aleatorio entre 0 y 17 el cual será la
posición en la que mutaremos el bit, es decir, si el bit en la posición del aleatorio se encuentra un 1 lo cambiamos a 0 y si es 0 lo
pasamos a 1.
En caso de que no se cumpla la condición de la probabilidad, es decir, no mutar, simplemente pasaremos el cromosoma sin
mutar (sin intercambiar nada)
G) Criterios de paro
Como criterios de paro solamente tenemos el numero de generaciones que controla el ciclo while.
Contreras Villanueva Israel
2163047829
2.- Implementación del algoritmo en Python
1.
2. import random
3. import math
4. import sys
5.
6. class Funciones:
7.
8. def Mostrar(matriz):
9. #print("La matriz es la siguiente:")
10. for fila in matriz:
11. for valor in fila:
12. print("\t", valor, end=" ")
13. print()
14.
15. def Mostrar_arreglo(arreglo):
16. #print("La matriz es la siguiente:")
17. for fila in arreglo:
18. print("\t", fila, end=" ")
19. print()
20.
21. def binarizar(decimal):
22. binario = ''
23. while decimal // 2 != 0:
24. binario = str(decimal % 2) + binario
25. decimal = decimal // 2
26. return str(decimal) + binario
27.
28. #Funcion que devuelve una lista de randoms diferentes entre si, recibe m ya
que esta definido por el ciclo
29. def unico(m,num_poblacion):
30. L=[m] #este es L[0]
31. i=1
32. while i<4:
33. x=random.randint(0,num_poblacion-1)
34. for j in range(0, len(L)):
35. if L[j]==x:
36. break
37. else:
38. L.append(x)
39. i+=1
40. return L
41. #--------------------------------------------------------------
42.
43. #--------------------------------------------------------------
44.
45. def creacion_de_poblacion(num_poblacion,num_variables,lim_inf,lim_sup):
46. poblacion = []
47. for i in range(num_poblacion):
48. poblacion.append([(int(bin(random.randint(2**17,2**18))[2:]) ),(int(bi
n(random.randint(2**17,2**18))[2:]) )])
49. return poblacion
50. #--------------------------------------------------------------
51.
52. #--------------------------------------------------------------
53.
54. def aptitud(poblacion,num_poblacion):
55. aptitud_pobla=[]
56. #print("\tx\t\t\ty")
57. for i in range(num_poblacion):
58. #funcion = -()
59. a=int(str(poblacion[i][0]), 2)
60. b=int(str(poblacion[i][1]), 2)
61.
Contreras Villanueva Israel
2163047829
62. x=-100+a*(100-(-100))/((2**18)-1) #El original es a 18
63. y=-100+b*(100-(-100))/((2**18)-1) #El original es a 18
64. #print("[",x,"\t",y,"]")
65.
66. funcion = 1/(1+(-(math.cos(x))*math.cos(y)*math.exp(-(math.pow((x-
math.pi),2))-(math.pow((y-math.pi),2))))) #Funcion de aptitud
67.
68. aptitud_pobla.append(funcion)
69. return aptitud_pobla
70. #--------------------------------------------------------------
71.
72.
73. def nex_generacion(aptitudes,modo,poblacion,num_poblacion):
74. elegidos = []
75.
76. if modo == "Ruleta":
77. probabilidad_indiv = []
78. probabilidad_acom = []
79. ruleta = []
80. promedio = sum(aptitudes)
81. for i in range(num_poblacion):
82. probabilidad = aptitudes[i] / promedio
83. ruleta.append(random.uniform(0, 1))
84. probabilidad_indiv.append(probabilidad)
85. if i == 0:
86. probabilidad_acom.append(probabilidad)
87. else:
88.
89. probabilidad_acom.append(probabilidad + probabilidad_acom[i-
1])
90. for j in range(num_poblacion):
91. for l in range(num_poblacion):
92. if ruleta[j] < probabilidad_acom[l]:
93. #print(l)
94. elegidos.append([poblacion[l][0],poblacion[l][1]])
95. break
96. #print("Probabilidad individual: \n",probabilidad_indiv)
97. #print("RULETA\n",ruleta)
98. #print("Probabilidad Acomulada: \n", probabilidad_acom)
99. #print("Los elegidos son : \n",elegidos)
100. return elegidos
101.
102. if modo == "Torneo":
103. for a in range(num_poblacion):
104. L=Funciones.unico(a,num_poblacion)
105. m=L[0]
106. i=L[1]
107. j=L[2]
108. k=L[3]
109. #Primer pelea de pareja
110. if(aptitudes[m]<aptitudes[i]):
111. primer_Ganador= m
112. else:
113. primer_Ganador=i
114. #Segunda pelea
115. if(aptitudes[j]<aptitudes[k]):
116. segundo_Ganador=j
117. else:
118. segundo_Ganador=k
119. #Pelea final
120. if(aptitudes[primer_Ganador]<aptitudes[segundo_Ganador]):
121. ganador_final=primer_Ganador
122. else:
123. ganador_final=segundo_Ganador
Contreras Villanueva Israel
2163047829
124. elegidos.append([poblacion[ganador_final][0],poblacion[ganador_fin
al][1]])
125. return elegidos
126.
127. def cruza_Punto(elegidos,num_poblacion,pos_Elegido): #elegidos,poblacion
128. cruzado = []
129. x_elegido=str(elegidos[pos_Elegido][0])
130. y_elegido=str(elegidos[pos_Elegido][1])
131. r=random.randint(1,17) #Aleatorio original es 17
132. aux=""
133. aux=aux.replace("",x_elegido[r-1:len(x_elegido)])
134. #print("aqui corto",r," ",pos_Elegido)
135. #print("Aux",aux)
136. #print(x_elegido)
137. #print(y_elegido)
138. x_elegido=x_elegido.replace(x_elegido[r-1:len(x_elegido)],y_elegido[r-
1:len(x_elegido)])
139. y_elegido=y_elegido.replace(y_elegido[r-1:len(x_elegido)],aux)
140. cruzado.append(x_elegido)
141. cruzado.append(y_elegido)
142. #print(x_elegido)
143. #print(y_elegido)
144. #print(cruzado)
145. return cruzado
146.
147.
148. def cruza_Puntos(elegidos,num_poblacion,pos_Elegido):
149. x_elegido=str(elegidos[pos_Elegido][0])
150. y_elegido=str(elegidos[pos_Elegido][1])
151. #print(x_elegido)
152. #print(y_elegido)
153. r1=random.randint(1,17) #Aleatorio original es 17
154. r2=random.randint(1,17) #Aleatorio original es 17
155. while(r1==r2):
156. r2=random.randint(1,17)
157.
158. #print("aqui corto",r1," ",pos_Elegido)
159. #print("aqui corto",r2," ",pos_Elegido)
160. if(r1>r2):
161. aux=r2
162. r2=r1
163. r1=aux
164. aux=x_elegido[r1:r2]
165. x_elegido=x_elegido.replace(x_elegido[r1:r2],y_elegido[r1:r2])
166. y_elegido=y_elegido.replace(y_elegido[r1:r2],aux)
167. cruzado=[]
168. cruzado.append(x_elegido)
169. cruzado.append(y_elegido)
170. #print(cruzado)
171. return cruzado
172.
173. def cruzamiento(elegidos,num_poblacion,modo):
174. probabilidad_cruza=0.5
175. lista_cruzados=[]
176. if(modo=="Punto"):
177. for i in range(num_poblacion):
178. if(random.uniform(0,1)<probabilidad_cruza):
179. cruzado=Funciones.cruza_Punto(elegidos,num_poblacion,i)
180. lista_cruzados.append(cruzado)
181. else:
182. lista_cruzados.append([str(elegidos[i][0]),str(elegidos[i][1])
])
183. return lista_cruzados
184. else:
185. for i in range(num_poblacion):
Contreras Villanueva Israel
2163047829
186. if(random.uniform(0,1)<probabilidad_cruza):
187. cruzado=Funciones.cruza_Puntos(elegidos,num_poblacion,i)
188. lista_cruzados.append(cruzado)
189. else:
190. lista_cruzados.append([str(elegidos[i][0]),str(elegidos[i][1])
])
191. return lista_cruzados
192.
193. def muta(lista_cruzados,num_poblacion,prob_muta):
194. muta=[]
195. for i in range(num_poblacion):
196. r=random.uniform(0,1)
197.
198. #print("Random",r)
199. if(r<prob_muta):
200. #print("Muto")
201. r_bit= random.randint(0,17) #Aqui modificar por su numero de bits
202. x=list(lista_cruzados[i][0])
203. #print("cadena separada por posiciones",x)
204. #print("bit a modificar",r_bit)
205. if(x[r_bit]=='1'):
206. x[r_bit]='0'
207. else:
208. x[r_bit]='1'
209. y=list(lista_cruzados[i][1])
210. # print("cadena separada por posiciones",y)
211. # print("bit a modificar",r_bit)
212. if(y[r_bit]=='1'):
213. y[r_bit]='0'
214. else:
215. y[r_bit]='1'
216. #x=str(x)
217. #y=str(y)
218. muta.append(["".join(x),"".join(y)])
219. else:
220. #print("No muto :(")
221. x=lista_cruzados[i][0]
222. y=lista_cruzados[i][1]
223. muta.append([x, y])
224. return muta
225.
226. def regresa_Mejor_generacion(muta,num_poblacion):
227. resultados=[]
228. mejor_resultado=sys.maxsize
229. x_mejor=0.0
230. y_mejor=0.0
231. for i in range(num_poblacion):
232. a=int(muta[i][0],2)
233. b=int(muta[i][1],2)
234. x=-100+a*(100-(-100))/((2**18)-1) #El original es a 18
235. y=-100+b*(100-(-100))/((2**18)-1) #El original es a 18
236. #print("variables antes de evaluar ",x,y)
237. funcion = (-(math.cos(x))*math.cos(y)*math.exp(-(math.pow((x-
math.pi),2))-(math.pow((y-math.pi),2))))
238. #print("Valores de evaluar f(x)",funcion)
239. if(funcion<mejor_resultado):
240. mejor_resultado=funcion
241. x_mejor=x
242. y_mejor=y
243. resultados.append([x_mejor,y_mejor])
244. resultados.append(mejor_resultado)
245. return resultados
Contreras Villanueva Israel
2163047829
1. from funciones import Funciones
2. import random
3. t=0 #Contador
4. num_poblacion = 50
5. Ngeneraciones=30
6. proba_muta=0.5
7. Mejor_resultado=[]
8. #Inicializa P(t)
9. a = Funciones.creacion_de_poblacion(num_poblacion,2,-100,100)
10. #print("Creando la poblacion \n")
11. #Funciones.Mostrar(a)
12. #-----------------------------
13.
14. #Evaluamos P(t)
15. b=Funciones.aptitud(a,num_poblacion)
16. #print("Aptitudes\n")
17. #Funciones.Mostrar_arreglo(b)
18. #-------------------
19.
20. while (t<Ngeneraciones):
21. t+=1
22. torneo_o_ruleta=random.randint(0,1)
23. #Seleccionamos ya sea por torneo o ruleta
24. if(torneo_o_ruleta==0):
25.
26. elegidos=Funciones.nex_generacion(b,"Ruleta",a,num_poblacion)
27. #print("Seleccionados por ruleta\n",len(elegidos))
28.
29. #Funciones.Mostrar(elegidos)
30. else:
31. elegidos=Funciones.nex_generacion(b,"Torneo",a,num_poblacion)
32. #print("Seleccionados por torneo\n",len(elegidos))
33. #Funciones.Mostrar(elegidos)
34. #-----------------------------------------
35.
36. punto_o_puntos=random.randint(0,1)
37. if(punto_o_puntos==0):
38. cruza=Funciones.cruzamiento(elegidos,num_poblacion,"Punto")
39. #print("Cruzados por un punto\n",len(cruza))
40. #Funciones.Mostrar(cruza)
41. else:
42. cruza=Funciones.cruzamiento(elegidos,num_poblacion,"Puntos")
43. #print("Cruzados por un puntos\n",len(cruza))
44. #Funciones.Mostrar(cruza)
45.
46.
47. #Mutamos
48. muta=Funciones.muta(cruza,num_poblacion,proba_muta)
49. #print("Muta\n")
50. #Funciones.Mostrar(muta)
51. print("Resultados",Funciones.regresa_Mejor_generacion(muta,num_poblacion))
52.
53. if(t==1):
54. Mejor_resultado=Funciones.regresa_Mejor_generacion(muta,num_poblacion)
55. else:
56. Contendiente=Funciones.regresa_Mejor_generacion(muta,num_poblacion)
57. if(Contendiente[1]<Mejor_resultado[1]):
58. Mejor_resultado=Contendiente
59.
60. #------------------------------------------------------------------------
61.
62. #Evaluamos P(t)
63. b=Funciones.aptitud(muta,num_poblacion)
64. #print("Aptitudes\n",len(b))
65. #Funciones.Mostrar_arreglo(b)
Contreras Villanueva Israel
2163047829
66. #-------------------
67.
68. print("El mejor resultado es: \n",Mejor_resultado[1],"\nCon
coordenadas \n",Mejor_resultado[0])
69.
3. Ejecución de varias corridas de la instancia del problema con diferentes variantes de los parámetros del problema
Para la cuarta corrida noto que si usamos más población de cromosomas que de generaciones nos acercamos más al valor del
mínimo que está en -1 con coordenadas 𝜋 𝑒𝑛 𝑥, 𝑦
Así que uso 1200 como tamaño de la población y 300 generaciones obteniendo el mejor de los resultados
Contreras Villanueva Israel
2163047829
Para la ultima corrida empleare todo el poder de computo y utilizare mas tiempo, usamos 500 generaciones y 2000 de tamaño
de población.
Una corrida que de igual forma se acerca al mínimo esperado pero que sufre de un leve atasco en las soluciones y no logro
rebasar el logro de su corrida anterior.
Contreras Villanueva Israel
2163047829
4. Análisis estadístico de los resultados
Para realizar el análisis estadístico utilizare un diagrama de cajas con el cuales podemos ver la tendencia de los valores y verificar
si este algoritmo fue funcional o no.
Utilizare los datos de la cuarta corrida la cual fue la que mas se acercó al valor deseado.
Como observamos los valores obtenidos en esa corrida fueron variados, pero asegurando que estábamos sobre el mínimo
esperado, observamos unos limites de las soluciones lo cual nos da un buen indicio de que el algoritmo siempre estuvo rondando
cerca de la solución esperada
En x=3.114712199066915 y y=3.1932952625093947