Algoritmo di Floyd-Warshall

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca
Algoritmo di Floyd-Warshall
ClasseAlgoritmo di ricerca
Struttura datiGrafo
Caso peggiore temporalmenteO(|V|3)
Caso ottimo temporalmenteΩ(|V|3)
Caso peggiore spazialmenteΘ(|V|2)

L'algoritmo di Floyd-Warshall calcola il cammino minimo per tutte le coppie di un grafo pesato e orientato con una complessità [1]. L'idea alla base di questo algoritmo è un processo iterativo che, scorrendo tutti i nodi, ad ogni passo h si ha (data una matrice A) nella posizione [i,j] la distanza - pesata - minima dal nodo di indice i a quello j attraversando solo nodi di indice minore o uguale a h. Se non vi è collegamento allora nella cella c'è infinito. Ovviamente alla fine (con h = numero di nodi) leggendo la matrice si ricava la distanza minima fra i vari nodi del grafo.

Premesso ciò, si può dire che il problema si risolve in programmazione dinamica facendo uso teoricamente di una matrice cubica dove le ordinate e le ascisse sono i e j, mentre h è la profondità. Praticamente, invece, possiamo usare una sola matrice reiterandola piano per piano in h. Si comincia col ricavare la matrice di adiacenza del grafo (infinito dove non vi è collegamento), poi basandoci su di essa cominciamo, in ogni passo h successivo si esaminano ogni cella[i,j] della matrice A: se la somma della distanza tra i ed il nuovo nodo in esame h sommata alla distanza fra h e j è minore della distanza direttamente fra i e j allora si sostituisce quest'ultimo con la precedente somma (per andare dal nodo i al nodo j mi conviene passare per il nodo h).

Detto in modo un po' più formale se (Ah-1[i,h] + Ah-1[h,j]) < Ah-1[i,j] allora Ah[i,j] = (Ah-1[i,h] + Ah-1[h,j]) dove h è il piano che stiamo analizzando.

Sotto potete vedere un algoritmo in pseudocodice del procedimento descritto:

Inizializzazione int [0..n, 0..n] dist; for i := 1 to n for j := 1 to n dist[i][j] := Weight(i,j);

dove Weight(i,j) è una funzione che riporta il peso dell'arco da i a j, 0 nel caso in cui i = j oppure infinito se non esiste un arco da i da j nel grafo.

floydWarshall(int [0..n, 0..n] dist) { for h := 1 to n for i := 1 to n for j := 1 to n if (dist[i][j] > dist[i][h] + dist[h][j]) then dist[i][j] := dist[i][h] + dist[h][j];

Ricostruzione dei Cammini Minimi[modifica | modifica wikitesto]

Al termine della procedura sopra riportata abbiamo solamente ottenuto il peso del cammino minimo tra ogni coppia di nodi, ma non sappiamo ancora quali siano effettivamente i nodi che formano tali cammini. Per ottenere anche il percorso si fa uso di un'ulteriore struttura dati dove memorizziamo, per ogni coppia (i,j) il predecessore di j nel cammino minimo che li collega. In fase di inizializzazione, ovviamente, il predecessore di j nel cammino minimo i → j è i. L'algoritmo si modifica leggermente introducendo questo nuovo elemento:

# inizializzazione
int [0..n, 0..n] dist;
int [0..n, 0..n] pred;
for i := 1 to n
    for j := 1 to n
        dist[i][j] := Weight(i,j);
        pred[i][j] := i;
    endfor
endfor

# floyd-warshall
for h := 1 to n
    for i := 1 to n
        for j := 1 to n
            if (dist[i][j] > dist[i][h] + dist[h][j]) then
                dist[i][j] := dist[i][h] + dist[h][j];
                pred[i][j] := pred[h][j];
            endif
        endfor
    endfor
endfor

Se il cammino minimo tra i e j passa per il nodo h allora il predecessore di j in ij sarà chiaramente il predecessore di j in hj.

Una volta ottenuta la struttura dati pred possiamo ricostruire i cammini minimi tra ogni coppia di nodi. Supponiamo di voler ricostruire il cammino minimo P1,5 e che questo sia 1,3,4,5. Utilizziamo pred in questo modo:

  1. Partiamo da pred[1][5], vale 4
  2. Consideriamo ora pred[1][4], vale 3
  3. Ora pred[1][3], che vale 1: Cammino ricostruito.

Note[modifica | modifica wikitesto]

  1. ^ Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein, Introduction to Algorithms, The MIT Press, 2009, Sezione 25.2 pag. 693, ISBN 978-0-262-53305-8.

Bibliografia[modifica | modifica wikitesto]

Voci correlate[modifica | modifica wikitesto]

Altri progetti[modifica | modifica wikitesto]

Collegamenti esterni[modifica | modifica wikitesto]

  Portale Matematica: accedi alle voci di Wikipedia che trattano di matematica