• Aucun résultat trouvé

1 Le but du jeu Un

N/A
N/A
Protected

Academic year: 2022

Partager "1 Le but du jeu Un"

Copied!
9
0
0

Texte intégral

(1)

Parcours minimal sur un graphe pondéré : l'algorithme de Dijkstra

1 Le but du jeu

Un graphe pondéré est un ensemble de sommets (que nous numéroterons 1,2,3. . .) qui peuvent être reliés entre eux par des arêtes. A chaque arête est associé un poids. Par exemple :

1 2

3 4

5 6

2

1 5

3 1

4 2

On peut alors envisager des chemins allant d'un sommet à un autre en empruntant des arêtes (par exemple le chemin 2→1→3→5). La somme des poids des arêtes empruntées dénit alors le poids du chemin considéré (dans l'exemple, le poids du chemin est 2 + 5 + 4 = 11 ).

Notre objectif est, étant xés un sommet de départ D et un sommet d'arrivée A, de déterminer un chemin allant de D à A qui a un poids minimal (dans l'exemple ci-dessus, le chemin observé n'est pas minimal puisque le chemin 2→1→5est de poids 5, strictement inférieur à11). Ce genre de problème se rencontre fréquemment dans des cas pratiques. Par exemple les sommets peuvent représenter des stations de métro, les arêtes matérialisent les liaisons directes entre les stations par les lignes de métro et le poids de chaque arête correspond au temps mis par le métro pour aller d'une station à l'autre. La recherche d'un chemin de poids minimal de D à A correspond dans ce cas à la recherche de l'itinéraire le plus rapide pour aller de la station D à la station A. Ou encore si les sommets représentent des villes et les arêtes les autoroutes reliant ces villes avec pour poids les distances entre deux villes reliées, il s'agit d'aller d'une ville à une autre par l'itinéraire le plus court en distance.

Très concrètement, lorsqu'un GPS détermine l'itinéraire pour aller d'un point à un autre, il résout exactement un problème de recherche de parcours minimal sur un graphe dont les sommets sont divers points géographiques (villes, villages, intersections de route etc) et dont les arêtes décrivent les liaisons routières entre ces points. Les poids des arêtes sont les distances, ou les temps, ou encore les coûts de ces liaisons, selon qu'on souhaite trouver l'itinéraire le plus court, le plus rapide, ou le plus économique.

On peut également envisager que les arêtes ne se parcourent que dans un sens (le graphe est alors dit orienté). Par exemple :

(2)

1 2

3 4

5 6

2

1 5

3 1

4 2

Avant de présenter l'algorithme que nous allons mettre en oeuvre pour réaliser notre objectif, pensons un peu la structure de données qui va nous permettre de rendre compte de la géométrie du graphe sur lequel notre programme va travailler. Une remarque importante s'impose d'emblée : la position géométrique des sommets dans le plan, ainsi que le positionnement des arêtes ne sont d'aucune importance pour ce qui nous intéresse. Si nous avions, dans l'exemple du début, représenté le graphe de la façon suivante :

1 2

3 4

5 6

2 1

5

3 1

4 2

rien n'aurait changé pour le problème qui nous occupe !1 La seule chose qui importe est le nombre de sommets et les poids des arêtes qui les relient.

La première idée qui vient à l'esprit pour mettre en mémoire un graphe à nsommets est d'utiliser un tableauAà deux dimensions (ou un tableau de tableaux, pour une structure de base avec Python) tel que A[i][j] est le poids de l'arête qui relie le sommet i au sommet j (et A[i][j] vaudrait 0 si les deux sommetsietj ne sont pas reliés). Reprenant l'exemple du début, le tableau en question serait :

A=

0 2 5 0 3 0 2 0 0 1 0 0 5 0 0 1 4 2 0 1 1 0 0 0 3 0 4 0 0 0 0 0 2 0 0 0

