ALGORITMO DE DIJKSTRA

PRESENTACIÓN POR:

IVÁN RODRIGO CASTILLO CAÑAS

SANTIAGO GÓMEZ HERNÁNDEZ

DIEGO ANDRES POVEDA GONZALEZ 

ACERCA DEL ALGORITMO

Creado por Edsger Dijsktra (Paises Bajos).

 

Determina la ruta más corta desde un nodo origen hacia los demás nodos para ello es requerido como entrada un grafo cuyas aristas posean valores denominadas peso. El peso determina diferentes tipos de valores: distancia, moneda, porcentajes, etc.

Para desarrollar el algoritmo, la mayoría de veces se trabaja con grafos simples, ya que para reducir la complejidad se aconseja exista una sola arista entre cada par de vértices. Cada vértice puede tener relación con 1 o más vértices por medio de aristas. También se aplica en grafos dirigidos.


Es importante que el grafo esté etiquetado (sea un grafo etiquetado) para poder llevar a cabo su ejecución. Cada vértice tiene un nombre que puede ser una letra y cada arista recibe como identificación un número. Este número será el peso.

TIPOS DE GRAFOS QUE UTILIZA EL ALGORITMO

FUNCIONAMIENTO

El grafo se etiqueta de tal manera que todos los vértices tengan un nombre (recomendado una letra) y cada arista debe ser relacionada con un número

1. Se escoge el nodo inicio, en este caso el nodo A. Luego, se marca en el nodo la distancia desde el nodo anterior, pero como no lo hay, se deja nulo.

2. De los nodos adyacentes de A, se marca el peso acumulado junto con el nodo antecesor, es decir, A.

3. De los nodos ya visitados, se escoge el nodo de menos peso acumulado, en este caso, el nodo C.

4. De los nodos adyacentes de B, se marca el peso acumulado junto al nodo antecesor (nodo B).

5. Se toman los nodos adyacentes a C que no estén marcados de azul y se calculan sus pesos acumulados, sumando el que ya se tiene con el peso de la siguiente ruta.

6. De los nodos ya visitados y no marcados de azul, se toma el de menor peso, en este caso el D.

7. Como queda sólo un nodo por seleccionar, se da por terminado el algoritmo, con el que ya se puede determinar la ruta más corta del nodo de inicio (nodo A) a otro.

PSEUDOCÓDIGO

 Considerar distancia[ i ] como la distancia mas corta del
 vértice origen ingresado al vértice i.

1  método Dijkstra(Grafo,origen):
2      Se crea una cola de prioridad Q
3      Se agrega origen a la cola de prioridad Q
4      Mientras Q no esté vacío hacer:
5          Se elimina un elemento de la cola Q llamado u
6          Si u ya fue visitado, se continúa sacando elementos de Q    
7          Se marca como visitado u
8          Para cada vértice v adyacente a u en el Grafo:
9              Sea w el peso entre vértices ( u , v )  
10             Si v no ha sido visitado:
11                Relajacion( u , v , w )

1  método Relajacion(actual,adyacente,peso):
2      Si distancia[ actual ] + peso < distancia[ adyacente ]
3         distancia[ adyacente ] = distancia[ actual ] + peso
4         Se agrega adyacente a la cola de prioridad Q
              /****************************************************
               ***Algoritmo: Dijkstra (One Source Shortest Path)
               ***Tipo: Grafos
               ***2017
              ****************************************************/
#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;
#define MAX 10005 //maximo numero de vértices
#define Node pair< int , int > //definimos el nodo como un par( first , second ) donde first es el vertice adyacente y second el peso de la arista
#define INF 1<<30 //definimos un valor grande que represente la distancia infinita inicial, basta conque sea superior al maximo valor del peso en alguna de las aristas

//La cola de prioridad de C++ por default es un max-Heap (elemento de mayor valor en el tope)
//por ello es necesario realizar nuestro comparador para que sea un min-Heap
struct cmp {
    bool operator() ( const Node &a , const Node &b ) {
        return a.second > b.second;
    }
};
vector< Node > ady[ MAX ]; //lista de adyacencia
int distancia[ MAX ];      //distancia[ u ] distancia de vértice inicial a vértice con ID = u
bool visitado[ MAX ];      //para vértices visitados
priority_queue< Node , vector<Node> , cmp > Q; //priority queue propia del c++, usamos el comparador definido para que el de menor valor este en el tope
int V;                     //numero de vertices
int previo[ MAX ];         //para la impresion de caminos

