ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

103
ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA MALLA VIAL DE LA CIUDAD DE BOGOTÁ LEONARDO RODRIGUEZ CASTAÑEDA UNIVERSIDAD DE LOS ANDES PREGRADO Bogotá, Junio de 2005

Transcript of ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Page 1: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ALGORITMOS PARA CALCULAR LA RUTA

MÁS CORTA EN LA MALLA VIAL DE LA

CIUDAD DE BOGOTÁ

LEONARDO RODRIGUEZ CASTAÑEDA

UNIVERSIDAD DE LOS ANDES

PREGRADO

Bogotá, Junio de 2005

Page 2: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ALGORITMOS PARA CALCULAR LA RUTA

MÁS CORTA EN LA MALLA VIAL DE LA

CIUDAD DE BOGOTÁ

Autor:

LEONARDO RODRIGUEZ CASTAÑEDA

Asesores:

FRANSISCO RUEDA FAJARDO

RAFAEL ARMANDO GARCIA GOMEZ

UNIVERSIDAD DE LOS ANDES

FACULTAD DE INGENIERIA

DEPARTAMENTO DE INGENIERIA DE SISTEMÁS Y COMPUTACION

Desarrollado para cumplir con el

requisito de grado para el titulo de

Ingeniero de Sistemas y Computación

Junio de 2005

Page 3: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

INDICE

OBJETIVOS ____________________________________________________________ 4

INTRODUCCION________________________________________________________ 5

DESCRIPCION DEL PROBLEMA_________________________________________ 6

ALGORITMOS DE GRAFOS BASICOS____________________________________ 8

ALGORITMO DE DIJKSTRA ___________________________________________ 11 Algoritmo de Dijkstra Formalmente_________________________________________________ 14 Análisis de Complejidad. __________________________________________________________ 17

ALGORITMO A-ESTRELLA ____________________________________________ 21 Algoritmo de A Estrella Básico Formalmente _________________________________________ 25 Análisis de Complejidad___________________________________________________________ 29

ESTRELLA POR SECTORES ____________________________________________ 32 Algoritmo de A Estrella Por Zonas Formalmente______________________________________ 39 Análisis de Complejidad. __________________________________________________________ 45

MODELO BÁSICO _____________________________________________________ 48

MODELO DE GRAFO DUAL ____________________________________________ 51

MODELO DE GRAFO DINÁMICO_______________________________________ 56

IMPLEMENTACION ___________________________________________________ 61

RESULTADOS OBTENIDOS Y CONCLUSIONES __________________________ 69

ANEXO I______________________________________________________________ 78

ANEXO 2. _____________________________________________________________ 82

ANEXO 3. _____________________________________________________________ 85

ANEXO 4. _____________________________________________________________ 87

ANEXO 5. _____________________________________________________________ 90

ANEXO 6. _____________________________________________________________ 93

ANEXO 7. _____________________________________________________________ 95

ANEXO 8. _____________________________________________________________ 97

REFERENCIAS _______________________________________________________ 102

Page 4: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

OBJETIVOS

• Realizar la comparación entre dos propuestas de solución al problema de

encontrar la ruta más corta entre dos puntos en un grafo real. Los

algoritmos seleccionados son el algoritmo A-Estrella y un algoritmo

propuesto basado en el algoritmo de A-Estrella, pero partiendo el grafo en

sectores.

• Los parámetros con respecto a los cuales serán comparados los algoritmos

son: requerimientos de memoria, tiempo de procesamiento y por último la

calidad de la respuesta obtenida. Es decir, serán comparados tanto en

eficiencia como en eficacia.

• La comparación del desempeño de los algoritmos seleccionados se debe

realizar también contra un algoritmo que se ha demostrado que es óptimo

en la mayoría de los requerimientos, este es el algoritmo de Dijkstra para el

camino más corto.

• El propósito principal de este proyecto es evaluar estos dos algoritmos, con

el fin de conocer la viabilidad de ser aplicados en aplicaciones de

georegerenciación para computación móvil.

Page 5: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

INTRODUCCION

La teoría de grafos es muy significativa a la hora de hablar de estructuras de datos,

dado que un grafo permite realizar la representación gráfica de una situación

particular; es por esto que se pretende realizar un análisis detallado de la malla vial

de Bogotá estudiando y analizando varios modelos y algoritmos que permitan

determinar cuál es el modelo y el algoritmo aplicable para una aplicación móvil;

aplicación que será descrita en este documento.

Existen múltiples problemas y situaciones cotidianas que se pueden modelar por

medio de grafos, esto permite que se tenga una mayor abstracción del modelo y de

la solución del problema. El uso de grafos para modelar algún problema en

particular permite determinar las relaciones existentes entre varios de los

componentes de dicho problema, identificando las rutas o posibles caminos entre

cada uno de los destinos correspondientes.

En este documento se podrá encontrar la descripción del problema a tratar, los

diferentes modelos y algoritmos analizados y la propuesta correspondiente para la

aplicación de un algoritmo determinado al problema que se manejará: el problema

de la malla vial de Bogotá.

Page 6: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

DESCRIPCION DEL PROBLEMA

Se desea proponer un sistema de algoritmos que permitan encontrar la ruta más

corta entre dos puntos dentro de la ciudad de Bogotá. La ruta debe ser calculada

empleando la malla vial existente en la ciudad de Bogotá. Se desea tener en cuanta

el sentido de las vías, así como las restricciones en los cruces que pueden ser

realizados. El cálculo del costo de pasar por una vía depende de la capacidad de

tráfico que puede soportar, así como de la longitud de la misma.

Para el desarrollo de este proyecto se cuenta con una base de datos con

información geográfica de la ciudad de Bogotá. Esta base de datos geográficos de

la malla vial de la ciudad de Bogotá, fue proporcionada por la empresa Procalculo

Prosis S.A. Esta base de datos fue desarrollada bajo el estándar del sistema de

archivos de información geográfica Shapefile. Este sistema de archivos de

información geográfica es propiedad de la compañía de investigación y desarrollo

de software ESRI. De alguna forma esta información debe ser abstraída para

construir un grafo, el cual debe representar la malla vial de la ciudad de Bogotá, y

debe reflejar las métricas utilizadas en el modelo. Después de tener el modelo

representado por un grafo, se deben utilizar algoritmos eficientes que solucionen el

problema de calcular la ruta más corta entre dos puntos en este grafo.

Para calcular la ruta más corta entre dos puntos dentro de la ciudad se propone

analizar y comparar dos algoritmos. El primer algoritmo a ser utilizado y

estudiado es el algoritmo de grafos A-Estrella, en el cuál cada intersección de la

malla vial es un nodo del grafo. El segundo algoritmo es una modificación del

Page 7: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

algoritmo A-Estrella, pero trabajando áreas geográficas dentro de la ciudad de

Bogotá, con sus diferentes interconexiones, estas áreas pueden ser los diferentes

barrios de la ciudad, o las localidades, y las interconexiones son los caminos que

interconectan cada uno de estos barrios.

Los algoritmos A-Estrella y A-Estrella por sectores deben ser comparados entre si

en cuanto a requerimientos de memoria, tiempo de procesamiento, y calidad de la

respuesta obtenida. Dada la naturaleza de estos algoritmos, es necesario comparar

los resultados contra un algoritmo óptimo en la mayoría de los aspectos. Este

algoritmo es el del camino más corto de Dijkstra.

El algoritmo de Dijkstra se ha demostrado que es óptimo, y que presenta un buen

desempeño en la mayoría de los casos. En el caso de grafos grandes, este algoritmo

requiere de un gran tiempo de procesamiento para encontrar la respuesta, es por esto que no

escogimos este algoritmo para ser aplicado en este problema. Hay que notar que la maya

vial de la ciudad de Bogotá tiene alrededor de 80 mil intersecciones y más de 140 mil

segmentos de camino vehicular, luego, dado que el algoritmo de Dijkstra tiene complejidad

espacial S (n) y complejidad temporal T (n2), el tiempo estimado de ejecución sería de 15

segundos para calcular un camino que recorra un cuarto de la ciudad, lo que lo hace

inaplicable en el caso de dispositivos móviles.

El propósito principal de este proyecto es evaluar estos dos algoritmos, con el fin de

conocer la viabilidad de ser aplicados en aplicaciones de georegerenciación para

computación móvil.

Page 8: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ALGORITMOS DE GRAFOS BASICOS

Un grafo es una estructura matemática que puede ser usada para modelar redes y

una gran cantidad de otros sistemas donde las relaciones entre los objetos juegan

un papel muy importante.

Un grafo está compuesto por un conjunto de vértices y otro de arcos. Los arcos

unen un vértice con otro. El conjunto vértices se denota con “V”, y el de arcos con

“E”. Los grafos pueden ser dirigidos o no dirigidos. Un grafo dirigido, es uno en el

cuál los arcos sólo tienen una dirección determinada, mientras que uno no

dirigido, los arcos tienen dirección en ambos sentidos. Un arco puede tener un

costo o impedancia asociado, el cuál representa el costo requerido de pasar de un

vértice a otro vértice, utilizando dicho arco. Un grafo está denotado de la siguiente

forma:

G = (V, E)

Donde V es el conjunto de vértices del grafo, y E es el conjunto de arcos. En este

trabajo vamos a modelar la malla vial de la ciudad de Bogotá en forma de grafo. El

grafo que va a modelar la malla vial tiene las siguientes características: Primero

que todo es un grafo planar, lo que significa que el grafo se puede dibujar sobre

un plano si que un arco cruce encima de otro. Esta restricción que estamos

definiendo en el grafo se debe a que la base de datos geografica de la malla vial de

la ciudad de Bogotá, que estamos usando presenta esta particularidad. Otras bases

de datos geofraficas de mallas viales no se pueden representar con grafos planares,

Page 9: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ya que inclyen información sobre tuneles y puentes. Este grafo es dirigido y cuenta

con un conjunto de aproximadamente 80 mil nodos y 130 mil arcos.

Sobre este grafo queremos calcular la ruta o camino más corto entre dos nodos.

Existen numerosos algoritmos de grafos, para encontrar el camino de un nodo a

otro nodo. Si queremos encontrar el camino más corto de un nodo a otro nodo, el

algoritmo de Dijkstra para el camino más corto, garantiza que si se encuentra un

camino de un nodo a otro nodo dado, este será el camino más corto. Este es un

algoritmo muy costoso en cuanto a complejidad espacial que es S (n) y tiempo de

proceso, ya que tiene complejidad temporal T (n2). Más adelante profundizaremos

sobre este tema.

Para disminuir el tiempo necesario para encontrar el camino más corto, entre dos

nodos dados, existen otros algoritmos que utilizan heurística, o información

adicional, para poder solucionar el problema. El algoritmo que presenta mejores

resultados es el A* o A-Estrella, el cuál utiliza una función de distancia entre el

nodo inicial y el nodo objetivo. Lo interesante de este algoritmo es que esta

distancia, no debe ser exacta para que el algoritmo funcione correctamente,

únicamente debe ser una distancia aproximada.

Muchas veces en la vida real, encontrar la respuesta óptima a un problema no

siempre es lo más importante. En muchas ocasiones es más importante obtener una

respuesta “buena” rápidamente, aunque esta respuesta no sea la óptima.

El algoritmo BFS (Best First Search) es una optimización del algoritmo breadth first

search que es utilizado en grafos arborescentes. Este algoritmo puede ser utilizado

en cualquier tipo de grafo. Este algoritmo ordena los arcos de un nodo utilizando

una heurística. La heurística utilizada en este algoritmo es la proximidad a la que

Page 10: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

se encuentra el nodo objetivo. El arco que conduzca más cerca al nodo objetivo es

colocado en la primera posición y así sucesivamente. Este algoritmo aunque

encuentra un camino mucho más rápidamente que el algoritmo de Dijkstra, no

necesariamente encuentra el camino optimo.

En este proyecto vamos a trabajar con tres algoritmos. El primer algoritmo con el

que vamos a trabajar es el algoritmo de Dijkstra, el cual garantiza que siempre

encuentra la respuesta óptima al problema de calcular la ruta más corta entre dos

nodos en un grafo.

El otro algoritmo con el que vamos a trabajar es el algoritmo A-Estrella. Este

algoritmo aunque no siempre encuentra la respuesta óptima, la respuesta es

obtenida mucho más rápidamente que la obtenida por el algoritmo de Dijkstra.

El último algoritmo fue propuesto por nosotros, y consiste en dividir el grafo en

zonas, y sobre estos sectores calcular el camino más corto, usando una versión del

algoritmo A-Estrella. Este algoritmo lo vamos a llamar en este documento como

A-Estrella por sectores.

A continuación vamos a hacer el análisis de estos tres algoritmos, iniciando con el

algoritmo de Dijkstra, y terminado con el algoritmo A-Estrella por sectores.

Page 11: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ALGORITMO DE DIJKSTRA

El algoritmo de Dijkstra es el algoritmo más simple para encontrar la ruta más

corta entre un nodo y todos los demás nodos pertenecientes al grafo G. Este

algoritmo supone que el grafo es dirigido y que los costos de los arcos son todos

positivos.

El problema de la ruta más corta se puede resolver utilizando programación lineal

sin embargo, debido a que el método simplex es de complejidad exponencial, se

prefiere utilizar algoritmos que aprovechen la estructura en red que se tiene para

estos problemas.

El problema del camino más corto escrito en forma de programación lineal es

presentado a continuación. Supongamos que los nodos del grafo G= (V, E), están

numerados de 1 a n, N = {1, 2,…, n}, y tambien tenemos una matriz L que contiene

los costos de todos los arcos del grafo. La matriz L esta definida de la siguiente

forma. L [i, j] = 0 si y solo si i = j, L[i, j] ≥ 0 para i ≠ j si existe el arco (i, j), y L[i, j]= ∞

si no existe el arco (i, j). El principio de optimalidad dice que si el nodo (k) hace

parte del camino más corto entre el nodo (i) y el nodo (j), entonces el camino entre

el nodo (i) y el nodo (k) y el camino entre el nodo (k) y el nodo (j) tambien tiene

que ser optimal.

Si se observa la estructura de una red se puede determinar que una red de

comunicaciones involucra un conjunto de nodos conectados mediante arcos, que

transfieren paquetes de datos desde determinados nodos origen a otros nodos

Page 12: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

destino. La forma más común para seleccionar la trayectoria (o ruta) de estos

paquetes de datos, se basa en la formulación de la ruta más corta. En particular a

cada arco se le asigna un escalar positivo el cuál se puede ver como su longitud,

costo, o capacidad máxima de tráfico. Este problema particular puede ser

solucionado utilizando algoritmos de flujo maximo.

Un algoritmo de trayectoria más corta, enruta cada paquete de información a lo

largo de la trayectoria de longitud mínima (ruta más corta) entre los nodos origen

y destino. Hay varias formas posibles de seleccionar la longitud de los enlaces. La

forma más simple es que cada enlace tenga una longitud unitaria, en cuyo caso, la

trayectoria más corta es simplemente una trayectoria con el menor número de

enlaces. De una manera más general, la longitud de un enlace puede depender de

su capacidad de transmisión y su carga de tráfico.

La solución siempre es encontrar la trayectoria más corta para el problema dado.

Esperando que dicha trayectoria contenga pocos enlaces no congestionados; de

esta forma los enlaces menos congestionados son candidatos a pertenecer a la ruta.

Hay algoritmos de enrutamiento especializados que también pueden permitir que

la longitud de cada enlace cambie en el tiempo, dependiendo del nivel de tráfico

de cada enlace. De esta forma un algoritmo de enrutamiento se debe adaptar a

sobrecargas temporales y enrutar paquetes omitiendo los nodos congestionados.

Dentro de este contexto, el algoritmo de ruta más corta para enrutamiento opera

continuamente, determinando la trayectoria más corta con longitudes que varían

en el tiempo.

El algoritmo de Dijkstra para ruta más corta, en términos generales, encuentran la

ruta más corta entre dos nodos, inicial a y final z, de la siguiente manera:

Page 13: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Todos los nodos de la red son etiquetados con números. Al principio, todos tienen

la etiqueta ∞ excepto el nodo inicial a que tiene la etiqueta 0. Los arcos tienen un

peso w (i, j) que representa la distancia del enlace (i, j). El algoritmo de Dijkstra

genera un conjunto con todos los nodos del grafo. De este conjunto selecciona el

nodo que tenga la etiqueta con el menor valor. Este nodo que ha sido seleccionado

queda marcado permanentemente, y es extraido del conjunto inicial y es

adicionado al conjunto de nodos marcados permantentemente. Posteriormente se

actualizan las etiquetas de los sucesores del nodo seleccionado, de tal forma que el

valor de la etiqueta del nodo sucesor nj es igual al valor de la etiqueta del nodo

seleccionado ni más el costo w (i,j). Esta actualizacion se realiza unicamente si el

sucesor cumple con las siguientes dos condiciones: el nodo no se encuentren en el

conjunto de nodos marcados permanentemente, y el valor de la etiqueta del nodo

es mayor al valor de la etiqueta actualizada.

Dicho de otra manera más específica, el algoritmo de Dijkstra se basa

fundamentalmente en marcar los nodos de una forma especial. La forma que

emplea el algoritmo de Dijkstra para marcar los nodos es la siguiente: El nodo que

va a ser marcado es seleccionado entre todos los nodos candidatos, es decir los que

no han sido marcados. La condición que debe cumplir el nodo para ser

seleccionado y marcado es que debe tener el menor costo acumulado del camino

desde el nodo origen. En el caso en que existan varios nodos con el mismo costo

mínimo, se puede seleccionar entre ellos cualquiera al azar, ya que más adelante

serán seleccionados y marcados. Esta simple regla de selección nos garantiza que

todos los nodos que han sido marcados, tienen el costo mínimo del camino entre

ellos y el nodo origen.

El algoritmo de Dijkstra es el único algoritmo que garantiza que una vez que un

nodo ha sido marcado, también se ha encontrado el camino mínimo entre el nodo

Page 14: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

origen y este nodo. Los demás algoritmos sólo garantizan que una vez que termina

el algoritmo se ha encontrado el camino mínimo.

A continuación vamos a explicar el algoritmo de Dijkstra. Primero vamos a

escribirlo formalmente y después vamos a hacer un análisis de complejidad.

Algoritmo de Dijkstra Formalmente

Dijkstra (G, s, W)

{Pre1: G = (V, E) ∧ s ∈V ∧ W: E ℜ+}

1: Inicializar (G, s, W)

2: M ∅

3: Q Nodos (G) {P1: Q = V - M}

{T1: Tam (Q) +1}

4: DO (Q ≠∅)

5: u Extraer-Mínimo-W (Q, W)

6: M M ∪ {u}

7: S Sucesores (u, G)

{Pre2: S: contiene los sucesores de u}

{P2: S ⊂ V ∧ (∀v: v ∈ S| : (∃ e : e ∈ E| : e(u,v))) }

{T: Tam (V) + 1}

8: DO (S ≠ ф)

9: v Extraer-Cualquiera (S)

10: IF Contiene (M, v) skip

11: Not Contiene (M, v) Relajar (u, v, W) FI

Page 15: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

OD

{Post2: sucesores de u ∩ W tienen costos relajados}

OD

{Post1: W: tiene los costos del camino mínimo desde s al resto de nodos del grafo}

El algoritmo presentado anteriormente es el algoritmo de Dijkstra, que calcula

únicamente el costo del camino mínimo entre el nodo origen y los demás nodos del

grafo G. Los parámetros de entrada de este algoritmo son un grafo G Dirigido con

todos los costo de sus arcos positivos; un nodo origen s, que pertenece al grafo G, y

por ultimo un parámetro de salida W el cuál contiene el costo mínimo entre el

nodo origen s, y todos los demás nodos del grafo G.

En la primera línea de este algoritmo asignamos un costo de camino infinito a

todos los nodos de G, menos al nodo inicial al cuál le asignamos un costo de

camino igual a cero, esto escrito formalmente es:

(∀ n: n ∈ V | n ≠ s: W [n] = ∞) ∧ W [s] = 0

En la segunda línea del algoritmo dejamos vacío el conjunto de los nodos

