Sebastián Cadavid-Sánchez
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # Tópicos de Optimización Avanzada ## Algoritmo _ACO_ para resolver problemas _TSP_ **Estudiantes:** Santiago Battezatti, Sebastián Cadavid-Sánchez, Rafael Ortega, Laura Tejada ### Índice 0. Objetivo 1. Problema de optimización a resolver: Traveller Salesman Problem 1.1. Algoritmo Greedy 1.2. Algoritmo Ant Colony Optimization 2. Desarrollo y Optimización de código 3. Implementacion del algoritmo con un problema real 3.1. Conjunto de datos 3.2. Solución del problema TSP 4. Conclusiones 5. Referencias ## 0. Objetivo El objetivo de este proyecto fue estudiar el problema de optimización del viajero (_Travelling Salesman Problem - TSP_) y su solución por medio del algoritmo de colonia de hormigas (_Ant Colony-ACO_). Realizar la implementación del algoritmo ACO en lenguaje `Python` en la librería [![ACO-TSP](https://gist.githack.com/C1587S/6f2fccb2473f9c9c8a093db7a03f9ab3/raw/f895b41f3ea45fd26c529b7e80ea4a3c69b0e0a5/ACO%20TSP%20pkg.svg)](https://github.com/optimizacion-2-2021-1-gh-classroom/practica-1-segunda-parte-ltejadal) para la solución de problemas TSP con conjuntos de datos reales. En las fases de desarrollo del proyecto se busca robustecer las implementaciones de la librería por medio de cómputo en paralelo y métodos de selección de hiper-parámetros. Así como probar la librería en lanzamientos de _pipelines_ con `kubeflow`y `kale`. En la sección 1 de este documento se describe el problema de optimización TSP a resolver y el algoritmo ACO. En la sección 2 se presenta una descripción general de la implementación de la librería `ACO-TSP`. En la sección 3 se presenta el uso de la librería para solucionar un problema TSP con una base de de datos utilizando un enfoque de _pipeline_. Finalmente, en la sección 4 se presentan las conclusiones. ### 1. Problema de Optimización a resolver: Traveller Salesman Problem (TSP) El problema de optimización a resolver consistió en el del Traveller Salesman Problem (TSP) que consiste en hallar el recorrido más corto para recorrer una serie de nodos interconectados entre sí. Así, dada una matriz de distancias entre cada nodo y todos los demás, se busca encontrar el mejor recorrido posible. Podemos formular el TSP como un problema de programación lineal en enteros, como sigue: $$\displaystyle \min_{0 \leq x_{ij} \leq 1} \sum\limits_{i=0}^{n} \sum\limits_{j\neq i, j=0}^{n} c_{ij} x_{ij}$$$$\text{sujeto a:}$$$$\sum\limits_{i=0, i \neq j}^{n} x_{ij} = 1, j = 0, ..., n$$$$\sum\limits_{j=0, j \neq i}^{n} x_{ij} = 1, i = 0, ..., n$$$$ u_i - u_j + nx_{ij} \leq n - 1, 1 \leq i \neq j \leq n $$ Donde: - $x_{ij}$ es igual a 1 si existe un camino de la ciudad $i$ a la ciudad $j$, y cero en otro caso. - $c_i$ es la distancia desde la ciudad $i$ hasta la ciudad $j$. - $n$ el número total de ciudades. - $u_i$ son variables artificiales para definir las restricciones del problema. En primer lugar, es necesario señalar que la opción de “fuerza bruta”, calcular todos los caminos posibles y elegir el que minimice el costo (la distancia total recorrida) es una opción que no se encuentra disponible por su costo computacional, especialmente a medida que el tamaño del conjunto de datos empieza a aumentar. En otras palabras, la solución por *fuerza bruta* no es escalable. Así, se procedió a investigar algunos algoritmos que permitieran resolver este problema. En particular, se investigaron dos algoritmos, el algoritmo *Greedy* y el algoritmo *Ant Colony Optimization*. ### 1.1. Algoritmo Greedy El algoritmo *Greedy* (avaricioso) es un algoritmo que consiste en elegir la opción menos costosa (o la que otorga una mayor ganancia en el corto plazo, de ahí su nombre) en cada iteración. Por su facilidad de implementación, este algoritmo suele ser utilizado como *baseline*; es decir, como una forma para determinar un punto de partida que debe ser mejorado al resolver un problema de optimización. Asimismo, es preciso señalar que el algoritmo *greedy* no fue diseñado específicamente para resolver el *Traveller Salesman Problem*, sino que se trata de una familia de algoritmos que pueden ser aplicados (replicando el razonamiento iterativo que se acaba de mencionar) a varios problemas de optimización. ### 1.2. Ant Colony Optimization En segundo lugar, investigamos el algoritmo *Ant Colony Optimization*, el cual decidimos implementar. Este algoritmo recibe su nombre porque imita el funcionamiento de una colonia de hormigas. Para ello, el algoritmo envía hormigas que eligen diferentes caminos, y en su trayectoría dejan feromonas. Esto imita lo que sucede en la realidad, ya que las hormigas son animales ciegos, que para elegir su camino se guían principalmente por el olor de feromonas dejado por otras hormigas. En la práctica, a medida que un camino se toma con mayor frecuencia, empiza a contar con una mayor cantidad de feromonas, aumentando la probabilidad de que las siguientes hormigas tomen ese mismo camino. Por medio de esta iteración de homigas, que de manera secuencial van recorriendo diferentes caminos (dejando feromonas y guiándose en parte por las feromonas previas que encuentran en su camino), el algoritmo realiza el proceso de encontrar el mejor camino para resolver el TSP. En otras palabras, al momento de decidir qué paso dar de un nodo al siguiente, cada hormiga se guía parcialmente por la cantidad de feromonas que hay en cada arista. En la implementación concreta del algoritmo, la cantidad de feronomas dejada por cada hormiga en su recorrido tiene una relación proporcional a qué tan bueno ha sido el performance de su tour (es decir el costo total de su recorrido, medido con la distancia). A su vez, el algoritmo cuenta con una propiedad de “evaporación” de las feromonas en el tiempo, que es fundamental para el proceso de optimización porque, a medida que se van encontrando nuevos caminos mejores que los anteriores, es preciso que estos cobren mayor peso para cada hormiga en sus decisiones, en comparación de los viejos caminos subóptimos. A continuación, describimos la implementación de este algoritmo y cómo buscamos mejorar y optimizar su código. ## 2. Desarrollo y Optimización de código En esta sección se describe de forma general el proceso de implementación de la librería [![ACO-TSP](https://gist.githack.com/C1587S/6f2fccb2473f9c9c8a093db7a03f9ab3/raw/f895b41f3ea45fd26c529b7e80ea4a3c69b0e0a5/ACO%20TSP%20pkg.svg)](https://github.com/optimizacion-2-2021-1-gh-classroom/practica-1-segunda-parte-ltejadal), y algunos de sus ḿetodos y funciones principales. La documentación detallada de la misma está disponible en la siguiente referencia: [![Documentation](https://gist.githack.com/C1587S/ccc36b3d60edb8329464588177bae5d2/raw/f91c3226a4e9627a1eef7c40d0356df75d114a30/ACO%20TSP%20Documentation.svg)](https://c1587s.github.io/ACO-TSP/index.html). ### 2.1 Implementación La implementación del algoritmo se dividió en distintas etapas, dirigidas a la solución de problemas TSP que se pueden enmarcar en un flujo (_pipeline_) dirigido, desde la carga de la base de datos, hasta la solución del problema y su visualización como se presenta en la Figura 1. ```flow st=>inputoutput: Lectura de datos op1=>operation: Grafo op2=>operation: Inicialización ACO op3=>operation: Selección de hiper-parámetros op4=>operation: Solución TSP op5=>operation: Visualización st->op1->op2->op3->op4->op5 ``` _**Figura 1** Diagrama de flujo de la implementación de la librería `ACO-TSP`. Donde _TSP_ es _Travelling Salesman Problem_ y `ACO` es el algoritmo _Ant-Colony_._ Inicialmente se abordó un enfoque funcional para cumplir todas las tareas del flujo anterior. Con el fin de robustecer la librería, se adoptó un enfoque orientado a objetos. Luego de realizar ejercicios de perfilamiento, se identificaron secciones del código donde el tiempo de ejecución podría reducirse, especialmente para problemas que implicaran más nodos en el grafo analizado. Para lo anterior se re-implementó el algoritmo incluyendo cómputo en paralelo. Las implementaciones de la librería `ACO-TSP` se realizaron en lenguaje `Python`, y el flujo de trabajo llevado a cabo se presenta en la Figura 2. ```mermaid gantt title Cronograma de implementación de código section Etapa 1 Estudio previo:a1, 2021-03-10, 13d Enfoque funcional:a2, 2021-03-15 , 15d section Etapa 2 Enfoque POO:2021-04-01 , 20d Optimización HP:2021-04-11 , 10d Perfilamiento:2021-04-15 , 10d Computo paralelo:2021-04-15 , 18d section Etapa 3 Visualización:2021-05-01 , 10d ``` _**Figura 2** Cronograma de implementaciones en la librería `ACO-TSP`._ ### 2.2 Clases, métodos y funciones La librería `ACO-TSP` tiene tres clases principales que ayudan a resolver problemas **TSP** con el algoritmo de colonia de hormigas: `ant`, `colony`, y `colony_mtw`. Dichas clases implementan diferentes métodos y funciones, cuyos elementos más relevantes se presentarán en esta sección. #### Clase `ant` Esta clase representa una hormiga de la colonia y su labor principal es realizar recorridos por el grafo, `G`, que representa la matriz de distancias. Para inicializarse se le debe proporcionar el grafo asociado al problema, un diccionario de distancias entre los nodos, e indicar por cuál nodo iniciará su recorrido. **Método _`walk_over_graph`_** Este es el único método de la clase `ant`, y busca que la hormiga recorra todo el grafo, `G`, iniciando y terminando en el mismo nodo, sin repetir ninguno. Al final de su recorrido, la hormiga reporta la ruta recorrida y su distancia asociada. Para poder decidir los caminos por donde se llevará a cabo su recorrido, la hormiga es provista de un nivel de atracción de cada nodo, el cual depende del nivel de atracción inicial (que depende de las distancias entre nodos) y el nivel de feromonas por los distintos caminos del grafo. En este sentido, cada vez que la hormiga llega a un nodo, la probabilidad de que decida hacia cuál vecino ir es afectada por los pesos asignados a cada uno por medio del diccionario de atracción. #### Clase `colony` La clase `colony` es una composición de varias hormigas, provenientes de la clase `ant` que van recorriendo grafo `G`. En particular, los diferentes recorridos que realizan las hormigas afectan los niveles de feromonas del grafo, y por lo tanto, también los niveles de atracción de cada nodo. Para iniciar una colonia se debe proporcionar el grafo, `G`, y dónde deben iniciar las hormigas. Adicionalmente, se puede indicar el número de hormigas que incluye la colonia, `n_ants`, y el número de iteraciones que se deben realizar, `max_iter`. **Metodo _`solve_tsp`_** Es el principal método de la clase `colony`, y obtiene la ruta más corta de la colonia encontrada por las hormigas y su distancia asociada. A continuación se enlistan los pasos que ejecuta la colonia de hormigas en cada iteración para resolver el problema TSP y el método (met) o función (func) que utiliza para la ejecución. 1. Computa el diccionario de atracción de los nodos (`atraccion_nodos` [func]). 2. Todas las hormigas de la colonia recorren `G` <u>secuencialmente</u> (`_colony_run` [met]). 2.1. Cada hormiga recorre el grafo y reporta la ruta y distancia encontradas (`walk_over_graph` [met]) 2.1. Se actualizan los niveles de feromonas de `G` (`_update_many_pheromone_levels` [met]). 3. Se ajustan los niveles de feromonas de acuerdo a una tasa de evaporación (`_evaporates_pheromone` [met]). En cada iteración la colonia guarda la mejor ruta y distancias obtenidas como atributos (`best_route` y `best_dist`, respectivamente), y en caso de que se obtenga una mejor, son reemplazados. Una vez ejecutado este método, es posible extraer dichos atributos para obtener la solución del problema obtenida por el algoritmo. #### Clase `colony_multiw` La clase `colony_multiw` se deriva de `colony`, e implementa cómputo en paralelo haciendo multiprocesamiento en el ḿetodo `solve_tsp`. Dicha implementación surgió de los ejercicios de perfilamiento realizados, los cuales indicaron que el mayor tiempo de cómputo se explicaba por la secuencialidad en el recorrido del grafo de las hormigas de la colonia en el método mencionado. La nueva implementación del método se logró utilizando la librería [`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html) de `Python`. En particular, la principal diferencia con respecto a `colony`, es que en cada iteración `colony_multiw` crea un _Pool_ de sub-procesos, y a cada uno le asigna un número aproximadamente equitativo de hormigas. Así, simultáneamente en cada sub-proceso un número de hormigas determinado recorre el grafo secuencialmente. Al final de la iteración, un proceso principal reune las rutas y las distancias obtenidas por todas las hormigas en todos los procesos, y la colonia almacena el mejor par como un atributo. A modo de ejemplo, en la Figura 3 se presenta un grafo dirigido para mostrar el procedimiento que se realiza en cada iteración el método `solve_tsp` en la clase `colony_multiw`. En esta representación se utilizan **3 procesos** y se seleccionan **4 hormigas**. Dado lo anterior, a un proceso se le asignan 2 hormigas, y una a los dos restantes. ```graphviz digraph hierarchy { nodesep=1 node [color=Blue, fontname=Courier, shape=box] edge [color=Black] colony_multiw->asignar_hormigas->{SP1 SP2 SP3} SP1->{h1 h2} h1->h1_recorre_G h2->h2_recorre_G SP2->{h3} h3->h3_recorre_G SP3->{h4} h4->h4_recorre_G {rank=same;SP1 SP2 SP3} {rank=same;h1 h2 h3 h4} {h1_recorre_G h2_recorre_G h3_recorre_G h4_recorre_G}->recolectar_soluciones recolectar_soluciones-> MejorSolucion->colony_multiw } ``` _**Figura 3** Representación del cómputo del método `solve_tsp` de la clase `colony_mtw` en cada iteración. Donde SP denota un subproceso. h_i denota a una hormiga con identificador i._ **Mejoras en tiempo de ejecución** La mejora en el tiempo de ejecución depende del _hardware_ en que es ejecutado el algoritmo. A continuación se presenta el desempeño en tiempo total de ejecución del algoritmo en dos máquinas con diferentes características, y se compara la mejora en tiempo con respecto a la ejecución secuencial. En particular, se resuelve problema TSP de $100$ ciudades chinas, elegidas aleatoriamente del conjunto de la [base de datos](https://www.math.uwaterloo.ca/tsp/world/countries.html) de *National Traveling Salesman Problems* de la Universidad de Waterloo. Se utilizan $100$ iteraciones, $1000$ hormigas, y valores de $1$, $5$, y $0.5$ para los parámetros de importancia del nivel inicial de atracción, importancia del nivel de feromonas, y nivel de evaporación, respectivamente. <center> | CPU(s) | CPU(s) utilizados | Computo | Tiempo (segs/mins) | Mejora en tiempo | |--------------------------------------------------|----------|--------------|--------------------|------------------| | Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz | 1 | Secuencial | 2699.36 s / 45 m | x1 | | Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz | 4 | Paralelo | 452.37 s / 7.5 m | x5.97 | | Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz | 1 | Secuencial | 794.74 s / 13.24 | x1 | | Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz | 12 | Paralelo | 21.60 s / 0.36 m | x36.79 | </center> _**Tabla 1** Comparación del tiempo de cómputo de la implementación secuencial y con cómputo en paralelo de `ACO-TSP` para diferentes arquitecturas._ ### 2.3 Optimización de hiper-parámetros El algoritmo de colonia de hormigas implementado incluye cinco hiper-parámetros: - Número de hormigas en la colonia (`n_ants`) - Máximo número de iteraciones (`max_iter`) - Importancia del nivel de atracción inicial (`rho`) - Importancia del nivel de las feromonas (`beta`) - Grado de evaporación de las feromonas (`alpha`) Para robustecer la librería, se implementó la rutina `optim_h_params` que utiliza la librería [`optuna`](https://optuna.org/), con el fin de utilizar técnicas de optimización bayesiana para buscar eficientemente los parámetros que maximizan una función objetivo en un "hiper-espacio". Seleccionamos un subconjunto de los datos a analizar, y los utilizamos para realizar dicho ejercicio de optimización, para el cual se debe definir una función objetivo. En este caso, queremos que el algoritmo encuentre la distancia de la ruta más corta que recorra todos los nodos del grafo, y que a su vez, sea lo más rápido posible en tiempo de ejecución. Para lo anterior, se propone minimizar la siguiente función objetivo: $$ obj = t + d^2 $$ Donde $t$ es el tiempo de ejecución en minutos, y $d$ es la distancia de la ruta encontrada por el algoritmo. Las clases `colony` y `colony_multiw` incluyen el método `optim_h_params`, el cual permite definir el número de intentos (`trials`) sobre los cuales se va a realizar muestreo sobre el espacio de hiper-espacio, y devuelve el conjunto de mejores hiperparámetros para el problema estudiado. ## 3. Implementación del algoritmo en un conjunto de datos En esta sección se utiliza la librería [`ACO-TSP`](https://github.com/C1587S/ACO-TSP/) para resolver el problema TSP en un conjunto de datos reales utilizando un enfoque de _pipeline_ que es ejecutado en [`kale`](https://github.com/kubeflow-kale/kale) en una instancia de AWS. En las siguientes subsecciones se explicarán: el conjunto de datos, los pasos incorporados en el _pipeline_, las caracaterísticas de la máquina utilizada, y los resultados asociados al ejercicio. ### 3.1. Descripción de la base de datos Se utilizó un conjunto de datos de la base de datos [National Traveling Salesman Problems](http://www.math.uwaterloo.ca/tsp/world/countries.html) de la Universidad de Waterloo que contiene las coordenadas de 71,009 ciudades en China, y se encuentra disponible en la siguiente [liga](http://www.math.uwaterloo.ca/tsp/world/ch71009.tsp). Este conjunto de datos contiene latitud y longitud para dichas ciudades, con lo cual se calcula la matriz de distancias, considerándolas como el costo asociado de ir de un nodo a otro. En este ejercicio se seleccionan 150 ciudades para el problema TSP y se utiliza un subconjunto de 50 para la selección de los mejores hiper-parámetros. ### 3.2 Arquitectura **Instancia EC2** El ejercicio de implementación se ejecutó en una instancia de EC2 de AWS con las características presentadas en la Tabla 2: <div align="center"> | Architecture | x86_64 | |---------------------|------------------------------------------------| | CPU op-mode(s) | 32-bit, 64-bit | | Byte Order | Little Endian | | CPU(s) | 4 | | On-line CPU(s) list | 0-3 | | Thread(s) per core | 2 | | Core(s) per socket | 2 | | Socket(s) | 1 | | Model name | Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz | | CPU MHz | 3099.932 | | BogoMIPS | 4999.99 | </div> ``` _**Tabla 2** Características de la instancia EC2 de AWS para la implementación de de ACO-TSP en un conjunto de datos real._ **Imagen de [`Docker`](https://www.docker.com/)** La librería cuenta con una imagen de Docker disponible en [Dockerhub](https://hub.docker.com/r/santibatte/ant_colony_jupyter/tags?page=1&ordering=last_updated) que permite instalar de forma estable todas las dependencias requeridas. Dicha imagen es utilizada en la instancia de AWS para ejecutar la implementación. ### 3.3 _Pipeline_ El _pipeline_ implementado en ésta ejecución se puede representar en la Figura 4. Los pasos se describen a continuación: - `imports`: se `ACO-TSP` y dependencias adicionales - `parametros`: Se definen los parámetros a utilizar durante la ejecución. - lectura de datos (`grafo_datos_hp`): Se extrae el grafo correspondiente a un subconjunto de la totalidad de los datos del problema, para realizar la optimización de hiper-parámetros. - lectura de datos (`grafo_datos_principales`): Se extrae el grafo asociado a la totalidad de ciudades (nodos) del problema. - lectura de datos (`coord_datos_principales`): Se extrae un `dataframe` con las coordenadas de cada uno de los nodos del problema. - `mapa_nodos`: Se grafica el mapa con la ubicación de cada nodo utilizando sus coordenadas. - `seleccion_hp`: Se realiza el estudio y selección de los mejores hiper-parámetros. - `hp_disco`: Se guardan los mejores hiper-parámetros en disco con formato de base de datos, `.db`. - `colonia_mtw`: Se instancía una colonia que utiliza computo en paralelo con los mejores hiper-paŕametros encontrados qe incorpora el grafo con la totalidad de los nodos. - `colonia`: Se instancía una colonia (sin cómputo en paralelo) con los mejores hiper-paŕametros encontrados qe incorpora el grafo con la totalidad de los nodos. (se utiliza para comparar con la implementación de `colonia_mtw`) - `resolver_TSP`: La colonia obtiene una solución al problema TSP para las especificaciones asignadas. - `distancia`: Se extrae la distancia ḿas baja de la solución. - `ruta`: Se extrae la ruta asociada a la distancia más baja. - `guardar_sln`: Guardar solución en disco con formato `.json` - `mapa_ruta`: Se grafica el mapa con la ubicación de cada nodo utilizando sus coordenadas y la ruta con la solución encontrada por la colonia. ```graphviz digraph hierarchy { nodesep=1 node [color=red, fontname=Courier, shape=box] edge [color=Black] imports->parametros->lectura_datos lectura_datos->{grafo_datos_hp grafo_datos_principales coord_datos_principales} coord_datos_principales->mapa_nodos grafo_datos_hp->seleccion_hp->hp_disco {grafo_datos_principales hp_disco}->{colonia_mtw, colonia} colonia_mtw->resolver_TSP colonia->resolver_TSP resolver_TSP->distancia resolver_TSP->ruta {distancia, ruta}->guardar_sln {coord_datos_principales, ruta}->mapa_ruta {rank=same;grafo_datos_principales coord_datos_principales grafo_datos_hp} edge[style=invis] # grafo_datos_principales->colonia_mtw } ``` _**Figura 4** _Pipeline_ para la implentación de la librería `ACO-TSP` con un conjunto de datos real._ ### 3.4. Implementación del código y resultados obtenidos En esta sección se presenta la implementación en `Python` y los resultados obtenidos, con el fin de ilustrar el uso de la librería. ```python # instalar libreria !pip install "git+https://github.com/C1587S/ACO-TSP#egg=ant-colony&subdirectory=src" &> /dev/null" &> /dev/null ``` - Importación de librerías a utilizar ```python import ant_colony as ac import json from multiprocessing import cpu_count import time import timeit ``` En este caso, las librerías `time` y `timeit` fueron importadas para mostrar los tiempos de ejecución del programa. - Definición de los paŕametros de la ejecución ```python ## parametros del algoritmo data_path = '../datasets/ch71009.tsp' init_node_ex = 0 hp_trials = 50 save_hp = True seed = 19519159 n_cities = 150 n_cities_hp = 50 n_cpu = cpu_count() ``` De los parámetros anteriores: * `data_path`: hace referencia al lugar donde se encuentra el conjunto de datos. * `init_node_ex`: indica el nodo en donde iniciaremos la implementación. * `hp_trials` es la cantidad de veces que se muestrea para buscar en el espacio de hiper-parámetros. * `save_hp` indica si los mejores hiper-parámetros encontrados serán guardados en un archivo con el nombre de "best_hiper_parameters.db" * `n_cities` es el número de ciudades sobre las cuales se realizará la ejecución. * `n_cities_hp` es la cantidad de ciudades que se usarán para el meustreo de hiper-parámetros. * `n_cpu` indica el número de CPU's disponibles en la computadora de ejecución. En este caso son 4. - Lectura y separación de datos Como se mencionó inicialmente, se utiliza un conjunto de datos principal para el problema TSP asociado a 150 ciudades, y se selecciona un subconjunto de 50 para la elección de los mejores hiper-parámetros. Por otro lado, se extrae el `dataframe` asociado a las coordenadas de los nodos del problema. ```python # lectura de datos ## 150 ciudades - coordenadas y grafo coord_df = ac.read_coord_data(data_path, n_cities=n_cities, seed=seed, coord_df=True) G = ac.read_coord_data(data_path, n_cities=n_cities, seed=seed, coord_df=False) ## 50 ciudades - grafo hp G_hp = ac.read_coord_data(data_path, n_cities=n_cities_hp, seed=seed, coord_df=False) ``` La función `read_coord_data` nos ayuda a leer la información que viene en formato de coordenadas, y transformarla en un grafo de `networkx`, si se utiliza el parámetro `coord_df=False`. Lo anterior, dado que la clase `colony_mtw` requiere el mismo para el funcionamiento de sus ḿetodos. Por otro lado, si se requieren obtener únicamente los datos de las coordenadas de los nodos se puede utilizar `read_coord_data` con el parámetro `coord_df=True`. - Mapa con los nodos del problema Para problemas que incluyen coordenadas resulta útil visualizar los nodos en un mapa con el fin de realizar una validación previa de los mismos. Para lo anterior, se incluyó la función `plot_nodes_map`, que se puede utilizar de la siguiente forma: ```python # visualizar y guardar mapa map_nodes = ac.plot_nodes_map(coord_df, save=True, save_as='map_nodes') map_nodes ``` ![mapa_nodos](https://i.imgur.com/Qf6L2ZX.png) _**Figura 5** Representación estática de los nodos en un mapa._ Una visualización ḿas no-estática del anterior mapa se encuentra disponible [aquí](http://acotspcities.s3-website-us-east-1.amazonaws.com/). - Estudio para selección de hiper-parámetros Para la selección de los mejores hiper-paŕametros se implementó la función `optim_h_params_mp`, cuyo funcionamiento se explica en secciones anteriores. Para este caso se utiliza el grafo destinado a esta parte del ejercicio, `G_hp`, y se especificó un muestreo de 10 intentos (`hp_trials=10`) en el "hiper-espacio". Para iniciar el estudio, se ejecuta: ```python # optimizacion de hiper-parametros y guardar en disco study = ac.optim_h_params_mp(G_hp, init_node = init_node_ex, trials = hp_trials, save = save_hp) ``` Ejecutándolo con `timeit`, mostró los siguientes resultados: ``` The slowest run took 13.82 times longer than the fastest. This could mean that an intermediate result is being cached. 2min 41s ± 4min 17s per loop (mean ± std. dev. of 15 runs, 10 loops each) ``` Al finalizar, los mejores hiper-parámetros se guardan como `best_hiper_params.db`. - Crear colonia con los mejores hiper-parámetros Una vez se han seleccionado los mejores hiper-parámetros, se instancía la clase `colony_multiw` con los mismos, y el grafo asociado al problema principal con 150 nodos, `G`. Adicionalmente, se selecciona el número de `subprocesos` como el total de CPU de la EC2, es decir, 4. ```python # cargar mejores hp best_params = ac.load_params('best_hiper_params.db') # instanciar colony_multiw con mejores hp colony_mw = ac.colony_multiw(G, init_node=0, n_workers = n_cpu, verbose=True, k_verbose=10, **best_params) ``` - Resolver problema TSP Para que la colonia solucione el problema TSP se utiliza el método `solve_tsp` de la misma: ```python # Nota: start_time y end_time no son necesarios para # la implementación de la paquetería, pero fueron utilizados # solamente con la finalidad de mostrar el tiempo de ejecución. start_time = time.time() colony_mw.solve_tsp() end_time = time.time() ``` Se obtienen los siguientes resultados para la solución del problema: La mejor ruta encontrada fue la siguiente: ``` Resumen: Nro. de hormigas: 4 Iteraciones: 10 Distancia: 470.2663138277652 Nodo inicial: 0 Ruta: [0, 86, 85, 60, 135, 8, 79, 109, 35, 56, 10, 15, 91, 128, 94, 105, 20, 2, 33, 41, 69, 93, 123, 59, 67, 118, 68, 114, 107, 75, 62, 108, 106, 149, 145, 4, 46, 19, 32, 148, 43, 36, 141, 88, 64, 66, 16, 17, 37, 99, 52, 12, 104, 127, 129, 26, 130, 24, 87, 78, 31, 25, 45, 55, 101, 116, 5, 136, 74, 147, 111, 51, 90, 50, 132, 47, 117, 126, 27, 58, 80, 125, 63, 11, 121, 122, 76, 40, 119, 61, 48, 23, 72, 96, 44, 81, 3, 6, 57, 53, 115, 103, 95, 89, 29, 1, 9, 14, 34, 70, 13, 139, 143, 84, 133, 21, 134, 146, 22, 92, 39, 110, 54, 137, 18, 124, 71, 83, 30, 65, 131, 138, 7, 112, 140, 82, 98, 120, 49, 97, 100, 77, 144, 102, 113, 28, 142, 42, 38, 73, 0] ``` ``` La solución con pool de workers tomó 14.3951 segundos. ``` Al ejecutar estos mismo resultados con `timeit`, se obtuvierons los siguientes tiempos: ``` 13.6 s ± 8.41 s per loop (mean ± std. dev. of 15 runs, 10 loops each) ``` - Visualizar solución Para observar la ruta con la mejor solución encontrada se incluyó la función `plot_rout_map`, la cual se puede utilizar de la siguiente forma: ```python # visualizar solución y guardar mapa como html map_route = ac.plot_rout_map(coord_df, colony_mw.best_route, path_type='ants', save=True, save_as='map_aco_route') map_route ``` ![map_route](https://i.imgur.com/Ve9eXUj.jpg) _**Figura 6** Representación de los nodos y la ruta solución en un mapa._ Una mejor visualización del mapa que permite el flujo ordenado del viajero entre nodos se encuentra disponible [aquí](http://acotspslnroute.s3-website-us-east-1.amazonaws.com/). - Guardar solución en disco Posteriormente, se guarda la solución encontrada por la colonia en forma de diccionario en un archivo `JSON`: ```python # extraer mejor ruta sln_r = colony_mw.best_route # extraer mejor distancia sln_d = colony_mw.best_dist # diccionario con soluciones sln_dic = {'route': sln_r, 'distance': float(sln_d)} # guardar solución en disco with open("aco_sln.json", "w") as outfile: json.dump(sln_dic, outfile) outfile.close() ``` ### Comparación con la clase `colony` Adicionalmente, para comparar el desempeño con la clase `ant_colony` (que no incluye cómputo en paralelo), se instancía una clase `colony` con los mejores hiperparámetros encontrados en el problema. ```python # instanciar colony con mejores hp colony_old = ac.colony(G, init_node=0, verbose=True, k_verbose=10, **best_params) ``` A continuación se resuelve el problema: ```python start_time = time.time() colony_old.solve_tsp() end_time = time.time() ``` Con esto, se obtuvieron los siguientes resultados: ``` Resumen: Nro. de hormigas: 4 Iteraciones: 10 Distancia: 515.1653410440995 Nodo inicial: 0 Ruta: [0, 86, 85, 71, 83, 30, 135, 60, 79, 8, 35, 109, 56, 139, 74, 11, 63, 5, 147, 125, 80, 58, 27, 126, 117, 47, 90, 51, 132, 50, 112, 23, 48, 39, 92, 54, 110, 122, 121, 76, 40, 22, 119, 61, 96, 44, 72, 127, 12, 129, 26, 104, 66, 16, 17, 37, 99, 52, 133, 84, 143, 134, 21, 95, 46, 4, 43, 32, 19, 148, 36, 149, 145, 62, 75, 107, 108, 106, 123, 93, 115, 103, 53, 3, 81, 57, 6, 138, 7, 144, 14, 59, 67, 114, 68, 34, 70, 13, 118, 137, 18, 124, 65, 136, 101, 116, 31, 25, 130, 24, 87, 78, 120, 98, 140, 82, 94, 91, 128, 69, 41, 2, 33, 20, 105, 29, 1, 9, 73, 146, 142, 42, 141, 88, 64, 111, 45, 55, 15, 10, 77, 49, 100, 97, 131, 113, 38, 102, 89, 28, 0] ``` Al ejecutar con `timeit`, se obtuvo lo siguiente: ``` 1.43 s ± 524 ms per loop (mean ± std. dev. of 15 runs, 10 loops each) ``` **Conclusiones de la comparación:** De la anterior sección es importante notar dos resultados. Para la implementación que no incorpora cómputo en paralelo se obtiene una distancia mayor y un menor tiempo de cómputo. Esto es explicado por dos mecanismos que se explican a continuación. Primero, la selección de hiper-parámetros seleccionó un número de 10 iteraciones luego de muestrear 50 veces sobre el hiper-espacio. En este sentido, al ser un número reducido de iteraciones, resulta costoso en términos de tiempo de ejecución el levantamiento de los 4 sub-procesos utilizados en `colony_mtw`, y esto le permite a `colony` mejorar el tiempo de ejecución. Cuando se incrementa el número de iteraciones, es posible observar las ganancias en tiempo de ejecución de la implementación en paralelo como se explica en la sección 2.2. Por otro lado, al ser un problema que incorpora 150 nodos, hay $150!$ posibles rutas. En este sentido, existe un componente aleatorio que le permitió a la clase `colony_mtw` encontrar una mejor ruta que a la clase `colony`. Sin embargo, poder buscar en un número razonable de posibilidades implica un elevado número de iteraciones y/o de hormigas en la colonia. Dado lo anterior, es posible que se deba escalar la búsqueda de hiper-parámetros con que incorpore lo anterior y permita a las colonias hacer una búsqueda más detallada de rutas para esperar convergencia en las soluciones. ### Conclusiones generales y trabajo futuro Se implementó la librería ACO-TSP que es aplicable a la solución de problemas del viajero (TSP) utilizando conjuntos de datos reales. La librería se implementó en tres etapas: implementación con enfoque funcional, implementación con programación orientada a objetos, y robustecimiento (computo en paralelo, optimización de hiperparámetros, y visualización). Adicionalmente, implementó ACO-TSP utilizando `kale` y `kubeflow` con el fin de demostar su utilización en un flujo de trabajo que incorpore _pipelines_. Por otro lado, cabe mencionar que es posible incorporar en la librería como ejercicios de robustecimiento dos mejoras inmediatas. Inicialmente, el uso de cómputo asíncrono podría mejorar la implementación con computo en paralelo que utiliza sub-procesos. Por otro lado, la solución de problemas con datos geo-espaciales introduce otro tipo de restricciones, como el uso de rutas con ciertas características especiales. Por ejemplo, el uso de carreteras terrestres. En ese sentido, es necesario ajustar el algoritmo y la forma en que procesa los datos con rescursos adicionales al grafo y matriz de distancias asociados al problema. ## 4. Referencias 1. [Problema del Viajante](https://es.wikipedia.org/wiki/Problema_del_viajante) (2021) Wikipedia 2. [Programación Lineal (PL) y Método Símplex](https://itam-ds.github.io/analisis-numerico-computo-cientifico/IV.optimizacion_en_redes_y_prog_lineal/4.2/Programacion_lineal_y_metodo_simplex.html) (2021) Erick Palacios 3. [Data for the Traveling Salesperson Problem](https://people.sc.fsu.edu/~jburkardt/datasets/tsp/tsp.html) (2019) People Sc 4. [Kochenderfer, M. J., & Wheeler, T. A. (2019). Algorithms for Optimization. Mit Press.](https://mitpress.mit.edu/books/algorithms-optimization) 5. [Cómputo en paralelo usando CPUs en un sistema de memoria compartida (SMC)](https://itam-ds.github.io/analisis-numerico-computo-cientifico/V.optimizacion_de_codigo/5.4/Computo_en_paralelo_usando_CPUS_en_SMC.html#multiprocessing) (2021) Erick Palacios

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully