Dérivée de Brzozowski

En Informatique théorique, et en particulier en théorie des automates finis, la dérivée de Brzozowski est un outil qui permet de construire un automate fini à partir d'une expression rationnelle ou régulière.

Elle tient son nom de l'informaticien Janusz A. Brzozowski qui, dans un article datant de 1964[1], en a étudié ses propriétés et a démontré que l’algorithme de calcul se termine.

Terminologie

La dérivée de Brzozowski s'applique à des expressions rationnelles, en relation avec les notions de langages formels et d'automates finis. On résume ici les définitions de ces notions.

Mots

Article détaillé : Mot (mathématiques).

Un alphabet A {\displaystyle A} est un ensemble quelconque, en général fini. On appelle lettres ses éléments. Un mot sur l'alphabet A {\displaystyle A} est une suite finie de lettres. On appelle mot vide, et on le note ε {\displaystyle \varepsilon } , le mot qui ne comporte aucune lettre.

La concaténation de deux mots w 1 {\displaystyle w_{1}} et w 2 {\displaystyle w_{2}} est le mot constitué des lettres de w 1 {\displaystyle w_{1}} suivies des lettres de w 2 {\displaystyle w_{2}} . On le note par simple juxtaposition w 1 w 2 {\displaystyle w_{1}w_{2}} .

Langage quotient

Article détaillé : langage formel.

Un langage (formel) sur alphabet A {\displaystyle A} est un ensemble de mots sur A {\displaystyle A} .

Pour un langage L {\displaystyle L} sur un alphabet A {\displaystyle A} et un mot u {\displaystyle u} sur A {\displaystyle A} , on appelle langage quotient (aussi langage résiduel ou quotient à gauche) de L {\displaystyle L} par rapport à u {\displaystyle u} l'ensemble des mots x {\displaystyle x} tels que u x {\displaystyle ux} est un mot de L {\displaystyle L} ; on le note u 1 L {\displaystyle u^{-1}L} . Formellement,

u 1 L = { x A u x L } {\displaystyle u^{-1}L=\{x\in A^{*}\mid ux\in L\}} .

Les formules suivantes sont utiles :

ε 1 L = L {\displaystyle \varepsilon ^{-1}L=L}  ; ( u v ) 1 L = v 1 u 1 L {\displaystyle (uv)^{-1}L=v^{-1}u^{-1}L}

La notation de langage résiduel est étendue aux parties par

X 1 L = u X u 1 L {\displaystyle X^{-1}L=\bigcup _{u\in X}u^{-1}L} .

Expressions régulières

Article détaillé : expression rationnelle.

Soit A {\displaystyle A} un alphabet fini. Les expressions régulières sur A {\displaystyle A} sont les expressions obtenues par récurrence comme suit :

  1. Les symboles 0 {\displaystyle 0} , 1 {\displaystyle 1} , et toute lettre a {\displaystyle a} pour a A {\displaystyle a\in A} sont de expressions régulières ;
  2. si e {\displaystyle e} et f {\displaystyle f} sont des expressions régulières, alors e + f {\displaystyle e+f} , e f {\displaystyle e\cdot f} (aussi noté e f {\displaystyle ef} ) et e {\displaystyle e^{*}} sont des expressions régulières;
  3. toute expression régulière est obtenue, à partir des expressions atomiques (1), par un nombre fini d'applications des règles de composition (2).

D'autres opérateurs, comme l'intersection ou la négation, sont ajoutées dans les applications aux traitements de textes, ainsi que d'autres extensions qui n'interviennent pas dans le contexte présent.

Langage dénoté par une expression

Les expressions régulières servent à décrire de façon concise un langage formel. En particulier, une expression rationnelle (qui est toujours finie) peut décrire un langage infini. Il est important de distinguer le l'expression et le langage qu'elle dénote, puisque qu'un même langage peut être décrit de multiples manières. C'est à cela que servent les symboles 0 {\displaystyle 0} et 1 {\displaystyle 1} , et la représentation de l’union par le symbole d'addition

Le langage dénoté par une expression e {\displaystyle e} est noté L ( e ) {\displaystyle L(e)} . Il est défini par récurrence sur la structure de l'expression comme suit:

  1. L ( 0 ) = {\displaystyle L(0)=\emptyset } , L ( 1 ) = { ε } {\displaystyle L(1)=\{\varepsilon \}} (le mot vide), L ( a ) = { a } {\displaystyle L(a)=\{a\}} pour a A {\displaystyle a\in A}
  2. L ( e + f ) = L ( e ) L ( f ) {\displaystyle L(e+f)=L(e)\cup L(f)} , L ( e f ) = L ( e ) L ( f ) {\displaystyle L(e\cdot f)=L(e)L(f)} , et L ( e ) = L ( e ) {\displaystyle L(e^{*})=L(e)^{*}} .

Notons qu'une expression régulière ne dénote qu'un seul langage, mais un même langage peut être dénoté par plusieurs expressions régulières différentes. Par exemple, les expressions ( a + b ) {\displaystyle (a+b)^{*}} et ( a b ) a {\displaystyle (a^{*}b)^{*}a^{*}} dénotent le même langage.

Dérivée d'une expression régulière

La dérivée de Brzozowski (ou dérivée tout court) d'une expression régulière est à nouveau une expression régulière. Le langage dénoté par l'expression dérivée est le quotient gauche (aussi appelé langage dérivé parfois) du langage dénoté par l'expression de départ. Les deux opérations de dérivation opèrent donc « en parallèle », l'une sur les expressions, l'autre sur les langages. Autant les expressions peuvent se manipuler par des algorithmes effectifs, autant la manipulation des langages n'est réalisable qu’indirectement, par une de leurs représentations finies.

Des applications concrètes de ces algorithmes ont vu le jour dans le contexte de l'analyse de textes XML[2].

Définition

Les dérivées sont indexées par un mot sur l'alphabet A {\displaystyle A} . Le but est d'obtenir, pour un mot u {\displaystyle u} et une expression e {\displaystyle e} , une nouvelle expression e {\displaystyle e'} telle que le langage L ( e ) {\displaystyle L(e')} soit le langage des mots de L ( e ) {\displaystyle L(e)} privés du préfixe u {\displaystyle u} . La dérivée par rapport à un mot u {\displaystyle u} est notée d u {\displaystyle d_{u}} [3]. L'objectif est donc de préserver la relation

L ( d u ( e ) ) = u 1 L ( e ) {\displaystyle L(d_{u}(e))=u^{-1}L(e)} ,

