Propriétés et limitesDans le dialogue d’impression, choisissez « Enregistrer au format PDF » comme destination.
Retour

Théorie des langages · C2 Langages réguliers · Chapitre 4 · 5 h

Propriétés et limites

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 :

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 · 1 question

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

  • L₁ est régulier, puisque L₂ l'estrégulier
  • L₁ n'est pas régulier : sinon L₁ ∩ L₂ le serait, par clôture de l'intersectionclôture par intersection, à rebours
  • On ne peut rien conclure sans connaître L₁ explicitementindécidable

Réponse : Les langages réguliers sont clos par intersection : si L₁ et L₂ étaient tous deux réguliers, L₁ ∩ L₂ le serait aussi. Or on sait que L₁ ∩ L₂ n'est PAS régulier, et que L₂ l'est. La seule possibilité est donc que L₁ ne soit pas régulier. C'est l'usage « retourné » des propriétés de clôture : elles servent autant à prouver la non-régularité qu'à construire des langages réguliers. C'est souvent plus simple que d'appliquer le lemme de pompage directement.

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 · 5 étapes

Un cycle d'automate : la boucle que le pompage exploite

  1. État initialL'automate démarre dans l'état r0. Mot à lire : « aaa ».
  2. Lecture de « a » (1/3)Depuis r0, la lettre « a » mène à r1.
  3. Lecture de « a » (2/3)Depuis r1, la lettre « a » mène à r2.
  4. Lecture de « a » (3/3)Depuis r2, la lettre « a » mène à r0.
  5. Mot acceptéTout le mot est lu et l'état d'arrivée r0 est acceptant : le mot « aaa » appartient au langage.

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 · 1 question

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)ᵖ ?

  • Parce que aᵖbᵖ est plus long, ce qui facilite le découpagelongueur
  • Parce que la contrainte |xy| ≤ p force alors y à ne contenir que des a, si bien que pomper déséquilibre le compte a/by coincé dans les a
  • Parce que (ab)ᵖ n'appartient pas au langage Lappartenance

Réponse : Le choix du mot est le cœur de la preuve. Avec w = aᵖbᵖ, la condition |xy| ≤ p oblige le facteur xy à rester dans les p premières lettres, qui sont toutes des a : y n'est donc fait que de a. Pomper y ajoute (ou retire) des a sans toucher aux b, ce qui rompt l'égalité du nombre de a et de b — le mot sort de L. Avec un mauvais choix comme (ab)ᵖ, le découpage pourrait pomper un bloc « ab » entier et rester dans un langage équilibré : l'adversaire s'en tirerait. (ab)ᵖ appartient d'ailleurs à Σ*, mais pas à L de toute façon.)

À 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 de code

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.

Point de départ

// 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);

Solution

function choisirMot(p) {
  // Le mot a^p b^p : sa longueur 2p >= p, et surtout comme |xy| <= p, le
  // bloc xy tombe ENTIÈREMENT dans les a. y ne contient donc que des a.
  return "a".repeat(p) + "b".repeat(p);
}

function choisirI(x, y, z) {
  // y = k a's (k >= 1). Pomper à i = 2 ajoute k a's SANS toucher aux b :
  // on obtient a^(p+k) b^p, qui a plus de a que de b -> hors de L.
  // (i = 0 marche aussi : a^(p-k) b^p, moins de a que de b.)
  return 2;
}

// jouer(3) et jouer(5) : GAGNÉ pour tout découpage -> L n'est pas régulier.
//
// ── Pourquoi ça marche, et pourquoi c'est LE raisonnement à retenir ─────────
//
// 1. Le choix du mot est le cœur de la preuve. En jouant a^p b^p, on exploite
//    la contrainte |xy| <= p : le facteur pompé y est COINCÉ dans la zone des
//    a. Pomper y déséquilibre alors le compte a/b, ce que L interdit. Un
//    mauvais choix de mot (ex. (ab)^p) laisserait l'adversaire s'en tirer.
//
// 2. C'est vous qui choisissez w et i ; l'adversaire choisit p et le découpage.
//    Vous devez gagner CONTRE TOUS ses choix — d'où la boucle qui teste tous
//    les découpages. La preuve est un « pour tout p, il existe w, pour tout
//    découpage, il existe i ».
//
// 3. L'intuition profonde : un automate fini a une MÉMOIRE BORNÉE (p états).
//    Pour reconnaître a^n b^n, il faudrait COMPTER les a jusqu'à un n
//    arbitraire, donc une mémoire non bornée. Le lemme de pompage est la
//    formalisation de « les automates finis ne savent pas compter ».
//
// 4. Portée : le lemme sert UNIQUEMENT à prouver qu'un langage N'EST PAS
//    régulier. Le vérifier ne prouve JAMAIS qu'un langage EST régulier — pour
//    ça, on exhibe un automate ou une expression régulière.

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 · 4 cartes

