Niveau : Terminale générale, enseignement de spécialité NSI
On a des sommets et des arrêtes ou arcs si la liaison n'est pas bidirectionnelle. Les sommets de notre graphe se sont les villes, les arrêtes représentent le poids : ici, la distance séparant deux villes entre elles.
Pour aller à Mulhouse à Nancy, quel sera le chemin le plus court :
Les successeurs de Mulhouse sont : Strasbourg, Nancy, Epinal et Vesoul
Les prédécesseurs de Vesoul sont : Nancy, Epinal et Mulhouse qui
sont également ses successeurs.
Pour trouver le chemin le plus court dans ce graphe il existe
l'algorithme de Dijkstra ou Prim traité à la fin du chapitre.
Les graphes sont employés par exemple par les GPS pour trouver le chemin le plus court entre deux villes
Définitions
Remarques.
Outre la représentation sagittale, il existe plusieurs moyens de représenter un graphe :
Définitions
S'il existe un arc (i; j) dans un graphe orienté, on dit que j est un successeur de i dans ce graphe.
Remarque.
On peut représenter un graphe par un tableau listant les successeurs de chaque sommet.
Exemple.
Sommet | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
Successeurs |
Définitions
S'il existe un arc (i; j) dans un graphe orienté, on dit que j est un prédécesseur de i dans ce graphe.
Remarque.
On peut représenter un graphe par un tableau listant les prédécesseurs de chaque sommet.
Exemple.
Sommet | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
Prédécesseurs |
Définitions
Exemple :
1 2 3 4 5
Définitions
S'il existe un arc (i; j) dans un graphe non orienté, on dit que i et j sont voisins.
Remarque.
La notion de voisin est l'équivalent pour les graphes non orientés des notions de prédécesseur et de successeur. On peut représenter un graphe par un tableau listant les voisins de chaque sommet.
Exemple.
Sommet | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
Voisins |
Exemple :
cliquez sur la matrice pour la modifier
On considère notre réseau routier :
Etablir le tableau des villes voisines
Ville | Epinal | Mulhouse | Nancy | Strasbourg | Vesoul |
---|---|---|---|---|---|
Voisins |
Donner la matrice d'ajacence du graphe
On considère notre réseau routier mais avec certaines routes en sens unique :
Etablir le tableau des villes voisines
Ville | Epinal | Mulhouse | Nancy | Strasbourg | Vesoul |
---|---|---|---|---|---|
Voisins |
Donner la matrice d'ajacence du graphe
On considère le graphe orienté donné par les tableau des successeurs ci-dessous :
Sommet | A | B | C | D | E |
---|---|---|---|---|---|
Successeurs | B | A, C, D | B | A |
Donner la matrice d'adjacence de ce graphe.
Tracer une représentation sagittale de ce graphe. https://app.diagrams.net/
0n considère la matrice ci-dessous :
Cette matrice peut-elle correspondre à un graphe non orienté ?
Tracer une représentation sagittale du graphe associé à cette matrice (on appellera A, B et C ses sommets).
Le but de cet exercice est de construire des représentations de graphes en Python. Dans cet exercice les sommets seront représentés par des entiers de 0 à n-1 où n est 'ordre du graphe. Pour faciliter les tests, une fonction d'affichage est fournie dans le affichier à compléter.
networkx
et valider.networkx
et installer-le.networkx
.matplotlib
de la même manière.Ce fichier contient :
afficher_grapheO
, qui permet d'afficher des graphes orientés, et plus
précisément les objets des classes GrapheO
ci-dessous, à conditions que
toutes les méthodes aient été écrites,GrapheNO
ci-dessous, à conditions que toutes les méthodes aient été écrites.1) Compléter le fichier avec une classe GrapheO
permettant de représenter des graphes orientés
grâce à leur matrice d'adjacence et décrite ci-dessous :
mat_adj
de type list[list[int]]
__init__(self, n) -> void
: initialise une matrice d'ajacence d'un graphe d'ordre n
sans aucun arcordre(self) -> int
: retourne l'ordre du grapheajouter_arc(self,i,j) -> void
: ajoute un arc du sommet i
au sommet j
existe_arc(self, i, j) -> bool
: retourne True
si il existe un arc du sommet i
au sommet j
liste_successeurs(self, i) -> list[int]
: retourne la liste des successeurs du
sommet i
2) Compléter le fichier avec une classe GrapheNO permettant de représenter des graphes non orientés grâce à leur matrice d'adjacence et décrite ci-dessous :
mat_adj de type list[list[int]]
__init__(self, n) -> void
: initialise une matrice d'ajacence d'un graphe d'ordre n
sans aucun arcordre(self) -> int
: retourne l'ordre du grapheajouter_arete(self,i,j) -> void
: ajoute une arête entre les sommets i
et j
existe_arete(self, i, j) -> bool
: retourne True si il existe une arête entre les sommets i
et j
liste_voisins(self, i) -> list[int]
: retourne la liste des voisins du sommet i
A partir de notre graphe des villes on peut constituer la file des successeurs FS :
Commençons par Mulhouse comme sommet en se référant à la matrice d'adjacence, Mulhouse a pour successeurs Strasbourg, Vesoul, Epinal et Nancy et c'est tout (-).
On enfile les autres lignes de ma matrice d'adjacence et obtient la file FS suivante :
Il est conseillé de construire une liste APS contenant les Adresses des Premiers Successeurs.
Définitions
Exemple :
Définition
La distance entre deux sommets d'un graphe est la longueur du plus court chemin reliant ces deux sommets, si un tel chemin existe. Si un tel chemin n'existe pas, la distance entre les deux sommets n'est pas définie.
Exemple :
Définitions
On considère un graphe, dans lequel on se fixe un sommet de départ. Dans le parcours en largeur du graphe, on visite :
Remarque.
Le parcours en largeur permet entre autres de déterminer les chemins les plus courts entre deux sommets. Il permet de ce fait de calculer la distance entre deux sommets.
Exemple :
Remarque.
Pour éviter de passer deux fois par le même sommet, il est nécessaire, lorsqu'on parcourt un graphe, de garder une trace des sommets déjà visités.
Exemple
Cette fois, on construit la matrice qui permet de donner le nombre
d'arrêtes
minimales séparant deux sommets
Partons de Strasbourg : On marque le sommet pour indiquer qu'il a
été visité puis on cherche les voisins. On marque les voisins et
progressivement on enlève les arrêtes des sommets déjà visités. Quand
tous les sommets sont marqués on obtient un arbre. Si On recommence en
partant d'un autre sommet (ville) on aura un arbre différent.
Le joueur (j) se trouve sur le sommet n°9 et la sortie (s) est au
n°32
Le graphe non orienté du labyrinthe est le suivant :
Matrice d'adjacence partielle du labyrinthe :
9
|
10 | 11 | 12 | 13 | 18 | 20 | 21 | 25 | 26 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | |
9 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
10 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
11 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
12 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
13 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
18 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
20 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
21 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
25 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
26 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
29 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
32 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
33 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
34 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
35 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
36 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
37 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
Télécharger puis décompresser le fichier Labyrinthe.zip. Ouvrir le fichier Labyrinthe_EL.py et ajouter y les fonctions permettant de trouver le chemin le plus court vers la sortie, en appliquant la théorie les graphes.
sommets
: la liste des sommets,Algorithme :
Instancier un objet de classe GrapheNO ayant comme grandeur le nombre de sommets Parourir les tous les sommets si le sommet[i]+1 est dans la liste des sommets alors ajouter une arrête entre sommets.index(sommets[i])et sommets.index(sommets[i]+1) si le sommets[i]+larg_laby est dans la liste des sommets ajouter une arrête entre sommets.index(sommets[i])et sommets.index(sommets[i]+larg_laby) Retourner la matrice d'ajacence et l'objet GrapheNO
Une façon de programmer un parcours en largeur est d'utiliser :
une liste deja_visites contenant tous les sommets déjà visités, une file a_visiter contenant les prochains sommets à visiter, une liste parcours, Au début, deja_visites et parcours sont vides, a_visiter contient uniquement le sommet de départ. Répèter jusqu'à ne plus avoir de sommet à visiter : défiler un sommet (notons le s), si s n'a pas déjà été visité : ajouter s dans la liste deja_visites, ajouter s dans la liste du parcours, enfiler tous les voisins de s dans la file a_visiter. retourner la liste du parcours largeur
parcours_largeur
qui prend en paramètre le graphe non orienté graphe
et l'indice du sommet de la position du personnage depart
,Fonction matrice_adjacence
paramètres :
la liste des sommets
Résultat :
Liste contenant la matrice d'adjacence
DEBUT
matrice ← []
ligne ← []
Pour chaque sommet dans la liste des sommets
Pour chaque som dans la liste des sommets
si le sommet = som-1 ou sommet = som+1 ou sommet = som+larg_laby ou sommet = som-larg_laby
empiler 1 dans la liste ligne
sinon
empiler 0 dans la liste ligne
empiler la ligne à la matrice
ligne ← []
affiche_matrice(sommets,matrice) # appel de la fonction qui affiche la matrice pour vérifier le résultat
retourne matrice
Fin
Algorithme
Fonction File_successeurs
paramètres :
matrice : liste matrice d'adjacence
sommets : liste des sommets
Résultats :
FS : la liste contenant la file des successeurs
APS : la liste des adresses des premiers successeurs
DEBUT
FS ← []
APS ← []
pour i variant de 0 à la hauteur de la matrice
empiler la longueur de FS dans la liste APS
pour j variant de 0 à la largeur de la matrice
si matrice[i][j]=1
empiler sommets[j] à la liste FS
empiler 0 à la liste FS
empiler la longueur de FS dans la liste APS
retourne la liste des successeurs et les adresses des 1er successeurs
Fin
On désire stocker la liste des sommets selon leur distance par rapport au nœud :
Ex : pour le nœud 10, on souhaite générer une liste de l'arbre
suivant : [[10],[9,18,11],[12,26],[13,20,25,34],[14,...],...]
Fonction parcours_largeur
paramètres :
noeud : représente la case du joueur
Résultat:
arbre : liste contenant les distances du noeud à chaque sommet
Debut:
arbre ← [[noeud]]
file ← [0,noeud]
visites ← [] # liste des sommets déjà visités
Tant que la longueur de la file contient plus d'un élément
rang ← [] # liste qui permet de stocker les successeurs du sommet courant
Tant que le premier élément de la file est >0: # la valeur 0 permet d'indiquer la fin de la file courante
sommet ← défiler la file # sommet = file.pop()
Empiler le sommet à la liste visites
indice ← sommets.index(sommet) # recherche de la position du sommet courant dans la liste des sommets
pour i variant de APS[indice] à APS[indice+1]-1: # recherche des voisins du sommet dans FS en excluant 0
si FS[i] n'est pas dans la liste visites
Enfiler FS[i] dans rang # rang.insert(0,FS[i])
Enfiler FS[i] dans file
Empiler FS[i] dans visite
Défiler la file (qui doit être 0) # condition d'arrêt du tant que
Empiler à l'arbre la liste rang
Enfiler la valeur 0 dans la file
retourne la liste arbre
Fin
Principe : on part de la sortie pour revenir vers la position joueur
Exemple de la sortie au sommet 32 :
Tant que la sortie n'a pas atteint la position du joueur :
Le sommet précédent devient la nouvelle sortie et le cycle recommence.
Cas du sommet 33 :
La liste du parcours lageur est réduite à [9,10,11,18,12,26,13,20,25,34,14,21]
Les voisins de 33 sont [25,32,34,41]
On a dans cette situation deux voisins qui sont également dans la liste du parcours : 25 et 34. Peut importe du voisin qu'on choisisa, puisque la longueur du chemin sera identique.
Chercher la colonne de la sortie dans la matrice d'ajacence et trouver le prédécesseur dans la ligne correspondante.
Exemple le prédécesseur de 32 est 33 :
Algorithme :
ch est une liste vide et contiendra les indices des sommets Tant que la sortie est différente de position alors Réduire la liste parcours à l'indexe de la sortie mémoriser dans une variables la liste des voisins de la sortie Parcourrir la liste des voisins si un voisin se trouve dans la liste des voisins memoriser ce voisin ajouter ce voisin au Chemin remplacer la sortie par le voisin retourner la liste des indexe des sommets
Ecrire en Python la fonction chemin
qui prend en paramètres le graphe
, le parcours
largeur : la liste des indexes, sortie
: l'indice de la sortie dans les sommets, pos
: l'indice de la position du joueur dans la liste des sommets.
Colez votre code python ci-dessous :
Les algorithmes de recherche de chemin, travaillent sur des graphes pondérés (par exemple pour rechercher la route entre un point de départ et un point d'arrivée dans un logiciel de cartographie). Ces algorithmes recherchent aussi souvent les chemins les plus courts. On peut citer l'algorithme de Dijkstra ou encore l'algorithme de Bellman-Ford qui recherchent le chemin le plus court entre un noeud de départ et un noeud d'arrivée dans un graphe pondéré.
La vidéo ci-dessous explique le principe de fonctionnement de l'algorithme de Dijkstra.
La vidéo ci-dessous explique le principe de fonctionnement de l'algorithme de Prim.
Fond : Texte : Tables : Thème du langage:
Contenu
sous licence CC BY-NC-SA 3.0
Pascal Hassenforder - Amandine Schreck 13/10/2020
MAJ le 16/04/2024