Está en la página 1de 12

Contreras Villanueva Israel

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.

Conceptualización del problema

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.

La función se evalúa en −100 ≤ 𝑥, 𝑦 ≤ 100

1.-Método de solución con algoritmos genéticos

El problema se trató usando algoritmos genéticos.

A) Función de aptitud

Ya que el problema busca la minimización se utiliza la siguiente función de aptitud:


1
1 + 𝑓(𝑥)
Donde f(x) es la función de Easom

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

C) Representación de las soluciones

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

100 − (−100) = 200

𝑃𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛 = 103

200(103 ) = 200000
2𝑥 ≥ 200000
𝑥 = 18

217 ≤ 200000 ≤ 218


Con esto cálculos podemos discretizar la solución x,y en binario del tipo:

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)

donde en general es:

𝑙𝑖𝑚 𝑠𝑢𝑝𝑒𝑟𝑖𝑜𝑟 − (𝑙𝑖𝑚𝑖𝑡𝑒 𝑖𝑛𝑓𝑒𝑟𝑖𝑜𝑟 )


𝑥 = 𝑙𝑖𝑚 𝑖𝑛𝑓𝑒𝑟𝑖𝑜𝑟 + 𝑑𝑒𝑐𝑖𝑚𝑎𝑙(𝑛𝑢𝑚𝑒𝑟𝑜𝑏𝑖𝑛𝑎𝑟𝑖𝑜2 ) ∗
2(𝑁𝑢𝑚𝑒𝑟𝑜 𝑑𝑒 𝑏𝑖𝑡𝑠 𝑚𝑎𝑥𝑖𝑚𝑜𝑠) − 1
Esto nos devuelve el valor original, es decir, el decodificado.

D) Selección por torneo y ruleta

Para esto se implementó la función nex_generacion esta función contiene los dos modos de cruza.

Selección por torneo:

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

Después se genera una segunda pelea con la pareja restante

Para casi terminar definimos la “pelea final” con los ganadores de la primera y segunda pelea.

Finalmente retornamos al elegido a la nueva población llamada elegidos

Selección por ruleta:

Para la ruleta necesitamos el vector aptitud que contiene la aptitud de cada cromosoma

Encontramos la aptitud total de la población F

Calculamos la probabilidad para cada cromosoma y la guardamos en un arreglo probabilidad_indiv


𝑛𝑢𝑚_𝑝𝑜𝑏𝑙𝑎𝑐𝑖𝑜𝑛−1
𝑝𝑟𝑜𝑏𝑎𝑏𝑖𝑙𝑖𝑑𝑎𝑑_𝑖𝑛𝑑𝑖𝑣 = ∑ 𝑎𝑝𝑡𝑖𝑡𝑢𝑑[𝑖] /𝐹
𝑖=0
Contreras Villanueva Israel
2163047829
Calculamos la probabilidad acumulada, esto es, la probabilidad del poblador actual más la anterior de todos los
cromosomas, cada probabilidad acumulada se guarda en un arreglo probabilidad_acom
𝑖−1
𝑝𝑟𝑜𝑏𝑎𝑏𝑖𝑙𝑖𝑑𝑎𝑑_𝑎𝑐𝑜𝑚 = ∑ 𝑝𝑟𝑜𝑏𝑎𝑏𝑖𝑙𝑖𝑑𝑎𝑑_𝑖𝑛𝑑𝑖𝑣[𝑗]
𝑗=0

E) Cruza en uno y dos puntos

Un punto:

Para la cruza en un punto seleccionamos un cromosoma

Generamos un aleatorio entre 0 y 17 para saber cual va a ser el punto de corte

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:

Para la cruza en dos puntos seleccionamos un cromosoma

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

Primer corrida con Ngeneraciones=10 y una población de 50 cromosomas.

Segunda corrida con Ngeneraciones=20 y una población de 100 cromosomas


Contreras Villanueva Israel
2163047829
Tercera corrida con Ngeneraciones = 5 y una población de 500 cromosomas

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

El mejor valor obtenido fue durante la cuarta corrida obteniendo un f(x)=-0.9949187361903258

En x=3.114712199066915 y y=3.1932952625093947

También podría gustarte