Algorithme De Dijkstra

Algorithme De Dijkstra

Algorithme de Dijkstra


En théorie des graphes, l'algorithme de Dijkstra sert à résoudre le problème du plus court chemin. Il permet, par exemple, de déterminer le plus court chemin pour se rendre d'une ville à une autre connaissant le réseau routier d'une région. Il s'applique à un graphe connexe dont le poids lié aux arêtes est positif ou nul.

L'algorithme porte le nom de son inventeur, l'informaticien néerlandais Edsger Dijkstra et a été publié en 1959[1].

En théorie de la complexité on démontre que cet algorithme est polynomial.

Sommaire

Principe sur un exemple

Il s'agit de construire progressivement, à partir des données initiales, un sous-graphe dans lequel sont classés les différents sommets par ordre croissant de leur distance minimale au sommet de départ. La distance correspond à la somme des poids des arêtes empruntées.

La première étape consiste à mettre de côté le sommet de départ et à repérer la distance du sommet de départ aux autres sommets du graphe. Cette distance est infinie si aucun arc ne relie le sommet au sommet de départ, elle est de n s'il existe un arc reliant ce sommet au sommet de départ et que le poids le plus faible (s'il existe plusieurs arcs) est de n.

La seconde étape consiste à repérer le sommet qui possède alors la plus courte distance au sommet de départ et à le mettre de côté. Pour tous les sommets restants, on compare alors la distance trouvée précédemment à celle que l'on obtiendrait via le sommet que l'on vient de mettre de côté et on ne conserve que la plus petite des valeurs. et on continue ainsi jusqu'à épuisement des sommets ou jusqu'à sélection du sommet d'arrivée.

Distance entre la ville A et la ville J

L'exemple suivant montre les étapes successives dans la résolution du chemin le plus court dans un graphe. Les nœuds symbolisent des villes identifiées par une lettre et les arêtes indiquent la distance entre ces villes. On cherche à déterminer le plus court trajet pour aller de la ville A à la ville J .

Étape 1 : à partir de la ville A, 3 villes sont accessibles, B, C, et E qui se voient donc affectées des poids respectifs de 85, 217, 173, tandis que les autres villes sont affectées d'une distance infinie.
Étape 2 : la distance la plus courte est celle menant à la ville B. Le passage par la ville B ouvre la voie à la ville F (85+80 = 165).
Étape 3 : La distance la plus courte suivante est celle menant à la ville F. Le passage par la ville F ouvre une voie vers la ville I (415).
Étape 4 : La distance la plus courte suivante est alors celle menant à la ville E. Le passage par la ville E ouvre une voie vers la ville J (675).
Étape 5 : la distance la plus courte suivante mène alors à la ville C. Le passage par la ville C ouvre une voie vers la ville G (403) et la ville H (320).
Étape 6: la distance la plus courte suivante mène à ville H(320). Le passage par la ville H ouvre une voie vers la ville D et un raccourci vers la ville J (487< 675).
Étape 7 : la distance la plus courte suivante mène à la ville G et ne change aucune autre distance.
Étape 8 : la distance la plus courte suivante mène à la ville I. Le passage par la ville I ouvre un chemin vers la ville J qui n'est pas intéressant (415+ 84 > 487).
Étape 9 : la distance la plus courte suivante mène à la ville J (487).

On connait ainsi le chemin le plus court menant de A à J, il passe par C et H et mesure 487 km.

Présentation sous forme de tableau

L'illustration par une série de graphes peut se révéler un peu longue. Il est d'autre part un peu plus difficile de repérer le chemin le plus court à l'issue du dessin. Ainsi l'algorithme de Dijsktra est souvent réalisé à l'aide d'un tableau dans lequel chaque étape correspond à une ligne.

A partir de la matrice des arcs orientés reliant les diverses villes :

Matrices des arcs orientés
à A à B à C à D à E à F à G à H à I à J
De A 0 85 217 173
De B 85 0 80
De C 217 0 186 103
De D 0 183
De E 173 0 502
De F 80 0 250
De G 186 0
De H 103 183 0 167
De I 250 0 84
De J 502 167 84 0

