cursus.

Cours 2 · Langages réguliersLeçon 4 sur 4

Propriétés et limites

5 h de lecture9 sections Version PDF

À la fin de cette leçon, vous saurez

Minimisation d'automate, propriétés de clôture, lemme de pompage et preuves de non-régularité — le cas a^n b^n, le second point qui coince.

Le bloc II touche à sa fin avec la question la plus profonde du cours. Jusqu'ici, chaque langage rencontré était régulier — on lui trouvait un automate. Mais est-ce toujours le cas ? Tous les langages sont-ils réguliers ?

La réponse est non, et savoir le prouver est le second point qui coince de l'année. Ce chapitre y mène en trois temps : d'abord un outil pour obtenir l'automate le plus économe (la minimisation), ensuite l'inventaire de ce que la classe régulière sait faire (les propriétés de clôture), enfin l'outil qui trace sa frontière (le lemme de pompage), avec l'exemple que le chapitre 1 avait mystérieusement mis de côté : anbna^n b^n.

La minimisation

Pour un langage régulier donné, il existe une infinité d'automates qui le reconnaissent — on peut toujours ajouter des états inutiles. Mais il en existe un seul de taille minimale, à renommage près : l'automate minimal. La minimisation est la procédure qui le trouve.

L'idée repose sur la relation d'équivalence du chapitre 2. Deux états sont indistinguables si, depuis l'un ou l'autre, exactement les mêmes mots mènent à l'acceptation — les fusionner ne change rien au langage reconnu. La minimisation regroupe les états indistinguables en classes d'équivalence, chaque classe devenant un état unique du minimal.

Deux usages justifient ce travail :

  • Comparer deux langages. Deux automates reconnaissent le même langage si et seulement si leurs minimaux sont identiques (à renommage près). C'est le test d'équivalence, sinon délicat.
  • Optimiser. Un analyseur lexical avec le moins d'états possible est plus rapide et plus léger — ce qui compte au chapitre 9.

Retenez surtout le résultat d'existence : à chaque langage régulier correspond un automate minimal unique, qui en est en quelque sorte l'empreinte.

Les propriétés de clôture

Une classe de langages est close par une opération si, en l'appliquant à des langages de la classe, on reste dans la classe. Les langages réguliers sont remarquablement stables :

OpérationLes réguliers sont-ils clos ?Comment on le voit
Union L1L2L_1 \cup L_2ouiun AFN qui lance les deux automates en parallèle
Concaténation L1L2L_1 \cdot L_2ouibrancher le premier sur le second (ε-transition)
Étoile LL^*ouiboucler l'automate sur lui-même
Complément L\overline{L}ouiéchanger acceptants/non-acceptants (automate complet)
Intersection L1L2L_1 \cap L_2ouiautomate produit, ou via De Morgan

Ces clôtures ne sont pas de simples curiosités : ce sont des outils de preuve. Elles permettent de construire de nouveaux langages réguliers sans repartir de zéro — et, retournées, de prouver la non-régularité. Si L1L2L_1 \cap L_2 n'était pas régulier alors que L2L_2 l'est, on en déduirait que L1L_1 ne l'est pas ; c'est une technique de repli quand le lemme de pompage est malcommode à appliquer directement.

Le complément mérite un rappel : sa clôture exige un automate complet (chapitre 3). C'est là que le soin apporté à l'état puits porte ses fruits.

Quiz · vérifiez votre compréhension Sans réponse

On sait que L₁ ∩ L₂ n'est pas régulier, et que L₂ est régulier. Que peut-on conclure sur L₁ ?

Le lemme de pompage

Voici l'outil central du chapitre, et l'un des plus subtils de l'année. Il repose sur une intuition simple qu'il faut avoir en tête avant la formule :

Un automate fini a un nombre fini d'états, donc une mémoire bornée. S'il lit un mot plus long que son nombre d'états, il repasse forcément par un même état — et la portion de mot lue entre ces deux passages forme une boucle que l'on peut répéter à volonté.

C'est le principe des tiroirs : plus de lettres que d'états, donc un état revisité.

L'animation rend cette boucle visible. L'automate ci-dessous compte les a modulo 3 ; sur le mot aaa, son chemin r0 → r1 → r2 → r0 revient à son point de départ. Ce cycle est exactement le facteur yy que le lemme « pompe » : puisqu'il ramène au même état, on peut le répéter (aaaaaa) ou le retirer (ε) sans jamais quitter le langage. Retenez l'image — c'est tout le mécanisme du lemme.

Animation · étape 1 / 50:00 / 0:11

L'automate démarre dans l'état r0. Mot à lire : « aaa ».

