Bonjour,
Dans notre leçon précédente, nous avons implémenté l'algorithme de Dijkstra à l'aide d'une file de priorité, une méthode efficace pour résoudre le problème du plus court chemin depuis une source unique. Nous avons établi que son approche gloutonne fonctionne à une condition cruciale : l'absence de poids négatifs sur les arcs.
Aujourd'hui, nous allons aborder un point essentiel pour le niveau d'exigence de l'Agrégation : la démonstration formelle de la correction de cet algorithme. Nous allons prouver rigoureusement pourquoi la stratégie gloutonne de Dijkstra conduit infailliblement à la solution optimale lorsque les poids sont non-négatifs. Cette preuve est un classique du genre, reposant sur un raisonnement par récurrence sur l'ensemble des sommets dont la distance est considérée comme définitive.
L'objectif de cette leçon est donc de vous apprendre à prouver la correction de l'algorithme de Dijkstra par récurrence sur l'ensemble des sommets finalisés.
1. La Stratégie de Preuve : Invariant de Boucle et Récurrence
La preuve de correction de l'algorithme de Dijkstra s'articule autour d'un invariant de boucle. L'idée est de démontrer qu'une certaine propriété reste vraie à chaque itération de la boucle principale de l'algorithme.
Partitionnons les sommets du graphe en deux ensembles à tout moment de l'exécution :
- : l'ensemble des sommets dont la distance la plus courte depuis la source a été finalisée.
- : l'ensemble des sommets "frontière", pour lesquels on a une estimation de distance, mais pas encore la certitude que ce soit la plus courte.

