Exercice 2 : Expressions régulières
Problème : Analyse, compilation et limites des expressions régulières à grande échelle
Section titled “Problème : Analyse, compilation et limites des expressions régulières à grande échelle”Filière : MPI
Matière : Informatique
Thème : Automates et langages, Expressions régulières
Énoncé
Section titled “Énoncé”Les expressions régulières (regex) sont omniprésentes dans l’industrie logicielle pour la validation de données, le filtrage de flux textuels ou l’analyse lexicale. Cependant, leur sémantique apparente de « boîte noire » masque des complexités algorithmiques redoutables, notamment face à des volumes de données massifs ou à des structures malicieusement conçues (attaques de type ReDoS - Regular Expression Denial of Service).
Ce problème se propose d’étudier la traduction formelle d’un sous-ensemble d’expressions régulières en automates finis déterministes (AFD), d’analyser la complexité spatiale et temporelle de cette transformation, et d’évaluer de manière critique les limites pratiques du modèle face à des contraintes industrielles réalistes (par exemple, le traitement de fichiers journaux de à ).
On considère un alphabet fini . L’ensemble des expressions régulières sur , noté , est défini inductivement par :
- (langage vide)
- (mot vide)
- Pour tout , (caractère unique)
- (concaténation)
- (alternance)
- (étoile de Kleene)
Questions
Section titled “Questions”Partie I : Représentation et arbres de syntaxe abstraite
Section titled “Partie I : Représentation et arbres de syntaxe abstraite”- (Q1) Définir un type algébrique en OCaml permettant de représenter les expressions régulières de .
- (Q2) Écrire une fonction OCaml
anullable : regex -> boolqui détermine si le langage engendré par une expression régulière contient le mot vide . - (Q3) Pour une expression , on définit l’ensemble des premiers (FIRST) comme l’ensemble des premiers caractères possibles des mots engendrés par . Formaliser mathématiquement cet ensemble, puis proposer une fonction OCaml calculant cet ensemble pour une expression donnée (on pourra utiliser des modules d’ensembles).
Partie II : Construction de Thompson et Déterministisation
Section titled “Partie II : Construction de Thompson et Déterministisation”- (Q4) Rappeler brièvement le principe de la construction de Thompson permettant de transformer une expression régulière en un automate fini non déterministe avec -transitions (AFN-). Quel est l’ordre de grandeur du nombre d’états de l’automate obtenu pour une expression de taille (mesurée par le nombre de symboles) ?
- (Q5) On dispose d’un AFN- à états. Décrire l’algorithme de construction par sous-ensembles (construction de Rabin-Scott) permettant d’obtenir un AFD équivalent. Quelle est la borne supérieure théorique du nombre d’états de l’AFD ainsi obtenu ? Commenter cette borne d’un point de vue réaliste.
- (Q6) Soit l’expression régulière sur l’alphabet . Évaluer le nombre d’états de l’AFD minimal reconnaissant le langage associé lorsque (ordre de grandeur d’une clé de hachage ou d’un préfixe réseau). Conclure quant à la faisabilité naïve de cette approche pour des grands (ex. ).
Partie III : Analyse critique et limites industrielles
Section titled “Partie III : Analyse critique et limites industrielles”- (Q7) En pratique, de nombreux moteurs de regex (comme PCRE en C ou le moteur de Java) n’utilisent pas la conversion en AFD mais un parcours par backtracking. Expliquer pourquoi certaines expressions, telles que évaluées sur une chaîne composée de 40 caractères suivis d’un , conduisent à une explosion combinatoire du temps de calcul (comportement en ).
- (Q8) On cherche à analyser un flux de données réseau à un débit () à l’aide d’un AFD stocké en mémoire vive (RAM). Sachant qu’un état de l’automate nécessite une table de transition de taille (avec pour l’ASCII étendu et des pointeurs sur 64 bits), estimer la taille maximale d’un AFD pour que sa table de transition tienne entièrement dans un cache L3 ultra-rapide de . Quelle est la conséquence pour des expressions régulières industrielles complexes ?
Pistes et Indications
Section titled “Pistes et Indications”- Q2 : Penser à une récurrence structurelle. Le langage d’une étoile contient toujours .
- Q5 : La construction par sous-ensembles peut théoriquement mener à états. Relier cela au théorème de Myhill-Nerode.
- Q6 : Pour , le langage correspond aux mots dont le -ième caractère en partant de la fin est un . Combien de contextes suffixes distincts cela génère-t-il ?
- Q8 : Convertir le débit en octets par seconde, puis évaluer la contrainte matérielle d’accès mémoire en cycles d’horloge CPU.
Corrigé pas à pas
Section titled “Corrigé pas à pas”Partie I
Section titled “Partie I”Q1: ** En OCaml, le type algébrique se traduit naturellement ainsi :
type regex = | Empty | Epsilon | Char of char | Concat of regex * regex | Alt of regex * regex | Star of regexQ2: ** La fonction anullable teste si :
let rec anullable (e : regex) : bool = match e with | Empty -> false | Epsilon -> true | Char _ -> false | Concat (e1, e2) -> anullable e1 && anullable e2 | Alt (e1, e2) -> anullable e1 || anullable e2 | Star _ -> trueQ3: ** Mathématiquement, .
Partie II
Section titled “Partie II”Q4: ** La construction de Thompson associe à chaque opérateur des gadgets à -transitions. Pour une expression de taille , l’AFN- produit possède au plus états et transitions. Q5: ** La construction par sous-ensembles (Rabin-Scott) produit un AFD dont l’ensemble des états est un sous-ensemble de l’ensemble des parties de l’AFN-. La borne supérieure est donc de états (où est le nombre d’états de l’AFN). Analyse critique : Cette explosion exponentielle rend la méthode naïve impraticable pour de grandes expressions, car la table de transition devient trop vaste pour la mémoire (phénomène de state explosion). Q6: ** Pour , le test porte sur la présence d’un à la -ième position en partant de la fin. Pour s’en souvenir, l’automate doit mémoriser les derniers caractères lus. Comme l’alphabet est binaire de taille 2, il y a histoires possibles pour les derniers caractères. L’AFD minimal possède donc exactement états. Pour , états. La construction d’un tel AFD est totalement infaisable en pratique (plusieurs dizaines de gigaoctets de mémoire rien que pour l’automate), démontrant la limite théorique de la déterministisation directe.
Partie III
Section titled “Partie III”Q7: ** Le backtracking évalue l’expression en testant récursivement les branches (notamment avec les fermetures de Kleene imbriquées comme ). Avec et une chaîne de caractères suivis de , le moteur tente toutes les partitions possibles des caractères dans les étoiles imbriquées, conduisant à chemins d’exploration. C’est la cause des vulnérabilités ReDoS, exploitables pour saturer un serveur web par déni de service. Q8: **
- Débit : . Pour traiter ce flux en temps réel, le processeur dispose de par octet.
- Contrainte mémoire : Un cache L3 de doit contenir la table de transition. Chaque état possède 256 transitions (pour ). Si une transition est un pointeur ou un indice sur 4 octets, un état occupe .
- Le nombre maximal d’états logeant dans le cache L3 est donc :
Conclusion critique : Dès que l’expression régulière est complexe (générant un AFD de plus de états), la table ne tient plus dans le cache L3 du processeur. Les accès répétés à la RAM principale (dont la latence est de l’ordre de ) provoquent des défauts de cache massifs. Il devient physiquement impossible de traiter un trafic réseau à avec un AFD pur de grande taille, obligeant les ingénieurs réseau à utiliser des architectures matérielles spécialisées (FPGA) ou des heuristiques d’évaluation partielle.