JairoDanielMT commited on
Commit
ac73fe9
·
1 Parent(s): b0d34dd

mejora con la implementación de early stopping

Browse files
Files changed (3) hide show
  1. pages/AG_2D.py +104 -11
  2. pages/AG_3D.py +105 -11
  3. pages/test.py +104 -26
pages/AG_2D.py CHANGED
@@ -251,6 +251,80 @@ def algoritmo_genetico(
251
  return mejor_solucion, mejor_distancia
252
 
253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  def visualizar_fitness_streamlit(fitness_historial):
255
  generaciones = list(range(len(fitness_historial)))
256
  fig_fitness = go.Figure()
@@ -323,7 +397,7 @@ if __name__ == "__main__":
323
  st.dataframe(data=data, use_container_width=True)
324
 
325
  # Configuraciones adicionales
326
- num_generaciones = st.sidebar.slider(
327
  "Número de Generaciones", min_value=10, max_value=1000, value=50
328
  )
329
  num_individuos = st.sidebar.slider(
@@ -336,17 +410,36 @@ if __name__ == "__main__":
336
  "Probabilidad de cruce", min_value=0.90, max_value=1.0, value=0.95, step=0.01
337
  )
338
  distancias_generadas, coordenadas_generadas = generar_distancias(num_ciudades)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
 
340
- # Ejecutar el algoritmo genético
341
- mejor_solucion, mejor_distancia = algoritmo_genetico(
342
- num_generaciones,
343
- num_ciudades,
344
- num_individuos,
345
- probabilidad_mutacion,
346
- distancias,
347
- coordenadas,
348
- probabilidad_cruce,
349
- )
350
 
351
  # Mostrar resultados
352
  st.success(f"Mejor solución encontrada: {mejor_solucion}")
 
251
  return mejor_solucion, mejor_distancia
252
 
253
 
254
+ def algoritmo_genetico_early_stopping(
255
+ num_generaciones,
256
+ num_ciudades,
257
+ num_individuos,
258
+ probabilidad_mutacion,
259
+ distancias,
260
+ coordenadas, # Asegúrate de tener este parámetro
261
+ probabilidad_cruce,
262
+ max_generaciones_sin_mejora,
263
+ ):
264
+ poblacion = generar_poblacion(num_individuos, num_ciudades)
265
+ mejor_solucion_historial = []
266
+ mejor_distancia_historial = []
267
+ peor = 0
268
+ fitness_historial = []
269
+ generaciones_sin_mejora = 0 # Inicializar contador de generaciones sin mejora
270
+
271
+ for _ in range(num_generaciones):
272
+ poblacion = sorted(
273
+ poblacion, key=lambda x: calcular_aptitud(x, distancias, coordenadas)
274
+ )
275
+ mejor_individuo = poblacion[0]
276
+
277
+ mejor_distancia = calcular_aptitud(mejor_individuo, distancias, coordenadas)
278
+ # Almacenar el mejor individuo y su distancia en cada generación
279
+ mejor_solucion_historial.append(mejor_individuo)
280
+ mejor_distancia_historial.append(mejor_distancia)
281
+
282
+ seleccionados = seleccion_torneo(
283
+ poblacion, distancias, coordenadas
284
+ ) # Pasa coordenadas aquí
285
+
286
+ nueva_poblacion = []
287
+ for i in range(0, len(seleccionados), 2):
288
+ padre1, padre2 = seleccionados[i], seleccionados[i + 1]
289
+ aleatorio_local = random.uniform(0, 1)
290
+ if aleatorio_local <= probabilidad_cruce:
291
+ hijo1 = cruzar(padre1, padre2)
292
+ hijo2 = cruzar(padre2, padre1)
293
+ else:
294
+ hijo1, hijo2 = padre1, padre2
295
+ hijo1 = mutar(hijo1, probabilidad_mutacion)
296
+ hijo2 = mutar(hijo2, probabilidad_mutacion)
297
+ nueva_poblacion.extend([hijo1, hijo2])
298
+
299
+ poblacion = nueva_poblacion
300
+ if peor < mejor_distancia:
301
+ peor = mejor_distancia
302
+ generaciones_sin_mejora = 0 # Reiniciar contador al mejorar
303
+ else:
304
+ generaciones_sin_mejora += 1
305
+
306
+ # Verificar Early Stopping
307
+ if generaciones_sin_mejora >= max_generaciones_sin_mejora:
308
+ st.warning(
309
+ "Early Stopping: Se detuvo el algoritmo debido a falta de mejora."
310
+ )
311
+ break
312
+
313
+ fitness_historial.append(fitness(mejor_distancia, peor, len(padre1)))
314
+ mejor_solucion = poblacion[0]
315
+ mejor_distancia = calcular_aptitud(mejor_solucion, distancias, coordenadas)
316
+ # Visualizar el proceso del algoritmo
317
+ visualizar_proceso_streamlit(
318
+ mejor_distancia_historial, mejor_solucion, coordenadas, mejor_distancia
319
+ )
320
+ # visualizar el fitness
321
+ visualizar_fitness_streamlit(fitness_historial)
322
+ # Visualizar el mejor camino encontrado
323
+ visualizar_camino_streamlit(mejor_solucion, coordenadas, mejor_distancia)
324
+
325
+ return mejor_solucion, mejor_distancia
326
+
327
+
328
  def visualizar_fitness_streamlit(fitness_historial):
329
  generaciones = list(range(len(fitness_historial)))
330
  fig_fitness = go.Figure()
 
397
  st.dataframe(data=data, use_container_width=True)
398
 
399
  # Configuraciones adicionales
400
+ num_generaciones = st.sidebar.number_input(
401
  "Número de Generaciones", min_value=10, max_value=1000, value=50
402
  )
403
  num_individuos = st.sidebar.slider(
 
410
  "Probabilidad de cruce", min_value=0.90, max_value=1.0, value=0.95, step=0.01
411
  )
412
  distancias_generadas, coordenadas_generadas = generar_distancias(num_ciudades)
413
+ checkbox = st.sidebar.checkbox("Early Stopping")
414
+ if checkbox:
415
+ max_generaciones_sin_mejora = st.sidebar.number_input(
416
+ "Limite de generaciones sin mejora",
417
+ min_value=5,
418
+ max_value=1000,
419
+ value=20,
420
+ step=5,
421
+ )
422
+ mejor_solucion, mejor_distancia = algoritmo_genetico_early_stopping(
423
+ num_generaciones,
424
+ num_ciudades,
425
+ num_individuos,
426
+ probabilidad_mutacion,
427
+ distancias,
428
+ coordenadas,
429
+ probabilidad_cruce,
430
+ max_generaciones_sin_mejora,
431
+ )
432
 
433
+ else:
434
+ mejor_solucion, mejor_distancia = algoritmo_genetico(
435
+ num_generaciones,
436
+ num_ciudades,
437
+ num_individuos,
438
+ probabilidad_mutacion,
439
+ distancias,
440
+ coordenadas,
441
+ probabilidad_cruce,
442
+ )
443
 
444
  # Mostrar resultados
445
  st.success(f"Mejor solución encontrada: {mejor_solucion}")
pages/AG_3D.py CHANGED
@@ -220,6 +220,80 @@ def algoritmo_genetico(
220
  return mejor_solucion, mejor_distancia
221
 
222
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  def visualizar_proceso_fitness_streamlit(fitness_arreglo):
224
  generaciones = list(range(len(fitness_arreglo)))
225
 
@@ -317,7 +391,7 @@ if __name__ == "__main__":
317
  )
318
 
319
  # Configuraciones adicionales
320
- num_generaciones = st.sidebar.slider(
321
  "Número de Generaciones", min_value=10, max_value=1000, value=50
322
  )
323
  num_individuos = st.sidebar.slider(
@@ -330,16 +404,36 @@ if __name__ == "__main__":
330
  "Probabilidad de cruce", min_value=0.9, max_value=0.95, value=0.01, step=0.01
331
  )
332
 
333
- # Ejecutar el algoritmo genético
334
- mejor_solucion, mejor_distancia = algoritmo_genetico(
335
- num_generaciones,
336
- num_ciudades,
337
- num_individuos,
338
- probabilidad_mutacion,
339
- distancias,
340
- coordenadas,
341
- probabilidad_cruce,
342
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
 
344
  # Mostrar resultados
345
  st.success(f"Mejor solución encontrada: {mejor_solucion}")
 
220
  return mejor_solucion, mejor_distancia
221
 
222
 
223
+ def algoritmo_genetico_early_stopping(
224
+ num_generaciones,
225
+ num_ciudades,
226
+ num_individuos,
227
+ probabilidad_mutacion,
228
+ distancias,
229
+ coordenadas, # Asegúrate de tener este parámetro
230
+ probabilidad_cruce,
231
+ max_generaciones_sin_mejora,
232
+ ):
233
+ poblacion = generar_poblacion(num_individuos, num_ciudades)
234
+ mejor_solucion_historial = []
235
+ mejor_distancia_historial = []
236
+ peor = 0
237
+ fitness_historial = []
238
+ generaciones_sin_mejora = 0 # Inicializar contador de generaciones sin mejora
239
+
240
+ for _ in range(num_generaciones):
241
+ poblacion = sorted(
242
+ poblacion, key=lambda x: calcular_aptitud(x, distancias, coordenadas)
243
+ )
244
+ mejor_individuo = poblacion[0]
245
+
246
+ mejor_distancia = calcular_aptitud(mejor_individuo, distancias, coordenadas)
247
+ # Almacenar el mejor individuo y su distancia en cada generación
248
+ mejor_solucion_historial.append(mejor_individuo)
249
+ mejor_distancia_historial.append(mejor_distancia)
250
+
251
+ seleccionados = seleccion_torneo(
252
+ poblacion, distancias, coordenadas
253
+ ) # Pasa coordenadas aquí
254
+
255
+ nueva_poblacion = []
256
+ for i in range(0, len(seleccionados), 2):
257
+ padre1, padre2 = seleccionados[i], seleccionados[i + 1]
258
+ aleatorio_local = random.uniform(0, 1)
259
+ if aleatorio_local <= probabilidad_cruce:
260
+ hijo1 = cruzar(padre1, padre2)
261
+ hijo2 = cruzar(padre2, padre1)
262
+ else:
263
+ hijo1, hijo2 = padre1, padre2
264
+ hijo1 = mutar(hijo1, probabilidad_mutacion)
265
+ hijo2 = mutar(hijo2, probabilidad_mutacion)
266
+ nueva_poblacion.extend([hijo1, hijo2])
267
+
268
+ poblacion = nueva_poblacion
269
+ if peor < mejor_distancia:
270
+ peor = mejor_distancia
271
+ generaciones_sin_mejora = 0 # Reiniciar contador al mejorar
272
+ else:
273
+ generaciones_sin_mejora += 1
274
+
275
+ # Verificar Early Stopping
276
+ if generaciones_sin_mejora >= max_generaciones_sin_mejora:
277
+ st.warning(
278
+ "Early Stopping: Se detuvo el algoritmo debido a falta de mejora."
279
+ )
280
+ break
281
+
282
+ fitness_historial.append(fitness(mejor_distancia, peor, len(padre1)))
283
+ mejor_solucion = poblacion[0]
284
+ mejor_distancia = calcular_aptitud(mejor_solucion, distancias, coordenadas)
285
+ # Visualizar el proceso del algoritmo
286
+ visualizar_proceso_streamlit(
287
+ mejor_distancia_historial, mejor_solucion, coordenadas, mejor_distancia
288
+ )
289
+ # visualizar el fitness
290
+ visualizar_proceso_fitness_streamlit(fitness_historial)
291
+ # Visualizar el mejor camino encontrado
292
+ visualizar_camino_streamlit(mejor_solucion, coordenadas, mejor_distancia)
293
+
294
+ return mejor_solucion, mejor_distancia
295
+
296
+
297
  def visualizar_proceso_fitness_streamlit(fitness_arreglo):
298
  generaciones = list(range(len(fitness_arreglo)))
299
 
 
391
  )
392
 
393
  # Configuraciones adicionales
394
+ num_generaciones = st.sidebar.number_input(
395
  "Número de Generaciones", min_value=10, max_value=1000, value=50
396
  )
397
  num_individuos = st.sidebar.slider(
 
404
  "Probabilidad de cruce", min_value=0.9, max_value=0.95, value=0.01, step=0.01
405
  )
406
 
407
+ checkbox = st.sidebar.checkbox("Early Stopping")
408
+ if checkbox:
409
+ max_generaciones_sin_mejora = st.sidebar.number_input(
410
+ "Limite de generaciones sin mejora",
411
+ min_value=5,
412
+ max_value=1000,
413
+ value=20,
414
+ step=5,
415
+ )
416
+ mejor_solucion, mejor_distancia = algoritmo_genetico_early_stopping(
417
+ num_generaciones,
418
+ num_ciudades,
419
+ num_individuos,
420
+ probabilidad_mutacion,
421
+ distancias,
422
+ coordenadas,
423
+ probabilidad_cruce,
424
+ max_generaciones_sin_mejora,
425
+ )
426
+
427
+ else:
428
+ mejor_solucion, mejor_distancia = algoritmo_genetico(
429
+ num_generaciones,
430
+ num_ciudades,
431
+ num_individuos,
432
+ probabilidad_mutacion,
433
+ distancias,
434
+ coordenadas,
435
+ probabilidad_cruce,
436
+ )
437
 
438
  # Mostrar resultados
439
  st.success(f"Mejor solución encontrada: {mejor_solucion}")
pages/test.py CHANGED
@@ -152,7 +152,6 @@ def visualizar_camino_streamlit(camino, coordenadas, mejor_distancia):
152
  textposition="top center",
153
  )
