PyRat : cours 2 L’équipe PyRat Rappel de l’objectif page 2/17 L’équipe PyRat PyRat : cours 2 Jalons Séance 1 ... Séance 2 ... Séance 3 Ramasser un unique morceau de fromage dans le labyrinthe Séance 4 ... Séance 5 ... Séance 6 Ramasser plusieurs morceaux de fromage dans le labyrinthe Séance 7 Gagner contre un adversaire page 3/17 L’équipe PyRat PyRat : cours 2 Parcours de graphe Retour sur l’algorithme aléatoire du TP 1 Il s’agit d’un parcours (on explore le graphe en se déplaçant de sommet en sommet voisin) C’est un algorithme local (seule l’information des voisins du sommet où l’on se trouve actuellement est utile, pas le graphe en entier) Aujourd’hui Nous allons nous déplacer vers un fromage (pas par hasard) Pour cela nous allons utiliser des parcours plus classiques Nous allons parler de parcours en profondeur d’abord et en largeur d’abord L’un d’entre eux permettra même de trouver le plus court chemin pour atteindre le fromage (si le graphe est non pondéré) page 4/17 L’équipe PyRat PyRat : cours 2 Quelques définitions Rappel : G = (V , E) Voisin On appelle voisin de i dans G la liste des sommets j tels que (i, j) ∈ E Arbre couvrant On appelle arbre couvrant d’un graphe G connexe et non-orienté un arbre obtenu à partir de G en retirant des arêtes Remarque : il existe souvent plusieurs arbres couvrants d’un même graphe Exemple : ⇒ page 5/17 L’équipe PyRat PyRat : cours 2 Exercice Trouver d’autres exemples d’arbres couvrants pour ce graphe : Trouver un exemple d’application à la recherche d’un arbre couvrant dans un graphe. page 6/17 L’équipe PyRat PyRat : cours 2 Deux philosophies Parcours en profondeur Parcours en largeur On explore dans une direction donnée d’abord, puis seulement quand on est bloqué on commence à faire demi-tour On explore les sommets par éloignement croissant en nombre d’arêtes avec le sommet de départ Cas du labyrinthe sans murs 3x3 page 7/17 L’équipe PyRat PyRat : cours 2 Exercice Un conducteur souhaite rejoidre la mer à partir d’un certain point de départ. Dans quels cas un parcours en largeur est-il préférable ? page 8/17 L’équipe PyRat PyRat : cours 2 Les algorithmes récursifs Cas du parcours en profondeur (pseudocode) def profondeur(sommet_courant): sommets_marqués.ajouter(sommet_courant) pour tout sommet i voisin de sommet_courant: si i n’est pas dans sommets_marqués: faire_quelque_chose(i) profondeur(i) Remarques : sommets_marqués est un ensemble. Il peut être implémenté à l’aide d’une liste, d’un tableau, d’une table de hachage etc Il faut parcourir les voisins d’un sommet à chaque étape, il vaut donc mieux avoir une représentation en mémoire du graphe adaptée Défi : comment programmer le parcours en largeur en récursif ? page 9/17 L’équipe PyRat PyRat : cours 2 Les files et les piles Prise de recul Un parcours est essentiellement une façon de choisir quel prochain sommet non déjà visité aller explorer Nous allons donc considérer avoir une structure de donnée pour les prochains sommets à visiter LIFO ou pile (stack) Last-In First-Out ou pile est une façon de gérer les priorités où le dernier élément ajouté est le premier consulté (pile de documents) FIFO ou file (queue) First-In First-Out ou file est une façon de gérer les priorités où le premier élément ajouté est le premier consulté (file d’attente) page 10/17 L’équipe PyRat PyRat : cours 2 Parcours unifié (itératif) Nouvel algorithme unifié def parcours(sommet_départ): structure_d_attente = nouvelle_structure() structure_d_attente.push(sommet_départ) sommets_marqués = {sommet_départ} tant que structure_d_attente n’est pas vide: sommet_courant = structure_d_attente.pop() faire_quelque_chose(sommet_courant) pour tout sommet i voisin de sommet_courant: si i n’est pas dans sommets_marqués: sommets_marqués.ajoute(i) structure_d_attente.push(i) Pour nos parcours Profondeur : prendre une pile pour structure_d_attente Largeur : prendre une file pour structure_d_attente page 11/17 L’équipe PyRat PyRat : cours 2 Exercice Dérouler un exemple de parcours en largeur et en profondeur à partir du sommet v1 sur l’exemple suivant : v3 v7 v5 v4 v2 v6 v1 page 12/17 L’équipe PyRat PyRat : cours 2 Routage Comment se déplacer ? Pour pouvoir lire un chemin à partir de l’arbre couvrant obtenu, il va falloir utiliser un algorithme de routage Routage Dans sa forme la plus simple, le routage se lit à l’envers : puisque le point de départ est connu, c’est le point d’arrivée qui est informatif On va ainsi lire un chemin du point d’arrivée au point de départ Cela suppose de modifier l’algorithme précédent en ajoutant un tableau de routage qui indique pour chaque sommet quel autre sommet l’a ajouté à la structure d’attente (à vous de le faire !) Une fois le parcours terminé, il va aussi falloir proposer un algorithme pour retrouver le chemin à partir du tableau de routage page 13/17 L’équipe PyRat PyRat : cours 2 Exercice Donner le routage du graphe suivant obtenu à partir d’un parcours en largeur démarrant de v1 : v3 v7 v5 v4 v2 v6 v1 page 14/17 L’équipe PyRat PyRat : cours 2 Estimer le temps de calcul d’un programme Où est-ce dans PyRat ? Une fois les parties terminées, les temps de calcul des programmes sont renvoyés (pensez toutefois à utiliser les constantes TURN_TIME = None et GAME_MODE = "test" dans votre launcher) Courbes Pour montrer l’impact d’un paramètre sur le temps de calcul, tracez le temps de calcul en fonction de votre paramètre Moyennes et écarts types Lorsque vous obtenez un point, ne vous contentez pas d’un test ! Faites de nombreux tests et moyennez Si vous voulez montrer qu’un algorithme est plus rapide qu’un autre, afficher les écarts types de vos temps simulés est une bonne idée, surtout si les courbes sont proches page 15/17 L’équipe PyRat PyRat : cours 2 Complexité et temps de calcul Complexité d’un algorithme On appelle complexité d’un algorithme le nombre d’opérations élémentaires nécessaires au maximum pour qu’il s’exécute en fonction de la taille de l’entrée C’est un outil mathématique formel, contrairement à des simulations qui dépendent entre autres de la puissance de la machine Plus de détails aux prochains cours Complexité des parcours Si on note N le nombre de nœuds du graphe, les parcours précédents ont une complexité de O(N) page 16/17 L’équipe PyRat PyRat : cours 2 C’est à vous Vous pouvez maintenant attaquer le TP 2 et commencer à résoudre le problème de la prochaine étape (ramasser un morceau de fromage) Objectifs Programmer un (ou des) programmes pour ramasser un morceau de fromage dans le labyrinthe Vous serez guidés pour l’écriture du parcours en largeur Comment les deux parcours se comparent ? Regarder le temps de calcul en fonction des paramètres du labyrinthe page 17/17 L’équipe PyRat PyRat : cours 2