Presentado por:
Marcos David Carrillo Builes
Tomás Escobar Rivera
Jose Fernando
López Ramírez
Esteban Vásquez Pérez
Profesor: Juan David Ospina Arango
Monitor: Andrés Mauricio Zapata Rincón
Universidad Nacional de Colombia
Facultad de Minas
Ingeniería de
Sistemas e Informática
07 de July de 2025
En el ámbito de la investigación operativa y la inteligencia artificial, los algoritmos de optimización heurística se han consolidado como herramientas fundamentales para abordar problemas complejos de optimización. Estos algoritmos son particularmente efectivos cuando los métodos exactos resultan inviables debido a la elevada dimensionalidad del espacio de búsqueda o a la naturaleza intrínsecamente combinatoria de los problemas, donde el número de posibles soluciones crece exponencialmente.
A lo largo de las últimas décadas, se han desarrollado y perfeccionado una amplia variedad de algoritmos heurísticos, cada uno con características únicas que los hacen adecuados para diferentes tipos de problemas. Entre estos, se destacan algoritmos como los basados en poblaciones, como los Algoritmos Genéticos (GA) y Optimización de Enjambre de Partículas (PSO), así como las estrategias de optimización basadas en búsquedas locales, como el Algoritmo de Colonia de Hormigas (ACO).
El presente trabajo se enfoca en el análisis comparativo de varios de estos algoritmos para diferentes instancias de problemas de optimización. A través de este estudio, se busca identificar las ventajas, limitaciones y condiciones en las que cada enfoque presenta un mejor desempeño, proporcionando así una visión integral para la selección de métodos de optimización heurística en futuras investigaciones.
De esta forma, se espera contribuir al entendimiento de las fortalezas y debilidades de estas técnicas, facilitando la elección informada de algoritmos para aplicaciones prácticas en campos tan diversos como la ingeniería, la logística y las ciencias computacionales.
## Loading required package: gganimate
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'gganimate'
## Loading required package: sf
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'sf'
## No se instalaron los paquetes: gganimate, sf
Optimice las funciones en dos y tres dimensiones usando un método de descenso por gradiente con condición inicial aleatoria
Optimice las funciones en dos y tres dimensiones usando: algoritmos evolutivos, optimización de partículas y evolución diferencial
Represente con un gif animado o un video el proceso de optimización de descenso por gradiente y el proceso usando el método heurístico.
¿Qué aportaron los métodos de descenso por gradiente y qué aportaron los métodos heurísticos? Para responder a esta pregunta considere el valor final de la función objetivo y el número de evaluaciones de la función objetivo. Para responder a esta pregunta es posible que se requiera hacer varias corridas de los algoritmos.
\[ f(\mathbf{x}) = 418.9829d - \sum_{i=1}^d x_i \sin(\sqrt{|x_i|}) \quad \text{(1)} \]
Descripción:
Dimensiones: \(d\)
La función de Schwefel cuenta con múltiples mínimos locales.
Dominio:
La función se evalúa en el hipercubo: \(x_i \in [-500, 500]\), para todo \(i = 1, \dots, d\).
Mínimo Global:
\(f(\mathbf{x}^*) = 0\), en \(\mathbf{x}^* = (420.9687, \dots, 420.9687)\)
# Función Schwefel
schwefel <- function(x) {
A <- 418.9829
d <- length(x)
z <- A * d - sum(x * sin(sqrt(abs(x))))
return(z)
}
Sabemos que la función de Schwefel tiene un mínimo local en \(x^*=(420.9687, \cdots, 420.9687)\)
## [1] 2.545567e-05
## [1] 3.818351e-05
Estos resultados representan valores aproximados a cero debido a errores de redondeo introducidos en la programación de la función.
Ahora vamos a visualizar la función:
Fig 1. Evaluación de Schwefel (2D)
Fig 2. Evaluación de Schwefel (3D)
Fig 3. Curvas de Nivel de Schwefel
\[ f(\mathbf{x}) = 1 + \frac{1}{4000} \sum_{i=1}^{d} x_i^2 - \prod_{i=1}^{d} \cos\left(\frac{x_i}{\sqrt{i}}\right) \quad \text{(2)} \]
Descripción:
Dimensiones: \(d\)
La función de Griewank tiene una estructura ondulada con múltiples mínimos locales, pero un único mínimo global en el origen.
Dominio:
\(x_i \in [-600, 600]\), para todo \(i = 1, \dots, d\)
Mínimo Global:
\(f(\mathbf{0}) = 0\), en \(\mathbf{x} = (0, \dots, 0)\)
# Función Griewank (2D y 3D)
griewank <- function(x) {
sum_term <- sum(x^2) / 4000
prod_term <- prod(cos(x / sqrt(seq_along(x))))
return(1 + sum_term - prod_term)
}
## [1] 0
## [1] 0
Estos resultados representan el mínimo global de la función de Griewank, que es 0 en el origen.
Fig 4. Evaluación de Griewank (2D)
Fig 5. Evaluación de Griewank (3D)
Fig 6. Curvas de Nivel de Griewank
Como podemos ver, las funciones cuentan con varios mínimos locales
que pueden hacer que un método numérico basado en el gradiente sea
propenso a errores. Para ello vamos a ver cómo se comporta la solución
del método optim(method = "BFGS")
que es el más parecido al
que vimos en clase. Este método Quasi-Newton optimiza la función
utilizando una aproximación del gradiente y la matriz Hessiana, sin
calcularlos directamente.
Antes de esto vamos a crear vectores para seguir las soluciones halladas.
## initial value 790.168681
## iter 2 value 765.448307
## iter 3 value 729.639629
## iter 4 value 679.713597
## iter 5 value 613.806275
## iter 6 value 533.106774
## iter 7 value 443.514431
## iter 8 value 355.131538
## iter 9 value 138.514178
## iter 10 value 122.084251
## iter 11 value 120.486081
## iter 12 value 118.438625
## iter 13 value 118.438347
## iter 13 value 118.438347
## final value 118.438347
## converged
## initial value 34.562163
## iter 2 value 33.384366
## iter 3 value 33.254622
## iter 4 value 33.184890
## iter 5 value 33.184711
## iter 5 value 33.184711
## iter 5 value 33.184711
## final value 33.184711
## converged
Función | Óptimo_Global | Óptimo_Obtenido |
---|---|---|
Schwefel | f(420.9687, 420.9687) ≈ 0 | (-302.5247) con valor 118.4383 |
Griewank | f(0, 0) = 0 | (364.2416) con valor 33.1847 |
## initial value 1508.888943
## iter 2 value 1483.707203
## iter 3 value 1447.173577
## iter 4 value 1396.108891
## iter 5 value 1328.414538
## iter 6 value 1244.914455
## iter 7 value 1150.944012
## iter 8 value 1055.745413
## iter 9 value 473.273255
## iter 10 value 398.813939
## iter 11 value 398.132357
## iter 12 value 394.929298
## iter 13 value 394.916344
## iter 14 value 394.899954
## iter 14 value 394.899953
## iter 14 value 394.899953
## final value 394.899953
## converged
## initial value 10.534395
## iter 2 value 10.045718
## iter 3 value 9.513138
## iter 4 value 8.933348
## iter 5 value 8.884195
## iter 6 value 8.883244
## iter 7 value 8.883223
## iter 8 value 8.883221
## iter 8 value 8.883221
## iter 8 value 8.883221
## final value 8.883221
## converged
Función | Óptimo_Global | Óptimo_Obtenido |
---|---|---|
Schwefel | f(420.9687, 420.9687) ≈ 0 | (-25.8788, 420.9689) con valor 394.9 |
Griewank | f(0, 0) = 0 | (128.7406, -137.5913) con valor 8.8832 |
Más adelante vamos a visualizar estos métodos para tener una mejor forma de interpretar los resultados obtenidos. Además vamos a explicar por qué no se llega al óptimo global.
Nos enfocaremos en tres poderosos métodos heurísticos inspirados en la naturaleza:
Algoritmos Evolutivos (GA), que emulan el proceso de selección natural para encontrar soluciones óptimas.
Optimización por Enjambre de Partículas (PSO), basada en el comportamiento colectivo de animales como aves o peces.
Estrategias de Evolución Diferencial (DE), un método robusto de optimización global que combina mutación, cruce y selección.
Creamos una tabla para ver los resultados con varios valores posibles y comparar las soluciones para así elegir los mejores parámetros. De una vez la generalizamos para los otros métodos.
Mejor Valor | Iter Convergencia | Tamaño Población | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
7 | 0.0000 | 200 | 30 | 200 | 0.1860 |
8 | 0.0005 | 200 | 50 | 200 | 0.2425 |
6 | 0.0007 | 100 | 100 | 100 | 0.1851 |
3 | 0.0009 | 50 | 100 | 50 | 0.1018 |
9 | 0.0087 | 200 | 100 | 200 | 0.3776 |
5 | 0.0089 | 100 | 50 | 100 | 0.1237 |
4 | 0.7756 | 100 | 30 | 100 | 0.1022 |
2 | 7.0688 | 50 | 50 | 50 | 0.0777 |
1 | 116.1439 | 50 | 30 | 50 | 0.0700 |
Elegimos el mejor resultado que obtenemos y llamamos a la función para guardar su historial y poder graficarlo después.
Mejor Valor | Iter Convergencia | Tamaño Población | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
9 | 0.0037 | 200 | 100 | 200 | 0.4275 |
7 | 0.1020 | 200 | 30 | 200 | 0.2083 |
8 | 0.2948 | 200 | 50 | 200 | 0.2701 |
1 | 0.6273 | 50 | 30 | 50 | 0.0545 |
5 | 0.6758 | 100 | 50 | 100 | 0.1397 |
6 | 1.0476 | 100 | 100 | 100 | 0.2114 |
4 | 2.3853 | 100 | 30 | 100 | 0.1034 |
3 | 21.9866 | 50 | 100 | 50 | 0.1129 |
2 | 128.1358 | 50 | 50 | 50 | 0.0666 |
Mejor Valor | Iter Convergencia | Tamaño Población | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
1 | 0.0004 | 50 | 30 | 50 | 0.0573 |
5 | 0.0011 | 100 | 50 | 100 | 0.1340 |
2 | 0.0049 | 50 | 50 | 50 | 0.0695 |
7 | 0.0071 | 200 | 30 | 200 | 0.2138 |
9 | 0.0076 | 200 | 100 | 200 | 0.4287 |
6 | 0.0076 | 100 | 100 | 100 | 0.2204 |
4 | 0.0081 | 100 | 30 | 100 | 0.1050 |
8 | 0.0099 | 200 | 50 | 200 | 0.2718 |
3 | 0.0107 | 50 | 100 | 50 | 0.1134 |
Mejor Valor | Iter Convergencia | Tamaño Población | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
7 | 0.0152 | 200 | 30 | 200 | 0.2166 |
3 | 0.0169 | 50 | 100 | 50 | 0.1049 |
6 | 0.0219 | 100 | 100 | 100 | 0.2349 |
9 | 0.0328 | 200 | 100 | 200 | 0.4418 |
8 | 0.0345 | 200 | 50 | 200 | 0.2872 |
5 | 0.0475 | 100 | 50 | 100 | 0.1341 |
2 | 0.1013 | 50 | 50 | 50 | 0.0658 |
4 | 0.1079 | 100 | 30 | 100 | 0.0968 |
1 | 0.1513 | 50 | 30 | 50 | 0.0498 |
Mejor Valor | Iter Convergencia | Tamaño Enjambre | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
7 | 0.0000 | 3373 | 20 | 200 | 0.1310 |
9 | 0.0000 | 11963 | 60 | 200 | 0.3996 |
8 | 0.0000 | 7693 | 40 | 200 | 0.2521 |
4 | 0.0000 | 1831 | 20 | 100 | 0.0649 |
6 | 0.0000 | 5772 | 60 | 100 | 0.1930 |
2 | 0.0001 | 1975 | 40 | 50 | 0.0789 |
1 | 0.0003 | 987 | 20 | 50 | 0.0371 |
3 | 0.0044 | 2609 | 60 | 50 | 0.1041 |
5 | 118.4384 | 3830 | 40 | 100 | 0.1205 |
Mejor Valor | Iter Convergencia | Tamaño Enjambre | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
9 | 0.0000 | 11285 | 60 | 200 | 0.4191 |
8 | 0.0000 | 7956 | 40 | 200 | 0.2926 |
6 | 0.0001 | 5408 | 60 | 100 | 0.1961 |
5 | 0.0015 | 3996 | 40 | 100 | 0.1219 |
1 | 0.6164 | 943 | 20 | 50 | 0.0298 |
3 | 1.7939 | 2951 | 60 | 50 | 0.0900 |
2 | 11.3273 | 1888 | 40 | 50 | 0.0630 |
7 | 118.4384 | 3949 | 20 | 200 | 0.1321 |
4 | 118.4385 | 1997 | 20 | 100 | 0.0697 |
Mejor Valor | Iter Convergencia | Tamaño Enjambre | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
7 | 0.0000 | 3966 | 20 | 200 | 0.1660 |
9 | 0.0001 | 11039 | 60 | 200 | 0.4674 |
8 | 0.0048 | 7975 | 40 | 200 | 0.3729 |
4 | 0.0060 | 1997 | 20 | 100 | 0.0765 |
2 | 0.0074 | 1518 | 40 | 50 | 0.0644 |
5 | 0.0074 | 3692 | 40 | 100 | 0.1406 |
6 | 0.0087 | 5289 | 60 | 100 | 0.2406 |
3 | 0.0234 | 2552 | 60 | 50 | 0.1019 |
1 | 0.0400 | 928 | 20 | 50 | 0.0528 |
Mejor Valor | Iter Convergencia | Tamaño Enjambre | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
7 | 0.0211 | 3961 | 20 | 200 | 0.1451 |
9 | 0.0218 | 11974 | 60 | 200 | 0.5213 |
5 | 0.0229 | 3934 | 40 | 100 | 0.1817 |
8 | 0.0298 | 7963 | 40 | 200 | 0.3199 |
4 | 0.0366 | 1990 | 20 | 100 | 0.0931 |
6 | 0.0561 | 5935 | 60 | 100 | 0.2474 |
1 | 0.1320 | 942 | 20 | 50 | 0.0879 |
3 | 0.1413 | 2653 | 60 | 50 | 0.1133 |
2 | 0.1713 | 1310 | 40 | 50 | 0.1162 |
Mejor Valor | Iter Convergencia | Tamaño Población | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
7 | 0.0000 | 200 | 30 | 200 | 0.0356 |
8 | 0.0000 | 200 | 50 | 200 | 0.0444 |
9 | 0.0000 | 200 | 70 | 200 | 0.0598 |
4 | 0.0000 | 100 | 30 | 100 | 0.0156 |
5 | 0.0000 | 100 | 50 | 100 | 0.0225 |
6 | 0.0000 | 100 | 70 | 100 | 0.0489 |
3 | 0.0001 | 50 | 70 | 50 | 0.0154 |
2 | 0.0004 | 50 | 50 | 50 | 0.0123 |
1 | 0.0061 | 50 | 30 | 50 | 0.0233 |
Mejor Valor | Iter Convergencia | Tamaño Población | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
8 | 0.0000 | 200 | 50 | 200 | 0.0439 |
9 | 0.0000 | 200 | 70 | 200 | 0.0801 |
7 | 0.0000 | 200 | 30 | 200 | 0.0300 |
6 | 0.0000 | 100 | 70 | 100 | 0.0302 |
5 | 0.0003 | 100 | 50 | 100 | 0.0212 |
4 | 0.0035 | 100 | 30 | 100 | 0.0166 |
3 | 0.3471 | 50 | 70 | 50 | 0.0185 |
2 | 0.5456 | 50 | 50 | 50 | 0.0230 |
1 | 18.0467 | 50 | 30 | 50 | 0.0233 |
Mejor Valor | Iter Convergencia | Tamaño Población | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
9 | 0.0000 | 200 | 70 | 200 | 0.0724 |
8 | 0.0000 | 200 | 50 | 200 | 0.0578 |
7 | 0.0000 | 200 | 30 | 200 | 0.0437 |
6 | 0.0001 | 100 | 70 | 100 | 0.0592 |
2 | 0.0013 | 50 | 50 | 50 | 0.0150 |
5 | 0.0032 | 100 | 50 | 100 | 0.0268 |
4 | 0.0068 | 100 | 30 | 100 | 0.0186 |
1 | 0.0152 | 50 | 30 | 50 | 0.0098 |
3 | 0.0264 | 50 | 70 | 50 | 0.0200 |
Mejor Valor | Iter Convergencia | Tamaño Población | Máx Iteraciones | Tiempo (s) | |
---|---|---|---|---|---|
8 | 0.0077 | 200 | 50 | 200 | 0.0531 |
7 | 0.0079 | 200 | 30 | 200 | 0.0439 |
9 | 0.0080 | 200 | 70 | 200 | 0.0686 |
5 | 0.0171 | 100 | 50 | 100 | 0.0248 |
6 | 0.0229 | 100 | 70 | 100 | 0.0569 |
4 | 0.0439 | 100 | 30 | 100 | 0.0169 |
3 | 0.0592 | 50 | 70 | 50 | 0.0177 |
1 | 0.0671 | 50 | 30 | 50 | 0.0094 |
2 | 0.0701 | 50 | 50 | 50 | 0.0143 |
Nótese que a diferencia de los métodos clásicos como el descenso del gradiente, cada uno de los métodos heurísticos logra llegar al valor óptimo de 0.
Además, se puede observar que los resultados de Evolución Diferencial tienden a ser más eficientes y llegan a los óptimos en pocas iteraciones. Más adelante entraremos en detalle para comparar a estos algoritmos evolutivos.
Para crear la animación debemos generar múltiples imágenes usando el historial de soluciones evaluadas en la función objetivo.
Camino de la solución en Schwefel 2D
Fig 7. Camino de la solución en Schwefel 2D
Como podemos notar, los algoritmos numéricos dependen altamente de la elección del punto inicial \(x_0^*\). En el GIF se ve además que la solución se desplaza por fuera de la gráfica, esto se debe a que el optimizador podría estar explorando soluciones que se mueven en \(c(x1)\), pero al graficar los frames se pueden ver puntos intermedios en la solución. Sin embargo finalmente se vuelve a la gráfica cuando se está estabilizando el óptimo.
Camino de la solución en Schwefel 3D con curvas de nivel
Fig 8. Camino de la solución en Schwefel 3D
Camino de la solución en Griewank 2D
Fig 9. Camino de la solución en Griewank 2D
Camino de la solución en Griewank 3D con curvas de nivel
Fig 10. Camino de la solución en Griewank 3D
Fig 11. GA Schwefel 2D
Fig 12. GA Schwefel 3D
Fig 13. GA Griewank 2D
Fig 14. GA Griewank 3D
Fig 15. PSO Schwefel 2D
Fig 16. PSO Schwefel 3D
Fig 17. PSO Griewank 2D
Fig 18. PSO Griewank 3D
Fig 19. DE Schwefel 2D
Fig 20. DE Schwefel 3D
Fig 21. DE Griewank 2D
Fig 22. DE Griewank 3D
Los métodos clásicos presentan limitaciones importantes en escenarios complejos. Para funciones con múltiples mínimos locales o derivadas de difícil cálculo, como Schwefel y Griewank, el descenso del gradiente tiende a quedarse atrapado en óptimos locales que pueden estar lejos del global. En nuestras funciones de prueba, observamos que para Schwefel las soluciones halladas estaban muy alejadas del óptimo, mientras que en Griewank, aunque los resultados fueron algo mejores debido a su forma semi-cuadrática, el método también se asentó en mínimos no globales. Por este motivo, en optimización de funciones no convexas se suele preferir el uso de métodos heurísticos, los cuales analizamos a continuación.
En las visualizaciones (Figuras 7, 8, 9 y 10) se aprecia que, en Schwefel, el optimizador se mueve inicialmente pero pronto queda atrapado en un óptimo local. En Griewank, el punto apenas se desplaza desde su solución inicial debido a la naturaleza ondulada del paisaje de la función.
Nota: Aunque es posible encontrar mejores resultados seleccionando cuidadosamente la semilla inicial, un optimizador robusto no debería depender de esta elección.
Nótese que el paso en cada gif es simplemente un medidor de tiempo de fotograma para referencia y no representa el paso del optimizador
En las Tablas 3, 4, 5 y 6 se presentan los resultados para la optimización de Schwefel y Griewank en 2D y 3D. Estos resultados muestran que los algoritmos genéticos logran alcanzar valores cercanos o iguales al mínimo esperado. Aunque en algunas animaciones el movimiento hacia el óptimo no se muestra completamente, los resultados numéricos evidencian el éxito del algoritmo. Esta discrepancia puede deberse a limitaciones en la resolución de los gráficos, la construcción de los frames o a la dinámica propia del algoritmo.
En las Figuras 11, 12, 13 y 14 se observa que, con poblaciones de 30 y 100 individuos, los algoritmos genéticos obtienen soluciones consistentes en tiempos de ejecución razonables.
En la optimización mediante PSO se utilizaron tamaños de enjambre entre 20 y 60 partículas y máximos de 50 a 200 iteraciones, buscando balancear el tiempo de cómputo con la calidad de las soluciones.
Se observó que, en funciones como Schwefel, PSO puede requerir miles de iteraciones para llegar al óptimo global debido a la complejidad del paisaje de la función. Así, en algunos casos, las trayectorias de las partículas no alcanzan completamente el óptimo dentro del límite de iteraciones establecido, lo cual es un comportamiento esperado.
No se realizaron ajustes manuales de hiperparámetros, pues el objetivo era analizar el desempeño del algoritmo bajo configuraciones estándar.
A pesar de ello, los resultados numéricos en las Tablas 7, 8, 9 y 10 demuestran que PSO es capaz de encontrar el óptimo global, a cambio de un mayor número de iteraciones, sin comprometer gravemente la eficiencia del método.
Los métodos de Evolución Diferencial mostraron el mejor desempeño entre los métodos analizados. Según las Tablas 11, 12, 13 y 14, este algoritmo encontró consistentemente el óptimo global en Schwefel y Griewank, tanto en 2D como en 3D, utilizando poblaciones de entre 30 y 70 individuos.
Aunque en algunas visualizaciones no se observa claramente el desplazamiento progresivo hacia el óptimo, esto se debe a la dinámica exploratoria del algoritmo, que prueba soluciones diversas antes de converger. Sin embargo, los resultados numéricos avalan que el algoritmo logra alcanzar el óptimo en todos los casos.
Esto resalta la importancia de utilizar las visualizaciones como una herramienta de apoyo para entender la dinámica del algoritmo, pero siempre confirmando los resultados a través de los valores numéricos obtenidos.
La comparación entre métodos clásicos y heurísticos en la optimización de funciones complejas como Schwefel y Griewank muestra una clara ventaja de los métodos heurísticos. Mientras que el descenso del gradiente tiende a quedarse atrapado en óptimos locales, los algoritmos evolutivos y de enjambre, como los algoritmos genéticos, PSO y evolución diferencial, logran encontrar soluciones globales con alta efectividad.
Aunque las visualizaciones no siempre muestran de manera explícita el camino completo hacia el óptimo debido a limitaciones gráficas o a la propia naturaleza de los algoritmos, los resultados numéricos confirman la eficacia de los métodos heurísticos. Esto subraya la importancia de complementar las herramientas visuales con un análisis riguroso de los datos obtenidos.
En resumen, para problemas de optimización de alta complejidad y con múltiples óptimos locales, los métodos heurísticos se presentan como la mejor alternativa frente a los métodos clásicos de optimización.
Un vendedor debe hacer un recorrido por todas y cada de las 13 ciudades principales de Colombia.
Utilice colonias de hormigas y algoritmos genéticos para encontrar el orden óptimo. El costo de desplazamiento entre ciudades es la suma del valor de la hora del vendedor (es un parámetro que debe estudiarse), el costo de los peajes y el costo del combustible. Cada equipo debe definir en qué carro hace el recorrido el vendedor y de allí extraer el costo del combustible.
Adicionalmente represente con un gif animado o un video cómo se comporta la mejor solución usando un gráfico del recorrido en el mapa de Colombia.
Con el fin de modelar correctamente el problema, se procedió a
levantar los datos de desplazamiento entre cada par de ciudades.
Se creó una matriz origen-destino que contempla para
cada trayecto:
Un ejemplo parcial de esta matriz es el siguiente:
Posteriormente, esta información se reorganizó en una matriz de costos finales que resume el costo total de desplazamiento entre las ciudades principales, como se muestra a continuación:
Esta matriz servirá como entrada para los algoritmos de optimización (Colonias de Hormigas y Algoritmos Genéticos) para determinar el recorrido óptimo.
Para modelar el desplazamiento del vendedor, se seleccionó un Jeep Wrangler de características similares a las especificadas en el sitio oficial (Jeep, n.d.):
Este vehículo fue elegido por su robustez, fiabilidad para trayectos largos y condiciones variables de carretera.
El consumo promedio de combustible reportado para este tipo de vehículo es de aproximadamente 0,117 litros por kilómetro como máximo.
El precio de la gasolina en Colombia, actualizado para el momento del análisis, es de (Ministerio de Minas y Energía de Colombia, 2024):
Dado que:
el precio de la gasolina por litro se calcula como:
\[ \text{Precio por litro} = \frac{15.827 \, \text{COP}}{3.78541 \, \text{litros}} \approx 4181,05 \, \text{COP/litro} \quad \text{(3)} \]
El Jeep Wrangler seleccionado presenta un consumo promedio de:
Así, el costo de combustible para cada trayecto se determina como:
\[ \text{Costo de combustible} = \text{Distancia recorrida (km)} \times 0.117 \times 4181.05\quad \text{(4)} \]
Simplificando:
\[ \text{Costo de combustible} = \text{Distancia recorrida (km)} \times 489.18 \, \text{COP/km}\quad \text{(5)} \]
donde:
\[ 489.18 \, \text{COP/km} = 0.117 \times 4181.05 \quad \text{(6)} \]
Este valor representa el costo de combustible por cada kilómetro recorrido.
Para calcular el costo por hora del vendedor, se tuvieron en cuenta los siguientes conceptos:
Salario mínimo por hora:
Se consideró el salario mínimo dividido entre una jornada laboral de 8
horas diarias (Ministerio de
Trabajo de Colombia, 2025):
\[ \text{Salario mínimo por hora} = 6.189 \, \text{COP/hora} \quad \text{(7)} \]
Costo de alimentación diario:
Se estimó un costo promedio de alimentación de 30.000
COP, y se asumieron tres comidas diarias, por
lo que (DANE, n.d.):
\[ \text{Costo alimentación diaria} = 30.000 \times 3 = 90.000 \, \text{COP/día} \quad \text{(8)} \]
Costo de hospedaje diario:
Se asignó un costo estimado de hospedaje de 150.000 COP
por noche (DANE, n.d.):
\[ \text{Costo hospedaje diario} = 150.000 \, \text{COP/día} \quad \text{(9)} \]
La suma total de costos asociados por día es:
\[ \text{Costo total diario} = (6.189 \times 8) + 90.000 + 150.000 \quad \text{(10)} \]
Calculando:
\[ \text{Costo total diario} = 49.512 + 90.000 + 150.000 = 289.512 \, \text{COP} \quad \text{(11)} \]
Dado que en un día hay 24 horas, el costo de la hora del vendedor considerando todos los factores es:
\[ \text{Costo hora vendedor} = \frac{289.512}{24} \approx 12.063 \, \text{COP/hora} \quad \text{(12)} \]
Así, para cada trayecto entre ciudades, el costo asociado al tiempo del vendedor será:
\[ \text{Costo asociado al tiempo} = \text{Duración del trayecto (horas)} \times 12.063 \, \text{COP} \quad \text{(13)} \]
Este componente se sumará al costo de los peajes y al costo del combustible para determinar el costo total del recorrido.
\[ \text{Costo total} = \text{Tiempo viaje (hr)} \cdot \text{Costo hora vendedor (COP)} + \text{Distancia (km)} \cdot \text{Costo gasolina (COP/km)} + \text{Peajes (COP)} \quad \text{(14)} \]
Para obtener los datos de distancia (en kilómetros) y tiempo estimado de recorrido (en horas) entre ciudades, se utilizó Google Maps (Google, n.d.).
El valor de los peajes entre ciudades fue obtenido directamente de la plataforma oficial del Instituto Nacional de Vías de Colombia (INVIAS), específicamente a través de su sistema HERMES SIV.
Con el fin de optimizar el proceso de obtención de los datos de distancia y tiempo estimado entre ciudades, se desarrolló un pequeño procedimiento automático utilizando programación en Python.
## [1] "Ruta Vecino más cercano: Palmira -> Tuluá -> Armenia -> Pereira -> Manizales -> Medellín -> Bucaramanga -> Cúcuta -> Valledupar -> Soledad -> Barranquilla -> Cartagena -> Montería -> Bogotá -> Pasto -> Palmira"
## [1] "Costo total: 3887351 $ Pesos"
## [1] "Ruta Colonia de Hormigas: Palmira -> Tuluá -> Armenia -> Pereira -> Manizales -> Medellín -> Montería -> Cartagena -> Barranquilla -> Soledad -> Valledupar -> Cúcuta -> Bucaramanga -> Bogotá -> Pasto -> Palmira"
## [1] "Costo total: 3613332 $ Pesos"
Fig 22. Mejor Ruta usando Colonia de Hormigas
Fig 23. Mejor Ruta usando K-Vecino más cercano
Se logró representar correctamente el problema del viajante de comercio (TSP), incorporando no solo las distancias entre ciudades, sino también variables contextuales relevantes del territorio colombiano, como el costo de peajes, el consumo de combustible y la tarifa por hora del vendedor. Esta aproximación realista permite obtener soluciones más útiles y aplicables a escenarios logísticos reales.
La calidad y precisión de la matriz de costos fue clave para garantizar resultados confiables. Esta matriz fue generada automáticamente a partir de la API de Google Maps, combinando factores económicos como precios de combustible y tarifas, lo que permitió construir una representación detallada y actualizada del problema.
El algoritmo de Vecino Más Cercano produjo una ruta con un costo total de 3,887,351 pesos, siendo una heurística determinista y voraz que toma decisiones locales inmediatas, sin considerar el impacto global. Aunque es computacionalmente eficiente, tiende a quedarse atrapado en soluciones subóptimas.
Por su parte, el algoritmo de Colonia de Hormigas logró una ruta con un costo total de 3,613,332 pesos, lo que representa una mejora del 7.05% respecto al Vecino Más Cercano. Este enfoque estocástico es capaz de explorar un espacio de soluciones más amplio, evitando óptimos locales mediante el uso de feromonas, memoria colectiva y exploración probabilística.
Aunque ACO requiere mayor tiempo de cómputo y ajuste de parámetros, su desempeño superior en esta instancia demuestra su potencial en problemas complejos de optimización combinatoria. Con mayor número de iteraciones y calibración, es esperable que supere consistentemente a heurísticas simples como el Vecino Más Cercano.
Marcos David Carrillo Builes: Participó en la implementación del algoritmo de colonia de hormigas para la búsqueda de rutas óptimas entre las principales ciudades de Colombia. Realizó la recolección de coordenadas geográficas, la búsqueda de mapas base, y elaboró visualizaciones gráficas de las rutas obtenidas. Además, contribuyó en la documentación correspondiente a esta sección.
Tomás Escobar Rivera: Desarrolló e implementó diversos algoritmos heurísticos para abordar el problema de optimización planteado en el punto 1. Se encargó de la modularización y limpieza del código, la creación de funciones de visualización, el ajuste de hiperparámetros, y la elaboración de gráficos que ilustran el desempeño de los optimizadores. Redactó las conclusiones y documentó detalladamente el proceso de optimización heurística y elaboró las conclusiones de colonia de hormigas.
Jose Fernando López Ramírez: Fue responsable de la investigación bibliográfica y metodológica necesaria para construir la matriz de costos empleada en el análisis. Documentó su proceso de obtención y su aplicación dentro del marco general del proyecto.
Esteban Vásquez Pérez: Coordinó el formato general del informe, la gestión de paquetes y dependencias, así como la administración del repositorio y la publicación del trabajo. Implementó la optimización de la función de Schwefel mediante el método de descenso, y elaboró gráficos 2D, 3D y curvas de nivel. Además, redactó las conclusiones y documentación matemática del punto 1, construyó la matriz de costos en Excel y organizó la bibliografía del informe.
R Core Team. (2024). R: A language and environment for statistical computing. R Foundation for Statistical Computing. https://www.r-project.org/
Scrucca, L. (2013). GA: A Package for Genetic Algorithms in R. Journal of Statistical Software, 53(4), 1–37. https://cran.r-project.org/package=GA ↳ Utilizado para implementar el algoritmo genético (GA) y guardar el historial de soluciones en cada iteración.
Bendtsen, C. (2012). DEoptim: An R Package for Global Optimization by Differential Evolution. Retrieved April 2025, from https://cran.r-project.org/package=DEoptim ↳ Usado para aplicar el método de evolución diferencial y extraer la mejor solución por iteración.
Bendtsen, C. (2012). pso: Particle Swarm Optimization. Retrieved April 2025, from https://cran.r-project.org/package=pso ↳ Herramienta utilizada para implementar la optimización por enjambre de partículas (PSO) en 2 y 3 dimensiones.
Surjanovic, S., & Bingham, D. (n.d.). Schwefel Function (schwef). Simon Fraser University. Retrieved April 2025, from https://www.sfu.ca/~ssurjano/schwef.html ↳ Fuente utilizada para la definición matemática, dominio y mínimo global de la función de Schwefel.
Surjanovic, S., & Bingham, D. (n.d.). Griewank Function (griewank). Simon Fraser University. Retrieved April 2025, from https://www.sfu.ca/~ssurjano/griewank.html ↳ Fuente utilizada para la descripción formal, propiedades y representación de la función de Griewank.
R Documentation. https://www.rdocumentation.org/
Simon Fraser University. (s.f.). Home. https://www.sfu.ca/
Google. (n.d.). Google Maps Directions API. Retrieved
April 2025, from https://developers.google.com/maps/documentation/directions/start
↳ Fuente utilizada para obtener el tiempo y distancia entre ciudades
principales de Colombia.
Instituto Nacional de Vías de Colombia (INVIAS). (n.d.).
Sistema de Información de Peajes HERMES SIV. Retrieved April
2025, from https://hermes2.invias.gov.co/SIV/
↳ Fuente oficial para la consulta de tarifas de peajes por categoría
vehicular en Colombia.
Jeep. (n.d.). Jeep Wrangler - Gasoline Capabilities.
Retrieved April 2025, from https://www.jeep.es/jeep-wrangler/gasolina/capacidad
↳ Especificaciones del vehículo seleccionado, incluyendo consumo de
combustible por kilómetro.
Ministerio de Minas y Energía de Colombia. (2024). Precios de
la gasolina por galón en Colombia. Retrieved April 2025, from https://www.minenergia.gov.co/
↳ Fuente del precio actualizado de la gasolina para cálculo del costo
por litro.
Ministerio de Trabajo de Colombia. (2025). Salario mínimo
legal vigente 2025. Retrieved April 2025, from https://www.mintrabajo.gov.co/
↳ Fuente del salario mínimo legal mensual utilizado para estimar el
costo de la hora del vendedor.
DANE. (n.d.). Encuesta Nacional de Presupuestos de los
Hogares (ENPH). Retrieved April 2025, from https://www.dane.gov.co/
↳ Utilizada como referencia para estimaciones de gasto en alimentación y
hospedaje diarios.
Dorigo, M., & Blum, C. (2005). Ant colony optimization theory: A survey. Theoretical Computer Science, 344(2–3), 243–278. https://doi.org/10.1016/j.tcs.2005.05.020 ↳ Fuente académica que describe el algoritmo de optimización por colonia de hormigas (ACO), utilizado como base para la implementación en este trabajo.
OpenAI. (2025). ChatGPT (versión GPT-4.5) [Modelo de lenguaje grande]. https://chat.openai.com/
DeepSeek. (2024). DeepSeek: LLM. https://chat.deepseek.com/