marcados M. En la tercera línea del algoritmo colocamos todos los nodos del grafo

en el conjunto Q.

En la cuarta línea del algoritmo tenemos un ciclo, el cuál va a ser ejecutado hasta

que el conjunto Q no tenga elementos. Como el conjunto Q tiene todos los nodos

del grafo G, este ciclo se ejecutara exactamente m veces donde m es el número de

nodos que tiene el grafo G.

Page 16: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

La quinta línea de código es la parte fundamental de nuestro algoritmo. En esta

línea es donde se selecciona y se extrae el nodo que va a ser marcado del conjunto

de nodos Q. Anteriormente se explicó por qué esta selección del nodo candidato a

ser marcado es importante para garantizar que se encuentra el camino mínimo

entre el nodo origen y los nodos marcados.

En la sexta línea, agregamos el nodo que fue seleccionado (u) para ser marcado

permanente, al conjunto de nodos marcados M. En la siguiente línea, generamos

un conjunto de nodos V, que son sucesores del nodo u.

En la octava línea del algoritmo tenemos otro ciclo, que va a ser ejecutado hasta

que el conjunto S este vacío. Este ciclo se ejecutará un número variable de veces ya

que el conjunto S puede tener diferente cantidad de nodos. El número de

elementos que contiene el conjunto S, depende del grado de conectividad del

grafo, entre más alto el grado de conectividad de este, mayor será el número de

elementos que tendrá el conjunto S.

En la novena, décima y onceava línea, lo que hacemos es seleccionar y extraer un

nodo v del conjunto del conjunto S, y lo relajamos. Este proceso de relajación

consiste en lo siguiente: Si el nodo v, pertenece al conjunto de nodos marcados M,

no hacemos nada, de lo contrario, si el costo del camino W [v] es mayor al costo del

camino W [u] + Costo (u, v) actualizamos el costo de W [v]. Este algoritmo de

relajación se presenta a continuación.

Relajar (u, v, W)

{Pre: u, v ∈ nodos (G) ∧ v ∉ M}

IF W [v] > W [u] + Costo (u, v)

W [v] = W [u] + Costo (u, v)

Page 17: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

W [v] < W [u] + Costo (u, v) Skip

FI

{Post: W[v] tiene el costo mínimo parcial}

Con esto terminamos el algoritmo de Dijkstra. A continuación vamos a hacer un

análisis de complejidad de este algoritmo.

Análisis de Complejidad.

La complejidad del algoritmo de Dijkstra depende mucho de la estructura de datos

seleccionada para la implementación del algoritmo como veremos más adelante.

El problema de la ruta más es tipo P, es decir que tiene una solución en tiempo

polinomial. Por lo tanto un algoritmo que solucione este problema tiene una

comlejidad en el mejor de los casos polinomial.

Como mencionamos anteriormente, el algoritmo de Dijkstra no termina hasta que

se hallan marcado todos los nodos del grafo G. Por lo tanto la complejidad hasta el

momento es de orden n (donde n es el número de nodos del grafo G), ya que

tenemos que realizar n veces un sub-algoritmo para cada nodo. El sub-algoritmo

está comprendido entre las líneas 5 y 11 del algoritmo de Dijkstra.

Page 18: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En la línea 5 tenemos que encontrar el nodo con menor costo de camino en el

conjunto Q. Dependiendo de la estructura de datos utilizada para este conjunto Q,

la complejidad de este algoritmo cambia. Si por ejemplo tenemos una lista de

nodos desordenada, tenemos que buscar sobre todos los elementos de esta para

encontrar el nodo que tenga el mínimo costo. Por lo tanto este algoritmo tendría

una complejidad de O (m) donde m es el número de elementos en el conjunto Q.

hay que tener en cuenta que el número de elementos de este conjunto disminuye

cada vez que es ejecutado este algoritmo. Si en vez que esto utilizamos una pila

ordenada por el costo del camino la complejidad de este algoritmo sería O (1), ya

que el primer elemento es el que tiene el menor costo del camino.

En la línea 6 tenemos que adicionar un elemento al conjunto de nodos marcados

M. La estructura de datos seleccionada para el conjunto M es muy importante

como se vera más adelante. La complejidad de este algoritmo puede variar según

la estructura seleccionada entre O (1) en una lista cualquiera a O (n).

En la línea 7 tenemos que generar un conjunto con los sucesores de un nodo

especifico. Una vez más la estructura de datos es muy importante. En este caso es

la estructura de datos utilizada para almacenar el grafo. Si utilizamos una lista de

adyacencias, la complejidad es O (1).

En la línea 8 tenemos un ciclo que se debe ejecutar otro sub-procedimiento hasta

que el conjunto V sea vacío. La cota de este ciclo es el número de elementos del

conjunto V. El conjunto V contiene los sucesores de un nodo específico. Como

también dijimos anteriormente el número de sucesores depende del grado de

conectividad del grafo. Si tenemos una conectividad alta, el número de elementos

va a ser también alta. Para grafos con una baja conectividad, podemos decir que

este sub-algoritmo se ejecutara sólo una vez.

Page 19: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En la línea 9 si para el grafo utilizamos una lista de adyacencias, entonces el

conjunto V es por lo tanto también una lista. El procedimiento que realizamos en

esta línea es seleccionar y extraer un elemento de este conjunto. La complejidad

para esto es O (1).

En la línea 10 del algoritmo de Dijkstra, tenemos que buscar dentro del conjunto de

nodos marcados M, y responder si se encuentra o no un nodo especifico.

Dependiendo de la estructura de datos seleccionada, la complejidad de esta

instrucción cambia. La complejidad de esta instrucción puede variar entre O (1) y

O (n). Como nos podemos dar cuenta la estructura de datos de del conjunto M es

mejor seleccionarla para que tenga una complejidad baja ya que si el grafo tiene

una conectividad alta, y esta instrucción también tiene una complejidad alta,

podríamos tener en el peor de los casos un algoritmo con complejidad O (n2 m).

En la línea 11, tenemos que hacer el algoritmo de relajación. Para calcular la

complejidad de esta instrucción tenemos que tener en cuenta la estructura de datos

utilizada para almacenar los costos de los caminos de todos los nodos del grafo. La

mejor estructura para este caso es un arreglo, el cuál nos garantizaría una

complejidad de O (1). La estructura que se escoja en esta parte también es muy

importante como en el caso anterior.

Este algoritmo aunque es óptimo, no resulta práctico para aplicaciones donde el

tiempo de respuesta es crucial. Cuando el tamaño del grafo muy grande, el

algoritmo de Dijkstra presenta tiempos de respuesta que no pueden ser tolerados,

por ejemplo, cuando el numero de nodos es n=100.000, y la longitud del camino es

d = 100, se espera que se realicen 10.000 operaciones correspondientes a marcar los

nodos definitivamente, que con un procesador Pentium III de 1.5 GHz toma

Page 20: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

aproximadamente 13 segundos. Para sortear este inconveniente existen otros

algoritmos que son mucho más rápidos. Estos algoritmos cambian velocidad por la

calidad de la respuesta. Estos algoritmos usualmente utilizan información

adicional para encontrar una solución, que no siempre es la óptima. El mejor de

todos estos algoritmos es el A-Estrella, el cuál puede utilizar diferentes heurísticas.

A continuación vamos a hablar sobre el algoritmo A-Estrella.

Page 21: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ALGORITMO A-ESTRELLA

El algoritmo A-Estrella fue desarrollado en 1968 para combinar el enfoque

heurístico del algoritmo BFS, y el enfoque optimal del algoritmo de Dijkstra. El

algoritmo A-Estrella es el único algoritmo heurístico, que garantiza que encuentra

el camino más corto entre dos nodos dados. Este algoritmo es ampliamente

utilizado en video juegos, y en aplicaciones de inteligencia artificial, donde la

velocidad de respuesta es lo principal. Los juegos de video que más utilizan este

algoritmo son los de estrategia en tiempo real, en los cuáles los personajes deben

desplazarse de un punto a otro por un mapa determinado. También es utilizado

para implementar la inteligencia artificial de los oponentes controlados por el

computador, el cuál puede tener en cuenta muchos aspectos, como la cercanía con

los oponentes y el rango de visión entre otros.

El algoritmo A-Estrella funciona de la siguiente forma. El algoritmo tiene dos

conjuntos de vértices, a uno de estos conjuntos lo vamos a llamar Disponibles, y al

otro lo vamos a llamar Analizados. En el conjunto Disponibles se colocan los

nodos que son candidatos a ser examinados para escoger el camino, y en el

conjunto Analizados están los nodos que ya han sido examinados, y que hacen

parte de la ruta seleccionada. Inicialmente el conjunto Disponibles contiene

únicamente el nodo inicial, y el conjunto Analizados está vacío.

Para cada nodo n se definen los siguientes valores:

g (n): Es el costo de llegar del nodo inicial al nodo n.

Page 22: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

h (n): Es un estimado del costo de llegar del nodo n al nodo Final. Este costo es

calculado a partir de la función heurística utilizada.

F (n) = g (n) + h (n): Este es un estimado del costo de la solución que pasa por el

nodo n.

El algoritmo A-Estrella es similar al algoritmo de Dijkstra excepto por una pequeña

diferencia sutil, que consiste en la inclusión de una función heurística, que tiene

como objetivo modificar nuestro criterio de selección del nodo candidato a ser

marcado. Como se vera más adelante podemos parafrasear el algoritmo de

Dijkstra, para que se vea similar al algoritmo A-Estrella.

El algoritmo A-Estrella a diferencia del algoritmo de Dijkstra, no siempre

encuentra el camino óptimo, pero tampoco se desvía mucho de la respuesta

óptima. La precisión de este algoritmo depende totalmente de la función heurística

utilizada. Si la función heurística utilizada es igual a cero, es decir no se utiliza

heurística, el algoritmo A-Estrella es exactamente igual al algoritmo de Dijkstra.

El algoritmo de A-Estrella presenta su mayor desempeño en cuanto a velocidad y

optimalidad, cuando la función heurística nos dice cuanto cuesta llegar desde un

nodo dado hasta el nodo destino. Este caso es imposible de lograr de manera

efectiva, ya que para esto necesitamos saber cuál es el costo de los caminos entre

todos los nodos, lo que requiere haber calculado previamente el costo de la ruta

óptima entre todos los nodos, y tenerla almacenada. Por lo tanto para poder

solucionar este problema, tenemos que haber solucionado el mismo problema

previamente para todas las parejas de nodos del grafo. Adicionalmente la memoria

requerida para almacenar las respuestas crece de manera cuadrática, por lo cuál es

poco eficiente.

Page 23: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Si la función heurística subestima por mucho, la distancia entre un nodo dado y el

nodo destino, el tiempo de respuesta se degrada considerablemente. En el peor de

los casos obtendremos el mismo tiempo de respuesta que el algoritmo de Dijkstra,

pero tendremos la respuesta óptima.

Si por el contrario la función heurística sobreestima la distancia entre un nodo

dado y el nodo destino, también se degrada el tiempo de respuesta, y al mismo

tiempo disminuye la calidad de la respuesta obtenida. Más adelante vamos a

hablar sobre las funciones heurísticas que pueden ser utilizadas con este algoritmo.

Las funciones heurísticas que son usadas por el algoritmo A-Estrella dependen de

las características propias del grafo sobre el cual va a ser aplicado. La funcion

heurística es utilizada para estimar el costo óptimo de un camino entre dos nodos.

Hay que resaltar que esta funcion es utilizada solo para calcular un estimado del

costo del camino, y que no altera de ninguna forma el costo del camino real.

En nuestro caso particular, el grafo con el que estamos trabajando es una malla vial

real. Uno de los criterios que definimos para fijar el costo de los arcos en este grafo

es la distancia geográfica real, que corresponde a la distancia euclidiana entre dos

nodos adyacentes. El otro criterio es la capacidad de la via que esta representando

el arco. En esta malla vial se definen unicamente dos tipos carreteras: las vias

recidenciales y las vias principales.

Para este tipo de grafos los cuáles están relacionados geométricamente, en este caso

por la distancia euclidiana, se utilizan comúnmente dos tipos de funciones

heurísticas. Las dos funciones heurísticas son la longitud Euclidiana y la longitud

de Manhattan.

Page 24: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

La longitud Euclidiana es la distancia en línea recta entre dos puntos. Esta

heurística presenta mejores resultados, cuando los costos de los arcos dependen

únicamente de la longitud de los mismos. Cuando el costo de los arcos deja de

depender mucho de la distancia correspondiente, esta heurística genera errores

mucho más grandes. La función heurística euclidiana puede ser calculada de la

siguiente forma.

22),( )()( endnodeinodeendnodeinodeendnodeinodeE yYXXh −+−=

En la anterior ecuación, Xinode y Yinode son las coordenadas del nodo (i), y Xendnode y

Yendnode son las coordenadas del nodo destino. Si los costos de los arcos dependen

totalmente de la distancia, esta función heurística nos puede aproximar muy bien

cuál es el costo para llegar de un nodo a otro.

La función heurística de Manhattan es la suma de las distancias de los puntos en

las coordenadas X y Y. Esta distancia corresponde a la distancia del camino mas

corto, utilizando otra metrica. La función heurística de Manhattan es la siguiente.

||||),( endnodeinodeendnodeinodeendnodeinodeM YYXXh −+−=

En la anterior ecuación, Xinode y Yinode son las coordenadas del nodo i, y Xendnode y

Yendnode son las coordenadas del nodo destino. Aunque la función heurística

utilizada no aproxime correctamente el costo del camino entre dos nodos dados, el

camino que encontrará el algoritmo de A-Estrella se aproxima mucho al camino

óptimo. Adicionalmente estamos reduciendo considerablemente el espacio de

búsqueda, al buscar prioritariamente en los nodos que están en la dirección del

Page 25: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

camino hacia el nodo destino. En el algoritmo de Dijkstra el espacio de búsqueda

crece radialmente, y por consiguiente el tiempo de búsqueda es mayor.

Hay que resaltar que la funcion heurística de Manhattan entre una pareja de nodos

dados es mayor o igual a la funcion heurística Euclidiana entre los nodos de esta

pareja.

h M (i, j) ≥ h E (i, j)

De la anterior relación podemos intuir que si utilizamos la heurística de Manhattan

podemos conducir al algoritmo A-Estrella a obtener resultados diferentes al

óptimo, con una probabilidad igual o mayor que si utilizamos la funcion heurística

Euclidiana.

A continuación vamos a presentar el algoritmo A-Estrella formalmente, para poder

entender mejor su funcionamiento.

Algoritmo de A Estrella Básico Formalmente A-Estrella (G, nodo-Inicial, nodo-Final) {Precondición Q1: G = (V, E) ∧ nodo-Inicial, nodo-Final ∈V) 1: Disponibles: = φ 2: Analizados: = φ 3: Nodo-Actual: = Configurar-Nodo (nodo-Inicial, 0) 4: Nodo-Actual: = Asignar-Padre (nodo-Inicial, nodo-Inicial, Nodo-Actual) 5: Disponibles: = Disponibles ∪ Nodo

Page 26: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

{Invariante P1: Disponibles + Analizados ≤ G ∧ (∀v: v ∈ Analizados | : W(nodo-Inicial, v) ≥ WSP(nodo-Inicial, v)) } {Cota T1: G – (Disponibles + Analizados) +1} 6: DO Disponibles ≠ φ 7: Nodo-Actual: = Extraer-Nodo-Menor (Disponibles) 8: Analizados: = Analizados ∪ Nodo-Actual 9: IF Nodo-Actual. Nodo = nodo-Final 10: Disponibles: = φ 11: Nodo-Actual. Nodo ≠ nodo-Final

12: Sucesores: = Obtener-Sucesores (Nodo-Actual. Nodo)

{Precondición Q2: (∀v: v∈ Sucesores | : Adyacente(Nodo-Actual, v) )}

13: Contador: = 0 {Invariante P2: (∀v: v ∈ Analizados | : W(nodo-Inicial, v) ≥ WSP(nodo- Inicial, v))} {Cota T2: Sucesores. Número – Contador +1} 14: DO Contador < Sucesores. Número 15: Sucesor: = Sucesores [Contador] 16: Contador: = Contador +1 17: IF Contiene (Analizados, Sucesor) SKIP 18: NOT Contiene (Analizados, Sucesor) 19: Sucesor-Actual: = Configurar-Nodo (Sucesor, Nodo- Actual. Costo + Costo (Nodo-Actual. Nodo, Sucesor)) 20: Sucesor-Actual: = Asignar-Padre (Sucesor, Nodo-Actual. Nodo, Sucesor-Actual) 21: IF NOT Contiene (Disponibles, Sucesor) 22: Disponibles: = Disponibles ∪ Sucesor-Actual 23: Contiene (Disponibles, Sucesor) 24: IF Disponibles. G (Sucesor) > Nodo-Actual. Costo + Costo (Nodo-Actual. Nodo, Sucesor) 25: Eliminar (Disponibles, Sucesor) 26: Disponibles: = Disponibles ∪Sucesor-Actual

Page 27: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

FI FI FI OD {Poscondición R2: (∀v: v ∈ Analizados | : W(nodo-Inicial, v) ≥ WSP(nodo-Inicial, v)) } FI OD {Poscondición R1: Analizados: contiene el SP entre nodo-Inicial y el ultimo nodo. ∧ Disponibles: contiene nodos con G mínimo a partir del nodo-Inicial.}

En la primera y segunda línea del algoritmo, dejamos vacíos los dos conjuntos

Analizados, y Disponibles. El conjunto Disponibles cumple con la misma función

que el conjunto Q del algoritmo de Dijkstra, y el conjunto Analizados cumple el

mismo propósito del conjunto M de Dijkstra.

En la tercera y cuarta línea se configura el nodo inicial. Se asigna el costo del

camino a cero, y se coloca como padre del nodo inicial el mismo nodo. Cada uno

de los nodos que van a estar contenidos dentro de los conjuntos Disponibles y

Analizados, tienen asociados un nodo padre y un costo acumulado g del camino

desde el nodo inicial. Y por ultimo en la quinta línea adicionamos el nodo inicial al

conjunto de nodos disponibles.

En la sexta línea del algoritmo tenemos un ciclo que va a ser ejecutado hasta que no

queden elementos dentro del conjunto Disponibles. A diferencia del caso del

algoritmo de Dijkstra en este no sabemos exactamente cuantas veces se va a

ejecutar este procedimiento, lo único que podemos afirmar es que el peor de los

casos se va a ejecutar n veces donde n es el número de nodos del grafo G, que es lo

mismo que hace el algoritmo de Dijkstra. En el mejor de los casos, este

Page 28: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

procedimiento sólo se repite k veces donde k es el número de nodos que

comprenden el camino óptimo entre el nodo origen y el nodo destino.

La séptima línea del algoritmo A-Estrella es la única diferencia entre el algoritmo

de Dijkstra y este. En esta instrucción se selecciona y se extrae el nodo que tenga

menor función F, del conjunto de nodos disponibles. Como mencionamos

anteriormente si la heurística utilizada para calcular esta función F es cero, esta

instrucción sería equivalente a la del algoritmo de Dijkstra.

En la octava línea adicionamos el nodo que fue seleccionado anteriormente al

conjunto de nodos Analizados. En esta instrucción a diferencia del algoritmo de

Dijkstra, es que no se puede garantizar que el nodo que va a ser adicionado tiene

un costo y un camino optimo desde el nodo origen, pero si que es uno muy

aproximado al óptimo. En el único momento en el cuál podemos afirmar esto es

cuando no estamos usando una función heurística.

En la novena y décima línea del algoritmo, verificamos que el nodo que acabamos

de seleccionar es el nodo destino, en cuyo caso hemos encontrado un camino entre

el nodo origen y el nodo destino. Para terminar el algoritmo eliminamos todos los

nodos contenidos en disponibles.

En la línea doceava obtenemos los sucesores del nodo que ha sido marcado. En las

siguientes líneas, la 13 y la 14 tenemos un ciclo que realiza un procedimiento que

debe ser ejecutado m veces donde m es el número de sucesores del nodo marcado.

Al igual que para el algoritmo de Dijkstra, si el grado de conectividad es bajo,

podemos suponer que los procedimientos ejecutados dentro de este ciclo se

ejecutan sólo una vez.

Page 29: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En las líneas de la 15 a la 17 del algoritmo, estamos seleccionando un sucesor

cualquiera de nuestro conjunto de sucesores previamente definido, y en la última

línea, verificamos que este sucesor no se encuentre en el conjunto Analizados el

cuál contiene los nodos marcados.

Si el sucesor no se encuentra entre los nodos marcados realizamos las instrucciones

de las líneas 18 a la 26. En estas líneas configuramos el nodo sucesor que

seleccionamos anteriormente. Una vez configurado el sucesor, verificamos que el

nodo no se encuentre en el conjunto de nodos Disponibles, en tal caso lo

agregamos a este conjunto. Si el sucesor ya se encuentra en el conjunto

Disponibles, verificamos que el nodo que esta en este conjunto tenga un costo de

camino acumulado desde el nodo inicial g, mayor al costo g del sucesor que

estamos analizando. Si ocurre esto, tenemos que reemplazar el nodo que se

encuentra en el conjunto Disponibles, por el sucesor actual.

A continuación vamos a hacer un análisis de la complejidad del algoritmo A-

Estrella para podernos dar una idea de su comportamiento.

Análisis de Complejidad

El algoritmo A-Estrella al igual que el algoritmo de Dijkstra se basan

principalmente en marcar los nodos de menor costo, en uno hacia la dirección del

nodo destino y en el otro en todas las direcciones. En este tipo de algoritmos el

Page 30: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

número de nodos visitados durante la búsqueda del camino más corto es un buen

indicador del tamaño del espacio de búsqueda.

Si un algoritmo de búsqueda del camino más corto basado en marcar los nodos,

visita menos nodos durante la búsqueda de la respuesta, podemos decir que en

términos de velocidad de procesamiento es más eficiente.

El número de nodos visitados depende de la profundidad (d), que corresponde al

número de nodos que hacen parte del camino más corto entre el nodo origen y el

nodo destino y también depende de un factor de ramificación (b), que corresponde

al numero de arcos promedio que salen de los nodos del grafo.

El número de nodos visitados por el algoritmo BFS (Best First Search) durante la

búsqueda de la respuesta es del orden de O (bd). Este crecimiento exponencial en el

número de nodos visitados es conocido como explosión combinatoria, y es el

principal obstáculo para calcular el camino más corto en grafos grandes.

El algoritmo A-Estrella reduce el número de nodos visitados durante la búsqueda

de la respuesta a un orden de O (bed), donde be es el factor efectivo de ramificación.

Esta reducción en el número de nodos visitados se debe a que reducimos nuestro

espacio de búsqueda, al no tener en cuenta los nodos que no se encuentran en la

dirección del nodo destino.

En cuanto a la complejidad del algoritmo podemos decir que esta varía

considerablemente dependiendo de la función heurística utilizada. La complejidad

puede ser tan alta como el propio algoritmo de Dijkstra, y tan baja como el

algoritmo BSF. La complejidad del algoritmo de Dijkstra fue tratada anteriormente.

Page 31: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Tenemos que la complejidad del algoritmo BFS es O (n) donde n es la profundidad

del camino óptimo. Aunque a primera vista este algoritmo parece solucionar

eficientemente el problema del camino más corto, esto no es asi ya que el algoritmo

BFS no garantiza que el camino encontrado corresponde al camino óptimo.

A continuación vamos a presentar un modelo propuesto por nosotros el cuál lo

llamamos A-Estrella por sectores.

Page 32: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ALGORITMO A-ESTRELLA POR SECTORES

El algoritmo que va a ser presentado a continuación fue propuesto como una

alternativa para resolver el problema de la ruta más corta en grafos grandes. La

idea general es dividir el grafo total en sectores o zonas más pequeñas. El

propósito general de esta propuesta es analizar el desempeño de este modelo en

grafos grandes y con base a los resultados obtenidos, decidir la viabilidad de

aplicarlo en computación móvil.

La idea que generó este modelo fue la de reducir el espacio de búsqueda. Para

lograr esta reducción en el espacio de búsqueda se propuso segmentar el grafo en

zonas interconectadas entre si. En nuestro caso particular las zonas en las que está

dividido el grafo son los barrios o localidades de la ciudad de Bogotá.

Una vez que el grafo total ha sido dividido en zonas más pequeñas, nuestra

propuesta es aplicar un algoritmo que calcule la ruta más corta entre dos nodos del

grafo, pero calculando la trayectoria mínima primero usando las zonas y por

último refinando la trayectoria. El algoritmo que escogimos para aplicar a este

modelo fue el de A-Estrella. La siguiente gráfica nos ilustra un posible ejemplo de

cómo podemos segmentar un grafo en zonas.

Figura 1. Grafo dividido en cuatro sectores.

Page 33: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Como podemos ver en la gráfica anterior, hemos dividido el grafo total en cuatro

grafos más pequeños. Una vez que el grafo ha sido dividido en sectores, podemos

modelar cada una de estas zonas como un polígono de n lados. Cada uno de los

lados de este polígono representa la conexión de un nodo que pertenece a la zona

del polígono con un nodo de otra zona diferente por medio de un arco.

En el ejemplo presentado en la Figura 2 a), se muestra subgrafo, el cual está