On construit un tableau dans lequel les distances d'un sommet au sommet de départ sont regroupées dans une même colonne. Les sommets sélectionnés sont soulignés. Les distances des voies ouvertes par la sélection d'un nouveau sommet sont barrées si elles sont supérieures à des distances déjà calculées. Quand un sommet est sélectionné, c'est que l'on a découvert sa distance minimale au sommet, il est alors inutile de chercher d'autres distances de ce sommet au point de départ.



Algorithme de Dijsktra
à B à C à D à E à F à G à H à I à J
A 85 217 173
B(85A) - 217 173 165
F(165B) - 217 173 - 415
E(173A) - 217 - - 415 675
C(217A) - - - - 403 320 415 675
H(320C) - - 503 - - 403 - 415 487
G(403C) - - 503 - - - - 415 487
I(415F) - - 503 - - - - - 499487
J(487H) - - 503 - - - - - -
D(503H) - - - - - - - - -

La construction de ce tableau donne non seulement la distance minimale de la ville A à la ville J mais aussi le chemin à suivre (J - H - C - A) ainsi que toutes les distances minimales de la ville A aux autres villes rangées par ordre croissant.

Notations

Le graphe est noté G = (S,A) où :

  • l'ensemble S est l'ensemble des sommets du graphe G ;
  • l'ensemble A est l'ensemble des arêtes de G tel que : si (s1,s2) est dans A, alors il existe une arête depuis le nœud s1 vers le nœud s2 ;
  • on définit la procédure Poids(s1,s2) définie sur A qui renvoie le poids positif de l'arête reliant s1 à s2 (et un poids infini pour les paires de sommets qui ne sont pas connectées par une arête).

Principes

Dijkstra's algorithm.svg

Le poids du chemin entre deux sommets est la somme des poids des arêtes qui le composent. Pour une paire donnée de sommets sdeb (le sommet du départ) sfin (sommet d'arrivée) appartenant à S, l'algorithme trouve le chemin depuis sdeb vers sfin de moindre poids (autrement dit le chemin le plus léger ou encore le plus court).

L'algorithme fonctionne en construisant un sous-graphe P de manière à ce que la distance entre un sommet s de P depuis sdeb soit connue et soit un minimum dans G. Initialement P contient simplement le nœud sdeb isolé, et la distance de sdeb à lui-même vaut zéro. Des arcs sont ajoutés à P à chaque étape :

1. en identifiant toutes les arêtes ai = (si1,si2) dans P \times G tel que si1 est dans P et si2 est dans G ;
2. en choisissant l'arête aj = (sj1,sj2) dans P \times G qui donne la distance minimum depuis sdeb à sj2 en passant tous les chemins créés menant à ce nœud.

L'algorithme se termine soit quand P devient un arbre couvrant de G, soit quand tous les nœuds d'intérêt[2] sont dans P.

Algorithme

Fonction annexes

L'algorithme utilise les fonctions annexes suivantes.

Initialisation de l'algorithme

Initialisation(G,sdeb)
1 pour chaque point s de G
2    faire d[s] := infini             /* on initialise les sommets autres que sdeb à infini */[3]
3 d[sdeb] := 0                        /* sdeb étant le point le plus proche de sdeb */

Recherche du nœud le plus proche

  • On recherche le nœud le plus proche (relié par l'arête de poids le plus faible) de sdeb parmi les nœuds situés dans un ensemble Q, constitué des nœuds éloigné d'une arête des éléments de P. On utilise pour cela la fonction Trouve_min(). Le nœud trouvé est alors effacé de l'ensemble Q et est alors retourné à la fonction principale comme résultat de la fonction.

Mise à jour des distances

  • On met à jour des distances entre sdeb et s2 en se posant la question : vaut-il mieux passer par s1 ou pas ?
maj_distances(s1,s2)
1 si d[s2] > d[s1] + Poids(s1,s2)
2    alors d[s2] := d[s1] + Poids(s1,s2)

Fonction principale

Voici la fonction principale utilisant les précédentes fonctions annexes :

Dijkstra(G,Poids,sdeb)
1 Initialisation(G,sdeb)
2 Q := ensemble de tous les nœuds
3 tant que Q n'est pas un ensemble vide
4       faire s1 := Trouve_min(Q)
5          Q := Q privé de s1
6          pour chaque nœud s2 voisin de s1
7              faire maj_distances(s1,s2)

Le plus court chemin de sdeb à sfin peut ensuite se calculer itérativement selon l'algorithme suivant, avec A la suite représentant le plus court chemin de sdeb à sfin:

1 A = suite vide
2 s := sfin
3 A = s + A                   /* insère s au début de A */
4 tant que s != sdeb
5   s = prédecesseur[s]       /* on continue de suivre le chemin */
6   A = s + A

Améliorations de l'algorithme

Il est possible d'améliorer légèrement l'algorithme principal en arrêtant la recherche lorsque l'égalité s1 = sfin est vérifiée, à condition bien sûr de ne chercher que la distance minimale entre sdeb et sfin.

L'algorithme de Dijkstra pourra être mis en œuvre efficacement en stockant le graphe sous forme de listes d'adjacence et en utilisant un tas comme une file à priorités pour réaliser la fonction Trouve_min. Si le graphe possède m arcs et n nœuds, en supposant que les comparaisons des poids d'arcs soient à temps constant, et que le tas soit binomial, alors la complexité de l'algorithme est : \sigma [(m+n)\times ln(n)]. L'utilisation de tas de Fibonacci donne un meilleur temps d'exécution amorti : \sigma [m+n\times ln(n)].


Codes

Pseudo-code

 fonction Dijkstra (nœuds, fils, distance, debut, fin)
     Pour n parcourant nœuds
         n.parcouru = infini   // Peut être implémenté avec -1
         n.precedent = 0
     Fin pour
     debut.parcouru = 0
     PasEncoreVu = nœuds
     Tant que PasEncoreVu != liste vide
         n1 = minimum(PasEncoreVu)   // Le nœud dans PasEncoreVu avec parcouru le plus petit
         PasEncoreVu.enlever(n1)
         Pour n2 parcourant fils(n1)   // Les nœuds reliés à n1 par un arc
             Si n2.parcouru > n1.parcouru + distance(n1, n2)   // distance correspond au poids de l'arc reliant n1 et n2
                 n2.parcouru = n1.parcouru + distance(n1, n2)
                 n2.precedent = n1   // Dit que pour aller à n2, il faut passer par n1
             Fin si
         Fin pour
     Fin tant que
     chemin = liste vide
     n = fin
     Tant que n != debut
         chemin.ajouterAvant(n)
         n = n.precedent
     Fin tant que
     chemin.ajouterAvant(debut)
     Retourner chemin
 Fin fonction Dijkstra

Implémentation Caml

Voici le code d'implémentation Caml :

(* on suppose données des files de priorité *)
module H : sig
  type 'a t
  val empty : 'a t
  val is_empty : 'a t -> bool
  val add : int * 'a -> 'a t -> 'a t
  val extract_min : 'a t -> (int * 'a) * 'a t
end
 
(* l'adjacence est donnée sous la forme d'une fonction : adj v est la liste des voisins de v,
   avec leur distance ; la fonction suivante cherche le plus court chemin de v1 à v2 *)
let dijkstra (adj: 'a -> ('a * int) list) (v1:'a) (v2:'a) =
  let visited = Hashtbl.create 97 in
  let rec loop h =
    if H.is_empty h then raise Not_found;
    let (w,(v,p)),h = H.extract_min h in
      if v = v2 then 
        List.rev p, w
      else
        let h =
  	  if not (Hashtbl.mem visited v) then begin
  	    Hashtbl.add visited v ();
  	    List.fold_left (fun h (e,d) -> H.add (w+d, (e, e::p)) h) h (adj v)
  	  end else
  	    h
        in
          loop h
  in
    loop (H.add (0,(v1,[])) H.empty)

Applications

Une application des plus courantes de l'algorithme de Dijkstra est le protocole open shortest path first qui permet un routage internet très efficace des informations en cherchant le parcours le plus efficace.

Les routeurs IS-IS utilisent également l'algorithme. Les sites d'itinéraires routiers l'utilisent de la même manière et permettent de nombreuses adaptations en ajustant le poids des arcs comme par exemple : trajet le plus économique, le plus rapide...


Annexes

Références

Liens internes

Liens externes

Sources et indications supplémentaires

  1. (fr) « Principes de l'algorithme de Dijkstra ».
  2. Par exemple, les nœuds n'ayant pas d'arêtes autres que celle que l'on a parcourue pour arriver à eux, ne sont pas considérés comme des nœuds d'intérêt.
  3. Les symboles /* ... */ représentent des commentaires.
  • Portail des mathématiques Portail des mathématiques
  • Portail de l’informatique Portail de l’informatique
Ce document provient de « Algorithme de Dijkstra ».

Wikimedia Foundation. 2010.

Contenu soumis à la licence CC-BY-SA. Source : Article Algorithme De Dijkstra de Wikipédia en français (auteurs)

Игры ⚽ Поможем сделать НИР

Regardez d'autres dictionnaires:

  • Algorithme de dijkstra — En théorie des graphes, l algorithme de Dijkstra sert à résoudre le problème du plus court chemin. Il permet, par exemple, de déterminer le plus court chemin pour se rendre d une ville à une autre connaissant le réseau routier d une région. Il s… …   Wikipédia en Français

  • Algorithme de Dijkstra — En théorie des graphes, l algorithme de Dijkstra (prononcer [dɛjkstra]) sert à résoudre le problème du plus court chemin. Il permet, par exemple, de déterminer le plus court chemin pour se rendre d une ville à une autre connaissant le réseau… …   Wikipédia en Français

  • algorithme de Dijkstra — ● loc. m. ►ALGO algorithme classique, découvert par Dijkstra, Edsgar, permettant de calculer le plus court chemin reliant un sommet d un graphe orienté à tous les autres sommets …   Dictionnaire d'informatique francophone

  • Algorithme De Dantzig-Ford — L algorithme de Ford Dantzig résout un problème de plus court chemin. Il sert à trouver un chemin optimal (le plus court ou bien le plus long) entre deux sommets d un graphe orienté. Le graphe peut être avec ou sans circuit et les poids… …   Wikipédia en Français

  • Algorithme de Danteig-Ford — Algorithme de Dantzig Ford L algorithme de Ford Dantzig résout un problème de plus court chemin. Il sert à trouver un chemin optimal (le plus court ou bien le plus long) entre deux sommets d un graphe orienté. Le graphe peut être avec ou sans… …   Wikipédia en Français

  • Algorithme de Dantzig et Ford — Algorithme de Dantzig Ford L algorithme de Ford Dantzig résout un problème de plus court chemin. Il sert à trouver un chemin optimal (le plus court ou bien le plus long) entre deux sommets d un graphe orienté. Le graphe peut être avec ou sans… …   Wikipédia en Français

  • Algorithme de dantzig-ford — L algorithme de Ford Dantzig résout un problème de plus court chemin. Il sert à trouver un chemin optimal (le plus court ou bien le plus long) entre deux sommets d un graphe orienté. Le graphe peut être avec ou sans circuit et les poids… …   Wikipédia en Français

  • Algorithme De Ford-Bellman — L algorithme de Bellman Ford (Bell End Ford) (Richard Bellman, Samuel End et Lester Ford) est un algorithme de programmation dynamique qui permet de trouver des plus courts chemins, depuis un sommet source donné, dans un graphe orienté pondéré.… …   Wikipédia en Français

  • Algorithme de Ford-Bellman — L algorithme de Bellman Ford (Bell End Ford) (Richard Bellman, Samuel End et Lester Ford) est un algorithme de programmation dynamique qui permet de trouver des plus courts chemins, depuis un sommet source donné, dans un graphe orienté pondéré.… …   Wikipédia en Français

  • Algorithme de ford-bellman — L algorithme de Bellman Ford (Bell End Ford) (Richard Bellman, Samuel End et Lester Ford) est un algorithme de programmation dynamique qui permet de trouver des plus courts chemins, depuis un sommet source donné, dans un graphe orienté pondéré.… …   Wikipédia en Français

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”