Devoir maison : Automates pondérés À rendre le mercredi 10 mai Les automates pondérés sont, en quelque sort, une généralisation des fonctions séquentielles : ils permettent d’associer des valeurs tirées d’un demi-anneau aux calculs d’un automate. Contrairement aux fonctions séquentielles, les automates sous-jacents peuvent être non-déterministes. Demi-anneaux. Un demi-anneau est une structure algébrique S = hA, +, ×, 0̄, 1̄i tel que (i) hA, +, 0̄i est un monoı̈de commutatif ; (ii) hA, ×, 1̄i est un monoı̈de ; (iii) pour tout a, b, c ∈ A, on a a × (b + c) = (a × b) + (a × c) et (a + b) × c = (a × c) + (b × c) (loi de distributivité), et (iv) pour tout a ∈ A, on a a × 0̄ = 0̄ × a = 0̄ (0̄ est absorbant). Parfois on omet ×, c’est à dire ab denote a × b. Un demi-anneau S est commutatif si ab = ba pour tout a, b ∈ A. Il est dit borné idempotent si (i) + est idempotent ; (ii) l’ordre partiel v défini par a v b ssi a + b = a ne contient aucune chaı̂ne infinie descendante. Automates finis pondérés . Un automate fini pondéré (AFP) est défini par A = hQ, Σ, S, λ, µ, γi où Q est un ensemble d’états fini, Σ un alphabet fini, S = hA, +, ×, 0̄, 1̄i un demi-anneau, λ, γ : Q → A sont des fonctions d’entrée et sortie, respectivement, et µ : (Q × Σ × Q) → A une fonction de transition. a an Le poids d’un chemin C := q0 →1 qQ 1 · · · → qn (pour n ≥ 0) étiquetté avec le mot a1 · · · an , est le produit kCk := λ(q0 ) × ni=1 µ(qi−1 , ai , qi ) × γ(qn ). Le poids d’un état q est la somme (par rapport à +) de tous les chemins partant de q. Le poids d’un mot w, noté [[A]](w), est la somme de tous les chemins étiquettés par w. La sémantique de A est donc la fonction [[A]] : Σ∗ → S. a/0 0 a/1 a/1 0 b/0 a/0 b/0 0 0 b/0 Figure 1 – Un chemin dans A1 calcule la longueur d’un bloc de a consécutifs. 1 Exemple. La notation graphique, à l’image de l’automate A1 dans la Figure 1, est similaire à celle des fonctions séquentielles, avec λ, γ indiqués par des flèches entrants et sortants sur les états. On omet les éléments de λ, µ, γ avec poids 0̄. Interprètons A1 dans le demi-anneau hIN ∪ {−∞}, max, +, −∞, 0i. Dans cette interprétation, [[A1 ]](w) donne le nombre maximal de a consécutifs dans w. Remarques. Une transition avec poids 0̄ est comme une transition ‘non-existante’ (tout chemin passant par une telle transition aura poids 0̄). Du même, seuls les chemins partant d’un état q avec λ(q) 6= 0̄ et terminant à un état q 0 avec γ(q 0 ) 6= 0̄ contribuent un poids ‘intéressant’ à [[A]]. Par ailleurs, notons IB = h{0, 1}, ∨, ∧, ⊥, >i le demi-anneau booléen. Il est évident que, étant donné un automate fini A, on peut construire un AFP A0 sur IB tel que [[A0 ]](w) = 1 ssi w ∈ L(A). Il est parfois intéressant d’interpréter les transitions comme une function µ : Σ → S Q×Q qui associe à une lettre a une matrice µ(a) tel que µ(a)p,q indique le poids de la transition hp, a, qi. Dans ce cas, µ s’étend naturellement sur des mots de Σ∗ , et on peut noter [[A]](w) = λ · µ(w) · γ (avec λ vecteur de ligne et γ vecteur de colonne). Cette interprétation est admis quand son usage est non-ambigu. Quelques exemples 1. Soit Σ = {a, b}, w ∈ Σ∗ , et |w|a le nombre de a dans w. Construisez un AFP A sur Σ et IN tel que [[A]](w) = 2|w|a . 2. Soit A une fonction séquentielle. Construire un AFP A0 avec [[A0 ]](w) = [[A]](w) si ce dernier est défini et [[A0 ]](w) = ⊥ sinon. 3. Soit A un automate fini non-déterministe sur Σ. Pour un mot w ∈ Σ∗ , soit pA (w) le nombre de chemins acceptant pour w. Par exemple, si on interprète la Figure 1 comme un automate non-déterministe (en ignorant les poids), alors p(baab) = 3 car on peut choisir de basculer vers le deuxième état avec le premier a, le deuxième, ou pas de tout. Construisez, pour un A donné, un AFP A0 (avec un demi-anneau approprié) tel que [[A0 ]] = pA . Une petite application On considère une application à l’analyse statique de programmes. Soit V un ensemble fini de variables. Un instructions sur V est soit une affectation x := e(V 0 ), soit un branchement if e(V 0 ) avec x ∈ V, V 0 ⊆ V et e une expression quelconque dans laquelle les seuls variables sont celles de V 0 . L’ensemble des instructions est noté I(V ). Un graph de flot de contrôle G est un automate fini déterministe sur I(V ), avec un seul état initial q0 (sans transitions entrantes) et un seul état acceptant qf (sans transitions sortantes). G représente donc le comportement d’un programme simple qui manipule les variables de V et qui peut brancher en fonction de leurs valeurs. 2 x := x + y if w < 2 z := 2 · x Figure 2 – Exemple d’un chemin dans un graphe de flot de contrôle. Soit C un chemin de G terminant dans qf . Une variable x est dite vivante dans C si C contient une instruction qui utilise x dans une expression avant que x ne soit redéfinie par une affectation x := e(V 0 ). Par exemple, dans le chemin illustré dans la Figure 2, les variables x, y, w sont vivantes, mais z ne l’est pas (z est morte). Une variable x est dite vivante dans un état q s’il existe un chemin de q vers qf où x est vivante. Cette notion a des applications évidentes pour l’optimisation des compilateurs. Notons que pour cette question, la forme exacte des expressions n’importe pas, du coup dans ce qui suit on peut bien abstraire toutes les expressions vers une forme e(V 0 ). 4. Trouvez un demi-anneau S approprié pour calculer les variables vivantes et construisez un AFP G0 sur I(V ) et S tel que : (i) G0 garde les états de G ; (ii) S est borné idempotent ; (iii) pour tout chemin C de G0 terminant dans qf , kCk indique les variables vivantes dans C ; (iv) pour tout état q, kqk indique les variables vivantes dans q. Pour (iii) et (iv), il suffit que les variables vivantes pourront être recupérées depuis les poids par une projection simple. 5. Proposez un algorithme pour calculer le vecteur des valeurs kqk. Prouvez en particulier que votre algorithme termine bien. Donnez une estimation de complexité pour votre algorithme. Propriétés de clôture Soit S = hA, +, ×, 0̄, 1̄i et S 0 = hA0 , ⊕, ⊗, 0̄0 , 1̄0 i deux demi-anneaux. On appelle h : A → A0 morphisme de S vers S 0 si h(0̄) = 0̄0 , h(1̄) = 1̄0 , h(a + b) = h(a) ⊕ h(b) et h(a × b) = h(a) ⊗ h(b). Une fonction f : Σ∗ → A est dite reconnaissable s’il existe un AFP A sur Σ et S tel que [[A]] = f . Soient f, g : Σ∗ → A. On définit h(f ), f +g, f ×g par (h(f ))(w) = h(f (w)), (f + g)(w) = f (w) + g(w) et (f × g)(w) = f (w) × g(w). 5. Montrer ou réfuter : si f est reconnaissable et h un morphisme, alors h(f ) est reconnaissable. 6. Montrer ou réfuter : si f et g sont reconnaissables, f + g l’est aussi. 3 7. Montrer que si f et g sont reconnaissables et S commutatif, alors f × g est reconnaissable. 8. Montrer que le précédent n’est pas vrai en général sans commutativité. 4