ECOLE POLYTECHNIQUE ECOLES NORMALES SUPERIEURES ECOLE SUPERIEURE DE PHYSIQUE ET DE CHIMIE INDUSTRIELLES CONCOURS D'ADMISSION 2015 FILIERE MP HORS SPECIALITE INFO FILIERE PC COMPOSITION D'INFORMATIQUE B (XECLR) (Duree : 2 heures) L'utilisation des calculatrices n'est pas autorisee pour cette epreuve. Le langage de programmation choisi par le candidat doit etre specifie en tete de la copie. Enveloppes convexes dans le plan Ce sujet a pour objectif de calculer des enveloppes convexes de nuages de points dans le plan affine, un grand classique en geometrie algorithmique. On rappelle qu'un ensemble C R2 est convexe si et seulement si pour toute paire de points p, q C, le segment de droite [p, q] est inclus dans C. L'enveloppe convexe d'un ensemble P R2 , notee Conv(P ), est le plus petit convexe contenant P . Dans le cas ou P est un ensemble fini (appele nuage de points), le bord de Conv(P ) est un polygone convexe dont les sommets appartiennent a P , comme illustre dans la figure 1. 5 2 10 6 1 9 4 8 11 3 0 7 Figure 1 Un nuage de points, numerotes de 0 a 11, et le bord de son enveloppe convexe. Le calcul de l'enveloppe convexe d'un nuage de points est un probleme fondamental en informatique, qui trouve des applications dans de nombreux domaines comme : la robotique, par exemple pour l'acceleration de la detection de collisions dans le cadre de la planification de trajectoire, 1 le traitement d'images et la vision, par exemple pour la detection d'objets convexes (comme des plaques mineralogiques de voiture) dans des scenes 2d, l'informatique graphique, par exemple pour l'acceleration du rendu de scenes 3d par lancer de rayons, la theorie des jeux, par exemple pour determiner l'existence d'equilibres de Nash, la verification formelle, par exemple pour determiner si une variable risque de depasser sa capacite de stockage ou d'atteindre un ensemble de valeurs interdites lors de l'execution d'une boucle dans un programme, et bien d'autres encore. Dans ce sujet nous allons ecrire deux algorithmes de calcul du bord de l'enveloppe convexe d'un nuage de points P dans le plan affine. Le premier, dit algorithme du paquet cadeau, consiste a envelopper le nuage de points P progressivement en faisant pivoter une droite tout autour. Le deuxieme, dit de balayage, consiste a balayer le plan horizontalement avec une droite verticale, tout en maintenant au fur et a mesure l'enveloppe convexe de la partie du nuage situee a gauche de cette droite verticale. Les deux algorithmes sont illustres respectivement dans les figures 3 et 4. Le temps d'execution du premier algorithme est majore par une constante fois nm, celui du deuxieme par une constante fois n log n, ou n designe le nombre total de points de P et m le nombre de points de P appartenant au bord de Conv(P ). Rappelons que le temps d'execution d'un programme A (fonction ou procedure) est le nombre d'operations elementaires (comparaisons, additions, soustractions, multiplications, divisions, affectations, etc.) necessaires a l'execution de A. Sauf mention contraire dans l'enonce du sujet, le candidat n'aura pas a justifier des temps de calcul de ses programmes. Toutefois, il devra veiller a ce que ces derniers ne depassent pas les bornes prescrites. Dans toute la suite on supposera que le nuage de points P est de taille n 3 et en position generale, c'est-a-dire qu'il ne contient pas 3 points distincts alignes. Ces hypotheses vont permettre de simplifier les calculs en ignorant les cas pathologiques, comme par exemple la presence de 3 points alignes sur le bord de l'enveloppe convexe. Nos programmes prendront en entree un nuage de points P dont les coordonnees sont stockees dans un tableau tab a 2 dimensions, comme dans l'exemple ci-dessous qui contient les coordonnees du nuage de points de la figure 1 : i\j 0 1 0 0 0 1 1 4 2 1 8 3 4 1 4 4 4 5 5 9 6 5 6 7 7 -1 8 7 2 9 8 5 10 11 6 11 13 1 Precisons que les coordonnees, supposees entieres, sont donnees dans une base orthonormee du plan, orientee dans le sens direct. La premiere ligne du tableau contient les abscisses, tandis que la deuxieme contient les ordonnees. Ainsi, la colonne d'indice j contient les deux coordonnees du point d'indice j. Ce dernier sera nomme pj dans la suite. 2 Partie I. Preliminaires Question 1 Ecrire une fonction plusBas(tab, n) qui prend en parametre le tableau tab de taille 2 × n et qui renvoie l'indice j du point le plus bas (c'est-a-dire de plus petite ordonnee) parmi les points du nuage P . En cas d'egalite, votre fonction devra renvoyer l'indice du point de plus petite abscisse parmi les points les plus bas. Sur le tableau exemple precedent, le resultat de la fonction doit etre l'indice 7. Dans la suite nous aurons besoin d'effectuer un seul type de test geometrique : celui de l'orientation. Definition 1 Etant donnes trois points pi , pj , pk du nuage P , distincts ou non, le test d'orientation renvoie +1 si la sequence (pi , pj , pk ) est orientee positivement, -1 si elle est orientee negativement, et 0 si les trois points sont alignes (c'est-a-dire si deux au moins sont egaux, d'apres l'hypothese de position generale). Pour determiner l'orientation de (pi , pj , pk ), il suffit de calculer l'aire signee du triangle, comme illustre sur la figure 2. Cette aire est la moitie du determinant de la matrice 2 × 2 formee -- par les coordonnees des vecteurs - p- i pj et pi pk . pk pj pj + - pj pi p pk i pi = pk Figure 2 Test d'orientation sur la sequence (pi , pj , pk ) : positif a gauche, nul au centre, negatif a droite. Question 2 Sur le tableau exemple precedent, donner le resultat du test d'orientation pour les choix d'indices suivants : i = 0, j = 3, k = 4, i = 8, j = 9, k = 10. Question 3 Ecrire une fonction orient(tab, i, j, k) qui prend en parametres le tableau tab et trois indices de colonnes, potentiellement egaux, et qui renvoie le resultat (-1, 0 ou +1) du test d'orientation sur la sequence (pi , pj , pk ) de points de P . Partie II. Algorithme du paquet cadeau Cet algorithme a ete propose par R. Jarvis en 1973. Il consiste a envelopper peu a peu le nuage de points P dans une sorte de paquet cadeau, qui a la fin du processus est exactement le bord de Conv(P ). On commence par inserer le point de plus petite ordonnee (celui d'indice 7 dans l'exemple de la figure 1) dans le paquet cadeau, puis a chaque etape de la procedure on selectionne le prochain point du nuage P a inserer. 3 La procedure de selection fonctionne comme suit. Soit pi le dernier point insere dans le paquet cadeau a cet instant. Par exemple, i = 10 dans l'exemple de la figure 3. Considerons la 5 2 10 6 1 9 4 8 11 3 0 7 Figure 3 Mise a jour du paquet cadeau apres insertion du point p10 . relation binaire definie sur l'ensemble P \ {pi } par : p j pk orient(tab, i, j, k) 0. Question 4 Justifier brievement le fait que est une relation d'ordre total sur l'ensemble P \ {pi }, c'est-a-dire : - (reflexivite) pour tout j 6= i, pj pj , - (antisymetrie) pour tous j, k 6= i, pj pk et pk pj implique j = k, - (transitivite) pour tous j, k, l 6= i, pj pk et pk pl implique pj pl , - (totalite) pour tous j, k 6= i, pj pk ou pk pj . Ainsi, le prochain point a inserer (le point d'indice 5 dans la figure 3) est l'element maximum pour la relation d'ordre . Il peut se calculer en temps lineaire (c'est-a-dire majore par une constante fois n) par une simple iteration sur les points de P \ {pi }. Question 5 Decrire une realisation en Python de la procedure. Elle prendra la forme d'une fonction prochainPoint(tab, n, i), qui prend en parametre le tableau tab de taille 2 × n ainsi que l'indice i du point insere en dernier dans le paquet cadeau, et qui renvoie l'indice du prochain point a inserer. Le temps d'execution de votre fonction doit etre majore par une constante fois n, pour tous n et i. La constante doit etre independante de n et i, et on ne demande pas de la preciser. Question 6 Decrire a la main le deroulement de la procedure prochainPoint sur l'exemple de la figure 3. Plus precisement, indiquer la sequence des points de P \ {p10 } consideres et la valeur de l'indice du maximum a chaque iteration. On peut maintenant combiner la fonction prochainPoint avec la fonction plusBas de la question 1 pour calculer le bord de l'enveloppe convexe de P . On commence par inserer le point pi d'ordonnee la plus basse, puis on itere le processus de mise a jour du paquet cadeau jusqu'a ce que le prochain point a inserer soit de nouveau pi . A ce moment-la on renvoie le paquet cadeau comme resultat sans inserer pi une seconde fois. Un detail technique : comme la taille du paquet cadeau augmente peu a peu lors du processus, et qu'a la fin elle peut etre petite par rapport au nombre n de points de P , nous stockerons les 4 indices des points du paquet cadeau dans une liste. Par exemple, sur le nuage de la figure 1, le resultat sera la liste [7, 11, 10, 5, 2, 0]. Question 7 Ecrire une fonction convJarvis(tab, n) qui prend en parametre le tableau tab de taille 2 × n representant le nuage P , et qui renvoie une liste contenant les indices des sommets du bord de l'enveloppe convexe de P , sans doublon. Le temps d'execution de votre fonction doit etre majore par une constante fois nm, ou m est le nombre de points de P situes sur le bord de Conv(P ). Question 8 Justifier brievement le temps d'execution de l'algorithme du paquet cadeau. Intermede : piles d'entiers Dans la suite nous aurons besoin d'utiliser des piles d'entiers, dont on rappelle la definition ci-dessous : Definition 2 Une pile d'entiers est une structure de donnees permettant de stocker des entiers et d'effectuer les operations suivantes en temps constant (independant de la taille de la pile) : creer une nouvelle pile vide, determiner si la pile est vide, inserer un entier au sommet de la pile, determiner la valeur de l'entier au sommet de la pile, retirer l'entier au sommet de la pile. Nous supposerons fournies les fonctions suivantes, qui realisent les operations ci-dessus et s'executent chacune en temps constant : newStack(), qui ne prend pas d'argument et renvoie une pile vide, isEmpty(s), qui prend une pile s en argument et renvoie True ou False suivant que s est vide ou non, push(i, s), qui prend un entier i et une pile s en argument, insere i au sommet de s (c'esta-dire a la fin de la liste), et ne renvoie rien, top(s), qui prend une pile s (supposee non vide) en argument et renvoie la valeur de l'entier au sommet de s (c'est-a-dire a la fin de la liste), pop(s), qui prend une pile s (supposee non vide) en argument, supprime l'entier au sommet de s (c'est-a-dire a la fin de la liste) et renvoie sa valeur. Dans la suite il est demande aux candidats de manipuler les piles uniquement au travers de ces fonctions, sans aucune hypothese sur la representation effective des piles en memoire. Partie III. Algorithme de balayage Cet algorithme a ete propose par R. Graham en 1972. Nous allons ecrire la variante (plus simple) proposee par A. Andrew quelques annees plus tard. 5 La premiere etape consiste a trier les n points du nuage P par ordre croissant d'abscisse, en conservant tous les points de meme abscisse dans un ordre arbitraire. Question 9 Parmi les algorithmes de tri que vous connaissez, mentionnez-en un qui a un temps d'execution majore par une constante fois n log n sur les entrees de taille n. A partir de maintenant, on supposera que les points fournis en entree sont tries par abscisse croissante, comme c'est le cas dans l'exemple du tableau tab donne au debut du sujet. L'idee de l'algorithme est de balayer le nuage de points horizontalement de gauche a droite par une droite verticale, tout en mettant a jour l'enveloppe convexe des points de P situes a gauche de cette droite, comme illustre dans la figure 4. 5 5 5 2 2 10 6 1 2 4 10 6 9 1 4 11 0 4 8 11 3 0 7 1 9 8 8 3 10 6 9 11 3 0 7 7 Figure 4 Diverses etapes dans la procedure de balayage. La droite de balayage est en tirets. Plus precisement, l'algorithme visite chaque point de P une fois, par ordre croissant d'abscisse (donc par ordre croissant d'indice de colonne dans le tableau tab car celui-ci est trie). A chaque nouveau point pi visite, il met a jour le bord de l'enveloppe convexe du sous-nuage {p0 , · · · , pi } situe a gauche de pi . On remarque que les points p0 et pi sont sur ce bord, et on appelle enveloppe superieure la partie du bord de Conv{p0 , · · · , pi } situee au-dessus de la droite passant par p0 et pi (p0 et pi compris), et enveloppe inferieure la partie du bord de Conv{p0 , · · · , pi } situee au-dessous (p0 et pi compris). Le bord de Conv{p0 , · · · , pi } est donc constitue de l'union de ces deux enveloppes, apres suppression des doublons de p0 et pi . Par exemple, dans le cas du nuage P de la figure 4 gauche, le sous-nuage {p0 , p1 , p2 , p3 , p4 } a pour enveloppe superieure la sequence (p0 , p2 , p4 ) et pour enveloppe inferieure la sequence (p0 , p3 , p4 ), le bord de son enveloppe convexe etant donne par la sequence (p0 , p3 , p4 , p2 ). Informatiquement, les indices des sommets des enveloppes inferieure et superieure seront stockes dans deux piles d'entiers separees, ei (pour enveloppe inferieure) et es (pour enveloppe superieure). La mise a jour de l'enveloppe superieure est illustree dans la figure 5 : tant que le point visite (p9 dans ce cas) et les deux points dont les indices sont situes au sommet de la pile es (dans l'ordre : p8 et p5 ) forme une sequence (p9 , p8 , p5 ) d'orientation negative (voir la definition 1 pour rappel de l'orientation), on depile l'indice situe au sommet de es (8 dans ce cas). On poursuit ce processus d'elimination jusqu'a ce que l'orientation devienne positive ou qu'il ne reste plus qu'un seul indice dans la pile. L'indice du point visite (p9 dans ce cas) est alors insere au sommet de es. La mise a jour de l'enveloppe inferieure s'opere de maniere symetrique. 6 5 5 2 2 1 4 + 10 6 5 2 10 6 - 9 1 4 11 0 4 8 11 3 0 7 1 9 8 8 3 10 6 9 11 3 0 7 7 Figure 5 Mise a jour de l'enveloppe superieure lors de la visite du point p9 . Question 10 Ecrire une fonction majES(tab, es, i) qui prend en parametre le tableau tab ainsi que la pile es et l'indice i du point a visiter, et qui met a jour l'enveloppe superieure du sousnuage. Le temps d'execution de votre fonction doit etre majore par une constante fois i. Question 11 Ecrire une fonction majEI(tab, ei, i) qui effectue la mise a jour de l'enveloppe inferieure, avec le meme temps d'execution. Question 12 Ecrire maintenant une fonction convGraham(tab, n) qui prend en parametre le tableau tab de taille 2 × n representant le nuage P , et qui effectue le balayage des points de P comme decrit precedemment. On supposera les colonnes du tableau tab deja triees par ordre croissant d'abscisse. La fonction doit renvoyer une pile s contenant les indices des sommets du bord de Conv(P ) tries dans l'ordre positif d'orientation, a commencer par le point p0 . Par exemple, sur le nuage de la figure 1, le resultat de la fonction convGraham doit etre la pile s contenant la suite d'incides 0, 7, 11, 10, 5, 2 dans cet ordre, l'indice 0 se trouvant au fond de la pile s et l'indice 2 au sommet de s. Question 13 Analyser brievement le temps d'execution de l'algorithme de balayage decrit precedemment, en supposant une fois encore que les points du nuage fourni en entree sont deja tries par abscisse croissante. En deduire que le temps d'execution total de l'algorithme de Graham-Andrew est bien majore par une constante fois n log n. 7