//FUNCIÓN DE INICIALIZACIÓN
void init(){
    for( int i = 0 ; i <= V ; ++i ){
        distancia[ i ] = INF;  //inicializamos todas las distancias con valor infinito
        visitado[ i ] = false; //inicializamos todos los vértices como no visitados
        previo[ i ] = -1;      //inicializamos el previo del vertice i con -1
    }
}

//PASO DE RELAJACIÓN
void relajacion( int actual , int adyacente , int peso ){
    //Si la distancia del origen al vertice actual + peso de su arista es menor a la distancia del origen al vertice adyacente
    if( distancia[ actual ] + peso < distancia[ adyacente ] ){
        distancia[ adyacente ] = distancia[ actual ] + peso;  //relajamos el vertice actualizando la distancia
        previo[ adyacente ] = actual;                         //a su vez actualizamos el vertice previo
        Q.push( Node( adyacente , distancia[ adyacente ] ) ); //agregamos adyacente a la cola de prioridad
    }
}

//IMPRESIÓN (Camino mas corto desde el vertice inicial y final ingresados)
void print( int destino ){
    if( previo[ destino ] != -1 )    //si aun poseo un vertice previo
        print( previo[ destino ] );  //recursivamente sigo explorando
    printf("%d " , destino );        //terminada la recursion imprimo los vertices recorridos
}

//FUNCIÓN DIJKSTRA (ALGORITMO)
void dijkstra( int inicial ){
    init(); //inicializamos nuestros arreglos
    Q.push( Node( inicial , 0 ) ); //Insertamos el vértice inicial en la Cola de Prioridad
    distancia[ inicial ] = 0;      //Este paso es importante, inicializamos la distancia del inicial como 0
    int actual , adyacente , peso;
    while( !Q.empty() ){                   //Mientras cola no este vacia
        actual = Q.top().first;            //Obtengo de la cola el nodo con menor peso, en un comienzo será el inicial
        Q.pop();                           //Sacamos el elemento de la cola
        if( visitado[ actual ] ) continue; //Si el vértice actual ya fue visitado entonces sigo sacando elementos de la cola
        visitado[ actual ] = true;         //Marco como visitado el vértice actual

        for( int i = 0 ; i < ady[ actual ].size() ; ++i ){ //reviso sus adyacentes del vertice actual
            adyacente = ady[ actual ][ i ].first;   //id del vertice adyacente
            peso = ady[ actual ][ i ].second;        //peso de la arista que une actual con adyacente ( actual , adyacente )
            if( !visitado[ adyacente ] ){        //si el vertice adyacente no fue visitado
                relajacion( actual , adyacente , peso ); //realizamos el paso de relajacion
            }
        }
    }


    printf( "Distancias mas cortas iniciando en vertice %d\n" , inicial );
    for( int i = 1 ; i <= V ; ++i ){
        printf("Vertice %d , distancia mas corta = %d\n" , i , distancia[ i ] );
    }

    puts("\n**************Impresion de camino mas corto**************");
    printf("Ingrese vertice destino: ");
    int destino;
    scanf("%d" , &destino );
    print( destino );
    printf("\n");
}


int main(){
    int E , origen, destino , peso , inicial;
    scanf("%d %d" , &V , &E );
    while( E-- ){
        scanf("%d %d %d" , &origen , &destino , &peso );
        ady[ origen ].push_back( Node( destino , peso ) ); //consideremos grafo dirigido
        ady[ destino ].push_back( Node( origen , peso ) ); //grafo no dirigido
    }
    printf("Ingrese el vertice inicial: ");
    scanf("%d" , &inicial );
    dijkstra( inicial );
    return 0;
}

CÓDIGO FUENTE

COMPLEJIDAD

El Algoritmo de Dijkstra 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.

