Algorithme de Dijkstra et applications
Partie 1 : Graphes, algorithme de Dijsktra et New York
đ Introduction
Lâalgorithme de Dijkstra (du nom de son inventeur) sert principalement Ă trouver le plus court chemin entre une sommet de dĂ©part et un sommet dâarrivĂ© dans un graphe orientĂ© pondĂ©rĂ© par des nombres rĂ©els positifs. Ses applications sont donc diverses et peuvent aller de la simple recherche de chemin dans un graphe Ă des algorithmes de traitement dâimage.
âïž Graphe pondĂ©rĂ©
Définition formelle
Un graphe est un couple comprenant deux ensembles :
- les sommets du graphe (vertices en anglais)
- les arrĂȘtes du graphes (edges en anglais) dont chaque Ă©lĂ©ment est un couple de sommets (), Ă©tant le sommet de dĂ©part et le sommet dâarrivĂ© de lâarĂȘte.
Remarque : Nous prendrons toujours et supposerons Ă partir de maintenant que avec la taille de
Chaque graphe peut ĂȘtre pondĂ©rĂ©, câest Ă dire que lâon associe Ă chaque arrĂȘte une valeur par le biais dâune fonction poids . Dans notre cas lâensemble dâarrivĂ© est restreint Ă pour le bon fonctionnement de lâalgorithme. Pour simplifier, on suppose aussi que les arĂȘtes sont non orientĂ©es, câest Ă dire quâon ne distingue plus de quâon notera . Voici une reprĂ©sentation dâun graphe non orientĂ© Ă 6 sommets :

ConcrĂštement, on peut par exemple imaginer que les sommets du graphes reprĂ©sentent des villes et les arrĂȘtes des routes pondĂ©rĂ©es par leur longueur.
Un peu de vocabulaire
Voisin : et sont voisins si
DegrĂ© : Le degrĂ© dâun sommet est son nombre de voisins
Chemin : On Appelle chemin de longueur le couple ordonnée des sommets tel que pour tout
ConnexitĂ© : Un graphe est dit connexe si pour tout il existe un chemin reliant Ă
Représentations mémoire
On peut stocker les deux ensembles et mais ce nâest pas trĂšs efficace. Dans un premier temps et quitte Ă avoir une fonction dâĂ©tiquetage, on considĂšre que lâensemble est de la forme oĂč est le nombre de sommets du graphe.
ReprĂ©sentation sous la forme de listes dâadjacence
Cette représentation mémoire consiste à stocker les sommets voisins dans une liste de listes par exemple en python :
graphe1_listeadj = [[], [], []]
ReprĂ©sentation sous la forme dâune matrice dâadjacence
On peut aussi utiliser une matrice avec pour tout qui vaut si et ne sont pas voisins et le poids de lâarĂȘte les reliants si ils sont voisins.
đŁ Algorithme de Dijkstra
Une question naturelle se pose alors, Ă©tant donnĂ© un sommet de dĂ©part et un sommet dâarrivĂ© , existe-t-il un chemin de Ă et si oui, quelle est le plus court. Pour le rĂ©soudre, introduisons dâabord une structure de donnĂ©es appelĂ©e file de prioritĂ©.
File de priorité
Une file de prioritĂ© et une structure simple. Elle permet de mettre de cĂŽtĂ© dans un objet appelĂ©e file des Ă©lĂ©ments en leur associant un numĂ©ro de prioritĂ©, et dâextraire par la suite lâĂ©lĂ©ment de plus grande prioritĂ©. On est dotĂ© de 4 opĂ©rations appelĂ©es primitives sur cette structure:
file_vide()
renvoie la file vide
est_vide(f)
renvoie un booléen indiquant si la filef
est vide
enfile(f, x, p)
qui étant donnée une filef
, un élémentx
et une prioritép
, enfile lâĂ©lĂ©mentx
dans la filef
avec la prioritép
(mais ne renvoie rien)
defile(f)
renvoie lâĂ©lĂ©ment de plus haute prioritĂ© dans la filef
et le supprime de cette file
Ă noter que les deux derniĂšre fonctions on des effets de bords. Leur appel modifie f
quand bien mĂȘme enfile
ne renvoie rien.
Algorithme de Dijsktra
Lâalgorithme de Dijkstra est alors le suivant. On commence par une initialisation :
- on initialise un tableau
deja_traite
avec les sommets qui ont dĂ©jĂ Ă©tĂ© traitĂ©s. Ce tableau est un tableau de boolĂ©ens tous initialisĂ©s Ăfalse
. - On initialise un tableau
prec
de taille rempli de qui servira Ă reconstruire le plus court chemin entre et - On initialise un tableau
dist
de taille qui stocke la distance du plus court chemin découvert jusque là entre le sommet de départ et chaque sommet. Ce tableau rempli de sauf pour le sommet de départ dont la valeur image vaut - On initialise une file de priorité vide dans une variable
f
- On enfile dans cette file
f
le sommet de départ avec une priorité
On va alors itĂ©rativement dĂ©filer lâĂ©lĂ©ment de plus grande prioritĂ© de f
, et si il nâa pas encore Ă©tĂ© traitĂ©, mettre Ă jour la distance dist
des ses voisins au sommet de départ ainsi que prec
si nécessaire.
Voici un code python de lâalgorithme :
def dijkstra(liste_adj, starting_point):
# Initialisations
n = len(liste_adj)
f = file_vide()
enfile(f, starting_point, 0)
pred = [-1 for _ in range(n)]
dist = [float("inf") for _ in range(n)]
dist[starting_point] = 0
deja_traite = [False for _ in range(n)]
# Le traitement
while not est_vide(f):
u = defile(f)
if not dejaTraite[u]:
for (w, v) in liste_adj[v]:
if not dejaTraite[v] and dist[u] + w < dist[v]:
dist[v] = dist[u] + w
pred[v] = u
enfile(f, v, dist[u] + w)
dejaTraite[u] = True
return dist, pred
đœ Application Ă la recherche du plus court chemin dans New York
Donnons nous le graphe de New York :
Oui il sâagit bien dâun graphe, juste beaucoup plus grand. Chaque intersection reprĂ©sente un sommet et chaque route une arĂȘte pondĂ©rĂ©e par la distance de celle-ci. On peut alors se donner deux sommets, un de dĂ©part câest le point bleu du graphe, et un dâarrivĂ©, câest le point rouge. Lâalgorithme de Dijkstra et la reconstruction nous permettent alors de trouver le plus court chemin entre le sommet de dĂ©part et dâarrivĂ© :

VoilĂ , on a pu coder un petit GPS !!