Ce tableau est appelé matrice d'adjacence du graphe.

1. Je vous suggère fortement de prendre le temps de contempler les deux graphes pour vraiment vous convaincre que ce sont les mêmes...

(3)

Cette représentation pose quelques problèmes. Tout d'abord quelques problèmes mineurs : on pourrait avoir des arêtes de poids nuls, et alors on ne pourrait pas faire la diérence entre deux sommets reliés par une arête de poids nul et deux sommets non reliés. Je vous vois venir, vous allez me dire qu'il sut d'attribuer une valeur négative, −1par exemple, pour représenter l'absence d'arête. J'objecterais dans ce cas qu'on pourrait très bien avoir un graphe avec des poids négatifs et que du coup votre astuce tombe à l'eau. OK, dans le cadre du programme ociel de BCPST on ne s'intéresse qu'à des graphes de poids positifs (ce qui correspond à la grande majorité des cas où ce genre de problème se pose, suivez mon regard vers quelques lignes au-dessus avec ces histoires de métros, d'autoroutes et de GPS...).

Un autre inconvénient, plus fondamental celui-là, est la place occupée en mémoire par la structure de données adoptée. Pour un graphe àn sommets, le tableau envisagé est alors de n2 cases, et risque de contenir beaucoup de zéros qui ne sont pas vraiment utiles. En eet, dans le genre de problèmes pratiques qui débouchent sur la recherche de parcours minimaux (métro, routes...), chaque sommet n'est en général relié qu'à quelques sommets voisins. Une structure de données plus économe est la suivante, appelée liste chaînée des successeurs : on utilise encore un tableau de tableaux, mais cette fois A[i] est un tableau de la forme [s1, p1, s2, p2, . . .] où s1, s2, . . . sont les numéros des sommets accessibles depuis le sommet i, et p1, p2, . . . sont les poids des arêtes correspondantes. Dans notre exemple, le tableau obtenu pourrrait donc être :

A[1]= [2,2,3,5,5,3]

A[2]= [1,2,4,1]

A[3]= [1,5,5,4,6,2,4,1]

A[4]= [2,1,3,1]

A[5]= [1,3,3,4]

A[6]= [3,2]

On remarque que pour une ligneidonnée, il peut y avoir plusieurs ordres possibles : rien n'oblige à classer les sommets adjacents à i par ordre croissant.

On observe de plus que cette structure permet de manipuler des arêtes de poids nuls et même négatifs, et aussi d'avoir plusieurs arêtes qui relient les mêmes sommets (même si l'intéret d'une telle possibilité ne saute pas aux yeux, je vous l'accorde...).

Petit exercice en passant : reprendre le graphe orienté qui a été vu un peu plus haut et écrire les deux représentations associées.

2 L'algorithme de Dijkstra

On se place dans le cas où les poids des arêtes sont strictement positifs.

Le principe de l'algorithme, en très gros, est de partir du sommet de départ D, de découvrir pas à pas des chemins menant aux autres sommets du graphe, et d'identier parmi ces chemins ceux qui sont minimaux. Lorsque A seraparmi les sommets pour lesquels on a trouvé un chemin minimal, on aura résolu notre problème.

Voyons sur un exemple comment l'algorithme fonctionne. On souhaite trouver le chemin de poids minimal allant du sommet 1 au sommet 7dans le graphe suivant :

1 2 5

4 3 7

6

8

9

1 1

7

1

1

3

2

3 1

1

2 4

(4)