dividido en dos sectores. En la parte b) de esta figura, se muestra la representación

de este subgrafo en forma de poligono. En general podemos decir, que si tenemos

k arcos que salen de una zona determinada, entonces tenemos un polígono de k

lados que representa esta zona. De este polígono, cada uno de las aristas representa

un arco del grafo verdadero. En la siguiente gráfica ilustramos como podemos

aplicar este modelo.

Figura 2. a) Dos sectores de un grafo interconectados por cuatro arcos.

b) Modelo de polígono que representa el grado de la parte a).

Al modelar el grafo de esta forma estamos eliminando todos los nodos de una zona

específica, a excepción de los nodos que están interconectados con nodos de otras

Page 34: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

zonas. Esta es una reducción es significativa cuando estamos trabajando con grafos

considerablemente grandes.

Supongamos un caso hipotético, en el cuál tengamos un grafo de 30 mil nodos.

Supongamos que dividimos este grafo en tres zonas. Cada una de estas zonas va a

tener el mismo número de nodos. Adicionalmente suponemos que el grafo es

planar, para conseguir una reducción más grande. La distribución de estas zonas

es la siguiente: supongamos que la segunda zona está interconectada con la

primera y la tercera zona, pero la primera y la tercera zona no se encuentran

interconectadas; digamos que en la primera zona hay 100 nodos que tienen arcos

que interconectan otros 100 nodos de la segunda zona, y que otros 100 arcos

diferentes de la segunda zona tienen arcos que interconectan otros 100 nodos de la

tercera zona. Ahora queremos encontrar el camino más corto entro un nodo de la

primera zona al de la tercera zona. Lo primero que tendríamos que hacer es

calcular la ruta más corta entre el nodo inicial y los nodos que interconectan esta

zona con la segunda zona. Una vez estamos en uno de estos nodos frontera,

debemos encontrar la ruta más corta entre este nodo y todos los nodos frontera

entre la segunda y la tercera zona. Una vez estamos ahí, debemos calcular la ruta

más corta entre este nodo frontera y el nodo destino en la tercera zona.

Como podemos darnos cuenta, estamos reduciendo el espacio de búsqueda en este

caso a un tercio del tamaño original. Si el grafo original lo dividimos en más zonas

es posible que la reducción sea considerablemente más grande. Como veremos

más adelante es posible reducir mucho más nuestro espacio de búsqueda.

Si analizamos el algoritmo que seguimos para encontrar el camino más corto entre

estos dos puntos en diferentes zonas encontramos lo siguiente. Estamos dividiendo

Page 35: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

nuestro problema inicial en tres subproblemas iguales, pero de un tercio del

tamaño original. Esta estrategia se conoce comúnmente como dividir y conquistar.

Adicionalmente si tenemos precalculada alguna información, que en el proceso

anterior requiere de mucho esfuerzo, podemos mejorar la complejidad de este

algoritmo, y al mismo tiempo podemos reducir nuestro espacio de búsqueda.

La información que tenemos que precalcular para este algoritmo es la siguiente.

Debemos precalcular el costo y la ruta del camino más corto entre todos los nodos

frontera de cada una de las zonas. Al precalcular el costo y el camino más corto

entre los nodos frontera de una zona, estamos reduciendo el número de nodos

efectivos de una zona, al número de nodos frontera de esta zona. Esta reducción se

hace efectiva, cuando la zona no hace parte de la zona del nodo origen ni de la

zona del nodo destino.

Para el ejemplo que dimos anteriormente, al precalcular el costo y el camino más

corto entre todos los nodos frontera de cada una de las zonas del grafo, en la

segunda zona estamos reduciendo el espacio de búsqueda únicamente a 200

nodos, a comparación de los 10 mil nodos que hacen parte de esta zona.

A continuación vamos a dar un ejemplo más simple para ilustrar mejor la

reducción que estamos realizando. En la siguiente gráfica podemos ver un grafo, el

cuál está dividido en 5 zonas. Supongamos que queremos llegar del nodo azul de

la zona del extremo izquierdo, al nodo rojo de la zona del extremo derecho.

Page 36: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Figura 3. Grafo dividido por zonas para calcular la ruta más corta entre el nodo azul y el nodo rojo.

Si precalculamos los costos y los caminos entre los nodos frontera para este

ejemplo tendríamos una reducción considerablemente grande en el tamaño del

espacio de búsqueda de nuestro problema. En la siguiente gráfica podemos ver

como queda el grafo resultante el cuál sólo contiene los nodos frontera.

Figura 4. Grafo reducido aplicando el modelo por zonas.

Como podemos ver en la figura anterior, la reducción en el espacio de búsqueda

ocurre en todas las zonas a excepción de las dos zonas que contienen a los nodos

origen y destino. En la gráfica anterior, tenemos que recordar que los arcos en color

rojo representan tanto el camino óptimo el cuál pasa por los nodos

correspondientes de la zona en cuestión y el costo de dicho camino.

Page 37: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En la zona que contiene tanto el nodo origen como el nodo destino, el espacio de

búsqueda es reducido al tamaño de la zona, es decir contiene únicamente los

nodos de la zona en cuestión. Hay que notar, que si el grafo total ha sido dividido

en muchas zonas, el espacio de búsqueda de esta zona se reduce, pero el del

modelo por zonas es posible que aumente considerablemente.

Este modelo aunque parece solucionar todos nuestros problemas, para encontrar la

ruta más corta entre dos nodos en un grafo grande tiene un gran inconveniente.

Por un lado tenemos el problema del consumo de memoria requerido para

almacenar este grafo adicional. Tenemos que notar que en este grafo sectorizado,

tenemos una reducción de nodos con respecto al grafo original, pero al mismo

tiempo estamos aumentando el número de arcos totales. El otro gran problema es

que tenemos que precalcular toda la información, lo que requiere de un gran

esfuerzo computacional previo.

Para darnos una idea de cuál es el problema que implica este modelo, supongamos

lo siguiente. Supongamos que tenemos una zona que pertenece a un grafo, la cuál

contiene n nodos frontera. Cada uno de estos nodos tiene por lo menos n

sucesores. De estos n sucesores, tenemos que (n - 1) de estos sucesores son los otros

nodos frontera de la misma zona. Como el requisito para ser un nodo frontera es

tener por lo menos un sucesor que no pertenezca a su misma zona, entonces

debemos tener por lo menos un sucesor más, por lo tanto tenemos que cada nodo

frontera tiene por lo menos n sucesores. Tenemos que recordar que para cada uno

de estos sucesores debemos calcular tanto el costo, como el camino mínimo que

conecta estos dos nodos.

Page 38: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Otro problema que debe ser evidente para los lectores es el siguiente. En los

sectores que contienen los nodos inicial y final, tenemos que, en el caso en el que

una zona contenga el nodo inicial y no contenga el nodo final, es posible que

nuestro algoritmo diga que debemos llegar a nuestros nodos frontera y a partir de

esto calcular la ruta usando el modelo del grafo por sectores. El hecho que implica

llegar a los nodos frontera a primera vista no parece tan complicado, pero si lo

pensamos bien aumenta la complejidad de nuestro problema. Supongamos que

tenemos el nodo inicial en alguna parte dentro de una zona, pero este nodo inicial

no es un nodo frontera. Como nuestro algoritmo se basa en calcular la ruta mínima

usando los nodos frontera de la zonas, tenemos que llegar al nodo frontera que nos

aproxime más al nodo destino. Como no tenemos la certeza de cuál nodo frontera

hace parte de la ruta óptima, tenemos que calcular cuál es el costo en llegar a todos

los nodos frontera. Esto implica que tenemos que resolver el problema de la ruta

más corta entre dos nodos, el nodo inicial y un nodo frontera, n veces donde n es el

número de nodos frontera.

Aunque nuestro modelo por zonas reduce el tamaño del espacio de búsqueda en

forma extraordinaria de todas las zonas menos en las zonas que contienen el nodo

inicial y el nodo final. En estas dos zonas también estamos reduciendo el espacio

de búsqueda pero en menor proporción. En estas zonas tenemos un subgrafo que

si bien es de menor tamaño al grafo original, tenemos que resolver más veces el

una versión del problema original.

Más adelante proponemos una solución para este problema, la cuál si bien no nos

garantiza que nos encuentra la respuesta óptima, si nos reduce la complejidad y

por ende mejora el desempeño en velocidad de ejecución de nuestro algoritmo.

Page 39: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En este punto es conveniente concretar este algoritmo. A continuación vamos a

presentarlo formalmente. Recordemos que este algoritmo está basado en el

algoritmo A-Estrella.

Algoritmo de A Estrella Por Zonas Formalmente A-Estrella-Zonas (G, nodo-Inicial, nodo-Final) {Precondición Q: G = (V, E) ∧ nodo-Inicial, nodo-Final ∈ G) 1: Disponibles: = φ 2: Analizados: = φ 3: Nodo-Actual: = Agregar-Camino-SP (nodo-Inicial, nodo-Inicial) 4: Nodo-Actual: = Configurar-Nodo (Nodo-Actual, 0) 5: Nodo-Actual: = Asignar-Padre (nodo-Inicial, nodo-Inicial, Nodo-Actual) 6: Disponibles: = Disponibles ∪ Nodo {Invariante P1: Disponibles: contiene nodos con G mínimo a partir del nodo-Inicial. ∧ Analizados: Analizados: contiene el SP entre nodo-Inicial y el ultimo nodo. } {Cota T1: G. Número – (Disponibles. Número + Analizados. Número) +1} 7: DO Disponibles ≠ φ 8: Nodo-Actual: = Extraer-Nodo-Menor (Disponibles) 9: Analizados: = Analizados ∪ Nodo-Actual 10: IF Nodo-Actual. Nodo = nodo-Final 11: Disponibles: = φ 12: Nodo-Actual. Nodo ≠ nodo-Final

13: IF Nodo-Actual. Zona = nodo-Final. Zona ∧ Es-Nodo-Frontera (Nodo-

Page 40: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Actual. Nodo, Nodo-Actual. Nodo. Zona) 14: Sucesores: = Obtener-Sucesores-Totales (Nodo-Actual. Nodo) 15: Sucesores: = Sucesores ∪ Nodo-Final

16: Nodo-Actual. Zona = nodo-Final. Zona ∧ NOT Es-Nodo-Frontera (Nodo-Actual. Nodo, Nodo-Actual. Nodo. Zona) 17: Sucesores: = Obtener-Sucesores-Frontera (Nodo-Actual. Nodo) 18: Sucesores: = Sucesores ∪ Nodo-Final 19: Nodo-Actual. Zona ≠ nodo-Final. Zona ∧ Es-Nodo-Frontera (Nodo-Actual. Nodo, Nodo-Actual. Nodo. Zona)

20: Sucesores: = Obtener-Sucesores-Totales (Nodo-Actual. Nodo)

21: Nodo-Actual. Zona ≠ nodo-Final. Zona ∧ NOT Es-Nodo-Frontera (Nodo-Actual. Nodo, Nodo-Actual. Nodo. Zona) 22: Sucesores: = Obtener-Sucesores-Frontera (Nodo-Actual. Nodo)

FI {Precondición Q2: (∀v: v∈ Sucesores | : Adyacente(Nodo-Actual, v) )}

23: Contador: = 0 {Invariante P2: (∀v: v ∈ Analizados | : W(nodo-Inicial, v) ≥ WSP(nodo- Inicial, v))} {Cota T2: Sucesores. Número – Contador +1} 24: DO Contador < Sucesores. Número 25: Sucesor: = Sucesores [Contador] 26: Contador: = Contador +1 27: IF Contiene (Analizados, Sucesor) SKIP 28: NOT Contiene (Analizados, Sucesor) 29: Sucesor-Actual: = Agregar-Camino-SP (Nodo-Actual. Nodo, Sucesor-Actual. Nodo)

Page 41: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

30: Sucesor-Actual: = Configurar-Nodo (Sucesor-Actual, Sucesor-Actual. G) 31: Sucesor-Actual: = Asignar-Padre (Sucesor-Actual. Nodo, Nodo-Actual. Nodo, Sucesor-Actual) 32: IF NOT Contiene (Disponibles, Sucesor) 33: Disponibles: = Disponibles ∪ Sucesor-Actual 34: Contiene (Disponibles, Sucesor) 35: IF Disponibles. G (Sucesor) > Sucesor-Actual. G 36: Eliminar (Disponibles, Sucesor) 37: Disponibles: = Disponibles ∪ Sucesor-Actual FI FI FI OD {Poscondición R2: (∀v: v ∈ Analizados | : W(nodo-Inicial, v) ≥ WSP(nodo-Inicial, v)} FI OD {Poscondición R1: Analizados: contiene el SP entre nodo-Inicial y el ultimo nodo. ∧ Disponibles: contiene nodos con G mínimo a partir del nodo-Inicial.}

Este algoritmo es básicamente el mismo que el algoritmo A-Estrella, la diferencia

radica en la selección de los sucesores correspondientes a cada nodo marcado. Para

la selección de los sucesores tenemos cuatro casos.

El primer caso está comprendido entre las líneas 13 a la 15 de este algoritmo. En

este caso, el último nodo que fue marcado se encuentra en la misma zona que el

nodo destino, y adicionalmente este nodo marcado es un nodo frontera de esta

zona. Los sucesores para este nodo son todos los nodos frontera de la misma zona

más los nodos frontera de otras zonas sobre los cueles incide un arco partiendo

desde este nodo. El nodo destino también debe ser sucesor de este nodo, pero para

Page 42: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

poder colocarlo en los sucesores, tenemos que calcular cuál es el camino más corto

hasta el y cuanto es el costo. La siguiente gráfica ilustra este caso.

Figura 5. a) Grafo por zonas. El nodo azul es el nodo marcado, y el nodo verde es el nodo destino. b) los nodos de color rojo

son los sucesores del nodo marcado azul. El nodo destino también es un sucesor, pero tenemos que calcular el camino más

corto hasta el, denotado como la flecha roja.

En la gráfica anterior, el nodo azul es el nodo marcado del que estábamos

hablando anteriormente, y el nodo verde es el nodo destino. En la parte b) de la

figura anterior, los nodos de color rojo son los sucesores totales del nodo marcado.

El nodo destino también debe ser un sucesor del nodo marcado. Como no sabemos

el camino mínimo, ni el costo entre el nodo marcado y el nodo destino, debemos

calcularlo. Este cálculo se hace más adelante en la línea 29 de este algoritmo. En

este caso el número de sucesores totales es igual a n + m + 1 donde n es el número

de nodos frontera de la zona del nodo marcado excluyéndolo, y m es el número de

nodos sucesores directos de otras zonas del nodo marcado, el nodo adicional es el

nodo destino.

El segundo caso ocurre en las líneas 16 a la 18 del algoritmo. En este caso, el ultimo

nodo que fue marcado se encuentra en la misma zona que el nodo destino, y este

nodo marcado no es un nodo frontera de esta zona. Este caso ocurre cuando el