Qu'est-ce que l'automate minimal, et à quoi sert la minimisation ?
Pour un langage régulier, c'est l'unique automate de taille minimale (à renommage près) qui le reconnaît. La minimisation regroupe les états INDISTINGUABLES (mêmes mots menant à l'acceptation) en classes d'équivalence. Usages : comparer deux langages (mêmes minimaux ⟺ même langage) et optimiser un automate (analyseur lexical plus rapide).
Par quelles opérations les langages réguliers sont-ils clos, et à quoi servent ces clôtures ?
Union, concaténation, étoile, complément (automate complet requis) et intersection. Ces clôtures servent à construire de nouveaux langages réguliers ET, retournées, à prouver la non-régularité : si L₁∩L₂ n'est pas régulier et L₂ l'est, alors L₁ ne l'est pas. C'est souvent plus simple que le lemme de pompage direct.
Que dit le lemme de pompage, et dans quel sens s'utilise-t-il ?
Si L est régulier, il existe p tel que tout mot w ∈ L avec |w| ≥ p s'écrit w = xyz avec |xy| ≤ p, |y| ≥ 1, et xyⁱz ∈ L pour tout i ≥ 0 (la boucle y se répète, se supprime ou reste). Il sert UNIQUEMENT à prouver qu'un langage N'EST PAS régulier (par l'absurde). Il ne prouve jamais la régularité — pour ça, on exhibe un automate ou une expression régulière.
Comment prouve-t-on que aⁿbⁿ n'est pas régulier, et quelle intuition cela illustre-t-il ?
On joue w = aᵖbᵖ : |xy| ≤ p force y à n'être que des a ; pomper (i = 2) donne a^(p+k)bᵖ, plus de a que de b, hors de L — contradiction, pour tout découpage. Intuition : un automate fini a une mémoire bornée et ne sait pas COMPTER jusqu'à un n arbitraire. Reconnaître aⁿbⁿ exige de retenir n ; d'où la pile du chapitre 8.

Exercices d'entraînement

Exercice 1

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.

Correction

Supposons LL régulier, de longueur de pompage pp. Choisissons le mot w=ap+1bpw = a^{p+1} b^{p}, qui appartient à LL (il y a bien plus de a que de b) et vérifie wp|w| \geq p.

Le lemme décompose w=xyzw = xyz avec xyp|xy| \leq p et y1|y| \geq 1. Comme xyp|xy| \leq p, le bloc xyxy tombe entièrement dans les p+1p+1 premières lettres, qui sont des a : donc y=aky = a^{k} avec k1k \geq 1.

Pompons vers le bas (i=0i = 0) : on retire yy, d'où xz=ap+1kbpxz = a^{p+1-k} b^{p}. Puisque k1k \geq 1, on a p+1kpp+1-k \leq p, c'est-à-dire un nombre de a au plus égal au nombre de b. La condition n>mn > m est violée : xzLxz \notin L. Contradiction. Donc LL n'est pas régulier.

Exercice 2

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).

Correction

Supposons LL régulier. Le langage aba^* b^* est régulier (une expression régulière le décrit). Les langages réguliers étant clos par intersection, LabL \cap a^* b^* serait régulier.

Or LabL \cap a^* b^* est exactement {anbnn0}\{a^n b^n \mid n \geq 0\} : les mots à la fois « autant de a que de b » et « des a puis des b ». Ce langage n'est pas régulier — contradiction. Donc LL n'est pas régulier.

Cette technique évite d'appliquer le lemme de pompage directement : on se ramène à un langage dont on connaît déjà la non-régularité.

Exercice 3

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.

Correction

On regroupe les états indistinguables (mêmes mots menant à l'acceptation).

  • C et D sont tous deux acceptants et absorbants : depuis l'un ou l'autre, tout mot est accepté. Ils sont indistinguables → une seule classe, « un a a déjà été lu ».
  • A et B sont non acceptants, et depuis chacun, un mot est accepté ssi il contient un a. Ils sont indistinguables → une seule classe, « aucun a lu pour l'instant ».

L'automate minimal a donc 22 états : « pas encore de a » (initial) et « au moins un a » (acceptant), avec δ(pas de a,a)=au moins un a\delta(\text{pas de }a, a) = \text{au moins un }a, les autres transitions bouclant sur la classe. Les états B et D étaient des doublons.