Puisqu'on part du sommet 1, il y a au moins un sommet dont on est sûr qu'on connait le chemin de poids minimal pour le rallier : le sommet 1! Ben oui, puisqu'on part de 1, on peut arriver en 1 par un chemin de poids 0 (aucune arête empruntée). D'accord, rien de fracassant dans ce constat, mais pour nous donner du c÷ur à l'ouvrage nous allons quand même visualiser notre découverte sur le graphe : le sommet 1sera colorié en rouge pour signaler qu'on a trouvé le chemin optimal menant à lui, et on va èrement marquer le poids de ce chemin (en l'occurence,0) :

10, 2 5

4 3 7

6

8

9

1 1

7

1

1

3

2

3 1

1

2 4

Regardons alors les sommets adjacents au sommet1qui vient d'être colorié. Puisqu'on sait atteindre le sommet1par un chemin de poids0, les arêtes reliant le sommet1aux sommets2et4 permettent d'atteindre ces deux sommets par des chemins de poids respectifs 1 et 7. Nous avons donc trouvé des chemins qui rallient les sommets 2 et 4, mais rien ne nous dit que ces chemins sont minimaux (d'ailleurs on voit bien que ce n'est pas le cas pour le sommet4puisque le chemin1→2→5→3→4 permet d'atteindre le sommet 4avec un poids de 4seulement). Prudence, donc... Nous allons baliser notre découverte en bleu et marquer les sommets2 et4avec les poids respectifs1et 7, et également signaler que les chemins correspondants sont des prolongements d'une arête de chemins menants au sommet 1. Cette dernière précaution prépare le moment où nous aurons trouvé le poids du chemin optimal menant au sommet convoité7et qu'il nous faudra reconstituer le chemin en question (principe du Petit Poucet...) :

10, 21,1 5

47,1 3 7

6

8

9

1 1

7

1

1

3

2

3 1

1

2 4

C'est ici que la géniale et pourtant simplissime idée de Dijkstra va apparaitre sous vos yeux émer- veillés ! A priori on sait rallier les sommets coloriés en bleu mais on ne sait pas si les chemins corres- pondants sont optimaux. Cependant, il y en a un pour lequel le chemin est forcément optimal, c'est celui dont le poids marqué est le plus petit (en l'occurence le sommet2). En eet, si on considère un autre chemin qui va du sommet1au sommet 2, ce chemin passera par le sommet4et sera forcément plus lourd que le chemin 1 →2. On peut donc colorier en rouge le sommet 2 pour signaler qu'on a trouvé le chemin optimal menant à lui :

(5)

10, 21,1 5

47,1 3 7

6

8

9

1 1

7

1

1

3

2

3 1

1

2 4

On est tout content d'avoir trouvé le chemin optimal menant au sommet 2, et on va pousser notre avantage en observant les sommets adjacents au sommet 2: le sommet 1a déjà été colorié en rouge, on ne peut rien faire de plus pour lui. En revanche le sommet 5, qui n'avait pas encore été marqué, est à présent accessible : pour l'atteindre il sut d'aller au sommet 2 (chemin de poids 1) puis de franchir l'arête2→5(qui est de poids1). On sait donc aller du sommet de départ jusqu'au sommet 5 par un chemin de poids2, et en passant juste avant par le sommet 2. Colorions donc le sommet 5 en bleu, et marquons les informations correspondantes :

10, 21,1 52,2

47,1 3 7

6

8

9

1 1

7

1

1

3

2

3 1

1

2 4

Parmi les sommets marqués en bleu, c'est le sommet 5 qui a le plus petit poids marqué. Donc ce poids est optimal (vous avez bien rigolé quand je vous ai dit que l'idée de Dijkstra était géniale, tant le résultat vous semblait évident la première fois. Peut-être que cette fois vous commencez à entrevoir la force du procédé...) et on peut colorier en rouge le sommet 5, et dans la foulée marquer les sommets qui lui sont adjacents :

10, 21,1 52,2

47,1 33,5 7

64,5

8

9

1 1

7

1

1

3

2

3 1

1

2 4

