• Aucun résultat trouvé

Construction du complexe de Farey : l'algorithme et son code

N/A
N/A
Protected

Academic year: 2022

Partager "Construction du complexe de Farey : l'algorithme et son code"

Copied!
26
0
0

Texte intégral

(1)

DIAGRAMMES VOLUME 69+70 , 2013

Construction du complexe de Farey L'algorithme et son code

Saab Abou-Jaoudé

ancien professeur de mathématiques spéciales docteur d'état en mathématique

[email protected]

A.M.S. Sub. Class : 05 A 04 , 52 A 02 , 52 C 04

(2)

Résumé :

L'objectif de ce texte est de construire les composantes connexes du complexe de Farey plan, que nous avons appelé connexes de Farey. Nous avons démontré qu'ils sont des triangles ou des quadrilatères. Nous don- nons le code fortran qui permet de produire les connexes de Farey. Le code que nous avons produit est optimal en un sens que nous précisons.

Mots clé :

Complexe de Farey, Connexe de Farey, Polygone convexe, Convexe po- lygonal direct, Droite orientée, Demi-plan.

I Introduction

Dans le premier article de ce numéro de Diagrammes, nous avons mis en évidence la forme des connexes de Farey. Nous avons, en n d'article, décrit un algorithme qui permet de construire les connexes de Farey du complexe CF (m +1, n) à partir de ceux du complexe CF (m, n) . Nous avons dit et démontré que, au cours des constructions successives, les connexes transitoires sont toujours des triangles ou des quadrilatères. Le programme dont le code est ci-aprés, inrme ce résultat. Après analyse, nous nous sommes apercu que nous avons traité un des cas un peu trop vite et que l'ordre de parcours proposé ne permet pas de contrôler le nombre maximum d'arêtes d'un connexe de farey des étapes transitoires.

Nous avons apporté une modication à l'ordre de parcours des droites et nous démontrons qu'avec ce nouveau mode de parcours, le nombre maximum d'arêtes d'une facette est 6 . Nous exposons tout cela dans ce qui suit, en rappelant d'abord la méthodologie et la structure des données du programme codé en fortran 90, le langage de prédilection du calcul scientique.

II De CF (m, n) à CF (m + 1, n).

Le but de cette section est de rappeler et de corriger le théorème dont

la conséquence est un algorithme ecace pour calculer les composantes

(3)

connexes d'un complexe de Farey d'ordre (m + 1, n) à partir de celles d'ordre (m, n) .

D'abord quelques rappels. On est dans le plan réel ane muni d'un repère (O, i, j ) . :

• Une droite de Farey d'ordre (m, n) a une équation de la forme : ux + vy = w , avec u, v, w entiers, |u| 6 m, |v| 6 n .

• On note D

m,n

l'ensemble des droites de Farey d'ordre (m, n) qui rencontrent le carré unité.

• On note CF (m, n) le complémentaire de D

m,n

dans le carré unité et on l'appelle le complexe de Farey d'ordre (m, n) . Ses compo- santes connexes seront appelées facettes. On se conforme ainsi à la nomenclature introduite par la théorie des graphes planaires.

• On appelle sommet d'ordre (m, n) (de Farey) tout point d'inter- section de deux droites de Farey, et situé dans le carré unité.

• On appelle segment de Farey ou arête tout segment dont les extré- mités sont deux sommets consécutifs d'une droite de Farey

• On qualiera de négative (resp. positive) une droite de pente < 0 (resp. > 0 ). On dira qu'elle est de type N (resp. de type P )

• Le qualicatif horizontale (resp. verticale) est attribué à une droite dont une équation est de la forme vy = w (resp. ux = w ). On dira qu'elle est de type H (resp. V ).

• On dira qu'une droite est oblique si elle est soit positive soit néga- tive.

Enn, on se permettra de typer une arête par le type de la droite de Farey qui la contient.

Ceci posé, nous avons déjà mis en évidence la forme des composantes connexes de CF (m, n) .

Soit K une telle composante connexe, qu'on appellera facette pour faire court. Alors la frontière de K , notée F r(K) , est un triangle ou un quadrilatère.

• Si c'est un triangle, ses trois côtés ne peuvent être du même type.

• Si c'est un quadrilatère on peut nommer ses sommets A, B, C, D

de sorte que les deux arêtes opposés AB et DC soient de type P

(4)

(positives), les deux autres AD et BC étant de type N (négatives).

Nous savons de plus que si K a l'un des côtés de sa frontière de type H (horizontal) ou de type V (vertical), alors c'est un triangle et les deux autres côtés sont obliques et de type opposés ( N puis P ou P puis N ).

Encore quelques notations : l'ensemble D

m+1,n

− D

m,n

des droites d'équation (m+1)x+vy = w sera noté DD , le sous-ensemble des droites négatives (resp. positives, resp. verticales) de DD sera noté DN (resp.

DP , resp. DV ). Notons qu'il n'y a pas dans DD de droites horizontales.

Nous allons typer les facettes par la liste des types de leurs arêtes suc- cessives, parcourues dans le sens direct. Modulo le choix de l'arête de départ, les facettes de CF (m, n) , ainsi que celles de CF (m + 1, n) , sont :

• soit des quadrilatères et elles sont du type P N P N .

A

B C D

type quadrilatére P N P N

(5)

• soit des triangles et elles sont de l'un des types : V P N, HN P, N N P, P P N .

A B

C

A B

C

A B

C

A B

C

type triangle HN P, P V P, P N P, P N N

On numérote les droites de DD , de 1 jusqu'à p = card(DD) en nu- mérotant d'abord les droites de DV , puis celles de DN , puis celles de DP

1

. On va construire une suite de complexes CF

k

(m, n) avec CF

0

(m, n) = CF (m, n) . ayant construit CF

k

(m, n) , pour k < p , on construit CF

k+1

(m, n) en coupant, quand cela est possible, les facettes de CF

k

(m, n) par la droite de DD de numéro k + 1 . On obtient, une fois épuisées les droites de DD , CF

p

(m, n) = CF (m + 1, n) .

Nous rappelons le théorème de complexité spatiale suivant que Nous avons énoncé et démontré dans le premier article de ce numéro : Théorème 1

Si on construit progressivement CF (m +1, n) à partir de CF (m, n) en coupant par les droites de DV, puis par celles de DN et enn par celles de DP, la conguration du complexe obtenu à chaque étape n'admet pour composantes connexes que des triangles ou des quadrilatères.

Ce théorème est faux. La gure ci-dessous en témoigne.

A

B

C

DN DP

A

B

C

DN DP

1. cet ordre n'est pas le bon. le bon est DN puis DP puisDV

(6)

Facette ABC coupé par les droites DN et DP

Cette gure montre un pentagone produit en cours de parcours. ABC est une facette dont le côté AC est horizontal. DN en est une séquente négative et DP en est une sécante positive.

Voici l'énoncé correct, moyennant le bon ordre de numérotation des droites.

Théorème 2

Si on construit progressivement CF (m + 1, n) à partir de CF (m, n) en coupant par les droites de DN puis par celles de DP et enn par celles de DV , la conguration du complexe obtenu à chaque étape admet pour composantes connexes des polygônes de six côtés au plus.

Démonstration : La démonstration est fondée sur la remarque suivante : Si deux droites de DN se coupent à l'intérieur du carré unité, leur point d'intersection est un sommet d'ordre(m, n). Nous laissons au lecteur le soin de terminer la démonstration.

Remarque : en fait, la limite de "six" indiquée dans le théorème ci-

dessus peut se réduire à "cinq". Pourquoi ?

(7)

III Le code

1. Les utilitaires : parcours.f90

module DroiteFarey

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! !

! ! Une droite coupe les facettes d'un complexe de Farey.

! ! Toutes les variables sont entières.

! !

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! implicit none

integer*4, parameter, private : : nafmax=10

! répertoire de travail et paramètre de taille maxi.

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! character (len=len("C :/farey/")), parameter : : dir="C :/farey/"

character (len=len("fr")), parameter : : nom="fr"

integer*4, parameter, public : : mmax=40, nmax=40

integer*4, parameter, private : : nxmax = 2*mmax*nmax*(mmax+nmax)/3 integer*4, parameter, private : : nymax = nxmax

integer*4, parameter, public : : namax = nxmax*5 integer*4, parameter, private : : nsmax = namax/2 integer*4, parameter, private : : nfmax = 2*namax/3 integer*4, parameter, private : : opt = 1

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! le rectangle de travail rect =

! ! CoiN Bas Gauche, CoiN Bas Droit,

! ! CoiN Haut Gauche, CoiN Haut Droit

! ! ici, init à (0,0,2), (1,0,2), (0,1,2), (1,1,2)

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

integer*4, dimension(1 :3), private : : CNBG, CNBD, CNHG, CNHD

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! les bords bas positif BBP, haut négatif BHN

! ! gauche positif BGP, gauche négatif BGN

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

integer*4, parameter, private : : BBP=1, BHN=2, BGP=3, BGN=4 integer*4, dimension(0 :nxmax), private : : BordBP,BordHN

integer*4, dimension(0 :nymax), private : : BordG,BordD

(8)

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! ns = nombre de sommets,

! ! na = nombre d'arêtes,

! ! nf = nombre de facettes

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! integer*4, public : : NS,NA,NF,cnt

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! le "type" arêtes :

! ! FG, FD = Facette Gauche, Facette Droite

! ! SD, SF = Sommet Début, Sommet Fin

! ! AV, AP = arete AVant, arete APres

! ! (sur le support orienté)

! ! Sare = taille d'une arête.

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

integer*4, parameter, private : : FG=1,FD=2,SD=3,SF=4,AV=5,AP=6 integer*4, parameter, private : : Sare=6

integer*4, dimension(1 :Sare,1 :namax), private : : are

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! le "type sommet" (int,int,int)

! ! Ssom = Nombre de coordonnées d'un sommet

! ! Ici 3. On calcule en coordonnées homogènes entières

! ! avec la 3eme coordonnée strictement positive.

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! integer*4, parameter, private : : Ssom=3

integer*4, dimension(1 :Ssom,1 :nsmax), private : : som

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! type facette. En 0, le nombre d'arêtes

! ! suivi de la liste des arêtes

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

integer*4, parameter, private : : Sfac=nafmax, Sfacc=Sfac+2 integer*4, dimension(0 :Sfac,1 :nfmax), private : : fac

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! facettes courantes de travail FCUR et FCUR1

! ! nombre d'arête de FCUR dans FCUR(0)

! ! idem pour FCUR1

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

integer*4, dimension(0 :Sfacc), private : : FCUR,FCUR1 integer*4, private : : u, v, w, nav

(9)

integer*8, private : : counter=0

integer*4, parameter, private : : maxch=32 character(len=maxch), private : : chmax=""

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! liste des fonctions et sous-programme publics

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! public : : Initdata, ache

public : : DroiteV, DroiteN,DroiteH,DroiteP

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! liste des fonctions et sous-programme privés.

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! private : : scal, intersec, facettecommune

private : : RemplaceArete, CouperFacette private : : ASF, sgn, RAD, Sortie

private : : SortieSommet, SortieArete private : : VaGauche, VaDroite private : : CoupeBord, cvis, gcd

contains

integer*4 FUNCTION gcd(x,y)

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! renvoie le PGCD des entiers "x" et "y"

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! integer*4, intent(in) : : x,y

integer*4 : : a,b,c, xx, yy

do w = 1,v-1 ; call droiteH(0, v, w) ; print*," H ",cnt ; end do if (x<0) then ; xx = -x ; else ; xx = x ; end if

if (y<0) then ; yy = -y ; else ; yy = y ; end if

if (xx<yy) then ; b=xx ; a=yy ; else ; b=yy ; a=xx ; end if do while (b/=0) ; c=mod(a,b) ; a=b ; b=c ; end do gcd=a

end FUNCTION gcd

(10)

logical FUNCTION check(u,v,w)

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! teste si "(u,v,w)" sont premiers entre eux

! ! renvoie ".FALSE." s'ils le sont

! ! et ".TRUE." sinon (éviter un ".NOT.")

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! integer*4, intent(in) : : u,v,w

integer*4 : : x

x = gcd(u,v) ; cnt = 4 if (x .EQ. 1) then

check=.FALSE.

else

if ( gcd(x,w) .EQ. 1) then check=.FALSE.

else

check=.TRUE.

end if end if

end FUNCTION check

integer*4 FUNCTION scal(P)

integer*4, intent(in), dimension(1 :3) : : P scal=u*P(1)+v*P(2)-w*P(3)

end FUNCTION scal

SUBROUTINE DroiteV(a,b,c) integer*4, intent(in) : : a,b,c

if (check(a,b,c)) then ; return ; end if u=a ; v=b ; w=c

if (scal(CNBD).LE.0) then ; return ; endif if (scal(CNBG).GE.0) then ; return ; endif nav=0 ; call CoupeBord(BordBP,BBP) end SUBROUTINE DroiteV

(11)

SUBROUTINE DroiteH(a,b,c) integer*4, intent(in) : : a,b,c

if (check(a,b,c)) then ; return ; end if u=a ; v=b ; w=c

if (scal(CNHG).LE.0) then ; return ; endif if (scal(CNBG).GE.0) then ; return ; endif nav=0 ; call CoupeBord(BordG,BGN) end SUBROUTINE DroiteH

SUBROUTINE DroiteN(a,b,c) integer*4, intent(in) : : a,b,c

if (check(a,b,c)) then ; return ; end if u=a ; v=b ; w=c

if(scal(CNHD).LE.0) then ; return ; endif if (scal(CNHG).LE.0) then

nav=0 ; call CoupeBord(BordHN,BHN) return

endif

if (scal(CNBG).GE.0) then ; return ; endif nav=0 ; call CoupeBord(BordG,BGN) end SUBROUTINE DroiteN

SUBROUTINE DroiteP(a,b,c) integer*4, intent(in) : : a,b,c

if (check(a,b,c)) then ; return ; end if u=a ; v=b ; w=c

if (scal(CNBD).LE.0) then ; return ; end if if (scal(CNBG).LE.0) then

nav=0 ; call CoupeBord(BordBP,BBP) return

end if

if (scal(CNHG).GE.0) then ; return ; end if nav=0 ; call CoupeBord(BordG,BGP) end SUBROUTINE DroiteP

(12)

FUNCTION intersec(lc,ld,C,D) result(X) integer*4, intent(in) : : lc,ld

integer*4, intent(in), dimension(1 :Ssom) : : C,D integer*4, dimension(1 :Ssom) : : X

integer*4 : : dd,jc,jd if (ld>0) then

jd=ld ; jc=lc else

jd=-ld ; jc=-lc end if

X=jd*C-jc*D if (X(3)/=0) then

dd=gcd(gcd(X(1),X(2)),X(3)) if (dd>1) then ; X=X/dd ; end if else

print*,"X=", X,"u,v,w=",u,v,w

print*,"droites parallèles, jc,jd=",jc,jd,"C,D=",C,D X=(/0,0,1/)

stop

end if

if((X(1)<0) .OR. ((X(2)<0))) then print*, ("bug dans intersec")

print*,"X=", X," u = ",trim(cvis(u))," v = ",trim(cvis(v))," w = ",trim(cvis(w)) print*,"jc,jd=",jc,jd,"C,D=",C,D

X=(/0,0,1/)

stop

end if

end FUNCTION intersec

(13)

FUNCTION facettecommune(x,y) result(k) integer*4, intent(in) : : x,y

integer*4 : : ia, k

integer*4, dimension(1 :Sare) : : A,B if ((x==0).OR.(y==0)) then

k=0 ; else

A=Are( :,x) ; B=Are( :,y) ; ia=A(FD) ; k=A(FG)

if ((ia/=0) .and. ((ia==B(FD)) .or. (ia==B(FG)))) then ; k=ia ; end if end if

end FUNCTION facettecommune integer*4 FUNCTION sgn(F)

integer*4, intent(in), dimension(0 :Sfac) : : F integer*4 : : ja,jb,jc,jd

integer*4, dimension(1 :Sare) : : A,B integer*4 : : C,D

ja=F(1) ; A=Are( :,iabs(ja)) jb=F(F(0)) ; B=Are( :,iabs(jb))

if (ja>0) then ; jc=A(SF) ; else ; jc=A(SD) ; end if if (jb>0) then ; jd=B(SD) ; else ; jd=B(SF) ; end if C=scal(Som( :,jc)) ; D=scal(Som( :,jd))

if((C==0).OR.(D==0)) then sgn=0

else

if (C>0) then ; sgn=D ; else ; sgn=-D ; end if end if

end FUNCTION sgn

(14)

FUNCTION ASF(s,FF) result(F)

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! Accés Sommet Facette. Sommet S, facette F

! ! recherche de la facette F trversée par la droite

! ! passant par le sommet S

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! integer*4, intent(in), dimension(0 :Sfac) : : FF integer*4, dimension(0 :Sfac) : : F

integer*4, intent(in) : : s integer*4 : : i,j,kd,kf,L

integer*4, dimension(1 :Sare) : : A L=FF(0)

do i=1,L ; j=FF(i) ; A=Are( :,iabs(j))

if (((j<0) .and. (s==A(SF))) .or.((j>0) .and. (s==A(SD)))) then ; exit ; end if end do

if (i .LE. L) then if (i>1) then

F=(/L,(FF(j),j=i,L),(FF(j),j=1,i-1)/) else

F=FF end if

else ! tilt. Gros bug print*, "bug dans ASF", s,FF do j=1,L

i=FF(j) ; A=Are( :,iabs(i)) print*,"i,ns,A", i,s,Som(1 :3,s) kd=A(3) ; kf=A(4)

print*, kd,kf

print*,"somj",som(1 :3,kd),"somk",som(1 :3,kf),"..."

end do

stop

end if

end FUNCTION ASF

(15)

FUNCTION CouperFacette() result(T) integer*4, dimension(1 :4) : : T

integer*4 : : ja,jb,jc,jd=0,i,j,L,ar=0,k1,n1,n2,s3,s4=0 integer*4, dimension (1 :Ssom) : : C,D

integer*4, dimension(1 :Sare) : : B,A1,A2 integer*4, dimension(0 :Sfacc) : : F

L=FCUR(0) ; ar=FCUR(1)

if (ar>0) then ; B=Are( :, ar) ; jb=SF ; k1=B(FD) else ; B=Are( :,-ar) ; jb=SD ; k1=B(FG)

end if

s4=B(jb) ; D=Som( :,s4) ; jd=u*D(1)+v*D(2)-w*D(3) ; do i=2,L ; ar=FCUR(i) ; s3=s4 ; C=D ; jc=jd

if (ar>0) then ; B=Are( :, ar) ; ja=SD ; jb=SF ; k1=B(FD) else ; B=Are( :,-ar) ; ja=SF ; jb=SD ; k1=B(FG)

end if

s4=B(jb) ; D=Som( :,s4) ; jd=u*D(1)+v*D(2)-w*D(3) ; if (jd==0) then ; T=(/0,i,s4,0/) ; return ; end if

if (jc<0) then if(jd>0) then ; exit ; end if else if(jd<0) then ; exit ; end if

end if end do

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! sortie arête.

! !

! ! créer un nouveau sommet et deux nouvelles arêtes et les insérer dans A

! ! mettre à jour le nouveau sommet. mettre à jour le chainage arête.

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! NS=NS+1 ; Som( :,NS)=Intersec(jc,jd,C,D) ! créer un nouveu sommet.

A1=B ; A2=B ! créer deux nouvelles arêtes

n1=iabs(ar) ; ja=A1(AV) ; if (ja/=0) then ; Are(AP,ja)=n1 ; end if n2=NA+2 ; ja=A2(AP) ; if (ja/=0) then ; Are(AV,ja)=n2 ; end if A1(AP)=n2 ; A2(AV)=n1 ; A1(SF)=NS ; A2(SD)=NS ;

Are( :,n1)=A1 ; Are( :,n2)=A2 ; F=FCUR if (ar>0) then

FCUR=(/L+1,(F(j),j=1,i-1),n1,n2,(F(j),j=i+1,L),0/) if (k1/=0) then ; call RAD(-ar,-n2,-n1,k1) ; end if else

FCUR=(/L+1,(F(j),j=1,i-1),-n2,-n1,(F(j),j=i+1,L),0/) if (k1/=0) then ; call RAD(-ar,n1,n2,k1) ; end if end if ;

T=(/1,i,NS,k1/)

end FUNCTION CouperFacette

(16)

integer*4 FUNCTION Sortie(OldFac) integer*4, intent(in) : : OldFac

integer*4, dimension(1 :4) : : T integer*4, dimension(1 :Sare) : : B, C integer*4 : : i, j, k, L, sk, NewAre, NewFac

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! T=(ar,i,ns,k1). sortie entre arete A(i) et A(i+1) au sommet ns

! ! Si ar=0 alors sortie sommet ns avec k1=0

! ! Si ar=1 sortie arête déjà coupé (i) au sommet ns vers la facette k1

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! T=CouperFacette()

NA=NA+1 ; NewAre=NA ; NA=NA+T(1) NF=NF+1 ; NewFac=NF

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! créer la nouvelle arête en récupérant sommet debut de A(1). Le sommet n est ns

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! j=FCUR(1) ; i=T(2)

if (j>0) then ; B=Are( :,j) ; sk=B(SD) ; else ; B=Are( :,-j) ; sk=B(SF)

end if

C=(/OldFac,NewFac,sk,T(3),NAV,0/) ; ! très moche mais ecace.

Are( :,NewAre)=C

if (NAV/=0) then ; Are(AP,NAV)=NewAre ; end if NAV=NewAre

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! remplir les contenus de Fac(NewFac) et Fac(OldFac)

! ! Ne pas oublier les mises à jour des Are(i) à partir de A

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! L=FCUR(0)

do k=1,i j=FCUR(k)

if (j>0) then ; Are(FG,j)=NewFac ; else ; Are(FD,-j)=NewFac ; end if end do

Fac( :,NewFac)=(/i+1 ,(FCUR(k), k=1,i), -NewAre,0,0/) Fac( :,OldFac)=(/L-i+1, NewAre,(FCUR(k),k=i+1,L),0,0/) cnt = max(cnt,i+1,l-i+1)

if (T(1)==0) then

Sortie=SortieSommet(T(3),FCUR(i),FCUR(i+1)) else

Sortie=SortieArete(T(4)) end if

end FUNCTION Sortie

(17)

integer*4 FUNCTION SortieSommet(s,ad,ag) integer*4, intent(in) : : s, ad, ag

integer*4 : : i, j, kn

integer*4, dimension(1 :Sare) : : A

if (ad<0) then ; kn=AV ; else ; kn=AP ; end if A=Are( :,iabs(ad)) ; j=A(kn)

if (ag>0) then ; kn=AV ; else ; kn=AP ; end if A=Are( :,iabs(ag)) ; i=A(kn)

kn=FacetteCommune(i,j)

if (kn>0) then ; FCUR(0 :sfac)=ASF(s,Fac( :,kn)) ; end if SortieSommet=kn

end FUNCTION SortieSommet integer*4 FUNCTION SortieArete(k)

integer*4, intent(in) : : k integer*4 : : nb,y,z

if (k/=0) then FCUR=FCUR1 else

y=Som(2,NS) ; z=Som(3,NS)

if (y*CNBG(3)-z*CNBG(2)==0) then nb=BordBP(0) ; nb=nb+1

BordBP(nb)=NA ; BordBP(0)=nb else if (y*CNHG(3)-z*CNHG(2)==0) then

nb=BordHN(0) ; nb=nb+1

BordHN(nb)=NA ; BordHN(0)=nb else

nb=BordD(0) ; nb=nb+1 BordD(nb)=NA ; BordD(0)=nb end if

end if

SortieArete=k

end FUNCTION SortieArete

(18)

integer*4 FUNCTION VaGauche(ia,ka) integer*4, intent(in) : : ia,ka

integer*4 : : i,ib,k

integer*4, dimension(1 :Sare) : : A integer*4, dimension(0 :Sfac) : : F

k=ka ; F=Fac( :,k) ; ib=F(0) do

if (ia==0) then

print*, "... va gauche",u,v,w,ka

stop

end if

F=ASF(ia,F)

if (sgn(F)<0) then ; FCUR(0 :sfac)=F ; exit ; end if i=F(ib) ; A=Are( :,iabs(i)) ;

if (i>0) then ; k=A(FD) ; else ; k=A(FG) ; end if if (k>0) then

F=Fac( :,k) ; ib=F(0) else

print*, "bug dans VaGauche : ia = ",trim(cvis(ia))," ka = ",trim(cvis(ka)) print*, "Droite",u,v,w

print*,"facette ",F

stop

end if end do VaGauche=k

end FUNCTION VaGauche

SUBROUTINE RemplaceArete(ar,n1,n2,k) integer*4, intent(in) : : ar, n1, n2, k

integer*4 : : i, j, L

integer*4, dimension(0 :Sfac) : : F F=Fac( :,k) ; L=F(0)

do i=1,L ; if (ar==F(i)) then ; exit ; end if ; end do FCUR=(/L+1,n2, (F(j),j=i+1,L), (F(j),j=1,i-1),n1,0/) end SUBROUTINE RemplaceArete

(19)

integer*4 FUNCTION VaDroite(ia,ka) integer*4, intent(in) : : ia,ka

integer*4 : : i,ib,k

integer*4, dimension(1 :Sare) : : A integer*4, dimension(0 :Sfac) : : F

k=ka ; F=Fac( :,k) ; ib=F(0) do

if (ia==0) then

print*, "... va droite",u,v,w,ka

stop

end if

F=ASF(ia,F)

if (sgn(F)<0) then ; FCUR(0 :sfac)=F ; exit ; end if i=F(1) ; A=Are( :,iabs(i))

if (i>0) then ; k=A(FD) ; else ; k=A(FG) ; end if if (k>0) then

F=Fac( :,k) ; ib=F(0) else

print*, "bug dans VaDroite : ia = ",trim(cvis(ia))," ka = ",trim(cvis(ka)) print*, "Droite",u,v,w

print*,"facette ",F

stop

end if end do VaDroite=k

end FUNCTION Vadroite

SUBROUTINE RAD(ar,n1,n2,k) integer*4, intent(in) : : ar, n1, n2, k integer*4 : : i, j, L

integer*4, dimension(0 :Sfac) : : F F=Fac( :,k) ; L=F(0) ;

do i=1,L ; if (ar==F(i)) then ; exit ; end if ; end do FCUR1=(/L+1,n2,(F(j),j=i+1,L),(F(j),j=1,i-1),n1,0/) end SUBROUTINE RAD

(20)

SUBROUTINE CoupeBord(Bord,brd) integer*4, intent(in) : : brd

integer*4, intent(inout), dimension(0 :) : : Bord integer*4 : : nb,i,k,ia,ib,ja,jb,jd,jf,g

integer*4, dimension(1 :Sare) : : A,AA integer*4, dimension(1 :Ssom) : : B,C

NAV=0 ; nb=Bord(0) ; g=1 do i=1,nb

ia=Bord(i) ; A=Are( :,ia)

ja=A(SD) ; B=Som( :,ja) ; jd=u*B(1)+v*B(2)-w*B(3) jb=A(SF) ; C=Som( :,jb) ; jf=u*C(1)+v*C(2)-w*C(3) if ((jd==0).OR.(jf==0)) then ; g=0 ; exit ; end if

if((jd>0.AND.jf<0).OR.(jd<0.AND.jf>0)) then ; g=-1 ; exit ; end if end do ;

if (g>0) then

print*, "bug dans coupebord"

stop

end if

if (g<0) then ! On traverse l'arête 'ia'.

nb=nb+1 ; Bord(0)=nb NA=NA+1 ; Bord(nb)=NA

NS=NS+1 ; Som( :,NS)=Intersec(jd,jf,B,C) AA=A ; A(SF)=NS ; AA(SD)= NS

A(AP)=NA ; AA(AV)=ia ;

ib=AA(AP) ; if (ib>0) then ; Are(AV,ib)=NA ; end if Are( :,NA)=AA ; Are( :,ia)=A ;

if (brd==BBP) then ; k=A(FG) ; call RemplaceArete(ia,ia,NA,k) else ; k=A(FD) ; call RemplaceArete(-ia,-NA,-ia,k)

end if

else ! on a coupé le bord en un sommet

if (jf==0) then ; ia=A(AP) ; A=Are( :,ia) ; ja=A(SD) ; end if if (brd==BBP) then ; k=A(FG) ; k=VaGauche(ja,k)

else if (brd==BHN) then ; k=A(FD) ; k=VaDroite(ja,k) else if (brd==BGP) then ; k=A(FD) ; k=VaDroite(ja,k)

else if (brd==BGN) then ; ia=A(AV) ; A=Are( :,ia) ; k=A(FD) ; k=VaGauche(ja,k) end if

end if

do while (k/=0)

(21)

if (NA.GE.namax-2) then print*, "Débordement NA", NA print*," NS,NF", NS, NF print*, "droite ",u,v,w

stop

else ; counter=counter+1 ; k=Sortie(k) end if

end do

end SUBROUTINE CoupeBord FUNCTION cvis(n) result(ch)

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! renvoie une chaine de caractère

! ! "ch" représentant l'entier "n"

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! integer*4, intent(in) : : n

character(len=maxch) : : ch

character(len=10) : : digit="0123456789"

integer*4 : : i,j,k,m ch=chmax ; k=abs(n)

if (k==0) then ; m=2 ; else ; m=oor(log10(real(k)))+2 ; end if do i=m,2,-1 ; j=mod(k,10) ; k=k/10 ; ch(i :i)=digit(j+1 :j+1) ; end do

if (n<0) then ; ch(1 :1)="-" ; else ; do i=1,m ; ch(i :i)=ch(i+1 :i+1) ; end do ; end if end FUNCTION cvis

(22)

SUBROUTINE initdata

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! initialisation des données au carré

! ! (0,0),(1,0),(0,1),(1,1). Le cas "m=1,n=1"

! ! est complété en début du programme

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ns=4 ; na=4 ; nf=1

Som=0 ; are=0 ; fac=0

CNBG=(/0,0,1/) ; CNHG=(/0,1,opt/) CNBD=(/1,0,opt/) ; CNHD=(/1,1,opt/) Som( :,1)=CNBG ; Som( :,2)=CNBD Som( :,3)=CNHG ; Som( :,4)=CNHD

are( :,1)=(/1,0,1,2,0,0/) ;are( :,2)=(/1,0,2,4,0,0/) are( :,3)=(/0,1,1,3,0,0/) ;are( :,4)=(/0,1,3,4,0,0/) fac(0 :4,1)=(/4,1,2,-4,-3/)

BordBP(0)=1 ; BordHN(0)=1 ; BordG(0)=1 ; BordD(0)=1 BordBP(1)=1 ; BordHN(1)=4 ; BordG(1)=3 ; BordD(1)=2 end SUBROUTINE initdata

(23)

SUBROUTINE ache

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !

! ! ache les données sur l'écran

! ! et les écrit dans le chier

! ! "G :/SBN/bin/farey.txt"

! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! integer*4 : : i,j

print*, ns,",",na,",",nf

do i=1,ns ; print*,i, (trim(cvis(som(j,i)))//" ",j=1,Ssom) ; end do do i=1,na ; print*,i, (trim(cvis(are(j,i)))//" ",j=1,Sare) ; end do do i=1,nf ; print*,i, (trim(cvis(fac(j,i)))//" ",j=0,fac(0,i)) ; end do print*, "BordG", (trim(cvis(BordG(j)))//" ",j=0,BordG(0)) print*, "BordD", (trim(cvis(BordD(j)))//" ",j=0,BordD(0)) print*, "BordBP", (trim(cvis(BordBP(j)))//" ",j=0,BordBP(0)) print*, "BordHN", (trim(cvis(BordHN(j)))//" ",j=0,BordHN(0))

OPEN (UNIT=1,FILE='G :/SBN/bin/farey.txt',STATUS='REPLACE') write(1,*) ns,",",na,",",nf

do i=1,ns ; write(1,*)i,",", ((trim(cvis(som(j,i)))//","),j=1,Ssom) ; end do do i=1,na ; write(1,*)i,",", (trim(cvis(are(j,i)))//",",j=1,Sare) ; end do do i=1,nf ; write(1,*)i, ",",(trim(cvis(fac(j,i)))//",",j=0,fac(0,i)) ; end do write(1,*) "BordG ",",", (trim(cvis(BordG(j)))//",",j=0,BordG(0)) write(1,*) "BordD ",",", (trim(cvis(BordD(j)))//",",j=0,BordD(0)) write(1,*) "BordBP ",",", (trim(cvis(BordBP(j)))//",",j=0,BordBP(0)) write(1,*) "BordHN ",",", (trim(cvis(BordHN(j)))//",",j=0,BordHN(0)) close(1)

end SUBROUTINE ache

end module droitefarey

(24)

2. Le programme : farey.f90

program fareymn

use DroiteFarey integer*4 : : m,n,u,v,w m = 3 ; n = 2

print*, "entrée programme"

call initdata call droiteN(1,1,1) call droiteP(1,-1,0) call ache

print*," cas u <= 1"

do v = 2,n

do w = 1,v-1 ; call droiteH(0, v, w) ; print*," H ",cnt ; end do do w = 1,v ; call droiteN(1, v, w) ; print*," N ",cnt ; end do do w = -v+1,0 ; call droiteP(1,-v, w) ; print*," P ",cnt ; end do end do

print*," cas u>1 "

do u = 2,m

do w = 1,u-1 ; call droiteV(u, 0, w) ; print*," V ",cnt ; end do do v=1,n

do w = 1,u+v-1 ; call droiteN(u, v, w) ; print*," N ",cnt ; end do do w = -v+1,u-1 ; call droiteP(u,-v, w) ; print*," P ",cnt ; end do end do end do

! call ache

print*, "m = ",m,"n = ",n

print*, "ns = ",ns, "na = ",na,"nf = ",nf

end program fareymn

*2

2. La mauvaise version

(25)

program fareymn

use DroiteFarey integer*4 : : m,n,u,v,w m = 3 ; n = 2

print*, "entrée programme"

call initdata call droiteN(1,1,1) call droiteP(1,-1,0) call ache

print*," cas u <= 1"

do v = 2,n

do w = 1,v ; call droiteN(1, v, w) ; print*," N ",cnt ; end do do w = -v+1,0 ; call droiteP(1,-v, w) ; print*," P ",cnt ; end do do w = 1,v-1 ; call droiteH(0, v, w) ; print*," H ",cnt ; end do end do

print*," cas u>1 "

do u = 2,m do v = 1,n

do w = 1,u+v-1 ; call droiteN(u, v, w) ; print*," N ",cnt ; end do do w = -v+1,u-1 ; call droiteP(u,-v, w) ; print*," P ",cnt ; end do do w = 1,u-1 ; call droiteV(u, 0, w) ; print*," V ",cnt ; end do end do

end do

! call ache

print*, "m = ",m,"n = ",n

print*, "ns = ",ns, "na = ",na,"nf = ",nf

end program fareymn

**3

3. La bonne version

(26)

Références :

[1] Saab Abou-Jaoudé, Forme des connexes de Farey.

/arxiv.org/pdf/1312.4306.pdf (2013)

[2] Saab Abou-Jaoudé, Dénombrement de triplets d'entiers NDN.PDF (2014) diusé sur Whaller.com et à l'université de Strasbourg.

[3] Malcolm Douglas McIlroy. A note on discrete representation of lines.

ATT Technical Journal, 64(2) :481-490, 2984.

[4] Alain Daurat, Mohamed Tajine, Mahdi Zouaoui. About the frequen- cies of some patterns in digital planes. application to area estimators.

Computer Graphics, 2008.

Références

Documents relatifs

Réponse sociale de type visuel (vagues, lettres, pseudo lettres, lettres du prénom) C Trace d'encodage du sonore sans orthographe normée. (transcription non syllabique ou

Faux car la courbe représentative de la fonction carrée s'appelle une parabole.. 2 ) C g est une droite. Cette proposition

L’espace est rapporté au repère orthonormé direct

– Ensuite, l’un(e) explique sa résolution de [→] à l’autre : que faites-vous à chaque étape et pourquoi ; exemple : « Je veux isoler tel terme, pour cela je soustrais A(s + t)

Faire le tableau de variation de f et tracer sa courbe représentative sans oublier de tracer les

Pour le faire nous faisons un retour sur les polygones convexes plan à bord orienté en démontrant que si deux vecteurs côtés consécutifs du bord d'un tel polygone ne sont jamais dans

On dénit les segments de Farey comme étant les segments joignant deux sommets de Farey consédutifs sur une droite de Farey. Une droite de Farey passant par un sommets de Farey A

Le triplet (massif 1), correspond au signal de 3 protons équivalents entourés de 2 voisins. Ce signal apparaît alors sous la forme de (2+1) pics, soit