nodo origen y el nodo destino están en la misma zona. Los sucesores para el nodo

marcado que en este caso es también el nodo inicial, son los nodos frontera de la

misma zona y el nodo destino. La justificación para tener en cuenta a los nodos

frontera de esta zona es poder sortear correctamente casos como el que se muestra

en la siguiente gráfica.

Page 43: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Figura 6. a) Grafo con dos Zonas. El nodo azul es el nodo inicial y el nodo verde es el nodo final. b) Los nodos marcados en

rojo son los sucesores del nodo azul, en el modelo de grafos por zonas.

En el caso presentado en la figura anterior, si tenemos en cuenta el camino entre el

nodo azul (nodo inicial) y el nodo verde (nodo final), pasando únicamente por los

nodos de la region exterior (zona comprendida entre la linea puenteada azul y la

linea roja), encontraríamos un camino que no corresponde al óptimo. Si tenemos en

cuenta los nodos frontera de la zona azul como sucesores, el algoritmo encontrara

un camino mínimo que parara por las dos zonas.

El tercer caso ocurre entre las líneas 19 a la 20 de este algoritmo. En este caso el

nodo marcado y el nodo destino están en zonas diferentes. Adicionalmente el nodo

marcado es un nodo frontera del sector al que pertenece. En la siguiente gráfica se

presenta este caso.

Figura 7. Grafo modelado por sectores. El nodo azul es el nodo marcado, y el nodo verde es el nodo destino.

Page 44: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En la figura anterior, el nodo azul es el nodo marcado, y el nodo verde es el nodo

destino. Los arcos de color rojos son arcos que pueden no ser reales, es decir que

no existan en el grafo original. Estos arcos representan el camino más corto entre

dos nodos dados. Este camino ha sido precalculado anteriormente. Los nodos de

color rojo son nodos frontera de la zona correspondiente. Los demás nodos de las

zonas intermedio son eliminados de nuestro análisis en este modelo, tal y como se

explicó anteriormente.

Los sucesores del nodo marcado (el nodo de color azul), en este caso son los demás

nodos frontera de la misma zona a la que pertenece, y los nodos de otras zonas con

los que se encuentre interconectado directamente. Es decir que exista un arco que

los relacione en el grafo original. Este caso es muy similar al primer caso, a

diferencia que entre los sucesores no está el nodo destino.

El último caso ocurre entre las líneas 21 y 22 del algoritmo. En este caso el nodo

marcado y el nodo destino están en zonas diferentes. Adicionalmente el nodo

marcado no es un nodo frontera. En este caso, el nodo marcado es el mismo nodo

inicial, pero a diferencia del segundo caso, el nodo destino está en otra zona. La

siguiente gráfica muestra este caso.

Figura 8. Grafo modelado por sectores. El nodo azul es el nodo inicial y el nodo verde es el nodo destino.

Page 45: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En la figura anterior, el nodo azul es el nodo marcado, y el nodo verde es el nodo

destino. Los arcos de color rojos son arcos que pueden no ser reales, es decir que

no existan en el grafo original. Estos arcos representan el camino más corto entre

dos nodos dados. Este camino ha sido precalculado anteriormente. Los nodos de

color rojo son nodos frontera de la zona correspondiente. Los demás nodos de las

zonas intermedio son eliminados de nuestro análisis en este modelo, tal y como se

explicó anteriormente.

Para este caso los sucesores del nodo marcado son los nodos frontera de su sector.

Recordemos que en este algoritmo queremos aprovechar el procesamiento previo

que realizamos en los nodos frontera. Es por esto que queremos estar la mayor

cantidad de tiempo usando los nodos frontera del grafo sectorizado.

El algoritmo entre las líneas 23 a la 37 son las mismas que las del algoritmo

A-Estrella tradicional, de esta parte del algoritmo hablamos anteriormente en el

capitulo del algoritmo A-Estrella. A continuación vamos a hablar sobre la

complejidad de este algoritmo.

Análisis de Complejidad.

La complejidad del algoritmo A-Estrella por sectores aparentemente es la misma

que la del algoritmo A-Estrella normal, pero esto no correcto por lo menos para

esta versión del algoritmo. La diferencia en las complejidades entre estos dos

algoritmos proviene de línea 29 de este algoritmo. Esta línea realiza el siguiente

Page 46: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

procedimiento. Si no existe un arco del grafo original que interconecte el nodo

marcado y el nodo sucesor, o si tampoco se ha precalculado anteriormente cuál es

el costo del camino más corto entre par de nodos, debemos calcular el camino y el

costo de este camino.

Este proceso de calcular el camino mínimo y el costo de este, tiene una complejidad

que depende del algoritmo que sea utilizado. En el algoritmo de Dijkstra y en el de

A-Estrella se supone que la complejidad de esta operación es muy baja, es posible

que según la implementación usada, puede llegar a ser O (1).

Otra gran diferencia que existe entre el algoritmo A-Estrella básico y este algoritmo

es que el número de sucesores de cada nodo ha cambiado. Anteriormente

habíamos dicho que si la conectividad del grafo era baja, podíamos hacer una

aproximación en la complejidad del algoritmo. La aproximación es realizada en la

complejidad del ciclo interno que analiza a todos los sucesores de un nodo dado.

Como vimos anteriormente ese ciclo tiene una complejidad de por lo menos O(n),

donde n es el número de sucesores. En este algoritmo no podemos realizar esta

aproximación, ya que el número de sucesores ha aumentado considerablemente.

En los grafos que representan mallas viales reales, los nodos normalmente tienen

cuatro sucesores, pero en algunos casos pueden llegar a tener hasta ocho sucesores.

Podríamos decir, que el número de sucesores en este tipo de grafos es pequeño.

Por lo cuál podríamos realizar la aproximación que mencionamos anteriormente.

En el caso del algoritmo A-Estrella por sectores, el número de sucesores de cada

nodo es mucho mayor. Recordemos que cada nodo frontera tiene por lo menos n

sucesores. De estos n sucesores, (n – 1) son los otros nodos frontera de la misma

Page 47: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

zona del nodo que estamos analizando, y el nodo restante debe ser un nodo

frontera de otra zona.

Por el momento este número de sucesores n no parece tan problemático. Para

podernos dar una idea de lo problemático que puede llegar a hacer, debemos

utilizar un ejemplo real. Supongamos que una de nuestras zonas es un barrio

pequeño de la ciudad de Bogotá. Supongamos que el perímetro de este barrio es de

aproximadamente 30 cuadras por 30 cuadras (un cambio de diez números en la

nomenclatura). Esta zona podría llegar a tener aproximadamente 900 nodos, de los

cuáles 120 podrían ser nodos frontera. En el ejemplo anterior el número de

sucesores aumento aproximadamente 20 veces.

Con todo lo anterior podemos decir que el algoritmo A-Estrella por zonas tiene

una complejidad mayor a la del algoritmo A-Estrella básico. Si hacemos una

evaluación teniendo en cuenta sólo las complejidades de los algoritmos, el

algoritmo A-Estrella es mejor al algoritmo A-Estrella por sectores. Pero si los

comparamos según el desempeño obtenido en cuanto a velocidad de

procesamiento para resolver una misma pregunta, el resultado puede cambiar.

Page 48: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

MODELO BÁSICO

Los grafos usualmente son usados para representar modelos reales. En este

documento vamos a utilizar los grafos para modelar la malla vial real de la ciudad

de Bogotá. Existen diferentes formas de modelar una malla vial en forma de grafo.

La forma más simple de modelar una malla vial utilizando un grafo es la siguiente.

Los nodos son modelados como las intersecciones o las terminaciones de los

segmentos de las vías, y los arcos son los segmentos de las vías. Por lo tanto una

esquina de una malla vial es un nodo, y la vía en si es un arco. La siguiente gráfica

muestra como un ejemplo de este modelo.

Figura 9. a) Segmento de una mala vial. b) Representación del segmento de la malla vial de a) en forma de grafo.

En este modelo se supone que los arcos son no dirijidos. Este modelo es el más

simple que podemos utilizar. Puede ser utilizado para problemas simples, en los

cuáles no tenemos restricciones.

Este modelo, aunque muy utilizado para modelar mallas viales, no está en la

capacidad de modelar mallas viales reales. En la vida real tenemos restricciones de

Page 49: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

todo tipo. Las restricciones que vamos a tener en cuenta en nuestro trabajo son los

cruces y los retornos prohibidos.

A primera vista el problema de los cruces y los retornos prohibidos no parecen ser

tan difíciles de modelar. Una primera aproximación inocente es la de generar una

lista arcos ilegales para cada nodo en nuestro grafo. Esta lista sería consultada en

cada nodo, a la hora de seleccionar los sucesores válidos, cuando estamos

buscando el camino más corto entre dos nodos dados. Supongamos un grafo como

el de la siguiente gráfica.

Figura 10. Grafo con restricciones. El nodo azul es el nodo inicial, y el nodo final es nodo rojo.

En el grafo de la figura anterior, supongamos que queremos encontrar el camino

más corto entre el nodo E y el nodo C. Supongamos también que todos los arcos

tienen el mismo costo. Supongamos que para encontrar el camino más corto

decidimos usar el algoritmo de Dijkstra.

El algoritmo de Dijkstra primero marcaría el nodo “E”, después consultaría en la

lista de arcos ilegales. Como no hay arcos ilegales, los sucesores “D” y “E” son

relajados. Después marcamos el nodo “D”, verificamos en la lista, y relajamos el

nodo “A”. A continuación marcaríamos el nodo “B”, y consultamos en la lista de

restricciones. Como existe una restricción en el arco entre “B” y “C” al llegar por el

A B

D

C

E

Page 50: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

nodo “E”, no tendríamos ningún sucesor que relajar. Todo parece bien hasta este

punto. Después marcamos el nodo “A”. Los sucesores del nodo “A” son el nodo

“B” y el nodo “D”, como estos dos nodos ya están marcados los ignoramos.

Después marcamos el siguiente nodo con menor costo en la lista de disponibles.

Esta lista contiene sólo al nodo “C”. Como este nodo no ha sido relajado

anteriormente, tiene un costo infinito. Con esto terminaríamos la ejecución del

algoritmo de Dijkstra. Como el costo del nodo “C” al terminar el algoritmo es

infinito, esto quiere decir que no se encontró ningún camino entre el nodo “E” y el

nodo “C”. La respuesta que encontramos con el algoritmo de Dijkstra es incorrecta,

ya que si existe un camino, el cuál es “E-D-A-B-C”. La siguiente gráfica ilustra el

problema anterior.

Figura 11. a) Caminos mínimos encontrados por el algoritmo de Dijkstra en este modelo con restricciones. b) Camino

mínimo entre el nodo azul y el nodo rojo.

Como se mostró en el ejemplo anterior, este modelo no puede ser usado para

modelar una malla vial real con restricciones. Para lograr modelar grafos con este

tipo de restricciones, existen otros modelos los cuáles van a ser analizados a

continuación

A B

D

C

E

A B

D

C

E

Page 51: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

MODELO DE GRAFO DUAL

Como se mostró en el modelo básico anterior, existe la necesidad de emplear otro

modelo más sofisticado que sea capaz de modelar adecuadamente algunas de las

restricciones que existen en la vida real. Las restricciones en las que estamos

interesados son los giros prohibidos y los retornos en la vía restringidos.

El modelo que comúnmente es utilizado cuando se están modelando mallas viales

urbanas, consiste principalmente en generar un Grafo Dual. Este grafo es

construido de la siguiente forma. Los arcos del grafo original son convertidos en

nodos en el Grafo Dual, y los arcos son generados a partir de las restricciones

existentes en cada uno de los nodos del grafo original. En el proceso de

transformación hay que tener en cuenta lo siguiente.

Cuando estamos hablando de convertir los arcos en nodos, esto no se hace

directamente. La transformación que se realiza es la siguiente. Dados dos nodos A

y B del grafo original, si existe un arco o más que interconecten este par de nodos,

este conjunto de arcos son convertidos en un único nodo en nuestro Grafo Dual.

La generación de arcos en nuestro Grafo Dual ocurre de la siguiente forma.

Supongamos que tenemos un grafo como el mostrado en la Figura 12. Este grafo

consta de 5 nodos, 8 arcos. El nodo central está interconectado con los nodos

exteriores por medio de dos arcos. Suponemos que no existen restricciones en los

cruces.

Page 52: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Figura 12. Gráfica de un grafo, el cuál puede ser interpretado como una intersección en una malla vial.

La construcción del Grafo Dual es la siguiente. Primero generamos los nodos. Para

esto seleccionamos parejas de nodos que estén interconectadas. Por cada pareja de

nodos que sea seleccionada vamos a generar un nodo en nuestro modelo dual.

Para el grafo mostrado en la Figura 12, hay 4 parejas de nodos. Estas parejas de

nodos son: PN = {(A, D), (B, D), (C, D), (E, D)}. Para la generación de arcos en

nuestro Grafo Dual, el procedimiento es el siguiente.

Se deben verificar las restricciones existentes en los giros. Si existe una restricción

en un giro se omite el arco entre los nodos del Grafo Dual que están involucrados,

de lo contrario se genera un arco que los interconecta. En la Figura 13, se muestra

como es el Grafo Dual para el grafo mostrado en la Figura 12. Este grafo tiene un

menor número de nodos que el grafo original, pero el número de arcos aumenta

considerablemente.

Para cada intersección similar a la representada por el grafo mostrado en la Figura

A. el número de arcos que serán creados al no existir restricciones puede llegar a

ser igual a la combinación de los sucesores y los predecesores del nodo central.

A

B

C D

E

Page 53: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

a) b)

Figura 13. Representación del Grafo Dual. a) Grafo dual. b) Grafo Dual sobrepuesto al grafo original.

Este modelo aunque parece muy simple, nos puede ayudar a modelar algunas de

las restricciones que existen en la vida real. Este Grafo Dual es mejor que se

encuentre preconstruido antes de realizar algún cálculo. Aunque este modelo

parece solucionar todos nuestros problemas, esto no es verdad. Este modelo no

está en la capacidad de modelar restricciones en los retornos. El siguiente ejemplo

nos va a lustrar mejor este problema. Supongamos un grafo como el mostrado en

la Figura 14. En este grafo existen restricciones en tanto de giro como de retorno.

La restricción en el giro aparece en el nodo B, cuando entramos por el nodo A y

queremos llegar al nodo F. La restricción en el retorno existe en el nodo C, cuando

entramos por el nodo B y queremos regresar al mismo nodo B.

Figura 14. Grafo con restricciones de giro y de retorno.

AD

BD

CD

ED

A

B

C D

E

AD

BD

CD

ED

F

A B C D 1 1

1

1

Page 54: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Supongamos que queremos encontrar el camino más corto entre el nodo A y el

nodo F. El camino más corto entre estos dos nodos es SP1= {A, B, C, D, C, B, F}.

Sorprendentemente el camino encontrado usando el grafo dual es diferente. El

grafo dual es mostrado en la Figura 15.

Figura 15. Grafo dual correspondiente al grafo mostrado en la Figura 14.

Utilizando el Grafo Dual para encontrar el camino más corto entre los nodos A y F

del grafo original, los cuáles corresponden a los nodos AB y FB respectivamente de

este grafo. El camino encontrado es SP2 = {AB, CB, FB}. Como se puede observar,

el camino encontrado utilizando el grafo dual, es diferente al camino óptimo

encontrado en el grafo original. El camino correcto utilizando este modelo y

teniendo en cuenta todas las restricciones del modelo original debería ser SP3=

{AB, CB, DC, CB, FB}. El error en este modelo ocurre gracias a que el modelo del

Grafo Dual, no es capaz de representar las restricciones en los retornos. En este

modelo no estamos teniendo en cuenta la restricción en el retorno existente en el

nodo C del grafo original. Lo primero que uno propondría en este caso es colocar

una lista de restricciones en cada nodo de nuestro Grafo Dual, el cuál restringiría

las opciones a la hora seleccionar los sucesores de un nodo dado. Este caso sería

similar al propuesto en el modelo básico, explicado anteriormente. En este caso

ocurriría lo mismo, tendríamos que modificar el algoritmo utilizado para encontrar

el camino óptimo, para que pueda manejar adecuadamente las restricciones que

estamos imponiendo. Adicionalmente también tendríamos que modificarlos para

AB CB DC

FB

2

2 2

2

2

2

2

Page 55: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

que puedan encontrar caminos óptimos que pasan dos o más veces por un mismo

nodo.

Las modificaciones que deben sufrir los algoritmos tradicionales para tener en

cuenta estas restricciones, en especial la de encontrar el camino óptimo el cuál

puede pasar por un nodo más de una vez, es muy complicado y requiere de un

gran esfuerzo, el cuál en este caso no vale la pena asumir, ya que existen otras

alternativas menos costosas de desarrollar, pero al mismo tiempo más complejas y

que consumen más recursos, como se mostrará a continuación.

Page 56: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

MODELO DE GRAFO DINÁMICO

Después de analizar diferentes opciones, se logró desarrollar un modelo que es

capaz de representar las restricciones típicas a las que nos enfrentamos al modelar

mallas viales reales. Como lo habíamos mencionado anteriormente las principales

restricciones a las que nos tenemos que enfrentar son los cruces prohibidos y los

retornos en la vía. El modelo que presentamos en la sección anterior, nos permite

modelar cruces prohibidos, pero es incapaz de modelar restricciones en los

retornos. Como todos sabemos el camino más corto entre dos nodos de un grafo

está compuesto por una sucesión de nodos partiendo desde el nodo inicial, hasta

llegar al nodo final. Sobre esta sucesión de nodos, hay que notar que normalmente

cada uno de los nodos que componen este camino es único, es decir que no se pasa

dos veces o más por el mismo nodo, para alcanzar nuestro nodo objetivo. Al tener

en cuenta los retornos en la vía y los cruces prohibidos, se presenta el siguiente

paradigma. Este paradigma consiste en la posibilidad de encontrar un camino

óptimo entre dos nodos dados (un nodo de origen y un nodo de destino), el cuál

pasará dos o más veces por un mismo nodo. Este problema se puede visualizar

más fácilmente con el siguiente ejemplo. Suponga un grafo como el que se muestra

en la Figura 16.

Figura 16. Grafo con restricciones en los cruces y en los retoros.

E F

A B C D 1 1

1

1

1

Page 57: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En este grafo encontramos una restricción de giro en el nodo B, y una restricción en

el retorno en el nodo C. Supongamos que queremos encontrar el camino mínimo

entre el nodo A y el nodo E. Con el modelo que vimos anteriormente, el del Grafo

Dual, obtenemos el siguiente camino, SP1 = {A, B, C, B, F, E}, o en notación del

Grafo Dual. SPD1= {AB, BC, BF, FE}, muy similar al camino encontrado para la

Figura 15, en la sección anterior.

Como se puede observar al aplicar este modelo se obtiene una respuesta

equivocada, ya que estaríamos violando la restricción en el retorno en el nodo C.

La respuesta correcta es SP2 = {A, B, C, D, C, B, F, E}. Para lograr llegar a encontrar

está respuesta es necesario realizar cambios en los algoritmos para que tengan en

cuenta estas restricciones, o también es posible diseñar un nuevo modelo, el cuál

tenga en cuenta estas restricciones.

El siguiente modelo va a ser llamado Grafo Dinámico. La idea principal de este

modelo es generar un grafo paralelo al grafo original, el cuál es generado en

paralelo a la ejecución de un algoritmo que resuelva el problema de encontrar la

ruta más corta entre dos nodos dados.

Este Grafo Dinámico, tiene las siguientes características. Para cada nodo del grafo

original, el Grafo Dinámico, tendrá n nodos. Este número n de nodos, no es

constante y como máximo es igual al número de predecesores del nodo. Estos

nodos son generados la primera vez que un predecesor hace un llamado para saber

cuáles son sus sucesores válidos, es decir los sucesores con los cuáles no existe

ninguna restricción.

Si bien este Grafo Dinámico, logra modelar correctamente las restricciones con las

que estamos trabajando, el costo que estamos pagando en espacio de

Page 58: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

