Application des arbres binaires. Plan • Compter les arbres binaires
Transcription
Application des arbres binaires. Plan • Compter les arbres binaires
Application des arbres binaires. Plan • • • • • • Compter les arbres binaires Tétrarbres (quad trees) Problème des n corps Recherche dans un intervalle Recherche dans un nuage de points Recherche dans un arbre d’intervalles Amphi 8 1 Compter les arbres binaires (1) Rappel : un arbre binaire est soit vide, soit union disjointe d'une racine, d'un sous-arbre gauche et d'un sous-arbre droit. Si bn est le nombre d'arbres binaires distincts à n nœuds, on a donc : n-1 b0 = 1 bn = Σ bibn-i-1 i=0 La série B(x) = n b x Σ n n≥0 vérifie l'identité xB2(x) - B(x) + 1 = 0 Amphi 8 2 Compter les arbres binaires (2) La résolution de l'équation xB2(x) - B(x) + 1 = 0 donne bn = 1 n+1 ( )= 2n n (2n)! n!(n+1)! d'où bn ~ π-1/24nn-3/2 + O(4nn-5/2) (1) Dans un arbre, nombre de nœuds = 1 + nombre d'arcs (2) Dans un arbre binaire complet (tout nœud est d'arité 0 ou 2), nombre de feuilles = 1 + nombre de nœuds internes Amphi 8 3 Application des arbres binaires. Plan • • • • • • Compter les arbres binaires Tétrarbres (quad trees) Problème des n corps Recherche dans un intervalle Recherche dans un nuage de points Recherche dans un arbre d’intervalles Amphi 8 4 Une vision hiérarchique des images Une image est : • soit de couleur uniforme • soit formée de quatre images Amphi 8 NO NE SO SE SO NO NE SE 5 Tétrarbres (quad trees) Une image 2n x 2n est subdivisée itérativement en quadrants jusqu'au niveau du pixel. Amphi 8 NO NE SO SE 6 Tétrarbre associé à une image Amphi 8 7 Une échelle de 32 couleurs Amphi 8 8 Tétrarbre associé à une image Amphi 8 Merci à Luc Maranget... 9 Tétrabres en Java (1) class Tetrarbre { boolean couleur; // version noir et blanc boolean estFeuille; Tetrarbre so, no, ne, se; // Constructeur des feuilles Tetrarbre(boolean couleur) { this.estFeuille = true; this.couleur = couleur; } ... Amphi 8 10 Tétrarbres en Java (2) ... // Constructeur des nœuds internes Tetrarbre(Tetrarbre so, Tetrarbre no, Tetrarbre ne, Tetrarbre se) { this.estFeuille = false; this.so = so; this.no = no; this.ne = ne; this.se = se; } } static boolean[][] image; // pixels Amphi 8 11 Tétrarbres en Java (3) static boolean estMonochrome( Tetrarbre so, Tetrarbre no, Tetrarbre ne, Tetrarbre se) { return (so.estFeuille && no.estFeuille && ne.estFeuille && se.estFeuille && so.couleur == no.couleur && so.couleur == ne.couleur && so.couleur == se.couleur); } Amphi 8 12 t = taille/2 pixel (i, j) j j+t i NO NE SO SE i+t Amphi 8 13 Tétrarbres en Java (4) static Tetrarbre faireArbre(int taille, int i, int j) { if (taille == 1) return new Tetrarbre(image[i][j]); int t = taille/2; Tetrarbre so = faireArbre(t, i+t, j); Tetrarbre no = faireArbre(t, i, j); Tetrarbre ne = faireArbre(t, i, j+t); Tetrarbre se = faireArbre(t, i+t, j+t); if (estMonochrome(so, no, ne, se)) return new Tetrarbre(so.couleur); return new Tetrarbre(so, no, ne, se); } Amphi 8 14 Codage On code l'arbre par un parcours préfixe. Les nœuds internes sont codés 0 et les feuilles 1. Après chaque 1, on code la couleur de la feuille (0 pour blanc, 1 pour bleu). Equivaut au code : 0 11 10 00 On pourrait améliorer le code : 01 1 0110101110110011101110100111010111101010010111001011101111 Amphi 8 15 Tétrabres en Java (5) static void parcours(Tetrarbre a) { if (a != null) { if (a.estFeuille) System.out.print("1" + ((a.couleur) ? "1" : "0")); else // nœud interne System.out.print("0"); parcours(a.so); parcours(a.no); parcours(a.ne); parcours(a.se); } } Amphi 8 16 Autre avantage des tétrarbres • On peut changer facilement la couleur d'une image. • Faire une rotation d'un quart de tour. NO NE NE SE SO SE NO SO SO NO NE SE Amphi 8 NO NE SE SO 17 Application des arbres binaires. Plan • • • • • • Compter les arbres binaires Tétrarbres (quad trees) Problème des n corps Recherche dans un intervalle Recherche dans un nuage de points Recherche dans un arbre d’intervalles Amphi 8 18 Problème des n corps • Objectif : simuler le comportement de n particules (force de gravité ou électrostatique). • Solution directe, itérer les calculs suivants : – les n(n-1) forces F(p, q) entre 2 particules p et q, – la résultante des forces pour chaque particule, – le mouvement résultant pour une unité de temps. • Trop lent pour n grand. • Calcul hiérarchique – calculs exacts pour des particules proches; – on assimile les particules distantes à leur barycentre. Amphi 8 19 Algorithme de Barnes-Hut • Octabres: c'est la version 3D des tétrarbres : un cube est divisé récursivement en 8 cubes. • Calcul de la force F(p, C), sur la particule p, issue du cube C de coté c et de barycentre b. – Si C ne contient qu'une particule q, F(p, C) = F(p, q) – Si la distance de p à b est > α.c (par ex. α = 2 ou 3), F(p, C) = F(p, b) – Sinon F(p, C) = résultante (F(p, C1), ..., F(p, C8)) où C1, ..., C8 sont les 8 sous-cubes de C. A Hierarchical O(n log n) force calculation algorithm, J. Barnes and P. Hut, Nature, v. 324, Décembre 1986 Amphi 8 20 2 Tétrarbre associé 6 3 7 5 8 4 9 10 1 11 1 12 1 2 2 2 4 4 3 1 3 4 3 3 4 8 12 1 3 1 4 2 4 5 6 7 9 4 2 4 10 11 Réalisation • Données : pour chaque cube, la masse totale et le barycentre. Ce calcul peut se faire récursivement. • Gestion de l'octarbre – L'arbre est reconstruit à chaque unité de temps. – Cas le pire en O(n2). – En pratique, arbre de hauteur O(log n). • Pour une distribution uniforme en 3D, le nombre d'interactions à calculer est 3 28πα ~ (n log2 n) soit ~ 263(n log2 n) pour α = 3 9 Amphi 8 22 Résultats expérimentaux • Simulation d'un système de 5000 particules : 10 fois plus rapide qu'avec l'algorithme direct. • L'algorithme est facilement parallélisable. • La simulation réaliste d'une galaxie nécessite des millions d'étoiles. • On connaît un algorithme en O(n). En 1994, on a simulé 107 particules pour 103 pas de calcul (une semaine de calcul sur 500 processeurs...) Amphi 8 23 Application des arbres binaires. Plan • • • • • • Compter les arbres binaires Tétrarbres (quad trees) Problème des n corps Recherche dans un intervalle Recherche dans un nuage de points Recherche dans un arbre d’intervalles Amphi 8 24 Recherche en une dimension Problème : Compter les éléments d’un ensemble d’entiers qui sont dans un intervalle donné [min, max]. Exemple : E = {7, 9, 10, 12, 15, 20} Entre 12 et 19, il y a 2 éléments. L’ensemble est donné par un arbre binaire de recherche. Le prétraitement se fait en O(n log n), la recherche se fait en temps O(r + log n) où r est le nombre d'éléments trouvés. Amphi 8 25 Exemple • Entre 8 et 19, il y a 4 éléments. 10 7 3 20 9 6 15 25 • On peut couper les sous-arbres issus de 3 (à gauche de 7) et de 25 (à droite de 20). 12 5 Amphi 8 26 Exemple plus compliqué Entre 25 et 75 50 90 7 40 80 30 60 70 55 79 65 72 Amphi 8 27 En Java static int compter(Arbre a, int min, int max) { int total = 0; if (a == null) return total; if (a.contenu >= min) total += compter(a.filsG, min, max); if (a.contenu >= min && a.contenu <= max) total++; if (a.contenu <= max) total += compter(a.filsD, min, max); return total; } Amphi 8 28 Application des arbres binaires. Plan • • • • • • Compter les arbres binaires Tétrarbres (quad trees) Problème des n corps Recherche dans un intervalle Recherche dans un nuage de points Recherche dans un arbre d’intervalles Amphi 8 29 Recherche en deux dimensions Problème : Etant donné un ensemble de points dans le plan, déterminer ceux qui sont dans une zone donnée. Exemples : • Trouver les villes à moins de 100 km de Tours • Trouver les personnes entre 25 et 29 ans qui gagnent entre 1000 et 2000 euros par mois. Amphi 8 30 Recherche en deux dimensions E J G A K H D C B F I Problème : Nombre de points dans un rectangle donné. L Solution en deux étapes 1. Prétraitement : un arbre pour le nuage de points 2. Réponse : une recherche dans l’arbre Amphi 8 31 Arbres pour des points class Point { // Conflit avec MacLib ! int x, y; Point(int a, int b) { x = a; y = b; } } class Arbre { Point p; Arbre filsG, filsD; Arbre(Arbre g, Point v, Arbre d) { filsG = g; p = v; filsD = d; } } Amphi 8 32 Arbre pour un nuage de points Construire un arbre comme suit • le premier point coupe le plan en deux, horizontalement. • les points coupent des secteurs horizontalement aux niveaux pairs, et verticalement aux niveaux impairs. Amphi 8 33 Exemple E J G A A K H D C B F Amphi 8 I L 34 Exemple E J G A A K H B D C B F I L B est fils gauche de A car B.y < A.y Amphi 8 35 Exemple E J G A A K H D C B F B I C L C est fils gauche de A car C.x < B.x Amphi 8 36 Exemple E J G A A K H D C B F B I C D L D est fils droit de B car D.x > B.x Amphi 8 37 Exemple E J G A A K H D C B F B I C E D L E est fils droit de A car E.y > A.y D est fils droit de B car D.x > B.x Amphi 8 38 Insérer un point : au début • A la racine, le niveau est impair static Arbre ajouter(Point p, Arbre a) { return ajouter(p, a, false); } static Arbre ajouter(Point p, Arbre a, boolean vertical) { ... } Amphi 8 39 Insérer un point : une étape static Arbre ajouter(Point p, Arbre a, boolean vertical) { if (a == null) return new Arbre(null, p, null); boolean estAGauche = (vertical) ? (p.x < a.p.x) : (p.y < a.p.y); if (estAGauche) // insérer à gauche return new Arbre(ajouter(p, a.filsG, !vertical), a.p, a.filsD); else // insérer à droite return new Arbre(a.filsG, a.p, ajouter(p, a.filsD, !vertical)); } Amphi 8 40 La classe Rectangle class Rectangle { int g, d, b, h; } h g : abcisse du côté gauche d : abcisse du côté droit d g b : ordonnée du côté bas h : ordonnée du côté haut b Amphi 8 41 Le décompte (1) static int compter(Rectangle r, Arbre a, boolean vertical) { if (a == null) return 0; int total = 0; boolean aGauche = r.g <= a.p.x; boolean aDroite = a.p.x < r.d; boolean enBas = r.b <= a.p.y; boolean enHaut = a.p.y < r.h; boolean min, max; min = (vertical) ? aGauche : enBas; max = (vertical) ? aDroite : enHaut; ... // à suivre } Amphi 8 42 Le décompte (2) static int compter(Rectangle r, Arbre a, boolean vertical) { ... // suite if (min) total += compter(r, a.filsG, !vertical); if (aGauche && aDroite && enBas && enHaut) total++; if (max) total += compter(r, a.filsD, !vertical); return total; } Amphi 8 43 Application des arbres binaires. Plan • • • • • • Compter les arbres binaires Tétrarbres (quad trees) Problème des n corps Recherche dans un intervalle Recherche dans un nuage de points Recherche dans un arbre d’intervalles Amphi 8 44 Recherche d'un intervalle coupant Problème : Chercher, dans un ensemble d’intervalles, un élément qui rencontre un intervalle donné. Exemple : Dans une base d’événements, chercher un événement qui a eu lieu durant une période donnée. Amphi 8 45 Type abstrait de données Données : Un ensemble d'intervalles fermés [g, d]. Opérations : • ajouter un intervalle • supprimer un intervalle • chercher si l'ensemble contient un intervalle qui rencontre un intervalle donné v. Amphi 8 46 Structure de données • Les intervalles sont stockés dans un arbre binaire de recherche. • La clé utilisée pour comparer les nœuds est l'extrémité gauche des intervalles. • Chaque noeud n contient une information supplémentaire, dmax, qui est le maximum des extrémités droites des intervalles du sous-arbre issu de n. Amphi 8 47 Exemple dmax = max des extrémités droites du sous-arbre. 16:21 30 8:9 23 5:8 10 0:3 3 Amphi 8 6:10 10 [22,25] rencontre [11,14] non 25:30 30 15:23 23 17:19 20 26:26 26 19:20 20 48 Utilisation de dmax (1) dmax = max des extrémités droites du sous-arbre. 16:21 30 8:9 23 5:8 10 0:3 3 Amphi 8 6:10 10 Détermine dans quel sous-arbre chercher. 25:30 30 15:23 23 17:19 20 26:26 26 19:20 20 49 Intervalle [g, d]. Règle 1 Si filsG.dmax < g, inutile de chercher dans le sous-arbre gauche. Intervalle [22, 25] 16:21 30 8:9 23 5:8 10 0:3 3 Amphi 8 6:10 10 25:30 30 15:23 23 dmax = 10 < 22 17:19 20 26:26 26 19:20 20 50 Règle 2 (justifiée plus loin) Intervalle [g, d]=[22, 25] Si filsG.dmax ≥ g, inutile de chercher dans le sous-arbre droit. 16:21 30 8:9 23 5:8 10 0:3 3 Amphi 8 6:10 10 25:30 30 15:23 23 dmax = 23 > 22 dmax = 10 < 22 Intersection ! 17:19 20 26:26 26 19:20 20 51 Utilisation de dmax dmax = 23 > 11 dmax = 10 < 11 pas d'intersection ! Intervalle [11, 14] 16:21 30 8:9 23 5:8 10 0:3 3 Amphi 8 6:10 10 25:30 30 15:23 23 17:19 20 26:26 26 19:20 20 52 Justification Soit v = [g, d]. Soit [g', d'] un intervalle du sous-arbre gauche d'extrémité droite maximale. Par hypothèse, on a d' ≥ g. Supposons qu’aucun intervalle du sous-arbre gauche ne rencontre [g, d]. Alors [g, d] ∩ [g', d'] = ∅, d'où d < g'. Soit [g", d"] un intervalle du sous-arbre droit. On a g < d < g' < g" < d", donc [g, d] et [g", d"] sont disjoints. Donc aucun intervalle ne rencontre v ! Amphi 8 53 Les classes • Une classe d'intervalles • Une classe d'arbres binaires de recherche avec – un champ intervalle – un champ dmax • Il faut revoir le constructeur d'arbres pour le calcul de dmax! Amphi 8 54 Classe Intervalle class Intervalle { int min, max; Intervalle(int a, int b) { min = a; max = b; } } static boolean rencontre( Intervalle u, Intervalle v) { return u.min <= v.max && v.min <= u.max; } Amphi 8 55 Classe Arbre class Arbre { Intervalle u; int dmax; Arbre filsG, filsD; Arbre(Intervalle v, Arbre g, Arbre d) { u = v; filsG = g; filsD = d; dmax = calculDmax(v, g, d); } ... } Amphi 8 56 Classe Arbre class Arbre { ... static int calculDmax(Intervalle v, Arbre g, Arbre d) { int m = v.max; if (g != null && g.dmax > m) m = g.dmax; if (d != null && d.dmax > m) m = d.dmax; return m; } } Amphi 8 57 Recherche static Arbre chercher(Intervalle v, Arbre a) { if (a == null || rencontre(v, a.u)) return a; if (a.filsG != null) && a.filsG.dmax >= v.min) return chercher(v, a.filsG);//Règle 2 else return chercher(v, a.filsD);//Règle 1 } Amphi 8 58