Algorithme de Preparata-Hong

De testwiki
Aller à la navigation Aller à la recherche

En mathématiques et en informatique, plus particulièrement en géométrie algorithmique, l'algorithme de Preparata-Hong est une méthode algorithmique pour calculer le plus petit polygone (dans le plan) ou polyèdre (dans l'espace) qui englobe un ensemble fini de points donnés. Autrement dit, il s'agit de calculer l'enveloppe convexe d'un ensemble fini P de points dans l'espace euclidien de dimension 2 (le plan) ou de dimension 3 (l’espace). Cette méthode a été mise au point par Franco Preparata et Su Ji Hong[1]. Sa stratégie repose sur le paradigme connu en informatique sous le nom de « diviser pour régner ». Cet article présente uniquement le cas de la dimension 2.

Description du problème

Exemple d'une enveloppe convexe de 16 points.

On considère un ensemble fini P de n points. On suppose que tous les points ont toutes leurs coordonnées différentes (si tel n'est pas le cas, on supprime les doublons et on adapte la procédure). On cherche à trouver les sommets du polygone convexe qui contient tous les points de P.

Principe en dimension 2

On commence par trier les points de P dans l'ordre croissant selon la dernière (c'est-à-dire la deuxième) coordonnée. Soit (x1,...,xn) la liste des points de P après ce tri.

Premiers cas

Les premiers cas de l’algorithme diviser pour régner sont ceux où il y a 1, 2 ou 3 points dans P. Dans ce cas, le calcul de l’enveloppe convexe est facile : il s'agit du point lui-même dans le premier cas, du segment joignant les 2 points dans le deuxième cas et du triangle de sommet les 3 points pour le troisième cas.

Cas général : procédure récursive

S’il y a strictement plus de 3 points, on applique la stratégie diviser pour régner[1]. « Diviser » signifie ici qu'on sépare l’ensemble des points en deux parties, dites respectivement « inférieure » et « supérieure », avec le même nombre de points, à un point près au plus. On note A={x1,...,xn2} et B={xn2+1,...,xn} les deux sous-ensembles obtenus ; ils forment une partition de P. À cause de la convention d'ordonnancement des points, les premiers points du tri ont les deuxièmes coordonnées les plus petites, et A est donc la moitié (plus éventuellement un point) des points de P dont les ordonnées sont les plus petites, c'est-à-dire qui sont le plus « bas » dans une représentation plane. De même, B, le complémentaire de A dans P, comprend les points de P dont les deuxièmes coordonnées, leurs ordonnées, sont les plus grandes, donc les points qui sont les plus « hauts » dans le plan.

L'étape « Régner » consiste alors à calculer les enveloppes convexes respectives de A et B. On appelle pour simplifier « enveloppe convexe inférieure » l'enveloppe convexe de A et « enveloppe convexe supérieure » l'enveloppe convexe de B. Cette étape se fait récursivement en divisant à nouveau les deux parties, et ainsi de suite.

Il faut donc aussi savoir reconstruire l’enveloppe convexe globale à partir des enveloppes convexes inférieure et supérieure : cela s'effectue grâce à un algorithme dit « algorithme de fusion », qui relie les deux enveloppes à la fois à gauche et à droite (ici, « à gauche » correspond aux premières coordonnées les plus petites, « à droite » aux plus grandes). À droite, par exemple, l'algorithme va permettre de relier deux points provenant respectivement des parties inférieure et supérieure, en faisant en sorte que tous les points de P, dans les deux parties, soient tous à gauche de la droite joignant ces deux points.

Le principe de cet algorithme est le suivant[1] :

  • On part des points les plus à droite de chaque partie, c'est-à-dire des points dont la première coordonnée, l'abscisse, est la plus grande ; on appelle a le plus à droite dans A et b le plus à droite dans B,
  • On cherche a2 dans A tel que la pente de la droite (a2,b) soit supérieure à la pente de la droite (a,b),
  • On cherche b2 dans B tel que la pente de la droite (a2,b2) soit inférieure à la pente de la droite (a2,b),
  • On itère jusqu’à rencontrer un blocage.

À la fin de cet algorithme, on relie les deux derniers points trouvés, dans A et B respectivement.

On réalise ensuite la même opération à gauche de A et B, c'est-à-dire en partant des points dont la première coordonnée est la plus petite et en adaptant l’algorithme ci-dessus. On retire enfin les arêtes joignant des points intérieurs au nouveau polygone et devenues donc superflues, pour obtenir l'enveloppe convexe globale de P.

