Programme Tri Pimp A - info121A Récursivité Programmation IMPérative Avancée Dichotomie Frédéric Vernier Arbre xxx yyy Graphes Examen blanc inspiré du cours de Burkhart Wolff Traverse et Calculs dans Arbres Exemple: Graphes de Réseaux Réseau de transport Graphes omniprésent ! Stations (+type) Exemples Connexions Représentations de graphes Routes Parcours et Calculs etc. Exemple: Graphes Exemple: Recherche Labyrinthe La recherche d’une sortie d’un labyrinthe … Réseau sociaux (mais qui te like?) Exemple: Recherche Labyrinthe Recherche d’une sortie = arbre ensemble des chemins = graphe Exemple: Configurations en Jeux n queens peut avoir des cycles Graphe implicite Graphes : Définition … consistent d’un ensemble de sommets (noeuds) V et de liens entre eux, des arêtes (arcs) E entre eux, i.e. un ensemble de paires entre les V. … peuvent être orientés (E non-symétrique) Graphs : Definitions … peuvent avoir: cas: orientés - in-degré (example: 2) - out-degré (example: 2) cas non-orientés - degré (example: 2) des attributs sur des sommets (ex.: “graph coloré”) ou non-orientés (E symétrique) … peuvent avoir (en plus des arbres): boucles ([4,5,2,3]), des attributs sur des arêtes (ex.: “graph pondéré”) sommets avec plusieurs “pères” (2) Graphe : Représentation Représentation de Graphes: G = (V,E) ou V = {1,2,3,4,5,6} E = {(6,4),(4,3),(4,5),(5,2),(5,1),(2,1), (4,6),(3,4),(5,4),(2,5),(1,5),(1,2)} Graphe : Représentation Et, bien sur, une représentation par référence (position dans tableaux): [[2,5], [5,1], [2,4], [3,5,6], [1,2,4], [4]] … ou par une fonction: vector<ref> voisins(<ref>) Exemple de problème Différentes formes de graphes et de problèmes … [Wikipedia] Route problems !•!Hamiltonian path and cycle problems !•!Minimum spanning tree !•!Route inspection problem (also called the "Chinese Postman Problem") !•!Seven Bridges of Königsberg !•!Shortest path problem !•!Steiner tree !•!Three-cottage problem !•!Traveling salesman problem (NP-hard) Certaines Graph-Problèmes Problème du voyageur de commerce: pour un graphe pondéré G = (V, A, !) Exemple de problème Problème du chemin Hamiltonien: (pour des graphes orientés et non-orientés): … trouver un chemin qui passe par tous les sommets exactement une fois. … n’existe pas dans tous les graphes. Autre exemple graphe pondéré: visiter chaque sommet qu’une seule fois (sauf le départ et fin, qui sont égaux) Arbre couvrant de poids minimal (angl: Minimum spanning tree) minimiser le cout du chemin sommets tous liés problème d’optimisation récurrent et complexe (NP) poids minimal typiquement non-orienté, mais … Graphes & Arbres Graphs vs. Arbres: Marquages Arbres faciles à explorer par des algorithmes récursives Idée: explorer les graphes par construction de sous-arbres … … marquer les sommets déjà visitées … ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ marquer(A) de-marquer(A) est-marqué(A) Explicites et implicites Graphs Comme dans le cas des arbres, les sommets et les arrêtes peuvent être explicitement représentés (métro, shortest path navigation …) implicitement représentés: (jeux, labyrinthes … ) vector<ref> voisins(sommets S) visiter(S, op) ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ Schéma de parcours d’arbres Parcours en profondeur (depth-first) Variante: Parcours Postfixe. (Variantes infixe et prefixe analog arbres) void visiterGraph(Sommet A){ marquer(A) foreach(Sommet S : voisins(A)) if(nonMarque(S)) visiterGraph(S); visiter(A); de-marquer(A); } ✓ Schema evaluation de graphes code C++ Parcours en profondeur (depth-first) /* Rappel d’un algorithme de recherche: */ char char char char char Variante : Parcours Postfixe. (Variantes infixe et prefixe analogue aux arbres) <Res> evalGraph(Sommet A){ marquer(A); foreach(Sommet S : voisins(A)) if(nonMarque(A)) vector<Res> res=evalArete(A,S,evalGraph(S)); MUR VIDE EN_CONSTR IMPASSE CHEMIN = = = = = '#'; ' '; '?'; '@'; 'o'; typedef vector<vector<char> > Labyrinthe; Labyrinthe laby; de-marquer(A); … return eval(A, res); } code C++ code C++ /* Rappel d’un algorithme de recherche: */ /* Rappel d’un algorithme de recherche: */ bool chemin1_r(int x, int y){ //cout << x << "," << y << endl; laby[y][x] = EN_COURS; bool trouve = false; if (x==laby[laby.size()-2].size()-2 && y==laby.size()-2){ laby[y][x] = CHEMIN; return true; } if (laby[y][x+1]==VIDE) trouve=chemin1_r(x+1, y); if (! trouve && laby[y+1][x]==VIDE) trouve=chemin1_r(x,y+1); if (! trouve && laby[y][x-1]==VIDE) trouve=chemin1_r(x-1,y); if (! trouve && laby[y-1][x]==VIDE) trouve=chemin1_r(x,y-1); bool chemin1_r(int x, int y){ } marquer(x,y) le résultat laby[y][x] = EN_COURS; bool trouve = false; if (x==laby[laby.size()-2].size()-2 && y==laby.size()-2){ laby[y][x] = CHEMIN; donc voisin pas marqué return true; } if (laby[y][x+1]==VIDE) trouve=chemin1_r(x+1, y); if (! trouve && laby[y+1][x]==VIDE) trouve=chemin1_r(x,y+1); if (! trouve && laby[y][x-1]==VIDE) trouve=chemin1_r(x-1,y); if (! trouve && laby[y-1][x]==VIDE) trouve=chemin1_r(x,y-1); if (trouve)laby[y][x] = CHEMIN return trouve; } if (trouve)laby[y][x] = CHEMIN; return trouve; de-marquer(x,y) Parcours Labyrinthe Les Sommets: une “configuration”, i.e. un pair de: Parcours de graphes Intérêt particulier: Parcours en largeur (breadth first) l’état du labyrinthe, avec ses murs, ses cases encore vides, ses cases déjà visités Rappel: Structure de donné auxiliaire: File <X> (angl: Queue) la position actuelle: x et y First-in-first-out principle (FIFO) calculer les voisins de (x,y) : trouver positions voisins qui sont elements clé: operations File<X> FileVide ni déjà visité ni mur ! Graph implicite !!! Parcours de graphes Schéma d’un parcours en largeur (breadth first) ParcoursLargeur(Sommet A){ f = FileVide; enfiler(A, f); while (f != FileVide) { nœud = defiler(f); marquer(nœud); Visiter(nœud); //On choisit de faire une opération foreach(S:voisins(nœud) if (non_marque(S)) enfiler(S, f) de-marquer(nœud) } } Calculs dans graphes Schéma pour évaluation en largeur … <res> evalLargeur(Sommet A){ File<Pair<Sommet, res_tmp>> f = FileVide; <res> res = initRes() enfiler(A, f); while (f != FileVide) { nœud = defiler(f); marquer(nœud) foreach(S:voisins(nœud) if (non_marque(S)) <res_tmp> res_tmp = eval(nœud, S, res, f) res = update(nœud, S, res, res_tmp) enfiler((S, res_tmp),f) de-marquer(nœud) } return res } Parcours de graphes Quelle stratégie de parcours est meilleur pour “find_shortest_path” parcours en profondeur Résumé Graphes sont une structure de donnée (récurrente :-) en informatique Algorithmes efficaces de grand intérêt parcours en largeur une approche de leur parcours et utilisation : réduction en arbre (via marqueur) ??? et exploration avec des stratégies connues …