almacenamiento, ya sea memoria o disco duro, se ha incrementado

considerablemente.

En el peor de los casos, el cuál ocurre cuando queremos encontrar el camino más

corto desde un nodo fuente, hasta el resto de nodos del grafo, tendríamos que

generar un Grafo Dinámico con un conjunto de nodos n veces más grande que el

grafo original, ya que para cada nodo del grafo original, necesitamos n nodos que

lo representarían en nuestro Grafo Dinámico. En este caso nuestro Grafo Dinámico,

representaría todo el grafo original.

En el caso en el que sólo se requiera encontrar el encontrar el camino óptimo entre

dos nodos dados, nuestro Grafo Dinámico, sólo representaría una porción del grafo

original correspondiente a la zona analizada por el algoritmo utilizado.

El número de arcos requeridos para nuestro Grafo Dinámico, en el peor de los

casos sería el doble de los requeridos en el modelo dual analizado anteriormente.

Hay que recordar en este punto, que cada nodo del grafo original es representado

en nuestro Modelo Dinámico, como un grupo de k nodos. El camino con costo

mínimo corresponde al camino que conduzca desde el nodo inicial, hasta al nodo

final j (0< i < k+1), que tenga costo mínimo.

Si utilizamos el algoritmo A-Estrella para calcular el camino más corto entre dos

nodos usando este modelo de grafo, el tamaño del grafo generado es menor al que

genera el algoritmo de Dijkstra, el cuál se expone más adelante.

Para el algoritmo de Dijkstra, nuestro modelo alcanza casi el peor de los casos,

gracias a que este algoritmo analiza en orden los caminos con menor costo. Para

Page 59: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

estos dos algoritmos, una vez se ha alcanzado alguno de los k nodos destino, el

algoritmo termina, y se garantiza que el camino encontrado es mínimo.

El siguiente ejemplo ilustra como es la generación del Grafo Dinámico. Suponga que

se tiene un grafo como el mostrado en la Figura 17, en el cuál queremos encontrar

el camino mínimo entre A y E.

Figura 17. a) Grafo original. b) Primer paso de la generación del Grafo Dinámico.

Como se pude ver en la Figura 17 a), en el grafo original tenemos una restricción

de giro en el nodo B, y un retorno prohibido en el nodo C. En la parte b), podemos

ver que partimos desde nuestro nodo inicial A, llamado ahora en nuestro Grafo

Dinámico AA.

Miramos cuáles son sus sucesores válidos y los adicionamos a nuestro grafo. En

este caso adicionamos un nodo llamado AB, el cuál está conectado por un arco que

parte desde el nodo AA.

Analizamos ahora el nodo AB, y adicionamos los sucesores válidos de este a

nuestro grafo. De esta misma forma continuamos generando nuestro Grafo

Dinámico. Esto se encuentra ilustrado en la Figura 18.

A B C D 1 1

1

1

1

a) AA AB

b)

1

Page 60: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Figura 18. Proceso de generación del Grafo Dinámico.

En la figura Z, se puede observar que el camino mínimo ente el nodo A y el nodo E

es SP3 = {AA, AB, BC, CD, DC, CB, BF, FE}, el cuál es equivalente al camino que

habíamos mencionado anteriormente SP2 = {A, B, C, D, C, B, F, E}.

Todos los algoritmos de grafos son aplicables a este modelo. Lo único que hay que

tener en cuenta a la hora de emplear un algoritmo para este modelo, es que hay

que generar el grafo a medida que el algoritmo va analizando el grafo original.

AA

AB BC

BA

AB BC CD

AA

BA

AB

DC

CD

AA

BA BC AB

DC

CD

AA

BA BC

CB

AB

DC

CD

AA

BA BC

CB

BF

AB

DC

CD

AA

BA BC

CB

FB

BF FE

Page 61: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

IMPLEMENTACION

La base de datos geográficos de la malla vial de la ciudad de Bogotá, fue

proporcionada por la empresa Procalculo Prosis S.A. Esta base de datos fue

desarrollada bajo el estándar del sistema de archivos de información geográfica

Shapefile. Este sistema de archivos de información geográfica es propiedad de la

compañía de investigación y desarrollo de software ESRI. Esta compañía

desarrolla aplicaciones para sistemas de información geográfica GIS.

La compañía ESRI desarrolló una aplicación llamada ArcGIS. Esta aplicación es

una familia de integrada de productos de software de información geográfica GIS.

La Universidad de los Andes cuenta con la licencia ArcView para ArcGIS Desktop.

ArcGIS está desarrollada a base de ArcObjects, los cuáles son un grupo de

componentes de software de plataforma independiente, los cuáles están

desarrollados en C++. Adicionalmente estos componentes de software hacen uso

de la arquitectura COM “Microsoft Component Object Model”.

La arquitectura COM se puede ver simplemente como una forma simple de

especificar la forma en que los objetos son implementados y construidos en la

memoria y también la forma en que se comunican entre si los objetos. La

arquitectura COM incluso provee una sólida infraestructura a nivel del sistema

operativo, al soportar cualquier componente construido usando esta arquitectura.

En el sistema operativo Microsoft Windows, la infraestructura COM está

implementada directamente a nivel del sistema operativo. En otros sistemas

Page 62: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

operativos, esta infraestructura deberá ser proveída para que los ArcObjects

funcionen.

La funcionalidad de los ArcObjects puede ser accedida usando cuatro tipos de

API´s. estos cuatro tipos son COM, .NET, Java y C++. Con el tipo de licencia que

posee la Universidad de los Andes, sólo se puede tener acceso a los API´s COM y

.NET. Los API´s de COM pueden ser accedidos por cualquier lenguaje que

compile COM. Algunos de los lenguajes que compilan COM son Visual Basic,

Visual C++, y Delphi. Los API´s de .NET pueden ser accedidos por los lenguajes

Visual Basic .NET y C#.

Debido a que la base de datos con la información geográfica de la malla vial de la

ciudad de Bogotá esta en el formato Shapefile, y que la aplicación ArcGIS provee

los componentes ArcObjects, resulta más conveniente utilizarlos para procesar y

extraer la información de la base de datos geográfica, que desarrollar toda una

aplicación que procese esta base de datos.

Los API´s que se utilizaron fueron los COM a través del lenguaje Visual Basic 6.

En este lenguaje se desarrolló un DLL, el cuál utiliza ArcObjects para interactuar

con la base de datos geográfica. Este DLL genera un grafo con la información

relevante de la base de datos geográfica. La información geográfica que se

consideró relevante es la identificación y la ubicación geográfica de las

intersecciones, el sentido de las vías, las restricciones en los cruces, el tipo de la vía,

la longitud de la misma entre otras.

Se decidió generar un grafo a partir de la base de datos geográfica, en lugar de

acceder directamente a esta, debido a la velocidad de acceso a la información. Las

consultas en la base de datos geográfica a través de los ArcObjects, tienen un

Page 63: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

tiempo de consulta alrededor de 500 milisegundos según la complejidad de la

consulta realizada. Mientras que si generamos un grafo en memoria RAM, el

tiempo de consulta es mucho menor.

La base de datos geográfica de la ciudad de Bogotá a la que tuvimos acceso cuenta

con la siguiente información.

Tabla X. Descripción de la base de datos geográfica de la ciudad de Bogotá.

Nombre Descripción

FID Es un número entero usado como llave primaria de la base de datos

geográfica. Es usado para identificar cada segmento de vía.

Shape Es una cadena de caracteres que dice el tipo de base de datos que es. En

este caso en una base de datos de poli líneas.

FNODE_ En un número entero usado para identificar la terminal inicial de la poli

línea.

TNODE_ En un número entero usado para identificar la terminal final de la

polilinea.

LPOLY_ Es un número, que no tiene uso.

RPOLY_ Es un número, que no tiene uso

LENGHT Es un número que representa la longitud real de la poli línea. Está vació

BOG_MALLA Es un número, que no tiene uso.

OBJECTID Es un número, que no tiene uso.

ID_EDIT Es un número, que no tiene uso.

TIPO_VIA Es una cadena de caracteres usada para identificar el tipo de vía.

STREET_NAM Es la nomenclatura de la vía.

PREDIR No es usado. Se encuentra vació.

SUFDIR No es usado. Se encuentra vació.

NOMB_COMUN Es una cadena de caracteres con el nombre de la vía.

ONE_WAY Es una cadena de caracteres que identifica si el segmento de vía es

bidireccional o unidireccional.

FROMLEFT Es usado para generar restricciones de giro.

FROMRIGHT Es usado para generar restricciones de giro.

TOLEFT Es usado para generar restricciones de giro.

TORIGHT Es usado para generar restricciones de giro.

NOMENCLA Es una cadena de caracteres con la nomenclatura principal de la vía.

SHAPE_FID Es un número, que no tiene uso.

SHAPE_Lenght Es un número que representa la longitud real de la vía.

Page 64: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

La anterior tabla contiene todos los campos de la base de datos geográfica. Esta

base de datos geográfica está incompleta, le hacen falta información y campos. La

base de datos de información geográfica de la ciudad de Bogotá tiene los siguientes

problemas.

Los campos FNODE_ y TNODE_ los cuáles son usados como identificadores

únicos para los segmentos de las vías, se encontraban sin calcular, es decir que

todos tenían asignados el valor cero. Se desarrolló un script que generó

identificadores únicos para estos campos.

Los campos TIPO_VIA, STREET_NAM, y NOMENCLA, no tienen asignados

valores en todos los arcos de la base de datos geográfica. El campo TIPO_VIA pude

tener los siguientes valores, KR, DG, TV, CL, AK, AC, o vacío. Este campo lo

utilizamos para cambiar los pesos de los arcos del grafo. Las vías con identificador

AK y AC, son rutas de alta capacidad de tráfico, como autopistas y vías arteria. Los

demás identificadores son usados para vías residenciales.

El campo ONE_WAY, es usado para identificar si un segmento de vía es

unidireccional o bidireccional. En la base de datos geográfica de la ciudad de

Bogotá no existe un estándar para los valores que este campo puede tener. El valor

que más se encuentra en este campo es “B”, nosotros suponemos que este valor

significa que el segmento de vía es bidireccional. Los demás segmentos de vía son

considerados unidireccionales, y suponemos que tienen el sentido del nodo inicial

al nodo final, es decir de FNODE_ a TNODE_.

Los campos FROMLEFT, FROMRIGHT, TOLEFT, TORIGHT, son usados para

representar restricciones en los giros de las vías. Como sólo existen cuatro campos

Page 65: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

para representar las restricciones es posible que no podamos modelar todas las

restricciones posibles.

Podemos decir que la malla vial de la ciudad de Bogotá es relativamente

victoriana, ya que en sí se podría decir que la podemos aproximar a una

cuadrícula. Podemos decir que los arcos verticales son identificados por el campo

tipo vía que poseen el valor de AC, CL, TV, y los arcos horizontales los podemos

identificar también con este campo pero con los valores AK, KR, DG. Ya con esto

definido podemos interpretar los campos que representan las restricciones. La

siguiente gráfica muestra los posibles escenarios para modelar las restricciones

FROMLEFT y FROMRIGHT.

Figura 19. Los cuatro casos posibles para las restricciones de la base de datos geográfica de la ciudad de Bogotá.

Las restricciones en los cruces representadas por TOLEFT, y TORIGHT, son

análogas a las restricciones anteriores, pero cambiando el nodo FNODE por el

nodo TNODE. Para que estas restricciones sean válidas, el arco entre FNODE y

TNODE debe ser bidireccional.

El campo SHAPE_Lenght fue usado para ayudar a modelar el costo de los arcos en

el grafo. Este campo cumple con la misma función que el campo LENGHT, pero

este se encuentra vacío en la base de datos geográfica.

TORIGHTTOLEFT

FNODE

TNODE TORIGHT

TOLEFT

TNODE TORIGHT TOLEFT

FNODE

TNODE

FNODEFNODE

TORIGHT

TOLEFT

TNODE

Page 66: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En el DLL desarrollado, se implementaron diferentes algoritmos, unos para la

generación del grafo que representa la malla vial de la ciudad de Bogotá, y otros

para solucionar el problema de la ruta más corta entre dos puntos dados en la

ciudad de Bogotá.

Se desarrollaron cuatro diferentes algoritmos para la generación de un grafo que

representara la malla vial de la ciudad de Bogotá. Estos algoritmos son los

siguientes:

• Grafo Simple. Este grafo utiliza el modelo básico expuesto anteriormente.

En este grafo el costo de todos los arcos es el mismo.

• Grafo Modificado. Este grafo también utiliza el modelo básico, pero los

costos de los arcos han sido modificados teniendo en cuenta el tipo de vía

que representan.

• Grafo Con Restricciones. Este grafo se basa en el modelo simple, pero

adicionalmente calcula una lista con las restricciones de los cruces.

• Grafo por Sectores. Este grafo sólo contiene los nodos frontera de cada

sector, para ser usado por el algoritmo A-Estrella por sectores; debe usar

uno de los grafos anteriores adicionalmente.

Se desarrollaron también los siguientes algoritmos de grafos de la ruta más corta.

• Algoritmo Dijkstra Simple. Este algoritmo puede ser usado en el grafo

simple y en el grafo modificado.

• Algoritmo A-Estrella Simple. Este algoritmo puede ser usado en el grafo

simple y en el grafo modificado.

Page 67: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

• Algoritmo Dijkstra Con Restricciones. Este algoritmo pude ser usado

únicamente con el grafo con restricciones.

• Algoritmo A-Estrella Con Restricciones. Este algoritmo pude ser usado

únicamente con el grafo con restricciones.

• Algoritmo A-Estrella Por Sectores. Este algoritmo sólo puede ser usado en el

grafo por sectores.

El código fuente de estos algoritmos se encuentra en los anexos, al final del

documento. El código fuente se encuentra en el lenguaje Visual Basic 6.

Se desarrolló también un modulo que interactúa con los ArcObjects, para dibujar

sobre el mapa de la ciudad de Bogotá el camino encontrado por los algoritmos. En

la siguiente gráfica se muestra un ejemplo de la forma de visualización del mapa y

del camino encontrado por los algoritmos.

Figura 20. Ejemplo de visualización del camino más corto entre dos puntos en la ciudad de Bogotá.

Page 68: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Los algoritmos de cálculo de la ruta más corta adicionalmente a la información del

camino calculado, retornan un ArcObject el cuál tiene una interfase llamada

IPolyline. Este objeto contiene la información geográfica y gráfica del camino más

corto encontrado. Este objeto es utilizado para dibujar la ruta más corta calculada

sobre el mapa de la ciudad de Bogotá. En la figura anterior, la línea de color azul es

el camino encontrado por el algoritmo utilizado. Las otras líneas de color naranja

son vías de parte del mapa de Bogotá.

Los algoritmos desarrollados calculan la siguiente información, que permite hacer

una comparación entre ellos. Calculan la longitud en kilómetros del camino más

corto encontrado. También calculan el número de nodos que componen el camino

más corto calculado, el tiempo requerido para calcular dicho camino, y por último

el número de nodos marcados por cada algoritmo. A continuación vamos a

presentar los resultados obtenidos con estos algoritmos.

Page 69: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

RESULTADOS OBTENIDOS Y CONCLUSIONES

Para poder probar los diferentes algoritmos, fue necesario hacer algunas

modificaciones en la base de datos geográficos de la ciudad de Bogotá.

Adicionalmente fue necesario realizar un grupo de supuestos, ya que la

información contenida en esta base de datos está incompleta.

En la base de datos geográfica de la malla vial de la ciudad de Bogotá, cuenta con

las siguientes características. Esta base de datos geográfica, tiene mezclada la malla

vial vehicular con la malla vial peatonal, y no se hace ninguna diferenciación entre

ellas. Los campos FNODE y TNODE no se encontraban calculados, por lo que fue

necesario desarrollar un script que los calculara y los adicionara a la base de datos

geográfica de la malla vial de la ciudad de Bogotá.

El campo ONE_WAY el cuál es usado para decir si un arco es deterministico o no

deterministico, se encontró que puede tener los siguientes valores. Los valores para

este campo son “B”, “TF”, “FT”, “N”, “”. Como podemos ver, es necesario

establecer algunos supuestos para poder generar adecuadamente el grafo. Los

supuestos son. El valor “B” significa que el arco es bidireccional, es decir no

deterministico. El valor “TF” se supone que es un arco entre el nodo TNODE, al

nodo FNODE, y el valor “FT” corresponde a un arco entre el nodo FNODE, al

TNODE. Los valores “N” y “” fueron tomados como un arco entre el nodo

FNODE, y el nodo TNODE.

Page 70: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

En los campos TOLEFT, TORIGHT, FROMLEFT, FROMRIGHT no se encuentran

actualizados, y no cuentan con un estándar para los valores que puede tomar. Para

los valores de estos campos los supuestos son los siguientes. El valor -1 es

interpretado como una restricción en un giro, y los valores diferentes son tomados

como giros permitidos. Para el campo TIPO_VIA, se suponemos que los valores

AC y AK representan segmentos de vía de alta capacidad de tráfico, por lo cuál el

costo relacionado a estos arcos es menor al costo de las vías residenciales.

Como la base de datos geográfica de la malla vial de la ciudad de Bogotá, no

cuenta con un campo reservado para separar la ciudad geográficamente por

sectores, tales como localidades o barrios, es necesario generar un script que divida

la ciudad en zonas. Este script realiza una división de la ciudad en zonas

rectangulares, de igual tamaño.

Aunque todos los algoritmos fueron desarrollados, no todos pudieron ser

probados. El algoritmo A-Estrella por sectores no pudo ser probado, debido a

limitaciones de tiempo. Hay que recordar que para poder ejecutar este algoritmo es

necesario precalcular mucha información, como se explicó anteriormente.

La dificultad para realizar el cálculo de la información necesaria para que funcione

correctamente el algoritmo A-Estrella por sectores es la siguiente. La malla vial de

la ciudad de Bogotá fue dividida en 80 zonas geográficas rectangulares del mismo

tamaño. El número promedio de nodos frontera en cada zona es aproximadamente

500. El tiempo promedio para calcular la ruta más corta entre una pareja de nodos

frontera de una misma zona utilizando el algoritmo de Dijkstra es

aproximadamente 10 segundos.

Page 71: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Tenemos que recordar que para cada nodo frontera debemos calcular la ruta más

corta entre él y los demás nodos frontera de su misma zona. Con los datos

anteriores, podemos saber aproximadamente cuántas veces tenemos que calcular

la ruta más corta para un nodo. Para cada nodo frontera debemos ejecutar el

algoritmo de Dijkstra 500 veces. El tiempo estimado para este cálculo es de 5 mil

segundos, lo que corresponde a unos 84 minutos aproximadamente.

Como tenemos que realizar este cálculo para cada uno de los nodos frontera de

una zona, el tiempo necesario para procesar una zona es de 42 mil minutos, lo que

corresponde a unas 700 horas. Como se deben procesar 80 diferentes zonas, el

tiempo requerido es aproximadamente de 56 mil horas, lo que corresponde a 2300

días. Por lo tanto el tiempo requerido para procesar la información requerida para

que el algoritmo A-Estrella pueda ser utilizado es de aproximadamente 70 meses.

El tiempo requerido para procesar la información anterior se puede reducir, si

realizamos los calculos necesarios en paralelo. Esto se puede realizar, ya que

estamos resolviendo problemas indendientes. La solucion del problema de calcular

la ruta más corta entre dos nodos nodos frontera, no depende de la solucion de este

problema para otro par de nodos. Teniendo en cuenta lo anterior podemos

disminuir el tiempo requerido en una proporcion inversamente proporcional al

numero de procesadores empleados para el calculo de esta información.

Se realizaron algunas comparaciones para poder determinar cuál algoritmo

representa una mejor opción para resolver el problema de calcular la ruta más

corta en la malla vial de la ciudad de Bogotá.

La primera comparación que se realizo fue la de consumo de memoria. Para poder

realizar esta comparación, fue necesario utilizar las mismas estructuras de datos en

Page 72: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

los algoritmos en cuestión. Adicionalmente se realizaron adaptaciones a los dos

