Algoritmo de Dijkstra

Ejecución del algoritmo de Dijkstra
Tipo Algoritmo de búsqueda
Problema que resuelve Problema del camino más corto
Estructura de datos Grafo
Creador Edsger Dijkstra
Fecha 1959
Clase de complejidad P
Tiempo de ejecución
Peor caso


El algoritmo de Dijkstra, también llamado algoritmo de caminos mínimos, es un algoritmo para la determinación del camino más corto, dado un vértice origen, hacia el resto de los vértices en un grafo que tiene pesos en cada arista. Su nombre alude a Edsger Dijkstra, científico de la computación de los Países Bajos que lo concibió en 1956 y lo publicó por primera vez en 1959.[1][2]

La idea subyacente en este algoritmo consiste en ir explorando todos los caminos más cortos que parten del vértice origen y que llevan a todos los demás vértices; cuando se obtiene el camino más corto desde el vértice origen hasta el resto de los vértices que componen el grafo, el algoritmo se detiene. Se trata de una especialización de la búsqueda de costo uniforme y, como tal, no funciona en grafos con aristas de coste negativo (al elegir siempre el nodo con distancia menor, pueden quedar excluidos de la búsqueda nodos que en próximas iteraciones bajarían el costo general del camino al pasar por una arista con costo negativo).[3]

Algoritmo

editar

Teniendo un grafo dirigido ponderado de nodos no aislados, sea el nodo inicial. Un vector de tamaño guardará al final del algoritmo las distancias desde hasta el resto de los nodos.

  1. Inicializar todas las distancias en con un valor infinito relativo, ya que son desconocidas al principio, exceptuando la de , que se debe colocar en , debido a que la distancia de a sería .
  2. Sea (Se toma como nodo actual).
  3. Se recorren todos los nodos adyacentes de a, excepto los nodos marcados. Se les llamará nodos no marcados vi.
  4. Para el nodo actual, se calcula la distancia tentativa desde dicho nodo hasta sus vecinos con la siguiente fórmula: dt(vi) = Da + d(a,vi). Es decir, la distancia tentativa del nodo ‘vi’ es la distancia que actualmente tiene el nodo en el vector D más la distancia desde dicho nodo ‘a’ (el actual) hasta el nodo vi. Si la distancia tentativa es menor que la distancia almacenada en el vector, entonces se actualiza el vector con esta distancia tentativa. Es decir, si dt(vi) < Dvi → Dvi = dt(vi)
  5. Se marca como completo el nodo a.
  6. Se toma como próximo nodo actual el de menor valor en D (puede hacerse almacenando los valores en una cola de prioridad) y se regresa al paso 3, mientras existan nodos no marcados.

Una vez terminado al algoritmo, estará completamente lleno.

Complejidad

editar

Orden de complejidad del algoritmo:

O(|V|²+|A|) = O(|V|²), sin utilizar cola de prioridad, :O((|A|+|V|) log |V|) = O(|A| log |V|) utilizando cola de prioridad (por ejemplo, un montículo binario o un árbol binario balanceado). Por otro lado, si se utiliza un montículo de Fibonacci, sería O(|V| log |V|+|A|).

La complejidad computacional del algoritmo de Dijkstra se puede calcular contando las operaciones realizadas:

  • El algoritmo consiste en n-1 iteraciones, como máximo. En cada iteración, se añade un vértice al conjunto distinguido.
  • En cada iteración, se identifica el vértice con la menor etiqueta entre los que no están en Sk. El número de estas operaciones está acotado por n-1.
  • Además, se realizan una suma y una comparación para actualizar la etiqueta de cada uno de los vértices que no están en Sk.

Luego, en cada iteración se realizan a lo sumo 2(n-1) operaciones.

Entonces:

Teorema: El algoritmo de lpz realiza O(n²) operaciones (sumas y comparaciones) para determinar la longitud del camino más corto entre dos vértices de un grafo ponderado simple, conexo y no dirigido con n vértices.

En general:

Tiempo de ejecución = O(|A|.𝑻_𝒅𝒌+|v|.𝑻_𝒅𝒎)
|A|: Número de aristas
𝑻_𝒅𝒌: Complejidad de disminuir clave
|V|: Número de vértices
𝑻_𝒅𝒎: Complejidad de extraer mínimo

Pseudocódigo

editar

Estructura de datos auxiliar: Q = Estructura de datos cola de prioridad (se puede implementar con un montículo)

   DIJKSTRA (Grafo G, nodo_fuente s)       
       para uV[G] hacer
           distancia[u] = INFINITO
           padre[u] = NULL
           visto[u] = false
       distancia[s] = 0
       adicionar (cola, (s, distancia[s]))
       mientras que cola no es vacía hacer
           u = extraer_mínimo(cola)
           visto[u] = true
           para todos v ∈ adyacencia[u] hacer
               si ¬ visto[v]      
                   si distancia[v] > distancia[u] + peso (u, v) hacer
                       distancia[v] = distancia[u] + peso (u, v)
                       padre[v] = u
                       adicionar(cola,(v, distancia[v]))

Otra versión en pseudocódigo sin cola de prioridad

editar
función Dijkstra (Grafo G, nodo_salida s)
  //Usaremos un vector para guardar las distancias del nodo salida al resto
  entero distancia[n] 
  //Inicializamos el vector con distancias iniciales
  booleano visto[n] 
  //vector de boleanos para controlar los vértices de los que ya tenemos la distancia mínima
  para cada w ∈ V[G] hacer
     Si (no existe arista entre s y w) entonces
         distancia[w] = Infinito //puedes marcar la casilla con un -1 por ejemplo
     Si_no
         distancia[w] = peso (s, w)
     fin si 
  fin para
  distancia[s] = 0
  visto[s] = cierto
  //n es el número de vértices que tiene el Grafo
  mientras que (no_estén_vistos_todos) hacer 
     vértice = tomar_el_mínimo_del_vector distancia y que no esté visto;
     visto[vértice] = cierto;
     para cada w ∈ sucesores (G, vértice) hacer
         si distancia[w]>distancia[vértice]+peso (vértice, w) entonces
            distancia[w] = distancia[vértice]+peso (vértice, w)
         fin si
     fin para 
  fin mientras