Prêt à lancer · 0:00 / 0:11
Étapes

Formellement :

Lemme de pompage. Si LL est régulier, alors il existe une longueur pp (la « longueur de pompage ») telle que tout mot wLw \in L avec wp|w| \geq p peut s'écrire w=xyzw = xyz avec :

  • xyp|xy| \leq p,
  • y1|y| \geq 1 (le facteur yy n'est pas vide),
  • et pour tout i0i \geq 0, le mot xyizxy^iz appartient encore à LL.

Autrement dit, la boucle yy peut être répétée (i2i \geq 2), supprimée (i=0i = 0), ou laissée telle quelle (i=1i = 1), sans jamais sortir du langage. « Pomper » yy, c'est jouer sur ce ii.

L'utiliser : un jeu, et un sens de lecture

Le lemme sert dans un seul sens : prouver qu'un langage n'est pas régulier. C'est un raisonnement par l'absurde, et le meilleur moyen de ne pas s'y perdre est de le voir comme un jeu à quatre coups, dont vous devez sortir gagnant :

  1. L'adversaire suppose LL régulier et fournit la longueur pp (vous ne la connaissez pas).
  2. Vous choisissez un mot wLw \in L malin, avec wp|w| \geq p. C'est le coup décisif.
  3. L'adversaire découpe w=xyzw = xyz comme il veut, en respectant xyp|xy| \leq p et y1|y| \geq 1.
  4. Vous exhibez un ii tel que xyizLxy^iz \notin L — contradiction.

Si vous gagnez quel que soit le découpage, LL n'est pas régulier. L'ordre des quantificateurs est tout : « pour tout pp, il existe ww, pour tout découpage, il existe ii ». Vous contrôlez ww et ii ; l'adversaire contrôle pp et le découpage.

Le cas anbna^n b^n

Appliquons le jeu à L={anbnn0}L = \{a^n b^n \mid n \geq 0\} — le langage « autant de aa que de bb, les aa avant les bb » que le chapitre 1 avait déjà isolé.

Le choix du mot est tout : on joue w=apbpw = a^p b^p. Pourquoi celui-là ? Parce que la contrainte xyp|xy| \leq p oblige le bloc xyxy à tomber entièrement dans la zone des aa — le mot commence par pp lettres aa. Le facteur yy ne contient donc que des aa, et il en contient au moins un.

Il suffit alors de pomper : prendre i=2i = 2 donne ap+kbpa^{p+k} b^p avec k=y1k = |y| \geq 1 — plus de aa que de bb, donc hors de LL. Contradiction. Comme ce raisonnement vaut pour n'importe quel découpage, LL n'est pas régulier.

La leçon générale dépasse cet exemple : un automate fini ne sait pas compter jusqu'à un nombre arbitraire. Reconnaître anbna^n b^n exigerait de retenir nn, qui n'est pas borné, alors que l'automate n'a qu'un nombre fini d'états. Le lemme de pompage est la traduction rigoureuse de cette limite — et c'est justement pour compter qu'on introduira, au chapitre 8, une mémoire supplémentaire : la pile.

Quiz · vérifiez votre compréhension Sans réponse

Pour prouver que L = {aⁿbⁿ} n'est pas régulier avec le lemme de pompage, pourquoi choisit-on le mot w = aᵖbᵖ plutôt que, par exemple, w = (ab)ᵖ ?

À vous

L'exercice transforme le lemme en jeu jouable. L'adversaire annonce pp et essaie tous les découpages possibles ; vous devez fournir le mot w=apbpw = a^p b^p et le facteur pompé ii qui casse, et gagner contre chaque découpage.

C'est en jouant qu'on comprend pourquoi le choix du mot est décisif : c'est lui qui coince le facteur yy dans les aa. Une fois cette mécanique vue tourner, le lemme de pompage cesse d'être un enchaînement de quantificateurs opaque et devient une stratégie que vous savez dérouler.

Exercice · JavaScript · à vous de jouer

Prouvez que a^n b^n n'est pas régulier, en jouant contre un adversaire : il annonce une longueur p et découpe votre mot, vous choisissez le mot puis le facteur pompé qui sort du langage. Le secret est le choix du mot a^p b^p — il coince le facteur y dans les a.

En attente
// On veut PROUVER que L = { a^n b^n | n >= 0 } n'est pas régulier.
//   L = { ε, ab, aabb, aaabbb, ... }  (autant de a que de b, a avant b)
//
// Le lemme de pompage, vu comme un JEU en 4 coups :
//   1. L'adversaire (qui affirme « L est régulier ») annonce une longueur p.
//   2. VOUS choisissez un mot w de L, avec |w| >= p.
//   3. L'adversaire découpe w = x y z avec |xy| <= p et |y| >= 1 (y non vide).
//   4. VOUS choisissez un entier i tel que x y^i z ne soit PAS dans L.
//   Si vous gagnez QUEL QUE SOIT le découpage, L n'est pas régulier.

// Appartenance à L : autant de a que de b, tous les a avant tous les b.
function estDansL(mot) {
  const m = mot.match(/^(a*)(b*)$/);          // a...a puis b...b
  if (!m) return false;                        // un b avant un a -> non
  return m[1].length === m[2].length;          // même nombre
}

// ── À VOUS (2) : choisir le bon mot ─────────────────────────────────────────
// Pour une longueur p donnée, quel mot de L rend l'adversaire perdant ?
// Indice : il faut que |xy| <= p FORCE y à ne contenir que des a.
function choisirMot(p) {
  return ""; // à compléter, en fonction de p
}

// ── À VOUS (4) : choisir i qui casse ────────────────────────────────────────
// Étant donné un découpage x, y, z (avec y = que des a, forcé par l'étape 2),
// rendez un i tel que x + y.repeat(i) + z ne soit PAS dans L.
function choisirI(x, y, z) {
  return 1; // à corriger (i = 1 redonne w, qui EST dans L : mauvais choix)
}

// ── Le jeu : l'adversaire essaie TOUS les découpages valides ────────────────
function jouer(p) {
  const w = choisirMot(p);
  if (w.length < p || !estDansL(w)) { console.log("Mot invalide."); return; }
  console.log("p = " + p + ", vous jouez w = " + w + " (dans L, |w| >= p)");
  let vousGagnezToujours = true;
  for (let coupe = 1; coupe <= p; coupe++) {       // |xy| <= p
    for (let ly = 1; coupe - ly >= 0 && ly <= coupe; ly++) {
      const x = w.slice(0, coupe - ly);
      const y = w.slice(coupe - ly, coupe);
      const z = w.slice(coupe);
      if (y.length < 1) continue;
      const i = choisirI(x, y, z);
      const pompe = x + y.repeat(i) + z;
      if (estDansL(pompe)) {
        console.log("  PERDU sur x=" + x + " y=" + y + " z=" + z + " : " + pompe + " est dans L");
        vousGagnezToujours = false;
      }
    }
  }
  console.log(vousGagnezToujours ? "GAGNÉ pour tout découpage -> L n'est pas régulier." : "à revoir");
}

jouer(3);
jouer(5);

Console de sortie
Le résultat s'affiche dans la console

Ce que la suite en fait

Le bloc II est complet : vous savez décrire les langages réguliers de trois façons équivalentes, les optimiser, connaître leurs clôtures, et surtout prouver qu'un langage leur échappe. La frontière est tracée.

Le bloc III la franchit. Puisque les automates finis ne savent pas compter, on leur ajoute une mémoire : une pile. Le chapitre 7 introduit d'abord les grammaires hors contexte, une manière de engendrer les langages plutôt que de les reconnaître, capable justement de décrire anbna^n b^n ; le chapitre 8 leur associe les automates à pile, et donnera un lemme de pompage algébrique qui tracera, un cran plus haut, la frontière suivante.

À retenir

Flashcards · 1 / 4Toucher pour retourner

Exercices d'entraînement

Exercice 1 · cherchez avant de lire la correction

Non-régularité par pompage

Montrer, à l'aide du lemme de pompage, que le langage L={anbmn>m0}L = \{a^n b^m \mid n > m \geq 0\} n'est pas régulier.

Exercice 2 · cherchez avant de lire la correction

Non-régularité par clôture

Soit LL l'ensemble des mots sur {a,b}\{a, b\} comptant autant de a que de b. En utilisant une propriété de clôture, montrer que LL n'est pas régulier (on admet que {anbnn0}\{a^n b^n \mid n \geq 0\} ne l'est pas).

Exercice 3 · cherchez avant de lire la correction

Minimisation

Un AFD à 44 états A (initial), B, C, D reconnaît « les mots contenant au moins un a ». Ses transitions sont : δ(A,a)=C\delta(A,a)=C, δ(A,b)=B\delta(A,b)=B, δ(B,a)=D\delta(B,a)=D, δ(B,b)=A\delta(B,b)=A, et depuis C ou D, toute lettre mène à C ou D (états acceptants, absorbants). Montrer que son automate minimal a 22 états.

Fin de la leçon

Vous avez parcouru les 9 sections.

Marquez-la terminée pour faire avancer votre parcours, ou revenez sur un point avant de passer à la suite.