Le sommet 3 est le suivant à passer au rouge. Observant les sommets qui lui sont adjacents, on constate qu'on va pouvoir marquer le sommet 7, mais également améliorer la marque du sommet 4. En eet, en passant par le sommet 3 on rallie le sommet 4 avec un poids de 3 + 1 = 4, ce qui est meilleur que le poids 7 qui était jusqu'à présent attribué au sommet 4. On l'avait déjà évoqué, les marques des sommets bleus ne sont pas forcément optimales. Voici un exemple d'amélioration de marque.

(6)

10, 21,1 52,2

44,3 33,5 76,3

64,5

8

9

1 1

7

1

1

3

2

3 1

1

2 4

On a atteint le sommet 7 tant convoité ! Mais ne nous réjouissons pas trop vite. On sait que les marques de sommets en bleu ne sont pas forcément optimales, il faut travailler encore en peu.

Cas de gure intéressant : parmi les sommets bleus, il y en a deux qui sont marqués du plus petit poids : les sommets 4et 6. Dans ce cas on passe au rouge l'un ou l'autre au choix (il est à peu près clair que celui qu'on va délaisser verra arriver son tour très prochainement...). Passons donc le sommet4 au rouge :

10, 21,1 52,2

44,3 33,5 76,3

64,5

8

9

1 1

7

1

1

3

2

3 1

1

2 4

Le sommet4ne permet pas de marquer de nouveau sommet ni d'améliorer de marque déjà existante.

On passe au rouge le sommet 6 et dans la foulée on marque les sommets 8 et 9 mais on n'améliore pas la marque du sommet 7(4 + 3 = 7>6) :

10, 21,1 52,2

44,3 33,5 76,3

64,5

85,6

98,6

1 1

7

1

1

3

2

3 1

1

2 4

C'est à présent le sommet 8 qui passe au rouge, entrainant l'amélioration de la marque du sommet 9 :

(7)

10, 21,1 52,2

44,3 33,5 76,3

64,5

85,6

97,8

1 1

7

1

1

3

2

3 1

1

2 4

Et enn le sommet7 passe au rouge, indiquant qu'on a trouvé le chemin de poids minimal allant du sommet de départ1 au sommet d'arrivée 7 :

10, 21,1 52,2

44,3 33,5 76,3

64,5

85,6

97,8

1 1

7

1

1

3

2

3 1

1

2 4

Résultat des courses : le chemin de poids minimal allant de 1à 7est de poids 6et pour le trouver il sut de remonter à partir du sommet 7 jusqu'au sommet 1 grâce aux secondes marques de chaque sommet impliqué :7est marqué6,3, donc juste avant7il y a le sommet3.3étant lui-même marqué 3,5, le sommet 5 est juste avant, puis le 2, et enn le 1. Remettant ça dans l'ordre, on brandit èrement le résultat : 1→2→5→3→7.

Récapitulons le fonctionnement de l'algorithme :

Le sommet de départ est marqué avec une distance 0 et colorié en rouge. Les sommets qui lui sont adjacents sont marqués (poids et numéro du sommet de départ) et coloriés en bleu.

Tant que le sommet d'arrivé n'est pas colorié en rouge, on eectue la manipulation suivante : le sommet bleu avec la plus petite marque de poids passe au rouge, et les sommets non coloriés qui lui sont adjacents passent au bleu et sont marqués, tandis que les sommets qui lui sont adjacents mais qui étaient déjà coloriés en bleu voient leurs marques améliorées si possible.

Lorsque le sommet d'arrivé passe au rouge, on s'arête et on remonte le chemin optimal grâce aux secondes marques.

Quelques remarques :

Puisqu'on s'arrête dès que le sommet d'arrivée est colorié en rouge, il se peut très bien que certains sommets ne soient pas coloriés du tout lorsqu'on s'arrête.

A chaque étape de l'algorithme, les sommets en rouge sont les sommets dont on connait le chemin de poids minimal pour les atteindre à partir du sommet de départ. Les sommets en bleu sont ceux pour lesquels on a trouvé un chemin mais dont on ne sait pas s'il est minimal.

Les sommets non coloriés n'ont pas encore été atteints.

Les sommets en beu sont en quelque sorte une frontière mouvante entre les sommets en rouge et les sommets non coloriés. Chaque sommet non colorié est voué à entrer dans la frontière bleue, d'y attendre d'être celui qui a le poids le plus petit, et enn d'entrer dans le groupe des sommets en rouge. Ainsi, à partir du sommet de départ, le coloriage rouge se propage. On peut remarquer que les sommets deviennent rouge dans l'ordre des poids de leur chemin minimal depuis le sommet de départ (sur l'exemple, c'est d'abord le sommet 2qui a été colorié, car on

(8)

l'atteint en un chemin de poids 1, puis le sommet 5avec un poids de 2, puis le sommet 3 avec son poids de 3, puis les sommets 4et 6avec leur poids de 4etc).

Si le graphe est mal fait, il se peut qu'il ne soit pas possible d'aller de DàA. Par exemple avec le graphe orienté présenté page 2, il n'est pas possible d'aller du sommet 2au sommet6. Dans ce cas il arrive un moment où il n'y a plus de sommets bleus, et l'algorithme est en panne (il serait bon, lorsque vous passerez à la programmation, que vous prévoyiez ce cas de gure...) Malgré toute votre bonne volonté et mon éloquence, il est probable que vous ne maîtrisiez pas encore l'algorithme. Il serait peu judicieux de vous lancer dans la programmation sans pratiquer un peu l'algorithme à la main . Je vous suggère donc de reprendre le graphe sur lequel nous venons de travailler, et de dérouler vous-même l'algorithme de Dijkstra pour déterminer le chemin de poids minimal allant du sommet 9 au sommet 4.

Ensuite, déterminer le chemin de poids minimal pour aller du sommet 1 au sommet 2 dans le graphe orienté suivant :

1 2 3

4 5 6

7 8 9

8 1

1 3 1

3 2

1 1 1

1 1

3 Assez de baratin, place à la programmation !

Si vous avez bien compris ce qui précède, vous êtes prêts à vous lancer dans la programmation.

Exercice 1

Ecrire un programme qui, à partir d'un graphe donné (le choix de la structure de données pour représenter le graphe vous est laissé), d'un sommet de départDet d'un sommet d'arrivéeA, détermine un chemin minimal allant de D à A.

Exercice 2

L'algorithme de Dijkstra marche-t-il encore si on prend un graphe avec des poids négatifs ?

Exercice 3

Il se peut qu'il y ait plusieurs chemins minimaux allant de D à A. Par exemple, dans le cas qui a été développé dans la partie précédente, on a trouvé le chemin 1 → 2 → 5 → 3 → 7 qui est de poids 6, mais il y a aussi le chemin 1→2→5→6→ 8→7 qui est de même poids. On peut dans

(9)

ce cas décider de déterminer, parmi tous les chemins minimaux, un chemin qui présente un nombre minimal d'arêtes (dans l'exemple, on produira donc le chemin 1 → 2 → 5 → 3 →7 qui présente 4 arêtes alors que son concurrent en présente 5). Modier votre programme pour qu'il détermine un chemin minimal comportant le minimum d'arêtes possible (je ne veux pas vous mettre la pression, mais je considère cette question comme le test à l'acide pour déterminer si quelqu'un a réellement bien compris l'algorithme de Dijkstra...)2.

2. En fait si, je veux vous mettre la pression...

Références

Documents relatifs

2 Sans utiliser la règle, trouve les segments de

ajouté par le cerveau) (Les rectangles rouges et gris sont de même couleur). Segmentation

[r]

[r]

Colle dans chaque garage une voiture de la couleur demandée. JAUNE ROUGE BLEU

ROUGE ROSE BLEU VERT BLANC NOIR.. rouge rose bleu vert blanc

Consigne : Relie les noms des couleurs... Prendre des indices de reconnaissance

[r]