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:

  1. 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.
  2. Si può dimostrare partendo dalla definizione di , infatti: