Algorithmes de plus court chemin !! On considère un graphe valué "! chaque arc est muni d’un poids Plus court chemin dans un graphe !! Un chemin a pour poids la somme des poids des arcs qui le constituent !! Le problème des plus courts chemins consiste à déterminer le poids minimal d’un chemin d’un sommet à un autre, en supposant les poids positifs "! avec des poids qui peuvent être négatifs c’est moins facile Algorithmique avancée Hervé Blanchon !! Il existe plusieurs algorithmes "! algorithme de Floyd (en |S|3) IUT 2 – Département Informatique Université Pierre Mendès France 2 Plus court chemin sur un graphe non valué Plus court chemin sur un graphe non valué !! Soit G un graphe non valué !! Soit s le nœud v3. !! En utilisant un nœud s comme point de départ, on voudrait trouver le plus court chemin depuis s jusqu’à tous les autres nœuds. 1.! Le plus court chemin de s à v3 est de longueur 0 "! on peut marquer cette information [schéma de gauche] !! On est intéressé uniquement par le nombre d’arcs parcourus (soit la longueur des chemins) "! Si on était intéressé par les chemins, il faudrait mettre d’autres informations à jour 2.! On peut maintenant chercher tous les nœuds distants de 1 de s en cherchant les nœuds adjacents de s (via un arc) !! Il s’agit de v1 et v6. [schéma de droite] 3 4 Plus court chemin sur un graphe non valué Plus court chemin sur un graphe non valué 3.! On peut maintenant trouver les nœuds à distance 2 de s en cherchant les nœuds adjacents à v1 et v6 pour lesquels un plus court chemin n’est pas déjà connu (afin d’éviter de rentrer dans un cycle) !! Il s’agit de v2 et v4 [schéma de gauche] !! La stratégie mise en œuvre est une stratégie en largeur d’abord "! breadth-first search (BFS) ! File d’attente !! Les informations qu’il faut mémoriser pour chaque nœuds v sont les suivantes : "! la longueur du chemin depuis s vers v : dv (distance à s) 4.! On peut finalement trouver les nœuds à distance 3 de s en cherchant les nœuds adjacents à v2 et v4 !! il s’agit de v5 et v7 [schéma de droite] !! initialement aucun nœud n’est atteignable, sauf s dont la distance à s est égale à 0 "! le nœud précédent v sur le chemin qui l’atteint depuis s : pv "! un booléen qui permet de savoir si v a déjà été visité : known 5.! Tous les nœuds ont été examinés, c’est terminé. !! Ces informations sont mémorisées dans une table "! état initial : 5 Plus court chemin sur un graphe non valué 6 Autre trace !! Trace de l’algorithme V1 V2 origine V3 V4 V5 0 V6 V7 File: V3 7 8 Autre trace Autre trace 1 V2 V1 origine origine V3 V4 1 2 V2 1 V1 V6 V5 2 V3 V7 V4 1 File: V1 V6 V6 V5 V7 File: V6 V2 V4 9 Autre trace 10 Autre trace 2 V2 1 V1 origine V1 origine 2 V3 V4 1 V6 2 V2 1 V5 2 V3 V7 1 File: V2 V4 3 V4 V6 V5 V7 File: V4 V5 11 12 Autre trace Autre trace 2 V2 1 V1 origine V1 origine 2 V3 V6 2 3 V4 1 V5 V7 2 V2 1 V3 3 1 File: V5 V7 3 V4 V6 V5 V7 3 File: V7 13 Plus court chemin sans poids void unweighted( Vertex s ) { Queue<Vertex> q = new Queue<Vertex>( ); 2 V2 1 V1 origine 2 V3 3 V4 1 V6 14 V5 V7 for each Vertex v v.dist = INFINITY; // aucun des nœuds n’est atteint s.dist = 0; q.enqueue( s ); // distance à s, premier nœud, =0 // s est enfilé while( !q.isEmpty( ) ) { Vertex v = q.dequeue( ); // le nœud à traiter est défilé for each Vertex w adjacent to v if( w.dist == INFINITY ) // on ne met dans la file que les nœuds { // jamais atteints w.dist = v.dist + 1; // distance mise à jour w.path = v; // précédent mis à jour q.enqueue( w ); // le nœud traité est enfilé } 3 } } File: vide 15 Plus court chemin sur un graphe non valué Plus court chemin sur un graphe valué positif (vp) !! Algorithme utilisant une file pour les nœuds à explorer "! l’information Known n’est pas nécessaire !! Le problème est du même type que le précédent !! Information à mémoriser pour un nœud "! un sommet est connu ou non (known à False ou True) "! le sommet précédemment visité (pv) "! la distance parcourue jusqu’alors (dv) !! on ne met dans la file que les nœuds jamais atteints for each Vertex w adjacent to v if( w.dist == INFINITY ) { // distance mise à jour // précédent mis à jour // le nœud traité est enfilé !! cette distance est la plus courte de s à v en utilisant uniquement des sommets connus !! La méthode générale est l’algorithme de Dijkstra (1959) "! Algorithme glouton } !! celle qui semble être la meilleure option est choisie à chaque étape !! sachant que tous les plus courts chemins sont déjà connus !! Coût de l’algorithme "! O(|E|+|V|) !! E=nombre d’arcs !! V=nombre de nœuds 17 18 Plus court chemin sur un graphe vp Plus court chemin sur un graphe vp : exemple !! Classe nœud pour l’algorithme de Dijkstra !! Graphe de départ !! Configuration initiale des données "! "! 19 nœud de départ (s) : v1 longueur de chemin = 0 20 Plus court chemin sur un graphe vp : exemple Plus court chemin sur un graphe vp : exemple !! maintenant que v1 est connu, il faut mettre à jour les données "! les nœuds adjacents sont v2 et v4 "! les données concernant v2 et v4 doivent être mises à jour "! il faut traiter le nœud inconnu le plus proche !! v4 est traité d’abord, car il est plus proche de v1, et marqué comme connu "! les nœuds v3, v5, v6 et v7 lui sont adjacent et les données les concernant doivent être mises à jour "! il faut traiter le nœud inconnu le plus proche !! c’est v2 !! tous les plus courts chemins sont déjà connus !! c’est v4 1+2 1+2 1+8 1+4 21 22 Plus court chemin sur un graphe vp : exemple Plus court chemin sur un graphe vp : exemple !! v2 est traité et marqué comme connu "! les nœuds v4 et v5 lui sont adjacents "! v4 est connu : il n’est pas traité (on connaît déjà un plus court chemin qui conduit à v4) "! v5 n’est pas connu : il n’est pas mis à jour car aller vers v5 à travers v2 coûte 2+10 et on connaît déjà un chemin de coût 3 qui atteint v5 "! il faut traiter le nœud inconnu le plus proche !! v5 (à distance 3) est traité et marqué comme connu "! v7 (à distance 5) est le seul nœud adjacent !! il n’est pas mis à jour car 3+6 > 5 "! il faut traiter le nœud inconnu le plus proche !! c’est v3 !! c’est v5 (par exemple) inchangé inchangé 23 24 Plus court chemin sur un graphe vp : exemple Plus court chemin sur un graphe vp : exemple !! v3 (à distance 3) est traité et marqué comme connu "! les nœuds v1 et v6 lui sont adjacents "! v1 est connu : il n’est pas traité "! v6 n’est pas connu : il est mis à jour car aller vers v6 à travers v3 coûte 3+5=8 et le chemin que l’on connaît déjà coûte 9 (via v4) "! il faut traiter le nœud inconnu le plus proche !! v7 (à distance 5) est traité et marqué comme connu "! le nœud v6 lui est adjacent "! v6 n’est pas connu : il est mis à jour car aller vers v6 à travers v7 coûte 5+1=6 et le chemin que l’on connaît déjà coûte 8 (via v3) "! il faut traiter le nœud inconnu le plus proche !! c’est v6 !! c’est v7 9 -> 8 8 -> 6 25 26 Plus court chemin sur un graphe vp : exemple !! v6 (à distance 6) est traité et marqué comme connu "! aucun nœud ne lui est adjacent !! Trace !! pas de traitement "! aucun nœud est inconnu !! il n’y a plus rien à faire 27 Autre Trace Autre Trace !! Avec une file de priorité pour les (nœuds, distance) à traiter origine origine 0 4 V1 2 V3 0 V4 4 8 5 1 V5 4 1 V4 4 1 V5 File de priorité: (V0,0) 2 8 5 V6 10 V3 0 6 V1 3 1 2 V2 2 2 V0 10 3 1 2 V2 0 2 V0 6 V6 File de priorité: (V3 ,1) (V1 ,2) 29 Autre Trace 30 Autre Trace origine 0 V0 4 3 0 V5 9 4 4 1 3 2 V3 8 5 10 V4 3 0 6 V5 9 File de priorité: (V1 ,2) (V4 ,3) (V2 ,3) (V6 ,5) (V5 ,9) 10 1 2 V3 4 8 5 V6 5 V1 3 1 2 V2 2 2 V0 1 2 V2 0 V1 3 1 origine 2 2 1 V4 3 6 V6 5 File de priorité: (V4 ,3) (V2 ,3) (V6 ,5) (V5 ,9) 31 32 Autre Trace Autre Trace origine 0 2 V0 4 3 10 1 V5 3 V2 10 1 2 V3 0 6 V1 3 1 2 1 V5 File de priorité: 3 6 V6 5 8 (V2 ,3) (V6 ,5) (V5 ,9) V4 4 8 5 V6 5 9 File de priorité: V4 4 8 5 3 2 V3 0 4 2 2 V0 1 2 V2 0 V1 3 1 origine 2 (V6 ,5) (V5,8) (V5 ,9) 33 Autre Trace 34 Autre Trace origine 0 V0 4 3 0 V5 4 4 1 6 3 2 V3 8 5 10 V4 3 0 6 6 File de priorité: 35 2 V3 V5 File de priorité: (V5 ,6), (V5 ,8) (V5 ,9) 10 1 4 8 5 V6 5 V1 3 1 2 V2 2 2 V0 1 2 V2 0 V1 3 1 origine 2 2 1 V4 3 6 V6 5 (V5 ,8) (V5 ,9) 36 Autre Trace Plus court chemin sur un graphe vp origine 0 4 3 0 V1 1 2 V3 4 8 5 10 3 1 2 V2 2 2 V0 !! Pour imprimer le plus court chemin d’un nœud de départ vers un nœud v, on peut écrire un algorithme récursif qui suit un chemin par la gauche de la variable p : V5 6 1 V4 3 6 V6 5 Résultat final 37 !! Algorithme de Dijkstra "! Pseudo code !! Coût "! Nœuds !! une mise à jour par arc "! O(|A|) Total !! !! O(|N|2) Mise à jour des distances !! "! O(|N|) parcours de tous les nœuds "! "! Exemple recherche séquentielle du nœud de coût minimal "! !! 38 O(|A|+|N|2)=O(|N|2) Remarques "! si le graphe est complet |A|=!(|N|2) !! "! l’algorithme est optimal (linéaire en nombre d’arcs) dans le cas contraire |A|=!(|N|) !! l’algorithme est très lent 40