L'invariant que nous allons prouver par récurrence sur la taille de est le suivant :
Invariant : Pour tout sommet , la distance calculée par l'algorithme, notée , est égale à la distance réelle du plus court chemin de à , notée .
La preuve par récurrence se déroule en deux temps :
- Initialisation (Cas de base) : Au début, et . La propriété est vraie, car le plus court chemin de la source à elle-même est de longueur 0.
- Conservation (Étape de récurrence) : Supposons que l'invariant est vrai pour un ensemble de taille . L'algorithme choisit un sommet qui minimise et l'ajoute à . Nous devons prouver que pour ce nouveau sommet , on a bien .
2. Le Cœur de la Preuve : L'Étape de Récurrence
C'est ici que se trouve le nœud de la démonstration. Pour prouver que , nous allons utiliser un raisonnement par l'absurde.
Supposons le contraire : .
(Note : ne peut pas être inférieur à car l'algorithme ne construit que des chemins valides, donc les distances estimées sont toujours des majorants des distances réelles).
-
S'il existe un chemin plus court vers que celui de longueur , considérons ce chemin. Appelons-le . Ce chemin part de (qui est dans ) et arrive à (qui est dans ).
-
Il doit donc exister un premier sommet sur ce chemin qui n'est pas dans . Traversons le chemin depuis . Soit le premier arc du chemin tel que et .

-
Le chemin peut être décomposé : .
La longueur du plus court chemin jusqu'à , , est la longueur de ce chemin .Puisque les poids sont non-négatifs, .
De plus, la portion du chemin de à est elle-même un plus court chemin vers (propriété de sous-structure optimale). Donc, . -
Par notre hypothèse de récurrence, comme , nous savons que .
-
Quand l'algorithme a finalisé le sommet , il a relâché tous ses arcs sortants, y compris . À ce moment-là (ou peut-être avant, via un autre chemin), la distance a été mise à jour. Nous sommes donc certains que :
-
Combinons ces éléments :
Nous avons donc .
-
Maintenant, rappelons notre hypothèse de départ (par l'absurde) : . En combinant avec le point précédent, on obtient :
Nous avons trouvé un sommet tel que .
-
Ceci est une contradiction. L'algorithme de Dijkstra choisit justement le sommet de qui a la plus petite distance . Il aurait dû choisir (ou un autre sommet encore plus proche) et non .
Notre supposition initiale était donc fausse. Il est impossible que . Par conséquent, , ce qui achève notre étape de récurrence et prouve la correction de l'algorithme.
3. Formalisation et Visualisation de la Preuve
Maintenant que nous avons déconstruit la logique, étudions comment cette preuve est présentée de manière formelle.
La vidéo suivante expose ce raisonnement de façon très claire et dynamique. Elle utilise la même structure de preuve par contradiction, en supposant l'existence d'un premier sommet pour lequel l'algorithme commettrait une erreur.
Dijkstra's algorithm: proof of correctness
Pour une présentation animée de cette preuve, nous allons regarder une vidéo de Foundations of Data Science. Elle utilise la même logique de preuve par contradiction en considérant le 'premier' sommet pour lequel l'algorithme se tromperait, ce qui est une autre façon d'exprimer l'étape de récurrence.
Regardez la section de 03:23 à 12:38. Portez une attention particulière à la chaîne d'inégalités et à la manière dont chaque étape est justifiée : Pourquoi d(s,v) < v.distance ? (Hypothèse de contradiction) Pourquoi v.distance <= ui.distance ? (Propriété de la file de priorité) Pourquoi ui.distance <= ... ? (Opération de relâchement) Comment l'hypothèse de récurrence est utilisée pour le prédécesseur u_{i-1}. Comment la contradiction distance(s, v) < distance(s, v) est finalement atteinte.
Pour une formalisation écrite, typique de ce qui est attendu pour l'Agrégation, le document suivant est une excellente référence. Il structure l'algorithme de manière explicitement récursive.
[PDF] algorithme de Dijkstra - Laboratoire de Mathématiques d'Orsay
Passons maintenant à une formalisation écrite. Le document suivant, du Laboratoire de Mathématiques d'Orsay, présente la preuve de manière très structurée, ce qui est un modèle pour une rédaction de concours.
Lisez la fin de la section 1.1 (à partir de "CALCUL RÉCURSIF") et la preuve du Lemme 1.1. Notez que l'ensemble Ln correspond à notre ensemble S des sommets finalisés. Le lemme prouve que le sommet B choisi est bien le n+1-ième plus proche. C'est exactement notre étape de récurrence. Suivez attentivement la double inégalité (d(E, B) <= d et d(E, B') >= d) qui mène à la conclusion d(E, B) = d.
4. L'Importance Cruciale des Poids Non-Négatifs
Notre preuve repose de manière critique sur l'hypothèse des poids non-négatifs. Identifions où exactement.
L'étape clé est l'inégalité : .
Nous avons affirmé que . Si un poids négatif était autorisé sur ce segment de chemin, la longueur totale du chemin pourrait être inférieure à celle de son préfixe.
Un arc à poids négatif pourrait créer un "raccourci" vers un sommet déjà finalisé, invalidant la décision gloutonne de l'algorithme. La vidéo suivante illustre parfaitement ce point.
Dijkstra's algorithm: proof of correctness
Rappelons-nous de la leçon précédente : Dijkstra échoue avec des poids négatifs. Maintenant, nous pouvons voir précisément où dans la preuve cette condition est indispensable.
Regardez la section de 19:08 à 23:42. Elle montre : À quel endroit exact la chaîne d'inégalités de la preuve n'est plus valide. Un exemple concret où l'algorithme donne un résultat incorrect car il finalise un sommet trop tôt. Comment un cycle de poids négatif peut même faire entrer l'algorithme dans une boucle infinie.
Conclusion
La maîtrise de la preuve de correction de l'algorithme de Dijkstra est une étape importante. Elle solidifie votre compréhension de l'interaction entre l'approche gloutonne, les structures de données et les propriétés mathématiques du problème.
Points clés à retenir :
- La correction de l'algorithme de Dijkstra se prouve par récurrence sur la taille de l'ensemble des sommets finalisés.
- L'invariant essentiel est que pour tout sommet , la distance calculée est la vraie distance minimale .
- L'étape de récurrence se démontre élégamment par l'absurde, en montrant qu'un chemin supposé plus court contredirait la règle de sélection de l'algorithme.
- L'hypothèse des poids non-négatifs est fondamentale pour garantir qu'un chemin ne peut pas devenir "meilleur" en s'allongeant.
Dans notre prochaine leçon, nous aborderons la question inévitable : comment gérer les graphes avec des poids négatifs ? Nous étudierons l'algorithme de Bellman-Ford, qui lève cette contrainte au prix d'une complexité plus élevée, et qui nous permettra également de détecter la présence de cycles de poids négatif.