Projet Labyrinthe - Icare3D LO42 Frey_Crassin.pdf · Représentation graphique et interface ... Le...

download Projet Labyrinthe - Icare3D LO42 Frey_Crassin.pdf · Représentation graphique et interface ... Le but ce projet de LO42 était de manipuler les graphes et ... tous les liens d’un

If you can't read please download the document

Transcript of Projet Labyrinthe - Icare3D LO42 Frey_Crassin.pdf · Représentation graphique et interface ... Le...

  • Rapport de Projet LO42 Batrice Frey et Cyril Crassin Automne 2003

    Universit de Technologie de Belfort-Montbliard GI01

    Projet Labyrinthe

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 1

    Sommaire

    Introduction ............................................................................................ 2 1. Gnration du labyrinthe.................................................................. 3 1.1 Les Empilements................................................................. 3 1.2 Gnration du graphe dempilements ............................ 4 1.3 Les Salles .............................................................................. 5 1.4 Gnration du graphe de Salles ....................................... 6 2. Promenade au sein du labyrinthe ................................................... 7 2.1 Lalgorithme de dijkstra ..................................................... 7 2.2 Lalgorithme de DJSka ....................................................... 8 3. Recherche de l'entre optimale ...................................................... 10 3.1 Algorithme par recherche de successeur...................... 11 3.2 Algorithme par parcours concurrents........................... 13 4. Reprsentation graphique et interface utilisateur ...................... 14 Conclusion............................................................................................. 15

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 2

    Introduction Le but ce projet de LO42 tait de manipuler les graphes et les arbres de manire crer et parcourir un labyrinthe 3D compos de salles hexagonales. Nous avons ralis une application en JAVA pour traiter le problme qui nous a t soumis. Les salles sont disposes en empilements afin de faciliter la construction et de garantir la cohrence gographique de l'ensemble. Les salles adjacentes peuvent tre ou non relies entre elles ce qui cre des chemins dans le labyrinthe et peut engendrer des salles secrtes. La complexit de ce labyrinthe est d'autant plus importante que les salles ne sont pas forcment au mme niveau, ce qui fait entre 0 et 12 portes possibles par salle.

    Notre dmarche a t tout au long de ce projet de crer un code la fois efficace et structur pour en assurer une certaine volutivit et gnricit du code. Dans une premire partie, nous allons prsenter les principales structures de donnes mises en uvre puis nous expliquerons les algorithmes majeurs que nous avons implments pour assurer l'efficacit du programme et rsoudre les problmes poss et enfin nous prsenterons rapidement l'interface utilisateur mise en oeuvre.

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 3

    1. Gnration du labyrinthe 1.1 Les empilements

    La gnration des salles et de leurs liens se fait en deux tapes, on commence par gnrer un graphe d'empilements qui permettent ensuite de crer les salles de manire cohrente gographiquement dans l'espace. Ces empilements peuvent tres dcals les uns par rapport aux autres d'1/2 niveau en hauteur, cela tant gnr de manire alatoire pour chaque empilement. Les dimensions du graphe sont dtermines lors de l'initialisation de la construction. Toutes nos constructions utilisent une architecture objet, chaque lment tant reprsents par une classe contenant les mthodes pour construire les ensembles auxquels ils appartiennent. Un empilement possde un tableau de NB_LIENS rfrences (6 dans notre cas) vers ses empilements voisins. La cration d'un empilement provoque rcursivement la cration du graphe autour de ce dernier.

    public class Empilement { //Constructeur de dpart Empilement(int t[], int haut) //Construction rcursive Empilement(Empilement pere, int dirPere, int haut) //renvoi le numero de lien correspondant dans un empilement li private int reciprok(int dir)

    //Renvoi l'indice du lien prcdent correspondant dans empilement li au lien dir private int indiceDansPerePrec(int dir)

    //Renvoi l'indice du lien suivant correspondant dans empilement li au lien dir private int indiceDansPereSuiv(int dir) //Mise a jour des coordonnes de l'empilement private void majCoord(Empilement pere, int dirPere) //utilise pour calculer les coordonnes d'un nouvel empilement private int[] calcCoord(int co[], int dir) //Dtecte si un empilement sort de la zone construire boolean dehors(int coord[]) boolean dehors() //Construction de l'empilement void build() //Pour crer un lien rciproque entre empilements Empilement creeLien(Empilement fils, int dirFils) //indice lien precedent int prec(int i) //indice lien suivant int suiv(int i) //initialise la construction des voisins restants construire de l'empilement void creeFils(int dirPere) //Retourne l'empilement li selon direction Empilement getLien(int dir) //Coordonnees empilement int[] getCoord() //Creation des salles de l'empilement void creeSalles() //Cree les liens entre les salles de l'empilement et ses voisines void buildSallesLiens() //Initialise la creation du graphe de salles void buildSallesGraph() //Renvoi la salle la hauteur haut dans l'empilement Salle getSalle(int haut) //Renvoi la salle dans un empilement voisin selon une direction et une hauteur Salle getSalle(int dir, int haut) }

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 4

    1.2 Gnration du graphe dempilements La gnration de ce graphe est ralis a partir dune vision totalement locale

    du graphe. Chaque empilement ne connaissant simplement que les empilements situs au bout des liens quil possde.

    Les liens tant numrots de la faon suivante :

    On appellera rciproque dun lien (implment par la mthode reciprok de la

    classe Empilement) le lien situ sur sa face oppose, par exemple le rciproque de 5 est 2.

    Le nud premier est cr par la mthode Build de la classe Labyrinthe, classe de dpart de lapplication. Le constructeur prenant en paramtre un tableau de int reprsentant la taille maximum du labyrinthe et un int reprsentant la hauteur du nud premier est alors utilis pour paramtrer le Labyrinthe.

    La mthode build de lempilement est ensuite appele ce qui provoque lappel la mthode creeFils et initie la cration rcursive du graphe dempilements. Cette mthode fonctionne de la manire suivante :

    Elle commence par dtecter le sens de parcours de ses liens, il faut en effet

    non seulement crer de nouveaux empilements mais galement les liens vers les empilements existant car crs par dautres empilements. Il est fondamental que tous les liens dun empilement vers les empilements gnrs prcdemment soient crs avant den gnrer de nouveaux. En effet, pour savoir si lempilement situ au bout dun lien doit tre cr ou si il existe dj, lempilement se rfre au nud situ au bout dun lien connaissant celui gnrer.

    Par exemple dans le cas suivant :

    Pour crer le liens 4 (cf. schma prcdent) dans lempilement 3, il faut aller voir le liens 3 dans lempilement 2. Si il existe, cest quil faut simplement le reli, sinon on le cre. On test donc le liens prcdent et suivant le liens courant afin de savoir quoi faire. Pour dterminer le lien tester dans la salle 2 on utilisera la mthode indiceDansPereX de la classe Empilement.

    01

    23

    4

    5

    1 3

    2

    ?

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 5

    1.3 Les Salles La gnration du graphe de salles se fait travers la classe Salle qui

    fonctionne sur le mme principe que la classe Empilement avec cette fois 2*NB_LIENS rfrences sur des salles voisines numrotes comme pour les empilement, ltage infrieur succdant ltage suprieur. Les Salles sont stockes dans des ArrayList Java lintrieur de leurs empilements respectifs et ce sont ces derniers qui initient la cration du graphe de Salles. Les salles dterminent alatoirement leur cration si il s'agit d'une entre. La cration des liens entre salles se fait travers les empilements ce qui est efficace d'un point de vue complexit et garanti la cohrence gographique de l'ensemble.

    Les salles possdent galement une cordonne spatiale pour pouvoir en

    raliser laffichage, ces coordonns fonctionnes selon le principe suivant :

    0 1 2

    0 1 2

    3

    4

    x y

    public class Salle { //Nb de salles total static int nbSalles() ////pour DJSka//// //Renvoi le nud de l'arbre associ lors du parcours Noeud getNoeud() //Associe un nud de l'arbre void setNoeud(Noeud n) //Indique si un lien existe avec la salle s boolean lienVers(Salle s) ///////////////// //constructeurs Salle(Empilement e, int h, int ent) //Mme principe que dans Empilement + gestion du niveau private int reciprok(int dir, boolean croise) //Construction des liens et portes void build() //cree un lien vers une salle existante Salle creeLien(Salle fils, int dirFils, int ouverture) //Cf Empilement Salle getLien(int dir) int[] getCoord() //Porte ouverte ou non int getPorte(int dir) //Ouvre/ferme une porte int setPorte(int dir, int val) }

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 6

    Notre dmarche avait t dans un premier temps de vouloir gnrer directement le graphe de Salles sans passer par des Empilements en utilisant le principe des liens relatifs que nous avons employ pour les Empilements. Seulement il cest avr que la construction en une seule passe des liens et des salles en 3 dimensions tait impossible cause des dcalages qui font perdes la connaissance de nombreuses salles. De nombreuses Salles se trouvaient ainsi dupliqus car cres plusieurs fois, les liens vers des Salles existantes nayant pas t crs au bon moment dans les salles pres. Une connaissance cohrente simplement locale des salles cres semble donc impossible maintenir avec ce principe. La mthode crFils des Empilements a tout de mme hrite de cette recherche et son architecture permettrait facilement de gnrer un graphe 3D mais sans dcalages.

    Les empilements ne sont donc plus quun moyen de gnr le graphe de Salles et ne sont plus utiles par la suite, chaque salle possdant une rfrence directe vers chacun de ses voisins. Pour tenir compte du fait quune porte vers une salle adjacente puisse tre ouverte ou ferme, nous avons galement utilis un tableau de 2*NB_LIENS entiers placs 0, 1 ou de signifiant respectivement, porte pour le moment indfinie, porte ouverte, et porte ferme.

    1.4 Gnration du graphe de Salles

    Cette gnration se fait comme nous lavons prcis prcdemment en crant les 12 liens de chaque laide des empilements. Pour cela, les empilements fournissent une mthode getSalle qui renvoie une rfrence vers une salle situe dans un empilement voisin partir dune direction et dune hauteur lintrieur de lui-mme. Nous appelons ici direction un nombre entre 0 et 2*NB_LIENS-1 afin de tenir compte de la hauteur du lien.

    //Renvoi Salle dans l'empilement courant Salle getSalle(int haut){ //Si la sale n'existe pas if(haut>=hauteur || haut

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 7

    2. Promenade au sein du labyrinthe 2.1 Lalgorithme de Dijkstra

    A partir d'une entre donne nous devions tablir une carte sous la forme d'une arborescence donnant le chemin le plus court pour accder chaque salle.

    Pour construire ce graphe des plus courts chemins, notre premire ide fut de parcourir le graphe du labyrinthe en profondeur c'est dire visiter systmatiquement tous les nuds fils de chaque nud par un parcours rcursif. Cette ide nous est rapidement apparue tre extrmement coteuse car chaque nud est trait un grand nombre de fois, ce qui entrane une complexit trs leve (O(nx ) ou approchant). On procde en effet par raffinement successif du chemin le plus court chaque salle. Nous nous sommes donc mis la recherche d'un algorithme plus performant permettant de trouver le chemin le plus court chaque nud avec une complexit acceptable. Nous sommes ainsi partis de l'algorithme de Dijkstra qui donne la longueur des chemins minimaux pour gnrer un arbre de parcours de manire efficace en l'optimisant et l'adaptant notre problme.

    Voici l'algorithme original de Dijkstra :

    E : ensemble de tous les sommets du graphe V : ensemble des sommets ayant dj t visits L :tableau d'indice les successeurs de x, et dont les valeurs reprsentent le poids des arcs (x, successeur) Pi,j : poids de l'arc (i,j) V {1}; L(1) 0; Pour i de 2 N Si i est successeur de 1 alors L(i) P1,j sinon L(i) +infini Fin pour Tant que V E Trouver j pas dans V tel que L(j)=min{L(i),i pas dans V} V V union {j} Pour tout successeur i de j Si i pas dans V alors L(i) min{L(i), L(j)+Pj,i} Fin si Fin pour Fin tant que

    Le principe gnral de l'algorithme est de parcourir le graphe par niveau de profondeur et non plus en profondeur. Il s'agit de ce que l'on appel un algorithme "glouton".

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 8

    Dans cet algorithme, on part du sommet 1 : initialisation de l'ensemble V l'lment 1 et de l'lment L(1) 0.

    Ensuite pour tous les sommets qui restent, on regarde si le sommet est un successeur de 1. Si c'est le cas on met le poids de l'arc (1, successeur) la position L [successeur], sinon on met +infini pour signaler que cet lment du tableau n'a pas encore reu de valeur (sommet pas encore visit).

    Une fois cette tape termine, on relance une seconde boucle qui s'arrte lorsque tous les sommets ont t traits.

    On rcupre alors le sommet S qui na pas encore t visit (le sommet n'appartient pas V) et dont le poids est le plus petit dans le tableau des poids L.

    On rajoute alors ce sommet l'ensemble des sommets dj visits. Ensuite, on regarde les successeurs de ce sommet S : s'ils n'ont pas encore t

    visits et si la valeur de l'arc entre le sommet S et son successeur est infrieure la valeur prsente la position L[successeur], on remplace la valeur de L[successeur] par L(S) + poids entre les sommets S et successeur. On continue ainsi pour tous les successeurs de S, puis on cherche nouveau le plus petit poids du tableau L.

    Grce cette mthode, on trouve le plus court chemin entre un sommet de dpart et tous les autres sommets. En effet, on stocke dans un tableau le poids ou longueur du chemin partir du sommet de dpart, poids qui change si le passage par un sommet intermdiaire permet de diminuer sa valeur (chemin plus court). 2.2 Lalgorithme de DJSka

    Pour optimiser notre recherche des plus courts chemins dans notre graphe, nous avons choisi d'implmenter l'algorithme de Dijkstra de la manire suivante :

    Nous avons tout d'abord mis en place des structures de donnes efficaces pour stocker les nuds traits ainsi que les successeurs. Pour cela, nous avons utilis des tableaux associant chaque niveau (distance par rapport l'entre) une liste de salles. Ceci permet d'accder rapidement toutes les salles du niveau qui nous intresse. Concrtement, nous avons deux ArrayList JAVA stockant des ArrayList de salles pour chaque niveau.

    Avec lors de l'ajout d'une Salle: Schmatiquement:

    ArrayList sallesParcourues =new ArrayList(); ArrayList sallesPoids =new ArrayList();

    void addSalleArray(ArrayList al, Salle s, int decal){ if(al.size()

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 9

    Nous stockons galement le poids attribu a chaque salle directement dans les objets associs pou y accder directement. Tout ceci donne le code Java suivant dans la classe DJSka:

    Cet algorithme se rvle d'une efficacit assez importante, sa complexit thorique tant quasiment en O(m*log(n)) avec m arcs et n sommets.

    int build(Salle entree, int nbSalles, ArrayList sallesSecretes){ entree.poids=0; //ajout de l'entree dans le tableau des poids de salles (L) addSalleArray(sallesPoids, entree, decalIndicesPoids); Salle current; //Salle courante int poidsPere; //Poids de la salle traite une tape de l'algo //Tq on a des salles lies, cad placees ds la tableau de successeurs while(sallesPoids.size()>0){ //recherche du min poids dans sallesPoids current=(Salle)((ArrayList)sallesPoids.get(0)).get(0); poidsPere=current.poids; //recherche des successeurs de l'entree for(int i=0; ipoidsPere+1 || current.liens[i].poids==-1) chgPoids(current.liens[i],poidsPere+1 ) ; //on met a jour le poids } //enlever la salle parcourue de sallePoids rmSalleArray(sallesPoids); //insertion dans sallesParcourues de ce min addSalleArray(sallesParcourues, current, 0); nbSallesParcourues++; //Incremente le nb de salles parcourues current.parcouru=true; //On marque la salle comme parcourue sallesSecretes.remove(current); //Et on la retire de la liste des salles secretes //ajout de l'entree dans l'arbre if(arbre==null) //Si arbre vide arbre=new Noeud(current); else{ //Creation du nouveau noeud ds l'arbre et liaison avec ses peres Noeud nouvNoeud=new Noeud(current); //On recherche au poids precedent des salles lies a la salle courante for(int j=0; j

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 10

    3. Recherche de l'entre optimale Il nous a t demand de trouver en plus du chemin le plus court chaque salle partir de chaque entre, un algorithme capable de dterminer l'"entre optimale". Pour nous, une entre optimale serait une entre qui permet d'accder un maximum de salles le plus rapidement possible, c'est dire, dont l'arbre de parcours serait le plus dense et le moins profond. Nous avons tout d'abord rpondu cette demande en construisant l'arbre de parcours de chaque entre, puis, en comparant les arbres obtenus. Pour pouvoir faire mieux, c'est dire utiliser l'arbre gnr pour une entre afin de dterminer l'entre optimale, il faut absolument que le graphe ne soit pas dcoup en "zones d'influence" c'est dire des ensembles de salles (avec entres) sans lien entre eux. Dans ce cas, l'arbre gnr pour une entre n'est d'aucune utilit pour avoir des informations sur les autres zones accessibles par d'autres entres.

    Illustration 2D des zones d'influence autour de deux entres E1 et E2

    E2

    E1

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 11

    3.1 Algorithme par recherche de successeur Nous avons tout de mme russi concevoir un algorithme capable de

    dterminer cette entre optimale dans le cas d'un graphe sans "zone d'influence" et voici quoi notre rflexion a abouti :

    On part par exemple du graphe suivant :

    On gnre ensuite l'arbre de parcours partir du nud 0 :

    L'arbre obtenu a une profondeur maximale de 3. La question est alors : y a -t il moins profond ? On cherche des arbres de profondeur < 3.

    1- On peut liminer de l'tude la racine et les feuilles une profondeur 3 (7 et 8) car il on sait que le chemin le plus court pour aller de 7 0 et de 8 0 est de longueur 3. 2- Il reste (1, 2, 3, 4, 5, 6) tudier. Prenons 3, V(3) = {0, 4, 6}. On a dj des chemins de longueur 2. V(5) = {2, 6, 7} donc c'est bon. V(7) = {5, 8} donc a ne marche pas car 5 et 8 ne sont pas dans {0, 3, 6}. On arrte.

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 12

    L'arbre de racine 3 sera de profondeur au moins 3. On teste donc un autre sommet, par exemple : 2. Les sommets (0, 1, 3, 4, 5, 7, 8) sont atteignables par un chemin de longueur 2 maximum.

    Reste tester le voisinage de 6 qui doit tre inclus dans le voisinage de 2. V(2) = {0, 1, 4, 5} V(6) = {3, 5}

    5 est commun aux deux listes, il y a donc un chemin de longueur 2 maximum entre 2 et 6. Donc, on sait que l'entre 2 est meilleure que l'entre 0. Il suffit de re-gnrer son arbre de parcours l'aide de Dijkstra par exemple.

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 13

    En rsum : 1- Crer un arbre A0 partir d'une entre quelconque. 2- Rechercher un arbre A1 de profondeur infrieure : prof (A1) = prof (A0) - 1 Faire { - prendre une entre quelconque dans l'arbre.

    - mettre les nuds se trouvant une profondeur infrieure prof(A0) -2 dans une liste. - vrifier que les sommets restant ont leur voisinage dans la liste. Si oui, on, recommence sur cet arbre, sinon on retire le nud de la liste, des nuds traiter. Pour raliser cette opration, les matrices d'adjacence semblent tre les structures de donns les mieux adaptes et permettraient d'atteindre une complexit quasiment de l'ordre de n.

    } Jusqu' ce que tous les nuds soient traits Une fois un ou plusieurs nuds optimaux obtenus, on calcule son arbre.

    3.2 Algorithme par parcours concurrents Une autre technique pour trouver l'entre optimale dans un graphe sans

    "zone d'influences" isoles, consisterait gnrer les arbres de parcours pour chaque entre en parallle c'est dire tage par tage en s'arrtant ds que l'on rencontre un nud plus proche d'une autre entre. Par contre les structures de donnes mettre en place semblent assez complexes puisqu'il faut stocker dans chaque salle la distance chaque entre. On obtient ainsi des groupes de salles autours des entres, l'entre optimale tant alors l'entre regroupant le plus de salles.

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 14

    4. Reprsentation graphique et interface utilisateur

    Afin d'assurer une bonne comprhension du problme pos dans l'espace, nous avons cr une reprsentation graphique tridimensionnelle du graphe de salles tout comme de l'arbre de chemin minimum partir d'une entre. Cette reprsentation a t ralise l'aide d'une bibliothque 3D pour JAVA nomme Java3D et dveloppe par Sun pour un grand nombre de plates-formes. Ceci a donc t galement une bonne occasion pour nous de nous plonger dans une bibliothque complexe d'affichage. Il est intressant de noter que l'organisation d'une scne en Java3D est base sur une arborescence d'objets.

    L'affichage du labyrinthe propose 3 modes de reprsentation: - 1) Numros de Salles+Liens+Salles 3D transparentes - 2) Salles 3D - 3) Numros de Salles Dans tous les modes, l'arbre de parcours reste affich sous le labyrinthe ce qui

    permet une observation relativement aise. Nous avons implment ce systme daffichage dans une classe nomme

    J3D_DrawManager qui implmente une interface appele DrawManager qui fixe les mthodes daffichage des diffrents lments. Cette classe sert galement grer les entres utilisateurs avec les commandes suivantes. (Attention car tous les paramtrages se font au clavier dans la console et lors de lattente dune entre, la fentre daffichage se fige) :

    Mode N1 Le graphe de salles Mode N2 Reprsentation des salles en 3D

    - Souris+bouton gauche : Rotation de la vue Souris+bouton milieu : Zoom vue - Souris+bouton droit : Dplacement vue - touche a : Affichage de larbre gnr pour une entre, numro de lentre a prciser au clavier dans la console. - touche s : Mode daffichage des salles touche r : Cration dun nouveau Labyrinthe - touche t : Cration dun nouveau Labyrinthe avec paramtrage de la taille - touche e : Cration et affichage de larbre de parcours pour une entre quelconque

  • Batrice Frey et Cyril Crassin Rapport Projet IA41

    Universit de Technologie de Belfort-Montbliard 15

    Conclusion Ce projet nous a permis d'appliquer et de mettre en uvre la manipulation et le parcours de graphes ainsi que la cration d'arbres dans un langage objet. Nous avons t confront au problme du cot en puissance de calcul que demandent les algorithmes sur ce genre de structures en particulier lorsque la masse d'information traiter devient importante (dimensions du labyrinthe). Tous les algorithmes et structures de donnes ont t conus de telle sorte pouvoir tre utiliss dans d'autres applications et gnraliss pour diffrentes formes de salles, du fait que nous ayons pris soin de rendre le nombre de liens/voisins de chaque salle totalement paramtrable. Nous nous sommes galement attachs crer une interface utilisateur et plus particulirement une reprsentation graphique permettant une bonne comprhension du problme et de sa rsolution par le programme.