algoritmos de tal forma que los dos fueran casi idénticos. El algoritmo que más

cambió fue el algoritmo de Dijkstra. Este algoritmo se muestra a continuación

escrito formalmente.

Dijkstra (G, nodo-Inicial, nodo-Final) {Precondición Q: G: Grafo ∧ nodo-Inicial, nodo-Final ∈ G) 1: Disponibles: = φ 2: Analizados: = φ 3: Nodo-Actual: = Configurar-Nodo (nodo-Inicial, 0) 4: Nodo-Actual: = Asignar-Padre (nodo-Inicial, nodo-Inicial, Nodo-Actual) 5: Disponibles: = Disponibles ∪ Nodo {Invariante P: Disponibles: contiene nodos con G mínimo a partir del nodo-Inicial. ∧ Analizados: Analizados: contiene el SP entre nodo-Inicial y el ultimo nodo. } {Cota t: G. Número – (Disponibles. Número + Analizados. Número) +1} 6: DO Disponibles ≠ φ 7: Nodo-Actual: = Extraer-Nodo-Menor-W (Disponibles) 8: Analizados: = Analizados ∪ Nodo-Actual 9: IF Nodo-Actual. Nodo = nodo-Final 10: Disponibles: = φ 11: Nodo-Actual. Nodo ≠ nodo-Final

12: Sucesores: = Obtener-Sucesores (Nodo-Actual. Nodo)

{Precondición Q:}

13: Contador: = 0 {Invariante P:} {Cota T: Sucesores. Número – Contador +1} 14: DO Contador < Sucesores. Número 15: Sucesor: = Sucesores [Contador] 16: Contador: = Contador +1

Page 73: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

17: IF Contiene (Analizados, Sucesor) SKIP 18: NOT Contiene (Analizados, Sucesor) 19: Sucesor-Actual: = Configurar-Nodo (Sucesor, Nodo- Actual. Costo + Costo (Nodo-Actual. Nodo, Sucesor)) 20: Sucesor-Actual: = Asignar-Padre (Sucesor, Nodo-Actual. Nodo, Sucesor-Actual) 21: IF NOT Contiene (Disponibles, Sucesor) 22: Disponibles: = Disponibles ∪ Sucesor-Actual 23: Contiene (Disponibles, Sucesor) 24: IF Disponibles. G (Sucesor) > Nodo-Actual. Costo + Costo (Nodo-Actual. Nodo, Sucesor) 25: Eliminar (Disponibles, Sucesor) 26: Disponibles: = Disponibles ∪Sucesor-Actual FI FI FI OD {Poscondición R:} FI OD {Poscondición R: Analizados: contiene el SP entre nodo-Inicial y el ultimo nodo. ∧ Disponibles: contiene nodos con G mínimo a partir del nodo-Inicial.}

Al escribir el algoritmo de Dijkstra de esta forma, la única diferencia que existe con

respecto al algoritmo A-Estrella es la séptima línea. En esta línea se selecciona el

nodo que tenga menor costo acumulado en la lista de nodos disponibles. En el

algoritmo A-Estrella, en esta línea se utiliza la heurística para seleccionar cuál nodo

debe ser seleccionado.

Como logramos reescribir el algoritmo de Dijkstra en forma del algoritmo A-

Estrella, y adicionalmente usamos las mismas estructuras de datos en los dos

algoritmos, podemos concluir que utilizan la misma cantidad de memoria.

Page 74: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Otro método que utilizamos para realizar una comparación entre los dos

algoritmos fue la de analizar el espacio de búsqueda de los dos algoritmos. Con el

espacio de búsqueda nos referimos al número de nodos que fueron marcados para

encontrar la solución del problema. Las condiciones de la simulación fueron las

siguientes. Se realizaron alrededor de 50 simulaciones. En estas simulaciones, se

calculó el camino más corto entre dos puntos separados por una distancia (número

de nodos en la ruta más corta), que varía de los 100 a los 200 nodos. Las

condiciones presentes en estos 50 caminos son muy similares en topología, ya que

se escogieron zonas geográficas dentro de la malla vía de la ciudad de Bogotá, que

estuvieran pobladas en lo posible uniformemente. La siguiente gráfica muestra los

resultados obtenidos de esta comparación.

Espacio de Busqueda

0

5000

10000

15000

20000

25000

30000

Distancia del Objetivo

Nodo

s An

aliz

ados

DijkstraA-Estrel la

Figura 21. Espacio de búsqueda del algoritmo de Dijkstra y el algoritmo A-Estrella.

En esta gráfica podemos observar que el espacio de búsqueda del algoritmo de

Dijkstra es siempre mayor al espacio de búsqueda del algoritmo A-Estrella.

Page 75: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Relacion del Espacio de Busqueda de Dijkstra y A-Estrella

0

0,5

1

1,5

2

2,5

3

3,5

4

Dista ncia del Objetivo

d

Figura 22. Gráfica de comparación entre el espacio de búsqueda del algoritmo de Dijkstra y el algoritmo A-Estrella.

En la gráfica anterior podemos ver que el espacio de búsqueda del algoritmo de

Dijkstra en la mayoria de las veces es por lo menos el doble que el del algoritmo A-

Estrella. Si cambiamos un poco las condiciones de la simulación de estos

algoritmos, la relación en el tamaño de búsqueda de estos dos algoritmos cambia

considerablemente. Por ejemplo, si queremos calcular la ruta más corta entre los

puntos los cuales corresponden a extremos opuestos del mapa, el espacio de

busqueda para el algoritmo de Dijkstra pude llegar a abarcar la totalidad del grafo,

ya que el espacio de busqueda de este algoritmo crece en forma radial como lo

habiamos mencionado anteriormente. Para el algoritmo de A-Estrella, el espacio de

busqueda para este caso podria llegar a ser del mismo tamaño que el del algoritmo

de Dijkstra, ya que aunque el espacio de busqueda de este algoritmo crece en

direccion del nodo destino, en el caso de dos nodos en extremos opuestos podria

abarcar casi la totalidad del los nodos del grafo. Un ejemplo extremo para este caso

es un grafo en el cual representa una linea, la cual no se intersecta consigo misma

en ninguna parte, y queremos calcular la ruta optima entre los dos extremos del

grafo. En casos como estos el algoritmo de A-Estrella sufre una baja en su

Page 76: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

desempeño, hasta un punto en el cual se comporta igual que el algoritmo de

Dijkstra.

Recordemos que el espacio de búsqueda tiene una relación directa con el

desempeño en velocidad del algoritmo. Entre menor sea el espacio de búsqueda,

menor será el tiempo necesario para encontrar la solución del problema propuesto.

A continuación vamos a hacer una comparación entre los dos algoritmos con

respecto al tiempo empleado para la solución del problema, y la distancia del

camino objetivo. El ambiente de esta simulación comprende 100 casos, los cuáles

contemplan todos los posibles ambientes, para lograr obtener un aproximado para

el caso promedio.

Tiempo Vs Distancia

-50

0

50

100

150

200

250

300

Distancia del Objetivo

Tiem

po (S

egun

dos)

DijkstraA -Estrella

Figura 23. Gráfica de comparación de tiempos con respecto a la distancia del camino optimo.

En esta gráfica podemos ver que el tiempo requerido para solucionar el problema

del camino más corto en la malla vial de la ciudad de Bogotá, es mucho mayor

para el algoritmo de Dijkstra en el caso promedio. A continuación vamos a

presentar una gráfica donde realizamos una comparación entre el tiempo

requerido para calcular el camino más corto usando el algoritmo de Dijkstra y el

algoritmo A-Estrella.

Page 77: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Relacion de T iempo Vs Distancia

-5

0

5

10

15

20

25

30

35

40

Distancia

Figura 24. Relación entre el tiempo empleado por el algoritmo de Dijkstra y el algoritmo A-Estrella.

Como podemos ver, la relación entre el tiempo requerido para solucionar el

problema propuesto en el caso promedio es mayor siempre para el algoritmo de

Dijkstra. De esta gráfica podemos concluir que el algoritmo de Dijkstra necesita

alrededor de 8.5 veces más tiempo para solucionar el problema de calcular la ruta

más corta entre dos puntos en la malla vial de la ciudad de Bogotá, en el caso

promedio.

Page 78: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ANEXO I Código fuente del algoritmo que genera el grafo correspondiente a la malla vial de la ciudad de Bogotá, usando el modelo simple. Precondición: featureLayer debe referenciar el FeatureLayer del mapa de la malla vial de la ciudad de Bogotá. Postcondición: Se crea un grafo con la informacion geografica de la ciudad de Bogotá. Descripción: El grafo generado es almacenado en un objeto tipo directorio desarrollada por Microsoft, llamado “ Scripting Dictionary”. Este grafo no tiene encuenta restricciones en los giros. El modelo utilizado por el grafo es el modelo simple. Public Sub generarGrafoSimple(featurelayer As IFeatureLayer) Dim BogotáFeatureClass As IFeatureClass Dim resultQuery As IFeatureCursor Dim filtro As IQueryFilter Dim fila As IFeature Dim campos As IFields Dim posFNODE As Integer Dim posTNODE As Integer Dim posLENGHT As Integer Dim posFromLeft As Integer Dim posToLeft As Integer Dim posFromRight As Integer Dim posToRight As Integer Dim posOneWay As Integer Dim posTipoVia As Integer Dim nodo1 As Nodo Dim nodoAdj As Adjacente Dim poly As IPoly line Dim fpoint As IPoint Dim tpoint As IPoint Dim startTime As Single Dim endTime As Single startTime = Timer ' Definimos todo lo necesario para generar el grafo Set grafoSimple = CreateObject("Scripting.Dictionary") Set BogotáFeatureClass = featurelayer.FeatureClass Set campos = BogotáFeatureClass.Fields posFNODE = campos.FindField("FNODE_") posTNODE = campos.FindField("TNODE_") posLENGHT = campos.FindField("SHAPE_Leng") posOneWay = campos.FindField("ONE_WAY") posTipoVia = campos.FindField("TIPO_VIA") Set filtro = New QueryFilter Set resultQuery = BogotáFeatureClass.Search(filtro, False)

Page 79: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Set fila = resultQuery .NextFeature Do Until fila Is Nothing Set poly = fila.shape Set fpoint = poly .FromPoint Set tpoint = poly .ToPoint If grafoSimple.Exists(fila.Value(posFNODE)) And grafoSimple.Exists(fila.Value(posTNODE)) Then ' NODO FROM Y NODO T EXISTEN If fila.Value(posFNODE) <> fila.Value(posTNODE) Then ' MODIFICAMOS EN NODO FROM Set nodo1 = grafoSimple.Item(fila.Value(posFNODE)) Set nodoAdj = New Adjacente With nodoAdj .idEsri = fila.Value(posTNODE) .costo = fila.Value(posLENGHT) .idZona = generarZona(tpoint.X, tpoint.Y) Set .shape = fila.shape .direccion = fila.Value(posTipoVia) End With nodo1.agregarViejoNodoSucesor fila, nodoAdj, posTipoVia ' MODIFICAMOS EL NODO FROM EN EL DICCIONARIO Set grafoSimple.Item(fila.Value(posFNODE)) = nodo1 ' MODIFICAMOS EN NODO TO If fila.Value(posOneWay) = "B" Then Set nodo1 = grafoSimple.Item(fila.Value(posTNODE)) Set nodoAdj = New Adjacente With nodoAdj .idEsri = fila.Value(posFNODE) .costo = fila.Value(posLENGHT) .idZona = generarZona(fpoint.X, fpoint.Y) Set .shape = fila.shape .direccion = fila.Value(posTipoVia) End With nodo1.agregarViejoNodoSucesor fila, nodoAdj, posTipoVia ' MODIFICAMOS EL NODO TO EN EL DICCIONARIO Set grafoSimple.Item(fila.Value(posTNODE)) = nodo1 End If End If Else If grafoSimple.Exists(fila.Value(posFNODE)) And Not grafoSimple.Exists(fila.Value(posTNODE)) Then ' NODO FROM EXISTE Y NODO TO NO EXISTE ' MODIFICAMOS EN NODO FROM Set nodo1 = grafoSimple.Item(fila.Value(posFNODE)) Set nodoAdj = New Adjacente With nodoAdj .idEsri = fila.Value(posTNODE) .costo = fila.Value(posLENGHT) .idZona = generarZona(tpoint.X, tpoint.Y) Set .shape = fila.shape .direccion = fila.Value(posTipoVia) End With nodo1.agregarViejoNodoSucesor fila, nodoAdj, posTipoVia ' MODIFICAMOS EL NODO FROM A EL DICCIONARIO Set grafoSimple.Item(fila.Value(posFNODE)) = nodo1 ' CREAMOS EL NODO TO Set nodo1 = New Nodo With nodo1 .idEsri = fila.Value(posTNODE) .posX = tpoint.X .posY = tpoint.Y .idZona = generarZona(tpoint.X, tpoint.Y) End With If fila.Value(posOneWay) = "B" Then Set nodoAdj = New Adjacente With nodoAdj .idEsri = fila.Value(posFNODE)

Page 80: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

.costo = fila.Value(posLENGHT) .idZona = generarZona(fpoint.X, fpoint.Y) Set .shape = fila.shape .direccion = fila.Value(posTipoVia) End With nodo1.agregarNuevoNodoSucesor fila, nodoAdj End If ' AGREGAMOS EL NODO TO A EL DICCIONARIO grafoSimple.Add fila.Value(posTNODE), nodo1 Else If Not grafoSimple.Exists(fila.Value(posFNODE)) And grafoSimple.Exists(fila.Value(posTNODE)) Then ' NODO FROM NO EXISTE Y NODO TO EXISTE ' CREAMOS EL NODO FROM Set nodo1 = New Nodo With nodo1 .idEsri = fila.Value(posFNODE) .posX = fpoint.X .posY = fpoint.Y .idZona = generarZona(fpoint.X, fpoint.Y) End With Set nodoAdj = New Adjacente With nodoAdj .idEsri = fila.Value(posTNODE) .costo = fila.Value(posLENGHT) .idZona = generarZona(tpoint.X, tpoint.Y) Set .shape = fila.shape .direccion = fila.Value(posTipoVia) End With nodo1.agregarNuevoNodoSucesor fila, nodoAdj ' AGREGAMOS EL NODO FROM A EL DICCIONARIO grafoSimple.Add fila.Value(posFNODE), nodo1 ' MODIFICAMOS EN NODO TO If fila.Value(posOneWay) = "B" Then Set nodo1 = grafoSimple.Item(fila.Value(posTNODE)) Set nodoAdj = New Adjacente With nodoAdj .idEsri = fila.Value(posFNODE) .costo = fila.Value(posLENGHT) .idZona = generarZona(fpoint.X, fpoint.Y) Set .shape = fila.shape .direccion = fila.Value(posTipoVia) End With nodo1.agregarViejoNodoSucesor fila, nodoAdj, posTipoVia ' MODIFICAMOS EL NODO TO EN EL DICCIONARIO Set grafoSimple.Item(fila.Value(posTNODE)) = nodo1 End If Else ' NO EXISTE NINGUNO DE LOS NODOS If fila.Value(posFNODE) <> fila.Value(posTNODE) Then ' CREAMOS EL NODO FROM Set nodo1 = New Nodo With nodo1 .idEsri = fila.Value(posFNODE) .posX = fpoint.X .posY = fpoint.Y .idZona = generarZona(fpoint.X, fpoint.Y) End With Set nodoAdj = New Adjacente With nodoAdj .idEsri = fila.Value(posTNODE) .costo = fila.Value(posLENGHT) .idZona = generarZona(tpoint.X, tpoint.Y) Set .shape = fila.shape .direccion = fila.Value(posTipoVia) End With nodo1.agregarNuevoNodoSucesor fila, nodoAdj

Page 81: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

' AGREGAMOS EL NODO FROM A EL DICCIONARIO grafoSimple.Add fila.Value(posFNODE), nodo1 ' CREAMOS EL NODO TO Set nodo1 = New Nodo With nodo1 .idEsri = fila.Value(posTNODE) .posX = tpoint.X .posY = tpoint.Y .idZona = generarZona(tpoint.X, tpoint.Y) End With If fila.Value(posOneWay) = "B" Then Set nodoAdj = New Adjacente With nodoAdj .idEsri = fila.Value(posFNODE) .costo = fila.Value(posLENGHT) .idZona = generarZona(fpoint.X, fpoint.Y) Set .shape = fila.shape .direccion = fila.Value(posTipoVia) End With nodo1.agregarNuevoNodoSucesor fila, nodoAdj End If ' AGREGAMOS EL NODO TO A EL DICCIONARIO grafoSimple.Add fila.Value(posTNODE), nodo1 End If End If End If End If Set fila = resultQuery .NextFeature Loop endTime = Timer MsgBox "tiempo de proceso " & endTime - startTime & " segundos" End Sub

Page 82: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ANEXO 2. Código fuente del grafo que representa la malla vial de la ciudad de Bogotá, por sectores geográficos. Precondición: grafoSimple es una variable global que referencia el grafo de la ciudad de Bogotá. Este grafo es generado por el algoritmo que se encuentra en el Anexo 1. Postcondición: Se crea un grafo con la informacion geografica de la ciudad de Bogotá, los nodos son agrupados por zonas geograficas. Descripción: El grafo generado es almacenado en un objeto tipo directorio desarrollada por Microsoft, llamado “ Scripting Dictionary”. Este grafo no tiene encuenta restricciones en los giros. El modelo utilizado por el grafo es el modelo simple. Los nodos de este grafo tienen un atributo que identifica a que zona pertenecen. Public Sub generarGrafoZonas() Dim arregloGrafoSimpleKeys Dim nodoGrafoSimpleKey As Long Dim nodoSimple As Nodo Dim sucesoresKeys Dim sucesorKey As Long Dim sucesorAdj As Adjacente Dim numSucesores As Integer Dim nodosZona Dim nodosZonaKeys Dim nodoZonaIDKey As Long Dim nodoZonaEsriKey As Long Dim nodoSucesorZonaKey As Long Dim nodoZA As NodoZonaSimple Dim nodoActualZona As NodoZona Dim costo As PathResultado Dim i As Long Dim j As Long Dim z As Long Dim k As Integer Set grafoZonas = CreateObject("Scripting.Dictionary") Set nodosAgrupadosPorZona = CreateObject("Scripting.Dictionary") ' Iteramos sobre todos los nodos del grafo, para seleccionar y agrupar los nodos que sean de frontera arregloGrafoSimpleKeys = grafoSimple.keys For i = 0 To grafoSimple.Count - 1 nodoGrafoSimpleKey = arregloGrafoSimpleKeys(i) Set nodoSimple = grafoSimple.Item(nodoGrafoSimpleKey) If nodoSimple.esNodoFrontera Then Set nodoZA = New NodoZonaSimple With nodoZA .idEsri = nodoSimple.idEsri End With If nodosAgrupadosPorZona.Exists(nodoSimple.idZona) Then ' YA EXISTE LA ZONA ' obtenemos el dirZona

