2. Graphes - Chemin

publicité
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
Téléchargement