Algorithme de Bellman-Ford
# Algorithme de Bellman-Ford

L'algorithme de Bellman-Ford, aussi appelé algorithme de Bellman–Ford–Moore, est un algorithme qui calcule des plus courts chemins depuis un sommet source donné dans un graphe orienté pondéré. Il porte le nom de ses inventeurs Richard Bellman et Lester Randolph Ford junior (publications en 1956 et 1958), et de Edward Forrest Moore qui le redécouvrit en 1959.

Contrairement à l'algorithme de Dijkstra, l'algorithme de Bellman-Ford autorise la présence de certains arcs de poids négatif et permet de détecter l'existence d'un circuit absorbant, c'est-à-dire de poids total strictement négatif, accessible depuis le sommet source.

La complexité de l'algorithme est en $O(|S||A|)$ où $|S|$ est le nombre de sommets $|A|$ est le nombre d'arcs.

## Description

L'algorithme de Bellman-Ford calcule, étant donnés un graphe $G=(S,A)$ sans cycle de poids négatif et un sommet source $s\in S$, un plus court chemin de $s$ à chaque sommet de $G$. Il permet en plus de trouver un tel chemin en retournant les prédécesseurs de chaque sommet dans un tel chemin. En outre, il permet de détecter les cas où il existe un cycle de poids négatif et donc dans lesquels il n'existe pas nécessairement de plus court chemin entre deux sommets.

L'algorithme utilise le principe de la programmation dynamique (il est traité dans le chapitre portant sur la programmation dynamique dans certains livres d'algorithmique). Les sous-problèmes sont :

* $d[t,k]$ est la distance du sommet source s à t avec un chemin qui contient au plus k arcs.

On a :

* $d[t,0]=+\infty$ pour $t\neq s$ et $d[s,0]=0$ ;
* $d[t,k]=min\left[d[t,k-1],min_{{\text{arc }}(u,t)}(d[u,k-1]+poids(u,t))\right]$.

L'algorithme calcule les valeurs $d[t,k]$ par valeur de k croissante. La distance de s à t est $d[t,|S|-1]$.

## Pseudo-code

L'algorithme de Bellman-Ford s'écrit donc en utilisant directement la relation de récurrence donnée dans la section précédente.

À l'issue de l'exécution de cet algorithme, $d[u]$ représente la longueur d'un plus court chemin de $s$ à $u$ dans $G$, alors que $pred[u]$ représente le prédécesseur de $u$ dans un plus court chemin de $s$ à $u$. La valeur null signifie qu'aucun prédécesseur n'a pour l'instant été assigné à $pred[u]$.

L'algorithme de Bellman-Ford n'est correct que dans un graphe sans cycle de poids négatif. On peut détecter la présence d'un tel cycle (à condition qu'il soit accessible depuis le sommet $s$) de la façon suivante : il y a un cycle de poids négatif si et seulement si un nouveau tour de boucle fait diminuer une distance. Ainsi, à la fin de l'algorithme, on fait :

## Complexité

La complexité de l'algorithme est en $O(|S||A|)$ où $|S|$ est le nombre de sommets et $|A|$ est le nombre d'arcs. Cela correspond à une complexité en $O(|S|^{3})$ pour un graphe simple dense.

## Preuve de la correction

La démonstration de la correction de l'algorithme peut se faire par récurrence :

Lemme. Après $i$ répétitions de la boucle principale :

* Si $d[u]\neq +\infty$, alors $d[u]$ est le poids d'un chemin de $s$ à $u$ ;
* S'il existe un chemin de $s$ à $u$ d'au plus $i$ arêtes, alors $d[u]$ est au plus la longueur du plus court chemin de $s$ à $u$ comprenant au plus $i$ arêtes.

Preuve. Pour le cas $i=0$, correspondant à la première exécution de la boucle for, alors, d'une part, $d[s]=0$ et, pour tout sommet $u\neq s$, $d[u]=+\infty$, prouvant le premier point et, d'autre part, $s$ est le seul sommet tel qu'il existe un chemin d'au plus 0 arêtes le reliant à $s$.

Pour le cas $i$ non nul quelconque, alors :