Page 83: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Set nodosZona = nodosAgrupadosPorZona.Item(nodoSimple.idZona) ' adicionamos el nodoZona a dirZona nodosZona.Add nodoZA.idEsri, nodoZA ' modificamos el dirZona que esta en grafoZonas Set nodosAgrupadosPorZona.Item(nodoSimple.idZona) = nodosZona Else ' NO EXISTE LA ZONA ' creamos el dirZona Set nodosZona = CreateObject("Scripting.Dictionary") ' adicionamos el nodoZona a dirZona nodosZona.Add nodoZA.idEsri, nodoZA 'adicionamos el dirZona a grafoZonas nodosAgrupadosPorZona.Add nodoSimple.idZona, nodosZona End If End If Next ' Falta calcular los costos entre todos los nodos frontera ' nodosZonaKeys es un arreglo con las zonas nodosZonaKeys = nodosAgrupadosPorZona.keys MsgBox "número de zonas = " & nodosAgrupadosPorZona.Count For i = 0 To nodosAgrupadosPorZona.Count - 1 nodoZonaIDKey = nodosZonaKeys(i) ' nodosZona tiene todos los nodos frontera de una zona Set nodosZona = nodosAgrupadosPorZona.Item(nodoZonaIDKey) ' nodosZonaActualKeys es un arreglo con los ids de los nodos frontera de la zona nodosZonaKeys = nodosZona.keys For j = 0 To nodosZona.Count - 1 nodoZonaEsriKey = nodosZonaKeys(j) ' nodoZonaActual es un nodo frontera de la zona Set nodoZA = nodosZona.Item(nodoZonaEsriKey ) Set nodoActualZona = New NodoZona With nodoActualZona .idEsri = nodoZA.idEsri .idZona = nodoZonaIDKey Set .sucesores = CreateObject("Scripting.Dictionary") End With For z = 0 To nodosZona.Count - 1 nodoSucesorZonaKey = nodosZonaKeys(z) ' es un nodo frontera diferente de la misma zona ' estos dos son ID's If nodoSucesorZonaKey <> nodoZonaEsriKey Then Set sucesorAdj = New Adjacente ' calculamos el costo del path entre nodoZonaActual y nodoSucesorZonaKey Set costo = pathFinder_G_Path_AEstrellaZona(nodoZA.idEsri, nodoSucesorZonaKey) If Not (costo Is Nothing) Then With sucesorAdj .idEsri = nodoSucesorZonaKey .idZona = nodoActualZona.idZona .costo = costo.costo Set .shape = costo.path Set .shape = Nothing End With If nodoActualZona.sucesores.Exists(nodoSucesorZonaKey) Then MsgBox "hay un error se intento agregar un sucesor existente en el grafo de zonas" Else ' agregamos el sucesor frontera al nodo frontera actual nodoActualZona.sucesores.Add sucesorAdj.idEsri, sucesorAdj End If End If End If Next Set nodoSimple = grafoSimple.Item(nodoActualZona.idEsri) 'tenemos que adicionar los costos de los arcos que son sucesores de otra zona numSucesores = nodoSimple.númeroSucesores For k = 0 To numSucesores - 1 Set sucesorAdj = nodoSimple.obtenerSucesor(k)

Page 84: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

' el sucesor debe ser de otra zona If sucesorAdj.idZona <> nodoActualZona.idZona Then ' agregamos uno de los nodos de otra sona nodoActualZona.sucesores.Add sucesorAdj.idEsri, sucesorAdj End If Next If grafoZonas.Exists(nodoActualZona.idEsri) Then MsgBox "hay un error se intento adicionar un nodo existente en el grafo de zonas" Else ' adicionamos el nodo totalmente listo al grafo de zonas grafoZonas.Add nodoActualZona.idZona, nodoActualZona End If Next Next End Sub

Page 85: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ANEXO 3. Código fuente del cálculo de restricciones de giro. Precondición: featureLayer debe referenciar el FeatureLayer del mapa de la malla vial de la ciudad de Bogotá. Postcondición: Se genera una lista con las restricciones en los giros de la malla vial de la ciudad de Bogotá. Descripción: El grafo generado es almacenado en un objeto tipo directorio desarrollada por Microsoft, llamado “ Scripting Dictionary”. Este grafo no tiene encuenta restricciones en los giros. El modelo utilizado por el grafo es el modelo simple. Public Sub generarListaRestricciones(featurelayer As IFeatureLayer) Dim BogotáFeatureClass As IFeatureClass Dim resultQuery As IFeatureCursor Dim filtro As IQueryFilter Dim fila As IFeature Dim campos As IFields Dim posToLeft As Integer Dim posToRight As Integer Dim posFNODE As Integer Dim posTNODE As Integer Dim posTipoVia As Integer Dim nodoFromSimple As Nodo Dim nodoToSimple As Nodo Dim nodoLeft As Nodo Dim nodoRight As Nodo Dim idLeft As Long Dim idRight As Long Set listaRestricciones = CreateObject("Scripting.Dictionary") Set BogotáFeatureClass = featurelayer.FeatureClass Set campos = BogotáFeatureClass.Fields posToRight = campos.FindField("TORIGHT") posToLeft = campos.FindField("TOLEFT") posFNODE = campos.FindField("FNODE_") posTNODE = campos.FindField("TNODE_") posTipoVia = campos.FindField("TIPO_VIA") Set filtro = New QueryFilter Set resultQuery = BogotáFeatureClass.Search(filtro, False) Set fila = resultQuery.NextFeature Do Until fila Is Nothing If fila.Value(posFNODE) <> fila.Value(posTNODE) Then Set nodoFromSimple = grafoSimple.Item(fila.Value(posFNODE)) Set nodoToSimple = grafoSimple.Item(fila.Value(posTNODE)) If fila.Value(posToLeft) = -1 Then idLeft = idSucesorLeft(nodoFromSimple, nodoToSimple, fila.Value(posTipoVia)) If idLeft <> -1 Then If Not listaRestricciones.Exists(nodoFromSimple.idEsri & "," & nodoToSimple.idEsri & "," & idLeft) Then listaRestricciones.Add nodoFromSimple.idEsri & "," & nodoToSimple.idEsri & "," & idLeft, True End If End If End If

Page 86: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

If fila.Value(posToRight) = -1 Then idRight = idSucesorRight(nodoFromSimple, nodoToSimple, fila.Value(posTipoVia)) If idRight <> -1 Then If Not listaRestricciones.Exists(nodoFromSimple.idEsri & "," & nodoToSimple.idEsri & "," & idRight) Then listaRestricciones.Add nodoFromSimple.idEsri & "," & nodoToSimple.idEsri & "," & idRight, True End If End If End If End If Set fila = resultQuery.NextFeature Loop End Sub

Page 87: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ANEXO 4. Código fuente del algoritmo de Dijkstra. Precondición: idInitNode, idEndNode deben tener un valor entero positivo, menor a 132.538 grafoSimple es una variable global, la cual debe hacer referencia al grafo simple generado por el algoritmo del Anexo 1. Postcondición: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Descripción: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Para soluciuonarlo utiliza el algoritmo de Dijkstra. Se utiliza el modelo simple del grafo. Public Function pathFinderDijkstra(idInitNode As Long, idEndNode As Long) As IPoly line Dim disponibles Dim analizados Dim nodoActual As NodoDijkstra Dim sucesorActual As NodoDijkstra Dim geometry As IGeometry Dim segmentos As ISegmentCollection Dim poly line As IPoly line Dim i As Integer Dim numSucesores As Integer Dim contador As Long Dim startTime As Single Dim endTime As Single startTime = Timer If grafoSimple Is Nothing Then MsgBox "ERROR GRAFO SIMPLE ES NULL" Set pathFinderDijkstra = Nothing Exit Function End If Set disponibles = CreateObject("Scripting.Dictionary") Set analizados = CreateObject("Scripting.Dictionary") Set nodoActual = New NodoDijkstra With nodoActual .costoG = 0 Set .nodoGrafo = grafoSimple.Item(idInitNode) Set .nodoPadre = Nothing Set .shapePadre = Nothing End With disponibles.Add nodoActual.nodoGrafo.idEsri, nodoActual Do Until disponibles.Count = 0 Set nodoActual = extraerNodoConMenorW(disponibles) disponibles.Remove (nodoActual.nodoGrafo.idEsri) analizados.Add nodoActual.nodoGrafo.idEsri, nodoActual If nodoActual.nodoGrafo.idEsri = idEndNode Then disponibles.RemoveAll Else numSucesores = nodoActual.nodoGrafo.númeroSucesores For i = 0 To numSucesores - 1

Page 88: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

If Not analizados.Exists(nodoActual.nodoGrafo.obtenerSucesor(i).idEsri) Then Set sucesorActual = New NodoDijkstra With sucesorActual Set .nodoGrafo = grafoSimple.Item(nodoActual.nodoGrafo.obtenerSucesor(i).idEsri) Set .nodoPadre = nodoActual Set .shapePadre = nodoActual.nodoGrafo.obtenerSucesor(i).shape .costoG = nodoActual.costoG + nodoActual.nodoGrafo.obtenerSucesor(i).costo End With If Not disponibles.Exists(sucesorActual.nodoGrafo.idEsri) Then disponibles.Add sucesorActual.nodoGrafo.idEsri, sucesorActual Else If disponibles.Item(sucesorActual.nodoGrafo.idEsri).costoG > sucesorActual.costoG Then Set disponibles.Item(sucesorActual.nodoGrafo.idEsri) = sucesorActual End If End If End If Next End If Loop If nodoActual.nodoGrafo.idEsri = idEndNode Then endTime = Timer MsgBox "tiempo de proceso " & endTime - startTime & " segundos" MsgBox "el número de nodos analizados fue " & analizados.Count Set segmentos = New poly line Set sucesorActual = analizados.Item(idEndNode) Set nodoActual = analizados.Item(sucesorActual.nodoPadre.nodoGrafo.idEsri) contador = 1 MsgBox "El costo total del camino es " & sucesorActual.costoG Do Until nodoActual Is Nothing Set geometry = sucesorActual.shapePadre segmentos.AddSegmentCollection geometry Set sucesorActual = nodoActual If Not (nodoActual.nodoPadre Is Nothing) Then Set nodoActual = analizados.Item(nodoActual.nodoPadre.nodoGrafo.idEsri) Else Set nodoActual = Nothing End If contador = contador + 1 Loop Set poly line = segmentos poly line.SimplifyNetwork Set pathFinderDijkstra = poly line MsgBox "la distancia es " & contador Else MsgBox "NO EXISTE UN CAMINO ENTRE EL NODO INICIAL Y EL NODO FINAL" Set pathFinderDijkstra = Nothing End If End Function Private Function extraerNodoConMenorW(disponibles) As NodoDijkstra Dim arregloKeys Dim i As Long Dim idActual As Long Dim nodoActual As NodoDijkstra Dim wMinimo As Double Dim nodoMinimo As NodoDijkstra wMinimo = 50000 'infinito arregloKeys = disponibles.keys For i = 0 To disponibles.Count - 1 idActual = arregloKeys(i) Set nodoActual = disponibles.Item(idActual) If wMinimo > nodoActual.costoG Then Set nodoMinimo = nodoActual

Page 89: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

wMinimo = nodoActual.costoG End If Next Set extraerNodoConMenorW = nodoMinimo End Function

Page 90: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ANEXO 5. Código fuente del algoritmo A-Estrella simple. Precondición: idInitNode, idEndNode deben tener un valor entero positivo, menor a 132.538 grafoSimple es una variable global, la cual debe hacer referencia al grafo simple generado por el algoritmo del Anexo 1. Postcondición: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Descripción: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Para soluciuonarlo utiliza el algoritmo de A-Estrella. Se utiliza el modelo simple del grafo. Public Function pathFinderAEstrella(idInitNode As Long, idEndNode As Long) As IPoly line Dim geometry As IGeometry Dim segmentos As ISegmentCollection Dim poly line As IPoly line Dim disponibles Dim analizados Dim nodoActual As NodoAStar Dim sucesorActual As NodoAStar Dim nodoFinal As Nodo Dim i As Integer Dim numSucesores As Integer Dim contador As Long Dim startTime As Single Dim endTime As Single startTime = Timer If grafoSimple Is Nothing Then MsgBox "ERROR GRAFO SIMPLE ES NULL" Set pathFinderAEstrella = Nothing Exit Function End If Set nodoFinal = grafoSimple.Item(idEndNode) Set disponibles = CreateObject("Scripting.Dictionary") Set analizados = CreateObject("Scripting.Dictionary") Set nodoActual = New NodoAStar With nodoActual .costoG = 0 Set .nodoGrafo = grafoSimple.Item(idInitNode) Set .nodoPadre = Nothing Set .shapePadre = Nothing End With disponibles.Add nodoActual.nodoGrafo.idEsri, nodoActual Do Until disponibles.Count = 0 Set nodoActual = extraerNodoConMenorF(disponibles, nodoFinal) disponibles.Remove (nodoActual.nodoGrafo.idEsri) analizados.Add nodoActual.nodoGrafo.idEsri, nodoActual If nodoActual.nodoGrafo.idEsri = idEndNode Then disponibles.RemoveAll Else

Page 91: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

numSucesores = nodoActual.nodoGrafo.númeroSucesores For i = 0 To numSucesores - 1 If Not analizados.Exists(nodoActual.nodoGrafo.obtenerSucesor(i).idEsri) Then Set sucesorActual = New NodoAStar With sucesorActual Set .nodoGrafo = grafoSimple.Item(nodoActual.nodoGrafo.obtenerSucesor(i).idEsri) Set .nodoPadre = nodoActual Set .shapePadre = nodoActual.nodoGrafo.obtenerSucesor(i).shape .costoG = nodoActual.costoG + nodoActual.nodoGrafo.obtenerSucesor(i).costo End With If Not disponibles.Exists(sucesorActual.nodoGrafo.idEsri) Then disponibles.Add sucesorActual.nodoGrafo.idEsri, sucesorActual Else If disponibles.Item(sucesorActual.nodoGrafo.idEsri).costoG > sucesorActual.costoG Then Set disponibles.Item(sucesorActual.nodoGrafo.idEsri) = sucesorActual End If End If End If Next End If Loop If nodoActual.nodoGrafo.idEsri = idEndNode Then endTime = Timer MsgBox "tiempo de proceso " & endTime - startTime & " segundos" MsgBox "el número de nodos analizados fue " & analizados.Count Set segmentos = New poly line Set sucesorActual = analizados.Item(idEndNode) Set nodoActual = analizados.Item(sucesorActual.nodoPadre.nodoGrafo.idEsri) MsgBox "El costo total del camino es " & sucesorActual.costoG contador = 1 Do Until nodoActual Is Nothing Set geometry = sucesorActual.shapePadre segmentos.AddSegmentCollection geometry Set sucesorActual = nodoActual If Not (nodoActual.nodoPadre Is Nothing) Then Set nodoActual = analizados.Item(nodoActual.nodoPadre.nodoGrafo.idEsri) Else Set nodoActual = Nothing End If contador = contador + 1 Loop Set poly line = segmentos poly line.SimplifyNetwork Set pathFinderAEstrella = poly line MsgBox "la distancia es " & contador Else MsgBox "NO EXISTE UN CAMINO ENTRE EL NODO INICIAL Y EL NODO FINAL" Set pathFinderAEstrella = Nothing End If End Function Private Function extraerNodoConMenorF(disponibles, nodoFinal As Nodo) As NodoAStar Dim arregloKeys Dim i As Long Dim idActual As Long Dim poly As IPoly line Dim x1 As Double Dim y1 As Double Dim x2 As Double Dim y2 As Double Dim h As Double Dim fpoint As IPoint Dim nodoActual As NodoAStar Dim fMinimo As Double Dim nodoMinimo As NodoAStar fMinimo = 50000 'infinito arregloKeys = disponibles.keys

Page 92: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

For i = 0 To disponibles.Count - 1 idActual = arregloKeys(i) Set nodoActual = disponibles.Item(idActual) x1 = nodoActual.nodoGrafo.posX y1 = nodoActual.nodoGrafo.posY x2 = nodoFinal.posX y2 = nodoFinal.posY h = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) h = Math.Sqr(h) If fMinimo > (nodoActual.costoG + h) Then Set nodoMinimo = nodoActual fMinimo = (nodoActual.costoG + h) End If Next Set extraerNodoConMenorF = nodoMinimo End Function

Page 93: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ANEXO 6. Codigo fuente del algoritmo de Dijkstra usando el modelo multigrafo. Precondición: idInitNode, idEndNode deben tener un valor entero positivo, menor a 132.538 grafoSimple es una variable global, la cual debe hacer referencia al grafo simple generado por el algoritmo del Anexo 1. Postcondición: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Descripción: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Para soluciuonarlo utiliza el algoritmo de Dijkstra. Se utiliza el modelo multigrafo. Public Function pathFinderDijkstraRestricciones(idInitNode As Long, idEndNode As Long) As IPoly line Dim geometry As IGeometry Dim segmentos As ISegmentCollection Dim poly line As IPoly line Dim disponibles Dim analizados Dim nodoActual As NodoDijkstraMultiple Dim sucesorActual As NodoDijkstraMultiple Dim nodoFinal As Nodo Dim i As Integer Dim numSucesores As Integer Dim arcoFinal As String Dim contador As Long Dim startTime As Single Dim endTime As Single startTime = Timer If grafoSimple Is Nothing Then MsgBox "ERROR GRAFO SIMPLE ES NULL" Set pathFinderDijkstraRestricciones = Nothing Exit Function End If Set nodoFinal = grafoSimple.Item(idEndNode) Set disponibles = CreateObject("Scripting.Dictionary") Set analizados = CreateObject("Scripting.Dictionary") Set nodoActual = New NodoDijkstraMultiple With nodoActual .costoG = 0 Set .nodoGrafo = grafoSimple.Item(idInitNode) Set .nodoPadre = Nothing Set .shapePadre = Nothing .idMultigrafo = nodoActual.nodoGrafo.idEsri & "," & nodoActual.nodoGrafo.idEsri .idMultiPadre = "" End With disponibles.Add nodoActual.idMultigrafo, nodoActual Do Until disponibles.Count = 0 Set nodoActual = extraerNodoConMenorWMultiple(disponibles) If nodoActual Is Nothing Then MsgBox "que putas paso? Dijkstra"

Page 94: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

End If disponibles.Remove (nodoActual.idMultigrafo) analizados.Add nodoActual.idMultigrafo, nodoActual If nodoActual.nodoGrafo.idEsri = idEndNode Then disponibles.RemoveAll Else numSucesores = nodoActual.nodoGrafo.númeroSucesores For i = 0 To numSucesores - 1 If Not analizados.Exists(nodoActual.nodoGrafo.idEsri & "," & nodoActual.nodoGrafo.obtenerSucesor(i).idEsri) Then Set sucesorActual = New NodoDijkstraMultiple With sucesorActual Set .nodoGrafo = grafoSimple.Item(nodoActual.nodoGrafo.obtenerSucesor(i).idEsri) Set .nodoPadre = nodoActual Set .shapePadre = nodoActual.nodoGrafo.obtenerSucesor(i).shape .costoG = nodoActual.costoG + nodoActual.nodoGrafo.obtenerSucesor(i).costo .idMultigrafo = nodoActual.nodoGrafo.idEsri & "," & nodoActual.nodoGrafo.obtenerSucesor(i).idEsri .idMultiPadre = nodoActual.idMultigrafo End With If Not disponibles.Exists(sucesorActual.idMultigrafo) Then disponibles.Add sucesorActual.idMultigrafo, sucesorActual Else If disponibles.Item(sucesorActual.idMultigrafo).costoG > sucesorActual.costoG Then Set disponibles.Item(sucesorActual.idMultigrafo) = sucesorActual End If End If End If Next End If Loop If nodoActual.nodoGrafo.idEsri = idEndNode Then endTime = Timer MsgBox "tiempo de proceso " & endTime - startTime & " segundos" MsgBox "el número de nodos analizados fue " & analizados.Count Set segmentos = New poly line Set sucesorActual = analizados.Item(nodoActual.idMultigrafo) Set nodoActual = analizados.Item(nodoActual.idMultiPadre) MsgBox "El costo total del camino es " & sucesorActual.costoG contador = 1 Do Until nodoActual Is Nothing Set geometry = sucesorActual.shapePadre segmentos.AddSegmentCollection geometry Set sucesorActual = nodoActual If Not (nodoActual.nodoPadre Is Nothing) Then Set nodoActual = analizados.Item(nodoActual.idMultiPadre) Else Set nodoActual = Nothing End If contador = contador + 1 Loop Set poly line = segmentos poly line.SimplifyNetwork Set pathFinderDijkstraRestricciones = poly line MsgBox "la distancia es " & contador Else MsgBox "NO EXISTE UN CAMINO ENTRE EL NODO INICIAL Y EL NODO FINAL" Set pathFinderDijkstraRestricciones = Nothing End If End Function