fin función.

Al final, tenemos en el vector distancia en cada posición la distancia mínima del vértice salida a otro vértice cualquiera.

Formulación del algoritmo Dijkstra

editar

Para llevar a cabo la formulación de un modelo de red con el algoritmo Dijkstra es necesario saber de los nodos de inicio, de final y de transbordo de la red, posteriormente se analizan las etiquetas que se presentan en los arcos de la red, para así poder determinar la función objetivo del problema a formular.

En el siguiente ejemplo se presenta la formulación del modelo de Red de "Ejecución del algoritmo de Dijkstra"

Se formulan las variables de decisión denominadas Xij, que son variables binarias y determinan la activación del arco que conecta el nodo i con j.

En la red que "Ejecución del algoritmo de Dijkstra" las variables de decisión del problema son: X12,X13,X16,X23,X24,X36,X34,X65,X45.

Posteriormente se plantea la función objetivo que consiste en tomar la ruta que genere el menor valor de etiquetas de toda la red a través de arcos que conectan los nodos.

Función Objetivo= Minimizar 7*X12+9*X13+ 14*X16+10*X23+15*X24+2*X36+11*X34+9X65+6X45

Restricciones del problema. Para llevar a cabo el desarrollo de las restricciones del problema es necesario conocer el nodo de inicio, que en el caso de la red es el nodo 1, el nodo final que es el nodo 5 y los nodos de transbordo que son 2,3,4 y 6. Una vez identificados los nodos de la red se plantean las restricciones del problema

Restricciones del nodo inicial y final: También denominadas restricciones de oferta y demanda en algunos modelos de formulación. Estas restricciones le indican al modelo que solo debe tomar un arco que sale del nodo inicial y un arco que llega al nodo final, esto con el objetivo de garantizar que se cumplan las condiciones del algoritmo Dijkstra.

En el caso de la formulación del modelo las restricciones del nodo inicial y final son:

Nodo Inicial: X12 +X 13 +X16 = 1

Nodo Final: X65 + X45 = 1 .

Restricciones de nodos transbordo: Estas restricciones también denominadas restricciones de balance, tienen el objetivo de garantizar que todo el flujo que entra en el nodo de transbordo de igual manera debe salir, Estas restricciones se deben generar por cada uno de los nodos de transbordo de la red, en el caso del ejemplo, las restricciones de transbordo son:

Nodo 2: X12= X23 +X24

Nodo 3: X13+X23= X36+X34

Nodo 4 :X24+X34= X45

Nodo 6 :X16+X36 =X65

Restricciones de no negatividad: Con estas restricciones se garantiza que las variables del modelo no van a tomar valores negativos haciendo que el modelo de infectable.

Una vez planteadas todas las restricciones del modelo que garantice que se va a cumplir el algoritmo de Dijkstra en la red, se procede a resolver el modelo mediante algún software que permita obtener la solución óptima de dicho modelo.

Véase también

editar

Referencias

editar
  1. Frana, Phil (August 2010). «An Interview with Edsger W. Dijkstra». Communications of the ACM 53 (8): 41-47. doi:10.1145/1787234.1787249. 
  2. Dijkstra, E. W. (1959). «A note on two problems in connexion with graphs». Numerische Mathematik 1: 269-271. S2CID 123284777. doi:10.1007/BF01386390. 
  3. Knuth, D.E. (1977). «A Generalization of Dijkstra's Algorithm». Information Processing Letters 6 (1): 1-5. doi:10.1016/0020-0190(77)90002-3. 

Enlaces externos

editar

📚 Artikel Terkait di Wikipedia

Premio Dijkstra

Robert G.; Humblet, Pierre A.; Spira, Philip M. (1983), «A distributed algorithm for minimum-weight spanning trees», ACM Transactions on Programming Languages

Algoritmo de Bellman-Ford

McGraw-Hill, 2001. ISBN 0-262-03293-7. Section 24.1: The Bellman-Ford algorithm, pp.588–592. Datos: Q816022 Multimedia: Bellman–Ford algorithm / Q816022

Algoritmo de Johnson

roto disponible en Internet Archive; véase el historial, la primera versión y la última). Datos: Q2345824 Multimedia: Johnson's algorithm / Q2345824

Árbol recubridor mínimo

Nesetrilová (section 7 gives his algorithm, which looks like a cross between Prim's and Kruskal's) A Minimum Spanning Tree Algorithm with Inverse-Ackermann Type

Algoritmo shunting yard

Shunting yard algorithm Parsing Expressions by Recursive Descent Theodore Norvell © 1999–2001. Access date September 14, 2006. Infix to RPN Algorithm Original

Problema del camino más corto de Euclides

1145/177424.177501 .. Hershberger, John; Suri, Subhash (1999), «An optimal algorithm for Euclidean shortest paths in the plane», SIAM Journal on Computing

Problema de la amplitud

1287/opre.46.3.293 . Ullah, E.; Lee, Kyongbum; Hassoun, S. (2009), «An algorithm for identifying dominant-edge metabolic pathways», IEEE/ACM International

Algoritmo de Prim

en Wayback Machine. Prim's algorithm code Archivado el 25 de abril de 2009 en Wayback Machine. Datos: Q470813 Multimedia: Prim's algorithm / Q470813