PROBLEMA DEL AGENTE VIAJERO USANDO BÚSQUEDA TABU PROYECTO FINAL PROGRAMACIÓN CIENTIFICA ANGELES BAEZ OLVERA 4 JUNIO 2009 Descripción del problema: El problema del agente viajero o TSP como se le conoce en la literatura, consiste en visitar las n ciudades de un tour comenzando y terminando en la misma ciudad, visitando solamente una vez cada ciudad, y haciendo el recorrido en un costo mínimo, este costo de recorrido puede estar expresado en términos de tiempo o distancia, es decir, recorrer el mínimo de kilómetros o llevar a cabo un tour en el menor tiempo posible. El problema del agente viajero se puede modelar fácilmente mediante un grafo completo en donde los vértices del grafo son las ciudades y los arcos son los caminos, dichos arcos deben tener un peso, y este peso representa la distancia que hay entre dos vértices que están conectados por medio de dicho arco. Una solución del problema del agente viajero, se puede representar como una secuencia de n+1 ciudades, en donde un tour comienza y termina con la misma ciudad. Objetivo: El objetivo de este trabajo es resolver el problema del agente viajero usando Búsqueda Tabú. Usando utilizó el lenguaje computacional ANSI C. Búsqueda Tabú: Es un procedimiento metaheurítico cuya característica distintiva es el uso de memoria. La búsqueda tabú guía un proceso de búsqueda local para explorar el espacio de solución más allá del
óptimo local. Algoritmo de la Búsqueda Tabú: 11Comienza con una solución inicial. 11En la iteración inicial o en cualquier otra iteración, a partir de una solución actual, el proceso pasa a la mejor solución de su vecindario. 11El movimiento siempre se acepta a pesar de que la nueva solución sea peor que la anterior. El proceso se puede ciclar, por ello se utiliza una lista tabú, en la que se encuentran los movimientos que se consideran prohibidos, es decir aquellos que no se pueden tomar para la nueva solución durante un cierto numero de iteraciones, a menos que cumplan el criterio de aspiración, el cual consisten en determinar cuando un movimiento tabú puede ser tomado para la solución. Para este problema se tomo el criterio de aspiración por objetivo [1], el cual consiste en comparar el costo que presenta la solución con movimiento tabú, con el mejor costo encontrado hasta el momento, si este costo es mejor entonces se actualiza la mejor solución, con la nueva solución que presenta el movimiento tabú. PROGRAMA: Los parámetros: El programa tiene parámetros de entrada, de salida y los calculados dentro de el. Los parámetros de entrada: Decidir como introducir los datos al programa ya sea por teclado (opción 1) o llamarlos desde un archivo (opción 2). Si se toma la opción por teclado el programa pedirá al usuario: El número de ciudades que desea visitar. La ciudad en la que se desea iniciar el recorrido.
El número de iteraciones que se desea hacer. La distancia o tiempo entre cada ciudad. Si se toma la opción por archivo: los tres primero números que tenga el archivo van a indicar el número de ciudades a visitar, la ciudad de inicio y el número de iteraciones respectivamente y los demás número serán las distancias de las respectivas ciudades. Cabe aclarar que el programa esta diseñado suponiendo que todas las ciudades están conectadas con todas y que el viajar de la ciudad i a la ciudad j tiene la misma distancia o tiempo que viajar de la ciudad j a la ciudad i. Los parámetros de salida: La mejor solución en cada iteración. El mejor camino que debe recorrer el agente. La distancia o tiempo que implica dicho camino. Los parámetros que son determinados por el programa son: El tamaño del vecindario: Este parámetro se calcula haciendo la operación [(numero de ciudades*(numero de ciudades -3))/2], este forma de calcular el vecindario se decidió después de hacer varias pruebas y ver como se comportaba el tamaño del vecindario, tal vez no sea la mejor manera de determinarlo, pero con las instancia probadas funciono. El número de iteraciones que un movimiento es considerado tabú: Este parámetro es calculado sacando la raíz cuadrada del número de ciudades a visitar y tomando el entero de tal resultado. Se decidió tomarlo así basado en la referencia bibliográfica [1]. Las subrutinas: El programa se compone de una serie de subrutinas, se decidió trabajar con subrutinas para tener una mejor organización del programa y en caso de requerirse hacer mas accesible las modificaciones.
El programa se compone de 14 subrutinas y de la función principal main (que no puede faltar). A continuación se describe cada una de las subrutinas 1. validar: Se encarga de verificar que todos los parámetros de entrada sean correctos cuando se ingresan por teclado. Recibe como parámetros la dirección de una cadena, y devuelve uno si la cadena es de enteros y cero si la cadena no tiene enteros. 2. matrix_distancia: Con esta subrutina se captura la distancio o tiempo de viajar de la ciudad i a la ciudad j, el programa esta hecho de tal manera que considera que ir de la ciudad i a la cuidad j es lo misma distancia que desplazarse de la ciudad j a la ciudad i. Recibe como parámetros el número de ciudades a visitar y la dirección de la matriz donde se van a guardas las distancias o tiempos. 3. recupero_matriz: Es la encargada de hacer una copia de la matriz de distancia. Recibe el número de ciudades a visitar, y la dirección de la matriz que se va a copiar y la dirección de la matriz a la que se va a copiar. 4. co_vecindario: Hace una copia del vecindario. Recibe el número de ciudades a visitar, el tamaño del vecindario, la dirección donde esta el vecindario, y la dirección a donde se va a copiar. 5. Imprimo, imprimir_vec: Estas dos subrutinas se usan para imprimir en pantalla las matrices y los vectores que se desee. Recibe las dimensiones de la matriz o del vector y la direcciones de la matriz o vector a imprimir. 6. Greedy: Esta subrutina es la que se encarga de calcular la solución inicial, esta solución se calcula de manera greedy, es decir siempre que se hace un cambio de ciudad, lo hace tomando el camino de menor distancia o tiempo. Recibe el numero de ciudades a visitar, la ciudad de inicio del recorrido, la dirección de la matriz de distancia de las ciudades y la dirección del vector donde se guardara el recorrido. 7. costo_recorrido: Calcula la distancia o tiempo del recorrido indicado. Recibe el número de ciudades, la dirección de la matriz de distancia, y la dirección del vector del recorrido. 8. mov2_opt: En esta subrutina es donde se genera el vecindario de cada iteración. Se aplica el algoritmo 2-opt que básicamente remueve dos arcos del tour y reconecta los dos caminos creados;
hay una sola forma de reconectar los dos caminos de forma que siga manteniendo el tour válido. Si se remueven los arcos (i,j) y (k,l) la unica forma de reconectarlos manteniendo el tour es (i,k), (j,l). El vecindario se compone de las dos aristas que se remueven y del costo que se tiene al hacer el movimiento. Esta subrutina recibe el número de ciudades a visitar, el costo del tour, tamaño del vecindario, la dirección de la matriz de distancia, la dirección del vector que contiene el tour y la dirección de la matriz del vecindario. 9. Minimo:.Identifica el costo mínimo en el vecindario. Recibe como parámetros el tamaño del vecindario y la dirección de la matriz del vecindario. 10. actualizo_solucion: Actualiza la solución. Recibe el número de ciudades a visitar, la posición del mejor costo del vecindario, la dirección del vector tour, y la dirección del vecindario. 11. verifico_tabu: Revisa que el movimiento elegido sea o no tabú. Recibe de parámetros el número de ciudades a visitar, el tamaño de la lista tabu, la posición del mejor costo en el vecindario, y las direcciones de la lista tabú y el vecindario y regresa 0 si el movimiento elegido no es tabu y 1 si es tabú. 12. actualizo_tabu: Se encarga de actualizar la lista tabú. Recibe la posición del mejor costo del vecindario, el tamaño de la lista tabú, costo del tour y las direcciones de vecindario y la lista tabu. 13. todo: Realiza todo el proceso de búsqueda tabú, utilizando las subrutinas antes mencionadas. Recibe como parámetros el número de ciudades a visitar, la ciudad de inicio, el número de iteraciones a realizar y la dirección de la matriz de distancias. Y finalmente en la función main que es la que contiene la interfaz inicial del programa y las indicaciones que debe seguir el usuario. Instrucciones de compilación: 1. Para compilar escriba: gcc -lm proyecto.c
./a.out 2. En pantalla aparecerán las instrucciones a seguir 3. Si se desea escoger la opción por teclado debe presionarse el numero 1, si se desea la opción por archivo se presiona 2 y si se desea salir se presiona 3. 4. Si se escoge la opción por archiva, el usuario antes debe tener un archivo en el cual tenga los datos que se necesitan para el funcionamiento del programa. Experimentación: Se generaron varias instancias para comprobar que el programa funcionará correctamente, se probo con instancias pequeñas y con instancias grande. Las instancias grandes fueron llamadas desde archivo. Instancias pequeñas: Instancia 1: 3 ciudades, inicia 1 La matriz de distancia es: 0 8 10 8 0 15 Solución inicial:{1,2,3,1,} Con un costo de:33 La solución inicial es el mejor camino 10 15 0 Instancia 2: 6 ciudades, inicia 4, itera 15 La matriz de distancia es: 0 10 5 4 3 67 10 0 100 23 4 56 67 56 23 675 45 0 Solución inicial:{4,1,5,2,6,3,4,} Con un costo de:97 5 100 0 7 12 23 4 23 7 0 455 675 3 4 12 455 0 45
Instancia 3: 8 ciudades, inicia 2, itera 500 La matriz de distancias es: 0 3 4 56 78 98 76 4 3 0 32 2 43 54 6 78 4 32 0 98 100 123 400 345 56 2 98 0 232 43 5 67 78 43 100 232 0 8 98 90 98 54 123 43 8 0 65 4 76 6 400 5 98 65 0 2 4 78 345 67 90 4 2 0 Solución inicial:{2,4,7,8,1,3,5,6,2,} costo 179 El mejor tour {2,4,7,8,6,5,3,1,2} costo de 128 Intancias grandes: Intancia 1: 19 ciudades, inicia 13, itera 200 Solución inicial: 13,12,7,8,16,1,17,5,2,11,4,14,18,9,6,19,3,10,15,13 Con un costo de:218 El mejor tour: 13,12,11,2,5,18,1,16,8,7,15,4,14,17,10,3,19,6,9,13 con un costo de 92. Intancia 2: 35 ciudades, inicia 20, itera 2000 Solución inicial: 20,18,4,6,30,3,14,32,11,12,26,9,27,19,24,10,21,15,23,31,29,2,5,8,25,35,1,28,7,17,13,16,34,22,33,20 Con un costo de 240 El mejor camino es: {20,18,4,6,30,3,14,32,11,12,26,9,27,33,22,34,7,17,13,16,28,1,35,25,8,5,2,29,31,23,15,21,10,24,19,20,} con un costo de 119.
Conclusiones: El programa trabaja con instancias grandes y pequeñas y puede se de gran ayuda para optimizar el recorrido de viajes. En cuanto a la programación me costo un poco, pues el trabajar con apuntadores se me complico, pero al final quedo claro. Bibliografia: Glover, F and M Laguna (1997) Tabu Search, Kluwer Academic Publishers, Boston.