où, comme rappelé ci-dessus, on a u 1 L = { x A u x L } {\displaystyle u^{-1}L=\{x\in A^{*}\mid ux\in L\}} .

  • La dérivée par rapport à une lettre a {\displaystyle a} est définie par :
    1. d a ( 0 ) = d a ( 1 ) = 0 {\displaystyle d_{a}(0)=d_{a}(1)=0} , d a ( a ) = 1 {\displaystyle d_{a}(a)=1} , d a ( b ) = 0 {\displaystyle d_{a}(b)=0} pour toute lettre b a {\displaystyle b\neq a}
    2. d a ( e + f ) = d a ( e ) + d a ( f ) {\displaystyle d_{a}(e+f)=d_{a}(e)+d_{a}(f)} , d a ( e ) = d a ( e ) e {\displaystyle d_{a}(e^{*})=d_{a}(e)\cdot e^{*}} et
    d a ( e f ) = { d a ( e ) f  si  ε L ( e ) d a ( e ) f + d a ( f )  sinon.  {\displaystyle d_{a}(e\cdot f)={\begin{cases}d_{a}(e)\cdot f&{\text{ si }}\varepsilon \notin L(e)\\d_{a}(e)\cdot f+d_{a}(f)&{\text{ sinon. }}\end{cases}}}
  • La dérivée par rapport à un mot u a {\displaystyle ua} est définie par récurrence par la composition des dérivations par :
d u a = d a d u {\displaystyle d_{ua}=d_{a}\circ d_{u}} ,

avec d ε = Id {\displaystyle d_{\varepsilon }=\operatorname {Id} } . La formule pour le produit peut s'écrire autrement en introduisant une fonction auxiliaire qui teste si le langage dénoté par une expression contient ou non le mot vide. Cette fonction, notée c {\displaystyle c} et appelée le terme constant de l'expression[4], est définie par aussi par récurrence sur l'expression comme suit :

  1. c ( 1 ) = 1 {\displaystyle c(1)=1} , c ( 0 ) = c ( a ) = 0 {\displaystyle c(0)=c(a)=0} , pour toute lettre a {\displaystyle a} ,
  2. c ( e + f ) = m a x ( c ( e ) , c ( f ) ) {\displaystyle c(e+f)=max(c(e),c(f))} , c ( e f ) = c ( e ) c ( f ) {\displaystyle c(ef)=c(e)c(f)} et c ( e ) = 1 {\displaystyle c(e^{*})=1} .

La formule du produit s'écrit alors

d a ( e f ) = d a ( e ) f + c ( e ) d a ( f ) {\displaystyle d_{a}(e\cdot f)=d_{a}(e)\cdot f+c(e)\cdot d_{a}(f)}

Le résultat est le même sous réserve d'appliquer les identifications dites triviales, c'est-à-dire de supprimer les occurrences de 0 et de 1 où on peut le faire, en d'autres termes en utilisant les relations

0 + e e + 0 e , 0 e e 0 0 , 1 e e 1 1 {\displaystyle 0+e\equiv e+0\equiv e,0\cdot e\equiv e\cdot 0\equiv 0,1\cdot e\equiv e\cdot 1\equiv 1} .

Exemple

Considérons l'expression

( a b ) a {\displaystyle (a^{*}b)^{*}a^{*}}

Sa dérivée, par rapport à la lettre a {\displaystyle a} , est

d a ( ( a b ) a ) = d a ( ( a b ) ) a + c ( ( a b ) ) d a ( a ) = d a ( ( a b ) ) ( a b ) a + 1 1 a = ( d a ( a ) b + 1 d a ( b ) ) ( a b ) a + a = ( a b + 1 0 ) ( a b ) a = a b ( a b ) a + a . {\displaystyle {\begin{aligned}d_{a}{\bigl (}(a^{*}b)^{*}a^{*}{\bigr )}&=d_{a}{\bigl (}(a^{*}b)^{*}{\bigr )}a^{*}+c((a^{*}b)^{*})d_{a}(a^{*})=d_{a}{\bigl (}(a^{*}b){\bigr )}(a^{*}b)^{*}a^{*}+1\cdot 1\cdot a^{*}\\&={\bigl (}d_{a}(a^{*})b+1\cdot d_{a}(b){\bigr )}(a^{*}b)^{*}a^{*}+a^{*}=(a^{*}b+1\cdot 0)(a^{*}b)^{*}a^{*}=a^{*}b(a^{*}b)^{*}a^{*}+a^{*}.\end{aligned}}}

Pour plus de détails, on a gardé longuement les 0 et les 1 dans l'expression.

Propriétés

La propriété première est la formule suivante, valable pour toute expression e {\displaystyle e} et tout mot u {\displaystyle u} :

Propriété — Pour toute expression régulière e {\displaystyle e} et tout mot u {\displaystyle u} , on a : L ( d u ( e ) ) = u 1 L ( e ) {\displaystyle L(d_{u}(e))=u^{-1}L(e)} .

Pour un langage rationnel L {\displaystyle L} , la famille de langages u 1 L {\displaystyle u^{-1}L} , où u {\displaystyle u} parcourt l’ensemble de tous les mots, est finie. Cela n'implique pas que la famille des expressions d u ( e ) {\displaystyle d_{u}(e)} dérivées de e {\displaystyle e} soit finie, car on peut avoir une infinité d'expressions pour le même langage !

Finitude de l'ensemble des dérivées

Un théorème tout à fait remarquable, et qui est le résultat principal de l'article de Brzozowski de 1964, stipule que l'ensemble des dérivées d'une expression est finie sous réserve que l'on applique quelques simplifications aux formules, en plus de la suppression des 0 et 1. Ainsi, les deux expressions e + f {\displaystyle e+f} et f + e {\displaystyle f+e} sont considérées comme équivalentes (commutativité), de même e + e e {\displaystyle e+e\equiv e} (idempotence) et ( e + f ) + g ( e + ( f + g ) {\displaystyle (e+f)+g\equiv (e+(f+g)} (associativité).

Théorème (Brzozowski) — L'ensemble des dérivées d'une expression rationnelle est finie modulo l'identification d'expressions par les règles d'associativité, de commutativité, d'idempotence, et les identités faisant intervenir 0 et 1.

L'automate des expressions dérivées

Soit e {\displaystyle e} une expression régulière sur un alphabet A {\displaystyle A} , et soit Q = { d u ( e ) u A } {\displaystyle Q=\{d_{u}(e)\mid u\in A^{*}\}} l'ensemble de ses expressions dérivées. Cet ensemble — qui est fini par le théorème de Brzozowski — peut être vu comme l’ensemble des états d'un automate déterministe complet qui, de plus, reconnaît le langage L ( e ) {\displaystyle L(e)} . Pour cela, on définit la fonction de transition, pour un état q {\displaystyle q} et une lettre a {\displaystyle a} , par

q a = d a ( q ) {\displaystyle q\cdot a=d_{a}(q)} .

Ainsi, si q = d u ( e ) {\displaystyle q=d_{u}(e)} pour un mot u {\displaystyle u} , alors q a = d a ( d u ( e ) ) = d u a ( e ) {\displaystyle q\cdot a=d_{a}(d_{u}(e))=d_{ua}(e)} . L'état initial de l'automate est l'expression e {\displaystyle e} , les états terminaux sont les expressions f {\displaystyle f} telles que le terme constant est 1.

Cet automate, aussi appelé automate de Brzozowski reconnait le langage L ( e ) {\displaystyle L(e)} .

Exemple

Automate des expressions dérivées, par la méthode de Brzozowski.

Considérons l'expression

e = ( a + b ) a b ( a + b ) {\displaystyle e=(a+b)^{*}ab(a+b)^{*}}

Notons

f = d a ( e ) = e + b ( a + b ) , g = d a b ( e ) = d b ( f ) = e + ( a + b ) , h = d a b a ( e ) = d a ( g ) = e + b ( a + b ) + ( a + b ) {\displaystyle f=d_{a}(e)=e+b(a+b)^{*},g=d_{ab}(e)=d_{b}(f)=e+(a+b)^{*},h=d_{aba}(e)=d_{a}(g)=e+b(a+b)^{*}+(a+b)^{*}} .

L'automate obtenu a quatre états, les états g {\displaystyle g} et h {\displaystyle h} sont terminaux. Il est reproduit ci-contre[5].

Calcul pratique

Le calcul pratique de l'automate à partir de l’expression demande une représentation commode d'expressions rationnelles, comme peuvent le fournir les arbres ou alors des objets que l'on peut définir dans des langages de programmation évolués qui en permettent une manipulation facile. Ces arbres sont normalisés en supprimant les sommets étiquetés par 0 et 1 là où c'est possible, en faisant un choix pour la commutativité qui consiste par exemple à prendre comme premier terme celui qui est le plus petit lexicographiquement, et pour l'associativité de faire un choix analogue ou de représenter les opérandes non pas sous forme de suite, mais sous la forme d'un ensemble[6].

Extension : l'algorithme d'Antimirov

L'automate obtenu par la méthode de Brzozowski décrite ci-dessus est fini, déterministe, complet, mais n'a aucune raison d'être minimal. Il peut donc être victime de l'explosion exponentielle qui le rend impraticable. Une variante de la méthode de Brzozowski remplace la dérivée d'une expression, qui est une somme de termes, par l'ensemble des termes de cette somme. Cette petite modification a pour conséquence que les composants de l’automate se présentent comme des ensembles d'états, chacun présenté par un terme plus petit. La méthode d'Antimirov qui tire profit de cette observation a la propriété d'être non déterministe, mais d'avoir peu d'états (autant que l'automate de Glushkov); de plus, l'identification par les diverses identités de commutation et d'associativité n'est plus nécessaire[7].

Extension de la notion de dérivée

Soit e {\displaystyle e} une expression régulière sur A {\displaystyle A} , et soit a {\displaystyle a} une lettre. La dérivée de e {\displaystyle e} par rapport à a {\displaystyle a} [8] est un ensemble d'expressions régulières, défini récursivement par :

  1. d a ( 0 ) = d a ( 1 ) = 0 , d a ( a ) = 1 {\displaystyle d_{a}(0)=d_{a}(1)=0,d_{a}(a)=1} et d a ( b ) = 0 {\displaystyle d_{a}(b)=0} pour b a {\displaystyle b\neq a} ;
  2. d a ( e + f ) = d a ( e ) d a ( f ) {\displaystyle d_{a}(e+f)=d_{a}(e)\cup d_{a}(f)} , d a ( e ) = d a ( e ) e {\displaystyle d_{a}(e^{*})=d_{a}(e)e^{*}} et d a ( e f ) = d a ( e ) f c ( e ) d a ( f ) {\displaystyle d_{a}(e\cdot f)=d_{a}(e)\cdot f\cup c(e)d_{a}(f)} .
  3. De plus, d u a ( e ) = d a ( d u ( e ) ) {\displaystyle d_{ua}(e)=d_{a}(d_{u}(e))} pour tout mot u {\displaystyle u} .

On identifie ici un ensemble ayant un seul élément avec l'élément qui le compose. Par exemple, pour

e = ( a + b ) a b ( a + b ) {\displaystyle e=(a+b)^{*}ab(a+b)^{*}}

considéré comme le produit de ( a + b ) {\displaystyle (a+b)^{*}} par a b ( a + b ) {\displaystyle ab(a+b)^{*}} , on obtient

d a ( e ) = ( d a ( a + b ) ) a b ( a + b ) d a ( a b ( a + b ) ) = e b ( a + b ) {\displaystyle d_{a}(e)=(d_{a}(a+b)^{*})ab(a+b)^{*}\cup d_{a}(ab(a+b)^{*})=e\cup b(a+b)^{*}} .

Construction de l'automate

Automate des termes dérivés, par la méthode d'Antimirov.

L'ensemble des termes atomiques obtenus en dérivant e {\displaystyle e} est l'ensemble des termes dérivés de e {\displaystyle e} . Ce sont eux qui servent d'états à l'automate reconnaissant le langage. Le langage dénoté par un ensemble d'expressions rationnelles est par définition l'union des langages dénotés par les expressions. L'intérêt de cette dérivation par rapport à celle de Brzozowski réside dans le fait que l'automate obtenu a au plus | e | {\displaystyle |e|} états, où | e | {\displaystyle |e|} est la taille de e {\displaystyle e} .

L'automate déduit des termes dérivés a pour états les termes dérivés, et comme plus haut l'expression e {\displaystyle e} pour état initial et chaque expression f {\displaystyle f} telle que c ( f ) = 1 {\displaystyle c(f)=1} . Les transitions sont les triplets ( f , a , g ) {\displaystyle (f,a,g)} tels que g {\displaystyle g} est un terme figurant dans d a ( f ) {\displaystyle d_{a}(f)} .

Antimirov — L'automate déduit des termes dérivées d'une expression rationnelle e {\displaystyle e} reconnaît le langage dénoté par e {\displaystyle e} , et possède au plus | e | {\displaystyle |e|} états.

Exemple

Dans l'exemple ci-dessus, pour e = ( a + b ) a b ( a + b ) {\displaystyle e=(a+b)^{*}ab(a+b)^{*}} , les termes dérivés sont e {\displaystyle e} , b ( a + b ) {\displaystyle b(a+b)^{*}} et ( a + b ) {\displaystyle (a+b)^{*}} . L'automate des termes dérivés est :

Notes et références

  1. Brzozowski 1964.
  2. Pour un exposé historique, voir par exemple C. M. Sperberg-McQueen, Applications of Brzozowski derivatives to XML Schema processing, Extreme Markup Languages 2005, Montréal.
  3. On trouve aussi la notation / u {\displaystyle \partial /\partial u} , par exemple chez Sakarovitch 2003, p. 149.
  4. Notation et terminologie de Sakarovitch 2003, p. 148.
  5. Sakarovitch 2003, p. 153.
  6. Scott Owens, John H. Reppy et Aaron Turon, « Regular-expression derivatives re-examined », J. Functional Programming, vol. 19, no 2,‎ , p. 173-190 (DOI 10.1017/S0956796808007090, lire en ligne).
  7. Sakarovitch 2003, p. 159.
  8. Sakarovitch 2003, p. 159 dit B {\displaystyle \mathbb {B} } -dérivée.

Bibliographie

  • Janusz A. Brzozowski, « Derivatives of Regular Expressions », Journal of the ACM, vol. 11,‎ , p. 481–494 (DOI 10.1145/321239.321249).
  • Valentin M. Antimirov, « Partial Derivatives of Regular Expressions and Finite Automaton Constructions », Theor. Comput. Sci, vol. 155, no 2,‎ , p. 291-319
  • Jacques Sakarovitch, Éléments de théorie des automates, Paris, Vuibert, , 816 p. (ISBN 2-7117-4807-3, zbMATH 1188.68177)Document utilisé pour la rédaction de l’article
  • icône décorative Portail de l'informatique théorique