Se puede estimar la complejidad computacional del algoritmo de Dijkstra (en términos de sumas y comparaciones).El algoritmo realiza a lo más n-1 iteraciones, ya que en cada iteración se añade un vértice al conjunto distinguido. Para estimar el número total de operaciones basta estimar las que se llevan a cabo en cada iteración. 

A = Aristas. V = Vértices.

Otros ordenes de complejidad del algoritmo:

1. O((|A|+|V|) log |V|) = O(|A| log |V|) utilizando cola de prioridad.

2. Si se utiliza un Montículo de Fibonacci, sería O(|V| log |V|+|A|).

APLICACIONES Y USOS

ALGORITMO DE DIJKSTRA

Internet es una inmensa colección de redes más pequeñas interconectadas entre si.

La información, antes de que se envíe a través de estas redes, es dividida en cientos de miles de unidades llamadas, "paquetes".

ENRUTAMIENTO DE PAQUETES EN REDES

¿Cómo es posible visitar una página web alojada en un servidor que se encuentre a medio mundo de distancia?

Hay dispositivos de red llamados Enrutadores (o Routers en inglés), y su único propósito es aprender rutas por las cuales alcanzar otras redes, y así poder transferir paquetes de datos entre ellas, este proceso se conoce como "Enrutamiento".

FUNCIÓN DEL ROUTER

Enrutamiento se refiere al proceso en el que los routers aprenden sobre redes remotas, encuentran todas las rutas posibles para llegar a ellas y luego escogen las mejores rutas (las más rápidas) para intercambiar datos entre las mismas.

En un momento dado, un mensaje puede tardar cierta cantidad de tiempo en atravesar cada línea. (Por ejemplo, por efectos de congestión). El objetivo del algoritmo es encontrar un camino entre estos dos nodos cuyo coste total sea el mínimo. Los pesos de las aristas serían los costes.

APLICACIÓN DEL ALGORITMO

EL ENRUTAMIENTO

Un protocolo de enrutamiento seleccionará como mejor ruta, después de ejecutar el algoritmo, la ruta que tenga la métrica más baja y cada protocolo utiliza su propia métrica:

  • RIP utiliza una métrica de conteo de saltos.
  • OSPF utiliza Costo.
  • EIGRP utiliza una combinación de ancho de banda y retraso.

El algoritmo le indica al protocolo los valores necesarios para calcular y para determinar un valor métrico. La ruta con el valor métrico más bajo, resultante de este cálculo, se selecciona como mejor ruta.

LA MÉTRICA EN LA RED

SOFTWARE DE TRÁFICO AÉREO

Consiste en un agente de solicitudes de viaje que hace un programa de vuelos para los clientes. El agente tiene acceso a una base de datos con todos los aeropuertos y los vuelos como el número de vuelo, el aeropuerto de origen y destino y los horarios de salida y de llegada.

 

El programa determina la hora de llegada más temprana para el destino dado un aeropuerto de origen y hora de inicio.

APLICACIÓN DEL ALGORITMO

SISTEMAS DE INFORMACIÓN GEOGRÁFICA (S.I.G.)

S.I.G. es cualquier sistema de información capaz de integrar, almacenar, editar, analizar, compartir y mostrar la información geográficamente referenciada.

Un SIG destinado al cálculo de rutas óptimas para servicios de emergencias es capaz de determinar el camino más corto entre dos puntos teniendo en cuenta tanto direcciones y sentidos de circulación como direcciones prohibidas, etc. evitando áreas impracticables.

Un SIG puede mostrar la información en capas temáticas para realizar análisis multicriterio complejos.

APLICACIÓN DEL ALGORITMO

RECONOCIMIENTO AUTOMÁTICO DE VOZ

PLANIFICACIÓN DE MOVIMIENTO (ROBOTS)

OTRAS APLICACIONES

RUTAS MÁS CORTAS EN SISTEMAS DE TRANSPORTES PÚBLICOS

GOOGLE MAPS

Algoritmo de Dijkstra con código fuente

By Iván Castillo

Algoritmo de Dijkstra con código fuente

Presentación acerca del algoritmo de Dijkstra. Realizado por Iván Castillo, Bucaramanga, Colombia. Contacto Twitter: @castiillo_ircc

  • 1,003