Page 95: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ANEXO 7. Código fuente del algoritmo A-Estrella usando el modelo de multigrafo. Precondición: idInitNode, idEndNode deben tener un valor entero positivo, menor a 132.538 grafoSimple es una variable global, la cual debe hacer referencia al grafo simple generado por el algoritmo del Anexo 1. Postcondición: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Descripción: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Para soluciuonarlo utiliza el algoritmo de A-Estrella. Se utiliza el modelo simple del grafo. Public Function pathFinderAEstrellaRestricciones(idInitNode As Long, idEndNode As Long) As IPoly line Dim geometry As IGeometry Dim segmentos As ISegmentCollection Dim poly line As IPoly line Dim disponibles Dim analizados Dim nodoActual As NodoAStarMultiple Dim sucesorActual As NodoAStarMultiple Dim nodoFinal As Nodo Dim i As Integer Dim numSucesores As Integer Dim arcoFinal As String Dim contador As Long Dim startTime As Single Dim endTime As Single startTime = Timer If grafoSimple Is Nothing Then MsgBox "ERROR GRAFO SIMPLE ES NULL" Set pathFinderAEstrellaRestricciones = Nothing Exit Function End If Set nodoFinal = grafoSimple.Item(idEndNode) Set disponibles = CreateObject("Scripting.Dictionary") Set analizados = CreateObject("Scripting.Dictionary") Set nodoActual = New NodoAStarMultiple With nodoActual .costoG = 0 Set .nodoGrafo = grafoSimple.Item(idInitNode) Set .nodoPadre = Nothing Set .shapePadre = Nothing .idMultigrafo = nodoActual.nodoGrafo.idEsri & "," & nodoActual.nodoGrafo.idEsri .idMultiPadre = "" End With disponibles.Add nodoActual.idMultigrafo, nodoActual Do Until disponibles.Count = 0 Set nodoActual = extraerNodoConMenorFMultiple(disponibles, nodoFinal) If nodoActual Is Nothing Then MsgBox "que putas paso?" End If

Page 96: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

disponibles.Remove (nodoActual.idMultigrafo) analizados.Add nodoActual.idMultigrafo, nodoActual If nodoActual.nodoGrafo.idEsri = idEndNode Then disponibles.RemoveAll Else numSucesores = nodoActual.nodoGrafo.númeroSucesores For i = 0 To numSucesores - 1 If Not analizados.Exists(nodoActual.nodoGrafo.idEsri & "," & nodoActual.nodoGrafo.obtenerSucesor(i).idEsri) Then Set sucesorActual = New NodoAStarMultiple With sucesorActual Set .nodoGrafo = grafoSimple.Item(nodoActual.nodoGrafo.obtenerSucesor(i).idEsri) Set .nodoPadre = nodoActual Set .shapePadre = nodoActual.nodoGrafo.obtenerSucesor(i).shape .costoG = nodoActual.costoG + nodoActual.nodoGrafo.obtenerSucesor(i).costo .idMultigrafo = nodoActual.nodoGrafo.idEsri & "," & nodoActual.nodoGrafo.obtenerSucesor(i).idEsri .idMultiPadre = nodoActual.idMultigrafo End With If Not disponibles.Exists(sucesorActual.idMultigrafo) Then disponibles.Add sucesorActual.idMultigrafo, sucesorActual Else If disponibles.Item(sucesorActual.idMultigrafo).costoG > sucesorActual.costoG Then Set disponibles.Item(sucesorActual.idMultigrafo) = sucesorActual End If End If End If Next End If Loop If nodoActual.nodoGrafo.idEsri = idEndNode Then endTime = Timer MsgBox "tiempo de proceso " & endTime - startTime & " segundos" MsgBox "el número de nodos analizados fue " & analizados.Count Set segmentos = New poly line Set sucesorActual = analizados.Item(nodoActual.idMultigrafo) Set nodoActual = analizados.Item(nodoActual.idMultiPadre) MsgBox "El costo total del camino es " & sucesorActual.costoG contador = 1 Do Until nodoActual Is Nothing Set geometry = sucesorActual.shapePadre segmentos.AddSegmentCollection geometry Set sucesorActual = nodoActual If Not (nodoActual.nodoPadre Is Nothing) Then Set nodoActual = analizados.Item(nodoActual.idMultiPadre) Else Set nodoActual = Nothing End If contador = contador + 1 Loop Set poly line = segmentos poly line.SimplifyNetwork Set pathFinderAEstrellaRestricciones = poly line MsgBox "la distancia es " & contador Else MsgBox "NO EXISTE UN CAMINO ENTRE EL NODO INICIAL Y EL NODO FINAL" Set pathFinderAEstrellaRestricciones = Nothing End If End Function

Page 97: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

ANEXO 8. Código fuente del algoritmo A-Estrella por Sectores. Precondición: idInitNode, idEndNode deben tener un valor entero positivo, menor a 132.538 grafoSimple es una variable global, la cual debe hacer referencia al grafo simple generado por el algoritmo del Anexo 1. Postcondición: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Descripción: Soluciona el problema de encontrar la ruta más corta entre el nodo identificado con idInitNode y el nodo idEndNode. Para soluciuonarlo utiliza el algoritmo de A-Estrella por sectores. Se utiliza el modelo simple del grafo. Public Function pathFinderAEstrella_Zonas(idInitNode As Long, idEndNode As Long) As IPoly line Dim disponibles Dim analizados Dim sucesores Dim sucesoresKeys Dim i As Integer Dim sucesorKey As Long Dim nodoActual As NodoAStar Dim sucesorActual As NodoAStar Dim nodoFinal As Nodo Dim nodoInicial As Nodo Dim nodoZonaActual As NodoZona Dim sucesoresTotales Dim nodoAdj As Adjacente Dim camino As PathResultado Dim geometry As IGeometry Dim segmentos As ISegmentCollection Dim poly line As IPoly line If grafoSimple Is Nothing Then MsgBox "ERROR GRAFO SIMPLE ES NULL" Set pathFinderAEstrella_Zonas = Nothing Exit Function End If Set nodoFinal = grafoSimple.Item(idEndNode) Set nodoInicial = grafoSimple.Item(idInitNode) Set disponibles = CreateObject("Scripting.Dictionary") Set analizados = CreateObject("Scripting.Dictionary") Set nodoActual = New NodoAStar With nodoActual .costoG = 0 Set .nodoGrafo = grafoSimple.Item(idInitNode) Set .nodoPadre = Nothing Set .shapePadre = Nothing End With disponibles.Add nodoActual.nodoGrafo.idEsri, nodoActual Do Until disponibles.Count = 0 Set nodoActual = extraerNodoConMenorF(disponibles, nodoFinal)

Page 98: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

disponibles.Remove (nodoActual.nodoGrafo.idEsri) analizados.Add nodoActual.nodoGrafo.idEsri, nodoActual If nodoActual.nodoGrafo.idEsri = idEndNode Then disponibles.RemoveAll Else If nodoActual.nodoGrafo.idZona = nodoFinal.idZona And Not nodoActual.nodoGrafo.esNodoFrontera Then ' ES LA PARTE FINAL ' LOS DOS NODOS ESTAN DENTRO DE LA ZONA FINAL ' CASO 1 ' sucesores es del tipo (idEsri, idEsri) Set sucesores = generarSucesoresFrontera(nodoActual.nodoGrafo) ' esto es para verificar que no esta ya dentro de los sucesores If Not nodoFinal.esNodoFrontera Then sucesores.Add nodoFinal.idEsri, nodoFinal.idEsri End If sucesoresKeys = sucesores.keys For i = 0 To sucesores.Count - 1 sucesorKey = sucesoresKeys(i) If Not analizados.Exists(sucesorKey) Then ' calculamos el costo del camino usando sólo nodos de la misma zona camino = pathFinder_G_Path_AEstrellaZona(nodoActual.nodoGrafo.idEsri, sucesorKey) Set sucesorActual = New NodoAStar With sucesorActual Set .nodoGrafo = grafoSimple.Item(sucesorKey) Set .nodoPadre = nodoActual .costoG = nodoActual.costoG + camino.costo Set .shapePadre = camino.path End With If Not disponibles.Exists(sucesorActual.nodoGrafo.idEsri) Then disponibles.Add sucesorActual.nodoGrafo.idEsri, sucesorActual Else If disponibles.Item(sucesorActual.nodoGrafo.idEsri).costoG > sucesorActual.costoG Then Set disponibles.Item(sucesorActual.nodoGrafo.idEsri) = sucesorActual End If End If End If Next Else If nodoActual.nodoGrafo.idZona = nodoFinal.idZona And nodoActual.nodoGrafo.esNodoFrontera Then ' ES LA PARTE FINAL ' ESTAN EN LA MISMA ZONA, PERO EL INICIAL ES FRONTERA ' CASO 2 Set nodoZonaActual = grafoZonas.Item(nodoActual.nodoGrafo.idEsri) ' sucesoresTotales es del tipo (idEsri, Adjacente) Set sucesoresTotales = nodoZonaActual.sucesores camino = pathFinder_G_Path_AEstrellaZona(nodoActual.nodoGrafo.idEsri, idEndNode) Set nodoAdj = New Adjacente With nodoAdj .idEsri = nodoFinal.idEsri .idZona = nodoFinal.idZona .costo = camino.costo End With ' esto es para verificar que no esta ya dentro de los sucesores If Not nodoFinal.esNodoFrontera Then sucesoresTotales.Add nodoAdj.idEsri, nodoAdj End If sucesoresKeys = sucesoresTotales.keys For i = 0 To sucesores.Count - 1 sucesorKey = sucesoresKeys(i) If Not analizados.Exists(sucesorKey) Then Set nodoAdj = sucesoresTotales.Item(sucesorKey) Set sucesorActual = New NodoAStar With sucesorActual Set .nodoGrafo = grafoSimple.Item(sucesorKey) Set .nodoPadre = nodoActual .costoG = nodoActual.costoG + nodoAdj.costo

Page 99: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

End With If Not disponibles.Exists(sucesorActual.nodoGrafo.idEsri) Then If sucesorActual.nodoGrafo.idZona = nodoFinal.idZona Then camino = pathFinder_G_Path_AEstrellaZona(nodoActual.nodoGrafo.idEsri, sucesorActual.nodoGrafo.idEsri) With sucesorActual Set .shapePadre = camino.path End With Else With sucesorActual Set .shapePadre = nodoActual.nodoGrafo.obtenerSucesorByID(sucesorActual.nodoGrafo.idEsri).shape End With End If disponibles.Add sucesorActual.nodoGrafo.idEsri, sucesorActual Else If disponibles.Item(sucesorActual.nodoGrafo.idEsri).costoG > sucesorActual.costoG Then If sucesorActual.nodoGrafo.idZona = nodoFinal.idZona Then camino = pathFinder_G_Path_AEstrellaZona(nodoActual.nodoGrafo.idEsri, sucesorActual.nodoGrafo.idEsri) With sucesorActual Set .shapePadre = camino.path End With Else With sucesorActual Set .shapePadre = nodoActual.nodoGrafo.obtenerSucesorByID(sucesorActual.nodoGrafo.idEsri).shape End With End If Set disponibles.Item(sucesorActual.nodoGrafo.idEsri) = sucesorActual End If End If End If Next Else If (nodoActual.nodoGrafo.idZona <> nodoFinal.idZona) And nodoActual.nodoGrafo.esNodoFrontera Then ' ES LA PARTE INTERMEDIA ' ALGORITMO ENTRE ZONAS ' CASO 3 Set nodoZonaActual = grafoZonas.Item(nodoActual.nodoGrafo.idEsri) ' sucesoresTotales es del tipo (idEsri, Adjacente) Set sucesoresTotales = nodoZonaActual.sucesores sucesoresKeys = sucesoresTotales.keys For i = 0 To sucesores.Count - 1 sucesorKey = sucesoresKeys(i) If Not analizados.Exists(sucesorKey) Then Set nodoAdj = sucesoresTotales.Item(sucesorKey) Set sucesorActual = New NodoAStar With sucesorActual Set .nodoGrafo = grafoSimple.Item(sucesorKey) Set .nodoPadre = nodoActual .costoG = nodoActual.costoG + nodoAdj.costo End With If Not disponibles.Exists(sucesorActual.nodoGrafo.idEsri) Then If sucesorActual.nodoGrafo.idZona = nodoFinal.idZona Then camino = pathFinder_G_Path_AEstrellaZona(nodoActual.nodoGrafo.idEsri, sucesorActual.nodoGrafo.idEsri) With sucesorActual Set .shapePadre = camino.path End With Else With sucesorActual Set .shapePadre = nodoActual.nodoGrafo.obtenerSucesorByID(sucesorActual.nodoGrafo.idEsri).shape End With End If disponibles.Add sucesorActual.nodoGrafo.idEsri, sucesorActual Else If disponibles.Item(sucesorActual.nodoGrafo.idEsri).costoG > sucesorActual.costoG Then If sucesorActual.nodoGrafo.idZona = nodoFinal.idZona Then camino = pathFinder_G_Path_AEstrellaZona(nodoActual.nodoGrafo.idEsri, sucesorActual.nodoGrafo.idEsri) With sucesorActual

Page 100: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Set .shapePadre = camino.path End With Else With sucesorActual Set .shapePadre = nodoActual.nodoGrafo.obtenerSucesorByID(sucesorActual.nodoGrafo.idEsri).shape End With End If Set disponibles.Item(sucesorActual.nodoGrafo.idEsri) = sucesorActual End If End If End If Next Else If (nodoActual.nodoGrafo.idZona <> nodoFinal.idZona) And Not nodoActual.nodoGrafo.esNodoFrontera Then ' ES LA PARTE INICIAL ' NODO INICIAL - NODOS FRONTERA ' CASO 4 Set sucesores = generarSucesoresFrontera(nodoActual.nodoGrafo) sucesoresKeys = sucesores.keys For i = 0 To sucesores.Count - 1 sucesorKey = sucesoresKeys(i) If Not analizados.Exists(sucesorKey) Then ' calculamos el costo del camino usando sólo nodos de la misma zona camino = pathFinder_G_Path_AEstrellaZona(nodoActual.nodoGrafo.idEsri, sucesorKey) Set sucesorActual = New NodoAStar With sucesorActual Set .nodoGrafo = grafoSimple.Item(sucesorKey) Set .nodoPadre = nodoActual .costoG = nodoActual.costoG + camino.costo Set .shapePadre = camino.path End With If Not disponibles.Exists(sucesorActual.nodoGrafo.idEsri) Then disponibles.Add sucesorActual.nodoGrafo.idEsri, sucesorActual Else If disponibles.Item(sucesorActual.nodoGrafo.idEsri).costoG > sucesorActual.costoG Then Set disponibles.Item(sucesorActual.nodoGrafo.idEsri) = sucesorActual End If End If End If Next End If ' END CASO 4 End If ' END CASO 3 End If ' END CASO 2 End If ' END CASO 1 End If Loop If nodoActual.nodoGrafo.idEsri = idEndNode Then MsgBox "SE ENCONTRO UN CAMINO" MsgBox "el número de nodos analizados fue " & analizados.Count Set segmentos = New poly line Set sucesorActual = analizados.Item(idEndNode) Set nodoActual = analizados.Item(sucesorActual.nodoPadre.nodoGrafo.idEsri) MsgBox "El costo total del camino es " & sucesorActual.costoG Do Until nodoActual Is Nothing Set geometry = sucesorActual.shapePadre segmentos.AddSegmentCollection geometry Set sucesorActual = nodoActual If Not (nodoActual.nodoPadre Is Nothing) Then Set nodoActual = analizados.Item(nodoActual.nodoPadre.nodoGrafo.idEsri) Else Set nodoActual = Nothing End If Loop Set poly line = segmentos poly line.SimplifyNetwork Set pathFinderAEstrella_Zonas = poly line

Page 101: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

Else MsgBox "NO SE ENCONRO CAMINO" Set pathFinderAEstrella_Zonas = Nothing End If End Function

Page 102: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

REFERENCIAS

[1] Kolahdouzan, Mohammad R. Sharifzadeh, Mehdi. Shahabi, Cyrus. A Road Network

Embedding Technique for K-Nearest Neighbor Search in Moving Object Databases. Disponible en

http://infolab.usc.edu/DocsDemos/acmgis02.pdf. Consultado en Febrero de 2005.

[2] Brandes, Ulrik. Schulz, Frank. Wagner, Dorothea. Willhalm, Thomas. Generating Node

Coordinates for Shortest-Path Computations in Transportation Networks. Disponible en

http://www.inf.uni-konstanz.de/algo/publications/bsww-gncsp-04.pdf. Consultado en

Febrero de 2005.

[3] Chapter 1. Digital Library and Archives, University Libraries. Virginia Tech. Disponible en

http://scholar.lib.vt.edu/theses/available/etd-042499-225537/unrestricted/chap1.pdf.

Consultado en Febrero de 2005.

[4] Wagner, D. Willhalm, T. Drawing Graphs to Speed Up Shortest-Path Computations. Disponible

en http://delis.upb.de/paper/DELIS-TR-034.pdf . Consultado en Febrero de 2005.

[5] Faramroze Engineer. Fast Shortest Path Algorithms for Large Road Networks. Department of Engineering Science. University of Auckland. Disponible en http://www.esc.auckland.ac.nz/Organisations/ORSNZ/conf36/papers/Engineer.pdf. Consultado en Febrero de 2005.

[6] Claramunt, C. Jiang , B. Topological Analysis of Urban Street Networks. Disponible en

http://www.ecole-navale.fr/fr/irenav/cv/claramunt/EPB2003.pdf. Consultado en

Febrero de 2005.

[7] Holzer, Martin. Schulz, Frank. Willhalm, Thomas. Combining Speed-Up Techniques for

Shortest-Path Computations. Disponible en http://www.ira.uka.de/members/willhalm

/publications/hsw-cstsp-04.pdf. Consultado en Febrero de 2005.

[8] Mikola, T. Route Resolving Tools In Urban Análisis. Karttakeskus Ltd. Disponible en

www.geomatics.kth.se/~hans/C4_Final_Conf/COST_Final_PDF/Mikola_Fin.pdf.

Consultado en Febrero de 2005.

[9] Wagner, Dorothea. Willhalm, Thomas. Geometric Speed-Up Techniques for Finding Shortest

Paths in Large Sparse Grapas. Disponible en www.inf.uni-konstanz.de/Preprints/

papers/2003/preprint-183.pdf. Consultado en Febrero de 2005.

[10] Wagner, Dorothea. Willhalm, Thomas. Geometric Speed-Up Techniques for Finding Shortest

Paths in Large Sparse Graphs. Disponible en http://www.ilkd.uni-

Page 103: ALGORITMOS PARA CALCULAR LA RUTA MÁS CORTA EN LA …

karlsruhe.de/algo/people/dwagner/papers/ww-gsutf-03.pdf. Consultado en Febrero de

2005.

[11] Algoritmo de Dijkstra. Disponible en http://www.alumnos.unican.es/uc900

/Algoritmo.htm. Consultado eb Febrero de 2005.

[12] Tsai, Benny. Introduction to the A-Star Algorithm. Disponible en

http://upe.acm.jhu.edu/websites/Benny_Tsai/Introduction%20to%20AStar.htm.

Consultado en Febrero de 2005.

[13] Heyes-Jones, Justin. A* algorithm tutorial. Disponible en http://www.geocities.com/jheyes

jones/astar.html. Consultado en Febrero de 2005.

[14] Path Finding A* Algorithm. Disponible en http://www.edenwaith.com/products

/pige/tutorials/a-star.php. Consultado en Febrero de 2005.

[15] Eranki, Rajiv. Pathfinding using A* (A-Star). Disponible en http://rajiv.macnn.com/

tut/search.html. Consultado en Febrero de 2005.

[16] Batten, Christopher. Algorithms for Optimal Assembly. Disponible en

www.mit.edu/~cbatten/work/ssbc04/optassembly-ssbc04.pdf. Consultado en Febrero de

2005.

[17] Seet, Boon-Chong. Genping Liu, Bu-Sung Lee, Chuan-Heng Foh, Kai-Juan Wong, Keok-Kee

Lee. A-STAR: A Mobile Ad Hoc Routing Strategy for Metropolis Vehicular Communications.

Disponible en www.cemnet.ntu.edu.sg/Permocom/papers/2004/

astar%20networking2004.pdf. Consultado en Febrero de 2005.