Algorithme de fusion dans le cas de la dimension 2

Modèle:Animation

Décrivons ici l'algorithme que l'on va utiliser pour fusionner les enveloppes convexes supérieure et inférieure[1]. Soient A et B deux polygones convexes du plan euclidien. Soient n,m des entiers strictement positifs, représentant respectivement le nombre de sommets de A et de B. Soient {a1,...,an} et {b1,...,bm} les sommets en question. On suppose que les ordonnées des points du premier ensemble sont toutes strictement inférieures à celles des points du second ensemble. On suppose que dans la réunion de ces deux ensembles, les abscisses et les ordonnées sont distinctes deux-à-deux. Supposons aussi que dans chaque ensemble, on range les sommets dans le sens horaire de leur parcours sur le polygone à partir du sommet le plus "à droite" (celui d'abscisse la plus grande, il est représenté sur les figures ci-contre respectivement pour A et B par rA et rB). À l'aide de l'algorithme précédent, on cherche à calculer l'enveloppe convexe de la réunion de ces deux ensembles de points, qu'on va noter C, à partir de A et B. Pour des raisons pratiques, on pourra raisonner sur les indices des sommets de A et B respectivement modulo n et modulo m. Nous allons considérer que x1(a1)<x1(b1) (le cas x1(a1)>x1(b1) se traite de manière analogue, en ce qui concerne à la fois le pseudo-code et la correction).

Pour i=1,...,n et j=1,...,m, on note pi,j la pente de la droite (ai,bj). Pour i=1,...,n on note αi,i+1 la pente de la droite (ai,ai+1) et pour j=1,...,m on note βj,j+1 la pente de la droite (bj,bj+1). On note gA et gB respectivement les indices du sommet de A le plus "à gauche" (celui d'abscisse la plus petite) et du sommet de B le plus "à gauche" (celui d'abscisse la plus petite).

Le but de l'algorithme qui va suivre est de trouver la tangente droite de C. Voici le pseudo-code de l'algorithme, on notera x1(c) et x2(c) respectivement l'abscisse et l'ordonnée de cc est un point du plan euclidien, et on suppose que les coordonnées des sommets de A et B et que les valeurs αi,i+1 pour i=1,...,n et βj,j+1 pour j=1,...,m sont stockées dans des tableaux (accessibles à coût constant) :

Soient i1,j1

(***) On écrit pi,j=x2(bj)x2(ai)x1(bj)x1(ai)

Si αi,i+1pi,j et i<gA faire ii+1 et recommencer à partir de (***)

Si βj,j+1>pi,j et j<gB faire jj+1 et recommencer à partir de (***)

Renvoyer le couple (i,j)

Il est facile de voir que l'algorithme termine car on incrémente i et j de 1 à chaque fois que l'on doit recommencer à partir de la ligne (***) du pseudo-code ; dans le cas marginal où i=gA et j=gB, on passe directement à la dernière ligne de pseudo-code.

On remarque donc aussi que la complexité de l'algorithme est de l'ordre de O(gA+gB), et donc de l'ordre de O(n+m).

Correction de l'algorithme

Modèle:Section à sourcer

Rechercher la tangente droite consiste à trouver les indices i* dans {1,...,gA} et j* dans {1,...,gB} telles que les points ai* et bj* soient ses extrémités. On se restreint au cas i*gA et j*gB.

ligne brisée convexe

Grâce à la convexité de A et B, on remarque que les suites (α1,2,...,αgA1,gA) et (β1,2,...,βgB1,gB) sont décroissantes (la concaténation des segments associés est une fonction convexe).

tangente droite pour les convexes A et B

Ainsi, on peut caractériser géométriquement la pente de la tangente à droite pour qu'elle constitue bien un côté de l'enveloppe convexe issu de la fusion de A et B) de la manière suivante :

  • si i*>1, alors αi*,i*+1<pi*,j*αi*1,i* ;
  • si i*=1, alors α1,2<p1,j* ;
  • si j*>1, alors βj*,j*+1pi*,j*<βj*1,j* ;
  • si j*=1, alors β1,2pi*,1.


Il reste alors à montrer que l'algorithme renvoie bien ce que l'on souhaite, c'est-à-dire les indices i* dans {1,...,gA} et j* dans {1,...,gB} vérifiant la caractérisation ci-dessus.

On sait que l'algorithme s'arrête quand on a les deux conditions αi*,i*+1<pi*,j* et βj*,j*+1pi*,j*. Pour être sûr que i=i* et j=j*, il faut s'assurer que l'on a l'intégralité de la caractérisation précédente. Pour cela, on distingue trois cas :

  • soit on a i=j=1, auquel cas on a directement la caractérisation, l'algorithme renvoie bien ce que l'on souhaite ;
  • soit on a (i=1 et j>1) ou (i>1 et j=1) auquel cas soit une des deux dernières lignes du code n'est jamais exécutée, et on peut alors montrer facilement que l'on a la caractérisation voulue en examinant la seule ligne de code itérée ;
  • soit il y a déjà eu une itération des deux dernières lignes de pseudo-code, et on distingue alors deux sous-cas :

(1) l'indice j est le dernier indice auquel on a fait une incrémentation, auquel cas on avait βj,j+1>pi,j>αi,i+1 juste avant l'incrémentation, on a aussi pi,j+1pi,j (regarder le triangle (ai,bj,bj+1) sur la figure ci-contre) et par succession d'inégalités des pentes sur la chaîne (ai,bj+1,bj,...,b1), on réitère l'inégalité pour remonter à juste après la dernière incrémentation de l'indice i (qui existe par hypothèse) et l'indice j0 correspondant vérifie pi,j0αi1,i (car l'incrémentation de i indique de pi1,j0αi1,i et donc la chaîne (ai,ai1,bj0) est concave), par la chaîne d'inégalité on a bien pi,jαi1,i, de même (par inégalité des pentes sur la fonction convexe issue de la chaîne (ai,bj+1,bj)) cela donne βj,j+1>pi,j+1 : en incrémentant j (de 1), on a finalement les conditions pi,jαi,i1 et pi,j<βj1,j ;

(2) l'indice i est le dernier indice auquel on a fait une incrémentation, juste avant cette incrémentation on a αi,i+1pi,j. De même on ne peut pas avoir βj1,jpi+1,j, sinon on a la chaîne (ai+1,bj,bj1) qui est concave, ce qui entraîne (inégalité des pentes) pi+1,jpi+1,j1 et comme la chaîne (ai+1,ai,bj) est concave par hypothèse, on obtient αi,i+1pi+1,j1 et donc que la chaine (ai+1,ai,bj1) est concave , ce qui veut dire que αi,i+1pi,j1 ; si on revient sur le pseudo-code, si juste avant la dernière incrémentation de i on avait une incrémentation de j, alors on aurait eu d'après la troisième ligne de pseudo-code que αi,i+1<pi,j1, ce qui est impossible ; donc comme il est supposé qu'on a incrémenté j au moins une fois, juste avant la dernière incrémentation de i, on a encore une autre incrémentation de i avec pi1,jαi,i+1αi1,i ; il s'obtient alors par récurrence qu'on ne va jamais atteindre bj dans l'exécution de l'algorithme : contradiction. On a alors la première inégalité βj1,j>pi+1,j. Aussi, comme la chaîne (ai+1,ai,bj) est concave par hypothèse, on obtient directement pi+1,jαi,i+1. Donc, en incrémentant i (de 1), on a bien les conditions pi,jαi1,i et pi,j<βj1,j.

Ceci termine la preuve de la correction de l'algorithme[1].

Complexité temporelle de l’algorithme

On suppose que pour un ensemble initial de n points du plan, cet algorithme de fusion est exécuté en temps O(n). Ainsi, en notant C(n) la complexité temporelle associée au calcul de l'enveloppe convexe de n points du plan euclidien, stockés dans un tableau et triés par avance dans l'ordre croissant selon une coordonnée, on a la relation de récurrence suivante :

C(n)=2×C(n/2)+O(n)

Par le master theorem[2]Modèle:,[3] ou par une analyse à la main, on conclut que C(n) est en O(n×log2(n)). Comme le tri d'un tableau (par exemple par tri fusion) peut être réalisé en temps O(n×log2(n)), la complexité totale de l'algorithme est elle aussi en O(n×log2(n)).

Une autre approche du problème

Il existe une autre façon de calculer l'enveloppe convexe de P en calculant deux convexes non bornés tels que l'intersection des deux donne l'enveloppe convexe finale, et en déterminant pour chacun de ces convexes l'ensemble des segments et demi-droites qui les délimitent. Il s'agit d'une méthode proposée par F. Preparata et M. Shamos[4].

Notes et références

Modèle:Références

Voir aussi

Articles connexes

Liens externes

Modèle:Portail