154
  )
155
-
156
  fig_camino.add_trace(
157
  go.Scatter3d(
158
  x=[x[-1]],
@@ -165,7 +164,6 @@ def visualizar_camino_streamlit(camino, coordenadas, mejor_distancia):
165
  textposition="top center",
166
  )
167
  )
168
-
169
  # Añadir etiquetas a los puntos intermedios
170
  for i, (xi, yi, zi) in enumerate(zip(x[1:-1], y[1:-1], z[1:-1])):
171
  fig_camino.add_trace(
@@ -185,7 +183,6 @@ def visualizar_camino_streamlit(camino, coordenadas, mejor_distancia):
185
  scene=dict(aspectmode="cube"),
186
  title=f"Mejor Camino Encontrado\nDistancia: {mejor_distancia:.2f}",
187
  )
188
-
189
  # Mostrar el gráfico interactivo en Streamlit
190
  st.plotly_chart(fig_camino)
191
 
@@ -207,7 +204,7 @@ def algoritmo_genetico(
207
  mejor_distancia_historial = []
208
  peor = 0
209
  fitness_historial = []
210
- for generacion in range(num_generaciones):
211
  poblacion = sorted(poblacion, key=lambda x: calcular_aptitud(x, distancias))
212
  mejor_individuo = poblacion[0]
213
 
@@ -253,18 +250,16 @@ def algoritmo_genetico(
253
 
254
  def visualizar_proceso_fitness_streamlit(fitness_arreglo):
255
  generaciones = list(range(len(fitness_arreglo)))
256
-
257
- # Crear gráfico interactivo de evolución de la distancia
258
- fig_distancia = go.Figure()
259
- fig_distancia.add_trace(
260
  go.Scatter(x=generaciones, y=fitness_arreglo, mode="lines+markers")
261
  )
262
- fig_distancia.update_layout(
263
  title="Evolución del fitnesss en Cada Generación",
264
  xaxis_title="Generación",
265
  yaxis_title="fitness",
266
  )
267
- st.plotly_chart(fig_distancia)
268
 
269
 
270
  def visualizar_proceso_streamlit(
@@ -285,17 +280,85 @@ def visualizar_proceso_streamlit(
285
  st.plotly_chart(fig_distancia)
286
 
287
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  # Ejemplo de uso en Streamlit
289
  if __name__ == "__main__":
290
- # Configurar la interfaz de usuario con Streamlit
291
  st.title("Algoritmo Genético para el Problema del Viajante")
292
  st.sidebar.header("Configuración")
293
-
294
  num_ciudades = st.sidebar.number_input(
295
  "Número de Ciudades", min_value=5, max_value=100, value=10, step=5
296
  )
297
- num_generaciones = st.sidebar.slider(
298
- "Número de Generaciones", min_value=10, max_value=1000, value=50
299
  )
300
  num_individuos = st.sidebar.slider(
301
  "Tamaño de la Población", min_value=10, max_value=100, value=50, step=2
@@ -307,19 +370,34 @@ if __name__ == "__main__":
307
  probabilidad_cruce = st.sidebar.slider(
308
  "Probabilidad de Cruce", min_value=0.9, max_value=1.0, value=0.95, step=0.01
309
  )
310
-
311
  # Generar distancias aleatorias entre las ciudades y sus coordenadas tridimensionales
312
  distancias, coordenadas = generar_distancias(num_ciudades)
313
-
314
- # Ejecutar el algoritmo genético
315
- mejor_solucion, mejor_distancia = algoritmo_genetico(
316
- num_generaciones,
317
- num_ciudades,
318
- num_individuos,
319
- probabilidad_mutacion,
320
- distancias,
321
- probabilidad_cruce,
322
- )
323
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  st.success(f"Mejor solución encontrada: {mejor_solucion}")
325
  st.success(f"Mejor distancia encontrada: {mejor_distancia:.2f}")
 
152
  textposition="top center",
153
  )
154
  )
 
155
  fig_camino.add_trace(
156
  go.Scatter3d(
157
  x=[x[-1]],
 
164
  textposition="top center",
165
  )
166
  )
 
167
  # Añadir etiquetas a los puntos intermedios
168
  for i, (xi, yi, zi) in enumerate(zip(x[1:-1], y[1:-1], z[1:-1])):
169
  fig_camino.add_trace(
 
183
  scene=dict(aspectmode="cube"),
184
  title=f"Mejor Camino Encontrado\nDistancia: {mejor_distancia:.2f}",
185
  )
 
186
  # Mostrar el gráfico interactivo en Streamlit
187
  st.plotly_chart(fig_camino)
188
 
 
204
  mejor_distancia_historial = []
205
  peor = 0
206
  fitness_historial = []
207
+ for _ in range(num_generaciones):
208
  poblacion = sorted(poblacion, key=lambda x: calcular_aptitud(x, distancias))
209
  mejor_individuo = poblacion[0]
210
 
 
250
 
251
  def visualizar_proceso_fitness_streamlit(fitness_arreglo):
252
  generaciones = list(range(len(fitness_arreglo)))
253
+ fig_fitness = go.Figure()
254
+ fig_fitness.add_trace(
 
 
255
  go.Scatter(x=generaciones, y=fitness_arreglo, mode="lines+markers")
256
  )
257
+ fig_fitness.update_layout(
258
  title="Evolución del fitnesss en Cada Generación",
259
  xaxis_title="Generación",
260
  yaxis_title="fitness",
261
  )
262
+ st.plotly_chart(fig_fitness)
263
 
264
 
265
  def visualizar_proceso_streamlit(
 
280
  st.plotly_chart(fig_distancia)
281
 
282
 
283
+ def algoritmo_genetico_early_stopping(
284
+ num_generaciones,
285
+ num_ciudades,
286
+ num_individuos,
287
+ probabilidad_mutacion,
288
+ distancias,
289
+ probabilidad_cruce,
290
+ max_generaciones_sin_mejora,
291
+ ):
292
+ poblacion = generar_poblacion(num_individuos, num_ciudades)
293
+ mejor_solucion_historial = []
294
+ mejor_distancia_historial = []
295
+ peor = 0
296
+ fitness_historial = []
297
+ generaciones_sin_mejora = 0 # Inicializar contador de generaciones sin mejora
298
+
299
+ for _ in range(num_generaciones):
300
+ poblacion = sorted(poblacion, key=lambda x: calcular_aptitud(x, distancias))
301
+ mejor_individuo = poblacion[0]
302
+
303
+ mejor_distancia = calcular_aptitud(mejor_individuo, distancias)
304
+ # Almacenar el mejor individuo y su distancia en cada generación
305
+ mejor_solucion_historial.append(mejor_individuo)
306
+ mejor_distancia_historial.append(mejor_distancia)
307
+
308
+ seleccionados = seleccion_torneo(poblacion, distancias)
309
+
310
+ nueva_poblacion = []
311
+ for i in range(0, len(seleccionados), 2):
312
+ padre1, padre2 = seleccionados[i], seleccionados[i + 1]
313
+ aleatorio_local = random.uniform(0, 1)
314
+ if aleatorio_local <= probabilidad_cruce:
315
+ hijo1 = cruzar(padre1, padre2)
316
+ hijo2 = cruzar(padre2, padre1)
317
+ else:
318
+ hijo1, hijo2 = padre1, padre2
319
+ hijo1 = mutar(hijo1, probabilidad_mutacion)
320
+ hijo2 = mutar(hijo2, probabilidad_mutacion)
321
+ nueva_poblacion.extend([hijo1, hijo2])
322
+
323
+ poblacion = nueva_poblacion
324
+ if peor < mejor_distancia:
325
+ peor = mejor_distancia
326
+ generaciones_sin_mejora = 0 # Reiniciar contador al mejorar
327
+ else:
328
+ generaciones_sin_mejora += 1
329
+
330
+ # Verificar Early Stopping
331
+ if generaciones_sin_mejora >= max_generaciones_sin_mejora:
332
+ st.warning(
333
+ "Early Stopping: Se detuvo el algoritmo debido a falta de mejora."
334
+ )
335
+ break
336
+
337
+ fitness_historial.append(fitness(mejor_distancia, peor, len(padre1)))
338
+ mejor_solucion = poblacion[0]
339
+ mejor_distancia = calcular_aptitud(mejor_solucion, distancias)
340
+
341
+ # Visualizar el proceso del algoritmo
342
+ visualizar_proceso_streamlit(
343
+ mejor_distancia_historial, mejor_solucion, coordenadas, mejor_distancia
344
+ )
345
+ # visualizar el fitness
346
+ visualizar_proceso_fitness_streamlit(fitness_historial)
347
+ # Visualizar el mejor camino encontrado
348
+ visualizar_camino_streamlit(mejor_solucion, coordenadas, mejor_distancia)
349
+
350
+ return mejor_solucion, mejor_distancia
351
+
352
+
353
  # Ejemplo de uso en Streamlit
354
  if __name__ == "__main__":
 
355
  st.title("Algoritmo Genético para el Problema del Viajante")
356
  st.sidebar.header("Configuración")
 
357
  num_ciudades = st.sidebar.number_input(
358
  "Número de Ciudades", min_value=5, max_value=100, value=10, step=5
359
  )
360
+ num_generaciones = st.sidebar.number_input(
361
+ "Número de Generaciones", min_value=10, max_value=1000, value=50, step=10
362
  )
363
  num_individuos = st.sidebar.slider(
364
  "Tamaño de la Población", min_value=10, max_value=100, value=50, step=2
 
370
  probabilidad_cruce = st.sidebar.slider(
371
  "Probabilidad de Cruce", min_value=0.9, max_value=1.0, value=0.95, step=0.01
372
  )
 
373
  # Generar distancias aleatorias entre las ciudades y sus coordenadas tridimensionales
374
  distancias, coordenadas = generar_distancias(num_ciudades)
375
+ checkbox = st.sidebar.checkbox("Early Stopping")
376
+ if checkbox:
377
+ max_generaciones_sin_mejora = st.sidebar.number_input(
378
+ "Limite de generaciones sin mejora",
379
+ min_value=5,
380
+ max_value=1000,
381
+ value=20,
382
+ step=5,
383
+ )
384
+ mejor_solucion, mejor_distancia = algoritmo_genetico_early_stopping(
385
+ num_generaciones,
386
+ num_ciudades,
387
+ num_individuos,
388
+ probabilidad_mutacion,
389
+ distancias,
390
+ probabilidad_cruce,
391
+ max_generaciones_sin_mejora,
392
+ )
393
+ else:
394
+ mejor_solucion, mejor_distancia = algoritmo_genetico(
395
+ num_generaciones,
396
+ num_ciudades,
397
+ num_individuos,
398
+ probabilidad_mutacion,
399
+ distancias,
400
+ probabilidad_cruce,
401
+ )
402
  st.success(f"Mejor solución encontrada: {mejor_solucion}")
403
  st.success(f"Mejor distancia encontrada: {mejor_distancia:.2f}")