27 - Graphe : Largeur en Python
Logiciel nécessaire pour l'activité : -
Prérequis :
- Algo : Parcours en largeur d'un Graphe
Evaluation ✎ : 01-02-03-08-09-10-11-12-13-14-15
Documents de cours : open document ou pdf
1 - [rappel] Algorithme de parcours en largeur
Algorithme du parcours en largeur
ENTREES
- Un graphe noté g
- Un sommet qui servira de sommet origine, noté s appartenant au graphe g
SORTIE
Aucune ici mais on peut facilement modifier l'algorithme pour qu'il renvoie par exemple l'Arbre de parcours.
ALGORITHME PARCOURS EN LARGEUR
on initialise tous les sommets
POUR chaque sommet u appartenant au graphe g
u.couleur ← BLANC
u.distance ← INFINI
u.parent ← VIDE
Fin Pour
on initialise le sommet origine
s.couleur ← GRIS
s.distance ← 0
s.parent ← VIDE
on crée la file et on y place le sommet origine
a_traiter ← nouvelleFileVide()
enfiler(a_traiter, s)
on sort et active un sommet à la fois de la file
TANT QUE NON estVide(a_traiter)
u ← defiler(a_traiter)
POUR chaque sommet v appartenant à la liste d'adjacence du sommet u
SI v.couleur est BLANC
si on arrive ici, c'est que le sommet n'a pas encore été découvert
v.couleur ← GRIS
v.distance ← u.distance + 1
v.parent ← u
enfiler(a_traiter, v)
Fin Si
u.couleur ← NOIR
Fin Pour
Fin Tant Que
Renvoyer VIDE (∅)
Les informations liées au parcours sont stockées directement dans les sommets.
Aucune importance tant qu'il s'agit de réfléchir à la façon de gérer les choses. C'est plus ennuyeux lorsqu'on passe à l'implémentation réelle : modifier le graphe des routes à chaque fois qu'on lance le GPS n'est pas une bonne idée.
Dans les implémentations Python proposées, nous allons donc séparer les deux types de données :
- D'un côté le graphe avec les sommets et les arêtes
- De l'autre les informations sur le parcours en largeur.
2 - Implémentation du graphe
Il existe deux grandes familles d'implémentation des arêtes d'un graphe :
- Par une matrice d'adjacence
- Par des listes d'adjacence
Nous n'avons pas envie de fournir une fonction de parcours par implémentation...
Possibilité 1: matrice d'adjacence
Matrice d'adjacence :
[[0, 1, 1, 0, 0],
[1, 0, 0, 1, 0],
[1, 0, 0, 1, 0],
[0, 1, 1, 0, 1],
[0, 0, 0, 1, 0]
]
Possibilité 2 : l'ensemble des arêtes (dans un tuple car set n'est pas au programme)
Ensemble S des arêtes :
((0,1),
(0,2),
(1,3),
(2,3),
(3,4)
)
Possibilité 3 : listes d'adjacence dans un tableau
Listes d'adjacence stockées dans un tableau :
[[1, 2],
[0, 3],
[0, 3],
[1, 2, 4],
[3]]
Possibilité 4 : listes d'adjacence dans un dictionnaire
Listes d'adjacence stockées dans un dictionnaire :
{0: [1, 2], 1: [0, 3], 2: [0, 3], 3: [1, 2, 4], 4: [3]}
Possibilité ... : ...
Bref, il faut choisir un des formats en tant que format reconnu par notre fonction de parcours et fournir des fonctions de conversion de façon à toujours pouvoir y revenir.
Nous décidons de faire travailler nos fonctions de parcours sur des listes d'adjacences de la possibilité 4, qui ressemblent à ceci :
Listes d'adjacence stockées dans un dictionnaire :
{0: [1, 2], 1: [0, 3], 2: [0, 3], 3: [1, 2, 4], 4: [3]}
Dans le but de simplifier encore le problème, on considérera ici que les sommets ne contiennent aucune information à part leur numéro.
La liste d'adjacence caractérise donc le graphe en totalité.
>>> graphe = {0: [1, 2], 1: [0, 3], 2: [0, 3], 3: [1, 2, 4], 4: [3]}
>>> s = list(graphe.keys())
>>> s
[0, 1, 2, 3, 4]
>>> temporaire = []
>>> for s, lst_adj in graphe.items():
for s2 in lst_adj:
if not (s2, s) in temporaire:
temporaire.append( (s, s2) )
>>> a = tuple(temporaire)
>>> a
((0, 1), (0, 2), (1, 3), (2, 3), (3, 4))
>>> g = (s, a)
On voit donc qu'on peut passer du graphe "dictionnaire" au graphe version "mathématique".
Voici comment passer du graphe "mathématique" au graphe "dictionnaire".
01° Donner le dictionnaire dont les clés sont les étiquettes des sommets et les valeurs sont les listes d'adjacence de ce sommet.
1
2
3 |
|
...CORRECTION...
{0: [1, 2],
1: [0, 3],
2: [0, 3],
3: [1, 2, 4],
4: [3]
}
02° Lancer le programme puis expliquer comment fonctionne cette fonction en fournissant un commentaire sur les lignes de la fonction.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 |
|
...CORRECTION...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 |
|
3 - Implémentation de l'algorithme de parcours en largeur
03° Considérons que le graphe g est caractérisé par ceci :
>>> graphe = {0: [1, 2], 1: [0, 3], 2: [0, 3], 3: [1, 2, 4], 4: [3]}
Questions
- Quel code Python permet de récupérer une à une tous les sommets depuis le dictionnaire g ?
- Quel code Python permet de récupérer une à une toutes les listes d'adjacence des les sommets depuis le dictionnaire g ?
- Quel code Python permet de récupérer un par un à la fois un sommet et sa liste d'adjacence depuis le dictionnaire g ?
...CORRECTION...
for sommet in g.keys():
for liste in g.values():
for sommet, liste in g.items():
04° Pour réaliser le parcours en largeur, va-t-on avoir besoin d'un File ou d'une Pile ?
...CORRECTION...
Une File.
05° Lire le début de la documentation de façon à vous souvenir comment utiliser facilement une File en Python.
06° Compléter la fonction de parcours de façon à la faire fonctionner correctement :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 |
|
...CORRECTION...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 |
|
07° Expliquer comment fonctionne la fonction donner_chemin() qui permet de récupérer le chemin le plus court entre deux sommets.
4 - Plus simple
On peut en réalité se passer de la gestion des couleurs.
Il suffit de rajouter un tableau lié au parcours : dès qu'on découvre un sommet, on le place dans ce tableau qu'on pourrait nommé decouverts qui liste les sommets découverts.
Un sommet est BLANC s'il n'est pas dans decouverts.
Un sommet est GRIS ou NOIR s'il est dans decouverts.
Comment distinguer GRIS et NOIR ? A l'aide de la File des sommets a_traiter.
- Un sommet est BLANC s'il n'est pas dans decouverts.
- Un sommet est GRIS s'il est dans decouverts et a_traiter.
- Un sommet est NOIR s'il est dans decouverts mais plus dans a_traiter.
08° Compléter la fonction de parcours de façon à la faire fonctionner correctement sans gestion directe de la COULEUR :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 |
|
...CORRECTION...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 |
|
09° Réaliser cette troisième version qui ne sert à rien mais qui affiche simplement le nom des sommets découverts au fur et à mesure de l'exploration. Il s'agit d'une version simplifiée de la fonction précédente. Tentez de n'utiliser que la version algorithmique au pire, sans regarder directement le code Python de la question précédente.
Inutile donc de créer un dictionnaire stockant les informations obtenues lors du parcours. C'est une fonction qui ne sert à rien.
1
2
3
4
5
6
7
8 |
|
...CORRECTION...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 |
|
10° Modifier votre graphe de façon à l'agrandir un peu. Vérifier que vos fonctions de parcours en version 1 et 2 fonctionnent encore.
Enfin, rajouter quelques sommets de façon à rendre le graphe non-connexe : il doit être composé de deux sous-graphes qui ne se peuvent pas communiquer entre eux. Question : le parcours en largeur partant d'un côté permet-il d'apprendre des choses sur l'autre côté ?
5 - FAQ
Et on fait comment sur un graphe pondéré ?
On applique l'algorithme de Dijkstra.
Activité publiée le 09 04 2024
Dernière modification : 09 04 2024
Auteur : ows. h.