Cours 2 · Langages réguliersLeçon 2 sur 4
Automates non déterministes
5 h de lecture8 sections Version PDF
AFN et ε-transitions ; déterminisation par construction des sous-ensembles ; équivalence AFD/AFN — le premier point qui coince.
Le chapitre 3 a montré comment construire un AFD, et aussi sa difficulté : son déterminisme force à tout anticiper. Pour reconnaître « les mots qui se terminent par », il faut prévoir, à chaque lu, qu'il pourrait être l'avant-dernière lettre — sans le savoir encore. Cette gymnastique est pénible et source d'erreurs.
L'automate non déterministe supprime cette gêne : il s'autorise à « deviner ». Il est bien plus facile à écrire — et c'est là qu'est le miracle du chapitre : cette liberté ne coûte aucune puissance. Tout automate non déterministe se transforme mécaniquement en AFD équivalent. La transformation s'appelle la déterminisation, et c'est le premier des deux points qui coincent de l'année. Il devient mécanique dès qu'on l'a fait tourner une fois — ce que fait l'exercice.
L'automate non déterministe
Un automate fini non déterministe (AFN) a la même définition qu'un AFD, à une différence près, mais décisive : la fonction de transition rend un ensemble d'états.
Depuis un état en lisant une lettre , l'automate peut avoir plusieurs transitions possibles — ou aucune. Concrètement :
- : deux choix possibles ;
- : aucune transition — ce chemin meurt.
La règle d'acceptation change en conséquence, et c'est le point le plus important à comprendre :
Un AFN accepte un mot s'il existe au moins un chemin menant de l'état initial à un état acceptant.
Un seul chemin gagnant suffit. On peut imaginer l'automate explorant tous les chemins à la fois, en parallèle, et acceptant si l'un d'eux réussit. C'est cette lecture — « il existe un chemin » — qui rend les AFN si commodes : on écrit les transitions « utiles » et on laisse mourir les autres, sans se soucier d'un état puits.
Reprenons « se termine par » en non déterministe :
a, b ┌──┐ ▼ │ ──▶( q0 )──a──▶( q1 )──b──▶(( q2 ))En , lire offre deux choix : boucler sur (« ce n'est pas le bon »), ou partir vers (« je parie que le final commence ici »). L'automate n'a pas à trancher : si le pari est bon, le chemin existe et le mot est accepté. Comparez à l'AFD du chapitre 3, où il fallait gérer explicitement chaque cas : l'AFN dit simplement ce qu'on veut reconnaître.
L'animation déroule la lecture de aab. Observez la nouveauté par rapport au chapitre 3 : l'état
courant n'est plus unique mais un ensemble — l'automate explore tous les chemins à la fois, et
accepte dès que l'un d'eux atteint un état acceptant. À la fin, l'ensemble contient q2 : le mot
est accepté. C'est déjà, en germe, l'idée de la déterminisation.
L'automate démarre dans l'état {q0}. Mot à lire : « aab ». En non déterministe, on suit tous les chemins à la fois.
Les ε-transitions
Les AFN se dotent souvent d'un raccourci supplémentaire : les ε-transitions, des flèches étiquetées par le mot vide . Elles permettent de changer d'état sans lire aucune lettre.
( q1 )──ε──▶( q2 )Leur intérêt est purement pratique : elles servent à assembler des automates comme des pièces de Lego — brancher la sortie de l'un sur l'entrée d'un autre par une ε-transition, sans se soucier de raccorder les transitions. C'est exactement ce dont le chapitre 5 aura besoin pour construire un automate à partir d'une expression régulière (construction de Thompson).
Pour raisonner avec elles, on introduit l'ε-fermeture d'un état : l'ensemble de tous les états atteignables en ne suivant que des ε-transitions (y compris l'état lui-même). On l'intègre à la déterminisation ; l'idée générale reste la même, on ajoute simplement « et tout ce qu'on peut atteindre gratuitement par des ».
Un AFN, sur le mot w, possède trois chemins possibles depuis l'état initial : deux se bloquent (δ vide en cours de route) et un seul atteint un état acceptant. Le mot w est-il accepté ?
La déterminisation : construction des sous-ensembles
Comment exécuter un automate qui « devine » sur une machine réelle, qui elle ne devine pas ? En le transformant en AFD. L'idée est d'une élégance qu'il faut avoir comprise une fois pour toutes :
Un état de l'AFD représente l'ensemble de tous les états où l'AFN pourrait se trouver après avoir lu le préfixe courant.
Le non-déterminisme « où suis-je ? — plusieurs réponses possibles » devient un déterminisme « je suis dans cet ensemble d'états — une seule réponse ». La question redevient à réponse unique, donc déterministe. La construction, dite des sous-ensembles, procède ainsi :
- L'état initial de l'AFD est (avec son ε-fermeture s'il y a des ε-transitions).
- Depuis un état-ensemble , en lisant une lettre , on va dans l'union des pour tous les : « tous les états où l'on peut arriver ».
- Un état-ensemble est acceptant dès qu'il contient au moins un état acceptant de l'AFN — parce qu'il suffit qu'un chemin possible soit gagnant.
- On ne construit que les ensembles réellement atteignables, en partant de et en suivant les transitions.
Le point 3 est le plus souvent raté : on accepte dès qu'un des états possibles est acceptant, pas quand ils le sont tous. C'est le reflet direct de la règle existentielle de l'AFN.
Le coût, et l'équivalence
Combien d'états peut avoir le déterminisé ? Ses états sont des sous-ensembles de . Si l'AFN a états, il y a au plus sous-ensembles — c'est le de l'ensemble des parties du chapitre 2, qui se manifeste enfin. C'est le prix théorique du non-déterminisme : la déterminisation peut faire exploser le nombre d'états.
Deux nuances tempèrent cette borne. En pratique, on ne construit que les ensembles atteignables, et ils sont presque toujours bien moins nombreux que — dans l'exercice, 3 sur 8. Mais le pire cas existe réellement : certains langages exigent bel et bien un nombre exponentiel d'états une fois déterminisés, et c'est pourquoi on garde parfois l'AFN tel quel.
Au-delà du coût, la conséquence est le théorème central du chapitre :
Tout AFN peut être transformé en un AFD reconnaissant le même langage. AFD et AFN reconnaissent donc exactement la même classe de langages : les langages réguliers.
Le non-déterminisme est plus commode à écrire, jamais plus puissant. C'est un confort de conception, pas une extension du modèle — et c'est un résultat profond, car on aurait pu croire le contraire.
Un AFN a 4 états. Après déterminisation par construction des sous-ensembles, combien d'états l'AFD obtenu peut-il avoir au maximum, et pourquoi ne les atteint-on presque jamais tous ?
À vous
L'exercice fait tomber le blocage en rendant l'algorithme mécanique : vous implémentez la construction des sous-ensembles, puis vous la faites tourner sur l'AFN de « se termine par ». Vous voyez les états du déterminisé apparaître comme des ensembles , , — et la règle « acceptant = contient un acceptant » cesse d'être abstraite.
Codez-le, exécutez-le, relisez la trace : la déterminisation n'est plus un mystère mais une procédure que vous savez dérouler à la main.
Implémentez la déterminisation par construction des sous-ensembles : chaque état de l'AFD est l'ensemble des états où l'AFN peut se trouver. Faites-la tourner sur l'AFN de « se termine par ab » et lisez le résultat — c'est le point qui coince, il devient mécanique une fois codé.
// Un AFN reconnaît L = { mots sur {a,b} se terminant par 'ab' }. // Non déterminisme : depuis q0, lire 'a' peut RESTER en q0 (boucle) OU aller // en q1 (parier que le 'ab' final commence ici). δ rend un ENSEMBLE d'états. const afn = { etats: ["q0", "q1", "q2"], alphabet: ["a", "b"], initial: "q0", acceptants: ["q2"], // delta[etat][lettre] = LISTE d'états (peut être vide, ou à plusieurs) delta: { q0: { a: ["q0", "q1"], b: ["q0"] }, // le choix est ici q1: { a: [], b: ["q2"] }, // depuis q1, un 'b' complète "ab" q2: { a: [], b: [] }, }, }; // ── Outil : δ étendu à un ENSEMBLE d'états ────────────────────────────────── // Depuis un ensemble E d'états, en lisant 'lettre', où peut-on être ? // Réponse : l'union des δ(e, lettre) pour tout e dans E. function transitionEnsemble(afn, ensemble, lettre) { const arrivee = new Set(); for (const e of ensemble) for (const cible of afn.delta[e][lettre]) arrivee.add(cible); return [...arrivee].sort(); } // ── À VOUS : la construction des sous-ensembles ───────────────────────────── // Construire l'AFD dont les états sont des ENSEMBLES d'états de l'AFN. // - état initial de l'AFD = { initial de l'AFN } // - depuis un état-ensemble, δ_AFD(E, lettre) = transitionEnsemble(...) // - un état-ensemble est acceptant s'il CONTIENT un acceptant de l'AFN // - on n'explore que les ensembles ATTEIGNABLES (pas les 2^n en aveugle) function determiniser(afn) { const nom = (E) => "{" + E.join(",") + "}"; const initial = [afn.initial]; const aTraiter = [initial]; const vus = new Set([nom(initial)]); const deltaAFD = {}; const acceptantsAFD = []; while (aTraiter.length > 0) { const E = aTraiter.shift(); // à compléter : // 1. si E contient un état de afn.acceptants, ajouter nom(E) aux acceptants // 2. pour chaque lettre, calculer l'ensemble d'arrivée A // enregistrer deltaAFD[nom(E)][lettre] = nom(A) // si nom(A) jamais vu, l'ajouter à 'vus' et 'aTraiter' } return { initial: nom(initial), acceptants: acceptantsAFD, delta: deltaAFD }; } // ── Vérification ──────────────────────────────────────────────────────────── const afd = determiniser(afn); console.log("État initial :", afd.initial); console.log("Acceptants :", afd.acceptants.join(" ")); console.log("Transitions :"); for (const [E, trans] of Object.entries(afd.delta)) for (const [l, A] of Object.entries(trans)) console.log(" " + E + " --" + l + "--> " + A);
Ce que la suite en fait
Vous disposez maintenant de deux descriptions équivalentes des langages réguliers : l'AFD (exécutable, efficace) et l'AFN (facile à écrire), reliés par la déterminisation.
Le chapitre 5 en ajoute une troisième, purement textuelle : les expressions régulières, celles que vous croisez déjà dans les éditeurs et les outils de recherche. Le théorème de Kleene établira qu'elles décrivent exactement les mêmes langages que les automates — et la construction de Thompson, qui traduit une expression en automate, s'appuiera précisément sur les ε-transitions vues ici pour assembler les pièces.
À retenir
Exercices d'entraînement
Déterminiser un AFN
Soit l'AFN sur reconnaissant « les mots contenant le facteur ab » : états q0 (initial), q1, q2 (acceptant), avec
Déterminiser par la construction des sous-ensembles. Quels états-ensembles sont acceptants ?
ε-fermeture
Un AFN possède les états A, B, C et les transitions , , . Donner l'ε-fermeture de A.
Le non-déterminisme, plus concis
Donner un AFN à états pour « l'avant-dernière lettre du mot est a » sur . Combien d'états son AFD déterminisé possède-t-il ?
Vous avez parcouru les 8 sections.
Marquez-la terminée pour faire avancer votre parcours, ou revenez sur un point avant de passer à la suite.