Floyd-Warshall
L'algoritmo trova le distanze minime, restituendole su , tra tutte le coppie di nodi in , su un grafo orientato con possibili pesi negativi riportati nella matrice di adiacenza :
floyd_warshall(W)
n = W.rows = W.colums
D = {}
D[0] = W
for k = 1 to n
for i = 1 to n
for j = 1 to n
D[k][i,j] = min(D[k-1][i,k] + D[k-1][k,j], D[k-1][i,j])
return D[n]
All'interno della matrice , i pesi assumono valori:
La complessità è data dai tre cicli annidati, quindi .
Correttezza
L'algoritmo è corretto perchè alla fine, degli elementi della matrice , si ha che .
Si può dimostrare definendo , cioè l'insieme dei cammini semplici tra e , e , cioè l'insieme dei cammini i cui nodi intermedi, ovvero esclusi e , hanno valore .
Con questo si può notare che e che alla fine perchè tutti i nodi sono inclusi.
Si può quindi definire come il costo minimo dei cammini tra e che includono fino al -esimo nodo: per cui alla fine perchè e per la definizione .
Generazione matrici
La correttezza del corpo dei cicli si può dimostrare partizionando in , ovvero l'insieme dei cammini passanti per , e in , ovvero l'insieme dei cammini non passanti per :
Dalla definizione di ottenuta precedentemente è quindi possibile ricavare l'espressione dell'algoritmo: dato che, essendo semplici, i cammini passanti per si possono suddividere in due non passanti per .
Ottimizzazione
L'algoritmo si può ottimizzare riducendo il numero di matrici, tenendone una per l'iterazione corrente e una per la precedente. Inoltre è anche possibile salvarne una sola, purchè si soddisfino le condizioni per cui:
-
Si può dimostrare per induzione su :
- Caso base, per : è verificato per la definizione di , perchè
- Passo induttivo, assumendo che valga fino a : Inoltre, questo evidenzia che se , allora sarebbero presenti cicli negativi.
-
Si può dimostrare partendo dalla definizione di , infatti: