• Aucun résultat trouvé

5.5 Automates virtuels

5.5.2 L’automate des permutations

L’automate ne poss`ede qu’un ´etat, il est initial et a pour identifiant 1:

State src() const { return 1;

}

Le curseur ne peut ˆetre positionn´e que sur l’´etat initial qui est aussi terminal :

bool src_final() const { return true;

}

L’automate ´etant complet, δ1(q) est toujours d´efini, quelque soitq. Il est donc impossible que le curseur se retrouve sur l’´etat puits :

bool sink() const { return false; }

Le typage statique des patrons de classes et de fonctions autorise une optimisation compl`ete du code `a la compilation : les appels aux fonctions simples sont supprim´es grˆace `a l’inlining ainsi que celles ne renvoyant que des valeurs constantes connues au moment de l’instanciation du code. Ceci a pour effet de r´eduire `a n´eant le coˆut d’utilisation en temps et en espace d’un tel curseur.

5.5.2 L’automate des permutations

Prenons par exemple l’automate reconnaissant toutes les permutations du mot 012. La figure 5.4 montre l’arbre et l’automate minimal reconnaissant le langage {012, 021, 102, 120, 201, 210}.

La table de la figure 5.5 indique les tailles de l’arbre et de l’automate minimal reconnaissant les permutations d’un mot de longueur npour 5≤n≤10.

Le nombre d’´etats et de transitions de l’arbre est r´edhibitoire. Au-del`a den= 8 l’espace m´e-moire consomm´e mˆeme par les repr´esentations d’automates les plus ´economiques devient d´e-raisonnable car le nombre d’´etats et de transitions croit factoriellement. Cependant, l’extrˆeme redondance du langage reconnu entraine une diminution tr`es appr´eciable `a la minimisation,

88 CHAPITRE 5. LES ADAPTATEURS 2 1 2 1 0 1 2 2 0 2 0 1 0 1 0 2 1 2 1 0 1 2 0 2 0 0 1

Fig. 5.4 – L’arbre et l’automate minimal reconnaissant les permutations du mot 012 Arbre Automate minimal

Longueur Etats´ Transitions Etats´ Transitions

5 326 325 32 80 6 1957 1956 64 192 7 13700 13699 128 448 8 109601 109600 256 1024 9 986410 986409 512 2304 10 9864101 9864100 1024 5120

Fig.5.5 – Tailles des automates reconnaissant les permutations d’un mot de longueur n

mais ce n’est que reculer pour mieux sauter. Clairement les nombres d’´etats et de transitions de l’automate minimal suivent une loi exponentielle en fonction de la longueur du mot n:

|Q|= 2n

|∆|= n|Q|

2 =

n2n

2

Cette complexit´e spatiale nettement meilleure que celle de l’arbre reste exponentielle ce qui n’est g´en´eralement pas viable d’un point de vue pratique. La solution interm´edaire consiste `a construire directement l’automate minimal sans passer par la minimisation de l’arbre. Consid´erons l’automateA ayant pour alphabet Σ et pour ensemble d’´etats des parties de Σ :

A= (Σ, P(Σ),∅,{Σ},∆). L’´etat initial est l’ensemble vide et seul l’´etat Σ est final. L’ensemble des transitions ∆ est d´efini par :

(q, σ, p)∈∆⇔σ ∈Σ\q et p=q∪ {σ}

L’automate des permutations de{0,1,2}apparait `a la figure 5.6. Les ´etats y sont repr´esent´es par les partie de Σ correspondantes. Cet automate reconnaˆıt l’ensemble des permutations de Σ et est minimal. On en d´eduit l’algorithme de construction 5.1 enO(2|Σ|).

5.5. AUTOMATES VIRTUELS 89 0,1,2 0,1 2 0 1 0,2 2 1 0 1 1 2 2 0 1,2 2 0 0 1

Fig.5.6 – L’automate des permutations A({0,1,2}, P({0,1,2}),∅,{{0,1,2}},∆)

Algorithme 5.1 Permutations

Entr´ee : A(Σ, Q, i, F,∆), q∈P(Σ)

Q←Q∪q {Cr´eation d’un ´etat}

si q =∅ alors

i←q {Ajout de l’´etat initial}

fin si

si q = Σ alors

F ← {q} {Ajout de l’´etat final}

fin si

pour tout σ∈Σ\q faire

Permutations(A,q∪ {σ})

∆←∆∪(q, σ,(q∪ {σ})){Ajout d’une transition}

fin pour

Avec un temps de calcul exponentiel, cet algorithme ne constitue qu’une solution bancale au probl`eme. L’id´eal reste d’utiliser un curseur qui nous permettra tout simplement de nous passer de l’automate en incorporant une variante incr´ementale de l’algorithme de construction. Consid´eront l’impl´ementation des sous-ensembles suivante :

– Un sous-ensembleEid’un ensembleEest repr´esent´e par un vecteur de bitsede longueur

|E|. Par soucis de simplification, on ne consid`erera que des sous-ensembles de taille inf´erieure `a 33 repr´esentables par des entiers long de 32 bits.

– L’op´erateur<<d´ecale les bits d’un entieredenpositions vers la gauche et>>les d´ecale vers la droite, i.e. (e << 1) == (2*e) et (e >> 1) == (e/2). L’op´erateur binaire |effectue un OU bit `a bit des deux op´erandes et&un ET bit `a bit.

– On assigne un entier positif uniquej `a chaque ´el´ementx∈E etx∈Ei si et seulement si lejeme` bit de l’entier le repr´esentant est `a 1. Il en d´ecoule pour un ´el´ementxd’indice xet deux sous-ensemblesaetb que :

90 CHAPITRE 5. LES ADAPTATEURS {x} = 1 << x = 0 a∪b = a | b a∩b = a & b x∈a⇔({x} ∩a)6=∅ = (1 << x) & a != 0

Soit c un curseur pointant sur un ´etat q de l’automate des permutations d’un alphabet `a 32 lettres. Les ´etats sont des sous-ensembles de Σ et sont donc repr´esent´es par des entiers long non sign´es et l’op´erateur pr´efixe ~inverse les bits d’un entier. De plus, cmaintient une variable bool´eennepuitsvrai siqest l’´etat nul. Le code suivant impl´emente le comportement de c.

L’´etat courant est tout simplement q, le sous-ensemble de Σ :

State src() const { return q;

}

Un ´etat est terminal si l’ensemble qui lui correspond contient toutes les lettres de l’alphabet donc s’il ne contient que des bits `a 1 :

bool src_final() const { return q == ~0;

}

On ne peut avancer sur une transition ´etiquet´ee par a que si le sous-ensemble courant ne contient pas cette lettre. Si {a} ∩q =∅la transition est d´efinie et on ajoute a`a q par union, sinon on positionne `avraila variable bool´eenne puits:

bool forward(int a) { if (1 << a & q == 0) q = q | 1 << a; else puits = true; return !puits; }

Enfin, on interroge la variable puitspour savoir si cpointe sur l’´etat nul :

bool sink() const { return puits; }

5.5. AUTOMATES VIRTUELS 91 Chaque ´el´ement du sous-ensemble q de Σ est repr´esent´e par un bit `a 1. L’´etat initial de l’automate ´etant l’ensemble vide il est repr´esent´e par0et l’´etat final est l’entier dont tous les bits sont `a 1, soit ~0.

permutation_cursor c;

c = 0; // positionnement sur l’´etat initial c = ~0; // positionnement sur l’´etat final