* D'une part, supposons $d[v]$ soit mis à jour avec $d[v]:=d[u]+{\text{poids}}(u,v)$. Alors, comme $d[u]\neq +\infty$ (car sinon, la mise à jour n'aurait pas lieu),$d[u]$ représente le poids d'un chemin de $s$ à $u$. Donc, par construction, $d[v]$ est le poids d'un chemin de $s$ à $v$ ;
* D'autre part, soit $C$, un plus court chemin de $s$ à $v$ d'au plus $i$ arêtes. Soit $u$ le dernier sommet avant $v$ sur ce chemin. Soit $C'$, le sous-chemin de $C$ allant de $s$ à $u$. Alors, par induction, $C'$ est un plus court chemin de $s$ à $u$ d'au plus $i-1$ arêtes (en effet, sinon, il existe un chemin strictement plus court de $s$ à $u$. En y ajoutant l'arête de $u$ à $v$, on trouve un chemin strictement plus court que $C$ allant de $s$ à $v$, ce qui est contradictoire avec la définition de $C$). Alors, par hypothèse de récurrence, à l'issue de l'itération $i-1$, $d[u]$ était au plus la longueur d'un plus court chemin de $s$ à $u$ d'au plus $i-1$ arêtes. Ainsi, à la $i$-ème itération, $d[v]\leq d[u]+{\text{poids}}(u,v)$, en raison de la structure de l'algorithme. Or, cette dernière longueur est au plus la longueur d'un plus court chemin de $s$ à $v$.

Le lemme est donc démontré. Il s'ensuit que la longueur $d[u]$ est la longueur d'un plus court chemin de $s$ à $u$, ce qui prouve la correction de l'algorithme de Bellman-Ford dans le cas où $G$ n'a pas de cycle de poids négatif.

## Améliorations

On peut arrêter l'exécution de la boucle principale lorsque les distances sont inchangées. Le corps de la boucle principale est alors exécuté moins de $|S|-1$ fois. La complexité dans le pire cas est inchangée. Yen a décrit deux améliorations à l'algorithme de Bellman-Ford qui ne changent pas la complexité dans le pire cas mais qui le rend plus rapide en pratique.

* La première amélioration réduit le nombre de relaxations. Si d[u] n'a pas été modifié depuis une relaxation d'un arc (u, t), alors il n'y a pas besoin de relâcher les arcs (u, t) une deuxième fois. Ainsi, comme le nombre de sommets avec la distance correcte augmente au cours de l'algorithme, le nombre d'arcs à relâcher diminue à chaque itération. On gagne un facteur constant sur la complexité pour des graphes denses.
* La seconde amélioration de Yen consiste à choisir un ordre total arbitraire < sur les sommets puis à partitionner l'ensemble des arcs en deux sous-ensembles disjoints. Le premier sous-ensemble $E_f$ contient les arcs (u, t) avec u < t et le second, $E_b,$ contient les arcs (u, t) avec u > t. La boucle pour chaque arc (u, t) du graphe faire s'effectue de la façon suivante. Chaque sommet u est visité par ordre croissant <. Puis on relâche chaque arc (u, t) dans $E_f.$ Puis on visite les sommets u dans l'ordre décroissant >. On relâche les arcs (u, t) dans $E_b.$ Chaque itération de la boucle principale (sauf la première) ajoute au moins deux arcs dont les sommets ont des distances correctes, l'un dans $E_f$ et un dans $E_b.$ Cette amélioration réduit le nombre d'itérations de la boucle principale de $|S|-1$ à ${\frac {|S|}{2}}$.

Une autre amélioration par Bannister & Eppstein consiste à remplacer l'ordre total sur les sommets de la seconde amélioration de Yen par une permutation aléatoire. Ainsi, le pire cas de l'amélioration de Yen arrive peu souvent (le fait que les arcs d'un plus court chemin sont tantôt dans $E_f$ tantôt dans $E_b).$ Avec une permutation aléatoire comme ordre total, l'espérance du nombre d'itérations de la boucle principale est d'au plus ${\frac {|S|}{3}}$.

En 1993, Bahar et al. ont donné une implémentation de l'algorithme de Bellman-Ford pour des graphes représentés symboliquement à l'aide d'une structure de données appelée Algebraic Decision Diagrams (ADD), qui est une généralisation des diagrammes de décision binaire.

## Utilisations

Dans les réseaux informatiques, l'algorithme de Bellman-Ford est utilisé pour déterminer le cheminement des messages, à travers le protocole de routage RIP. On peut utiliser l'algorithme de Bellman-Ford pour résoudre un problème de programmation linéaire où les contraintes sont des différences. Par exemple : x - y ≤ 5, y - t ≤ 10, etc. Plus précisément, un tel système a une solution si et seulement si le graphe associé n'a pas de cycles de poids $négatif^,.$

