811 lines
33 KiB
TeX
811 lines
33 KiB
TeX
\documentclass[a4paper,french]{article}
|
|
|
|
\title{Mathématiques pour l'informatique\\Automates finis}
|
|
\author{}
|
|
\date{Dernière compilation~: \today{} à \currenttime}
|
|
|
|
\usepackage{../cours}
|
|
\usepackage{tikz}
|
|
\usetikzlibrary{automata, arrows.meta, positioning}
|
|
|
|
\begin{document}
|
|
|
|
\maketitle
|
|
\tableofcontents
|
|
|
|
\clearpage
|
|
\section{Définitions}
|
|
|
|
Automate = fonction qui dépend d'un état et d'un changement d'état.
|
|
Par exemple ON / OFF, la machine est en état d'arrêt ou en état de marche.
|
|
|
|
Autre exemple~: téléphone.
|
|
|
|
\begin{tabular}{lll}
|
|
\toprule
|
|
Mode & Évènement & Nouvel état \\
|
|
\midrule
|
|
avion & appel émis & avion \\
|
|
avion & bouton téléphonie & téléphonie \\
|
|
\midrule
|
|
téléphonie & bouton décrocher & communication \\
|
|
téléphonie & bouton avion & avion \\
|
|
\midrule
|
|
communication & bouton raccrocher & téléphonie \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
|
|
L'automate est sous un état, il a des entrées qui le font peut-être passer d'un état à un autre ou effectuer des actions.
|
|
|
|
Il faut en plus de cela définir un état initial (quel état avoir quand l'automate est mis en marche~?) et final (quel état avoir pour éteindre l'automate proprement~?)
|
|
|
|
Un nouvel état peut dépendre de l'état précédent ou pas.
|
|
On peut très bien trouver une action qui mette l'automate dans un état Y sans se soucier d'un autre état X dans lequel se trouve l'automate à un moment donné.
|
|
|
|
Un automate accepteur valide une suite d'entrée en fonction de certains critères.
|
|
Le changement d'état est interne à l'automate, et c'est une fois que toutes les entrées ont été analysées que la sortie se fait connaître.
|
|
|
|
Exemple~: déterminer si une suite de chiffres en entrée constitue un mois de l'année.
|
|
|
|
\begin{itemize}
|
|
|
|
\item \textbf{Mot}~:
|
|
Suite de \emph{symboles} issus de l'\emph{alphabet}. \\
|
|
Cas particulier~: le mot vide, noté $\varepsilon$.
|
|
On a du coup $x = x\varepsilon = \varepsilon x$.
|
|
|
|
\item \textbf{Alphabet}~:
|
|
Ensemble des \emph{symboles} utilisés en entrée de l'automate. \\
|
|
L'alphabet se note en général $\mathcal{A}$.
|
|
|
|
\item \textbf{Langage}~:
|
|
Ensemble de tous les mots pouvants être construits sur un alphabet donné. \\
|
|
On note $\mathcal{A}^*$ tous les mots y compris le mot vide.
|
|
On note $\mathcal{A}^+$ tous les mots sauf le mot vide.
|
|
|
|
On appelle \emph{langage reconnu} l'ensemble des mots que l'automate a validé.
|
|
|
|
\item \textbf{Langage complémentaire}~:
|
|
Le langage complémentaire est l'ensemble de mots qui n'appartient pas au langage reconnu par l'automate.
|
|
Si $L$ est le langage reconnu ($L \subseteq A^*$), alors $L'$ est le langage complémentaire, et $L' = A^* - L$.
|
|
|
|
\end{itemize}
|
|
|
|
\subsection{Notations}
|
|
|
|
\begin{itemize}
|
|
|
|
\item $A$ --- Alphabet
|
|
|
|
\item $Q$ --- États
|
|
|
|
\item $I$ --- États initiaux, avec $I \subseteq Q$
|
|
|
|
\item $T$ --- États terminaux, avec $T \subseteq Q$
|
|
|
|
\item $E$ --- Transitions \\
|
|
On note les transitions par un triplet $QAQ$.
|
|
|
|
\end{itemize}
|
|
|
|
L'automate est ainsi désigné par le quintuplet $< A, Q, I, T, E >$
|
|
|
|
Exemple~:
|
|
\begin{lstlisting}[gobble=8]
|
|
< {a, b, c, d, e},
|
|
{1, 2, 3, 4, 5, 6},
|
|
{1, 3, 6},
|
|
{6},
|
|
{(1,a,2), (1,a,4),
|
|
(2,a,2), (2,c,5), (2,d,5),
|
|
(3,b,2), (3,b,4),
|
|
(4,b,4), (4,c,5), (4,d,5),
|
|
(5,e,6)}
|
|
>
|
|
\end{lstlisting}
|
|
|
|
\subsection{Table de transitions}
|
|
|
|
Une table de transitions représente l'ensembe $E$.
|
|
Chaque ligne correspond à un état, chaque colonne à un symbole de l'alphabet.
|
|
|
|
Une table de transitions monte les transitions ($E$), l'alphabet ($A$, les colonnes de la table), les états ($Q$, les lignes de la table).
|
|
Il manque donc les ensembles $I$ et $T$, c'est-à-dire les états initiaux et terminaux.
|
|
On peut les représenter par des flèches ($\rightarrow$ pour l'ensemble $I$ et $\leftarrow$ pour l'ensemble $T$) sur le côté des lignes de la table (donc des états).
|
|
|
|
\begin{center}
|
|
\begin{tabular}{cc|c|c|c|c|c|}
|
|
\cline{3-7}
|
|
& & a & b & c & d & e \\
|
|
\cline{2-7}
|
|
$\rightarrow$ & \multicolumn{1}{|c|}{1} & 2,4 & & & & \\
|
|
\cline{2-7}
|
|
& \multicolumn{1}{|c|}{2} & 2 & & 5 & 5 & \\
|
|
\cline{2-7}
|
|
$\rightarrow$ & \multicolumn{1}{|c|}{3} & & 2,4 & & & \\
|
|
\cline{2-7}
|
|
& \multicolumn{1}{|c|}{4} & & 4 & 5 & 5 & \\
|
|
\cline{2-7}
|
|
& \multicolumn{1}{|c|}{5} & & & & & 6 \\
|
|
\cline{2-7}
|
|
$\rightarrow$ & \multicolumn{1}{|c|}{\multirow{2}{*}{6}} & & & & & \\
|
|
$\leftarrow$ & \multicolumn{1}{|c|}{} & & & & & \\
|
|
\cline{2-7}
|
|
\end{tabular}
|
|
\end{center}
|
|
|
|
\subsection{Graphe d'états}
|
|
|
|
Un graphe d'états est la représentation schématique d'un automate.
|
|
La table de transitions précédente est équivalent au graphe suivant~:
|
|
|
|
\begin{center}
|
|
\includegraphics[width=0.4\linewidth]{./img/graphe-etats-exemple.jpg}
|
|
\end{center}
|
|
|
|
\subsection{Types d'automates finis}
|
|
|
|
\subsubsection{Accessibilité}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Un automate accessible ne contient que des états qui peuvent être atteints.
|
|
|
|
\item Un automate co-accessible ne contient que des états pouvant mener à un état terminal.
|
|
|
|
\item Un automate émondé est à la fois accessible et co-accessible.
|
|
|
|
\end{itemize}
|
|
|
|
\subsubsection{Automate standard}
|
|
|
|
\begin{itemize}
|
|
|
|
\item il n'y a qu'un seul état initial
|
|
|
|
\item aucune transition n'arrive sur cet état initial
|
|
|
|
\end{itemize}
|
|
|
|
\subsubsection{Automate déterministe}
|
|
|
|
\begin{itemize}
|
|
|
|
\item il n'y a qu'un seul état initial (automate standard)
|
|
|
|
\item pour tout état donné, il n'y a qu'une seule transition possible
|
|
|
|
\end{itemize}
|
|
|
|
Un automate non déterministe est plus difficile à mettre en \oe{}uvre en algorithmique qu'un automate déterministe.
|
|
En effet, en plus des pointeurs d'état et de symbole courant, il faudra maintenir une pile des opérations possibles.
|
|
|
|
\subsubsection{Automate complet}
|
|
|
|
Pour tout état, il y a toujours une transition sortante pour chaque symbole de l'alphabet.
|
|
Cela veut dire qu'à tout état il y a toujours une action à faire pour tout symbole reçu.
|
|
|
|
Un automate complet est forcément également déterministe.
|
|
|
|
\subsubsection{Automate minimal}
|
|
|
|
Un automate est minimal s'il contient le moins d'états possible.
|
|
Pour un alphabet donné et un langage reconnaissable donné, il existe un et un seul automate minimal.
|
|
|
|
\subsubsection{Automate asynchrone}
|
|
|
|
Un automate asynchrone contient au moins une transition $\varepsilon$.
|
|
|
|
\paragraph{Transitions $\varepsilon$}
|
|
|
|
Une transition $\varepsilon$ permet de changer d'état sans consommer de symbole.
|
|
Ou en d'autres termes, elle permet de mofidier l'état courant sans modifier le symbole courant.
|
|
|
|
\paragraph{Fermetures $\varepsilon$}
|
|
|
|
Une fermeture $\varepsilon$ est l'ensemblre des états qu'on peut atteindre en n'utilisant que des transitions $\varepsilon$.
|
|
|
|
\section{Manipulations d'automates}
|
|
|
|
\subsection{Complétion}
|
|
|
|
On crée un état ``poubelle'' qui va accueillir les transitions manquantes sur chaque état~:
|
|
|
|
\begin{enumerate}
|
|
|
|
\item ajout de l'état poubelle $P$
|
|
|
|
\item toutes les transitions existantes sont gardées
|
|
|
|
\item ajout d'une transition vers l'état poubelle $P$ pour toute transition absente de $E$
|
|
|
|
\item ajout des transitions $(P, x, P)$ pour tout $x$ de l'alphabet
|
|
|
|
\end{enumerate}
|
|
|
|
\subsection{Standardisation}
|
|
|
|
La standardisation passe par trois étapes~:
|
|
|
|
\begin{enumerate}
|
|
|
|
\item ajout d'un nouvel état initial $i$
|
|
|
|
\item ajout de cet état initial à la liste des états terminaux si nécessaire (reconnait le mot vide)
|
|
|
|
\item duplication à partir de $i$ de toutes les transitions partant d'un état initial
|
|
|
|
\end{enumerate}
|
|
|
|
\subsection{Émondage}
|
|
|
|
Se fait en deux temps, d'abord rendre l'automate \emph{accessible}, puis \emph{co-accessible}.
|
|
Cette deuxième étape supprime l'état poubelle d'un automate complet, ce qui en fera un automate non complet.
|
|
|
|
Rendre un automate accessible~:
|
|
|
|
\begin{enumerate}
|
|
|
|
\item $Q' = I$
|
|
|
|
\item $\forall p \in I, \text{marque}(p) = \text{à traiter}$
|
|
|
|
\item tant qu'il existe un sommet accessible depuis un état initial qui n'a pas encore été traité, on prend un de ces sommets et on ajoute à l'automate tous les états accessibles depuis le sommet
|
|
|
|
\item $\text{marque}(p) = \text{déjà traité}$
|
|
|
|
\item $I' = I \cap Q'$
|
|
|
|
\item $T' = T \cap Q'$
|
|
|
|
\item on ne garde de l'automate de départ que les états auxquels on a accédé, et les transitions associées
|
|
|
|
\end{enumerate}
|
|
|
|
Pour la deuxième étape, consistant à rendre l'automate co-accessible, on suit les mêmes étapes mais en partant des états terminaux, en remontant dans l'autre sens~:
|
|
|
|
\begin{enumerate}
|
|
|
|
\item $Q' = T$
|
|
|
|
\item $\forall p \in T, \text{marque}(p) = \text{à traiter}$
|
|
|
|
\item tant qu'il existe un sommet accessible depuis un état terminal qui n'a pas encore été traité, on prend un de ces sommets et on ajoute à l'automate tous les états accessibles depuis le sommet
|
|
|
|
\item $\text{marque}(p) = \text{déjà traité}$
|
|
|
|
\item $I' = I \cap Q'$
|
|
|
|
\item $T' = T \cap Q'$
|
|
|
|
\item on ne garde de l'automate de départ que les états auxquels on a accédé, et les transitions associées
|
|
|
|
\end{enumerate}
|
|
|
|
\subsection{Passage au langage complémentaire}
|
|
|
|
Il faut commencer par compléter l'automate s'il n'est pas complet, puis on inverse les états terminaux et non terminaux.
|
|
|
|
\subsection{Déterminisation}
|
|
|
|
Pour passer d'un automate non déterministe à un automate déterministe, on va dérouler toutes les étapes de l'automate de départ en partant des états initiaux.
|
|
S'il y a plusieurs états initiaux, on crée un nouvel état initial qu'on note comme l'ensemble des états initiaux de l'automate de départ.
|
|
Ensuite, pour chaque transition possible on recopie les transitions en partant du nouvel état courant vers un ensemble d'états de l'automate de départ.
|
|
Cela nous fait créer de nouveaux états, qu'on utilise comme état courant pour trouver les nouveaux états qu'on peut rejoindre.
|
|
|
|
\begin{enumerate}
|
|
|
|
\item création de l'état initial~: ensemble de tous les états initiaux de l'automate non déterministe de départ
|
|
|
|
\item repérage des lignes dans le tableau de transitions concernant les états initiaux déterminés précédemment
|
|
|
|
\item pour chaque transition de chacune de ces lignes, identification des états cibles, et renseignement des ensembles d'états cibles dans le nouveau tableau de transitions
|
|
|
|
\item retour à l'étape de repérage des états déterminés précédemment
|
|
|
|
\item identification des ensembles contenant au moins un état terminal dans l'automate de départ
|
|
|
|
\end{enumerate}
|
|
|
|
Algorithme~:
|
|
|
|
\begin{itemize}
|
|
\item $Q' \leftarrow \{I\}$ \\
|
|
$I' \leftarrow \{I\}$ \\
|
|
$\text{marque}(I) = \text{à traiter}$
|
|
|
|
\item $\text{tant que } \{e' \in Q' \,|\, \text{marque}(e') = \text{à traiter}\} \neq \oslash$ \\
|
|
$\text{choisir } p' \in Q' \,|\, \text{marque}(p') = \text{à traiter}$
|
|
|
|
\begin{itemize}
|
|
|
|
\item $\forall x \in A$ \\
|
|
Soit $q' = \{q \in Q \,|\, \exists \, p \in p', (p,x,q) \in E\}$ \\
|
|
$q' \notin Q' \implies (Q' \leftarrow Q' \cup \{q'\}, \text{marque}(q') = \text{à traiter})$ \\
|
|
$E' \leftarrow E' \cup \{(p',x,q')\}$
|
|
|
|
\item $\text{marque}(p') = \text{déjà traité}$
|
|
|
|
\end{itemize}
|
|
|
|
\item $T' = \{p' \in Q' \,|\, \exists \, p \in p', p \in T\}$
|
|
|
|
\end{itemize}
|
|
|
|
\subsection{Minimisation}
|
|
|
|
\paragraph{Définition}
|
|
|
|
Un automate minimal est celui qui contient le moins d'états possibles parmi tous les automates complets et déterministes correspondant au même langage.
|
|
|
|
Pour un langage donné, il n'y a qu'un seul automate minimal.
|
|
Pour prouver que deux automates reconnaissent le même langage, on peut donc les minimiser, ce qui rendra deux fois le même automate minimal.
|
|
|
|
Pour minimiser un automate, il faut qu'il soit~:
|
|
|
|
\begin{itemize}
|
|
|
|
\item déterministe
|
|
|
|
\item complet
|
|
|
|
\item accessible
|
|
|
|
\end{itemize}
|
|
|
|
\paragraph{Méthode}
|
|
|
|
On commence par partir du principe que tous les états sont identiques.
|
|
Puis on sépare les états qui n'ont pas les mêmes suffixes.
|
|
Au bout d'un moment, tous les états regroupés ne pourront plus ête séparés.
|
|
|
|
\begin{itemize}
|
|
|
|
\item Regroupement de tous les états en deux groupes~:
|
|
$N$ (états non terminaux) et $T$ (états terminaux).
|
|
|
|
\item Pour chaque groupe, séparation des états qui ont des suffixes différents.
|
|
|
|
\item Pour chaque groupe nouvellement obtenu, refaire l'étape précédente, de manière itérative, jusqu'à ce qu'aucun groupe ne peut être séparé~:
|
|
|
|
\begin{itemize}
|
|
|
|
\item soit parce qu'il n'a qu'un état
|
|
|
|
\item soit parce que tous ses états ont les mêmes suffixes
|
|
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
\subsection{Suppression des transitions $\varepsilon$}
|
|
|
|
TODO\ldots
|
|
|
|
\subsection{Construction automatique d'automates}
|
|
|
|
\paragraph{Concaténation ($ab$)}
|
|
|
|
C'est la concaténation de l'automate reconnaissant $a$ et de l'automate reconnaissante $b$.
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[->, on grid, auto, node distance=2cm]
|
|
\node(0)[state, initial, initial text={}] {};
|
|
\node(1)[state, right = of 0] {};
|
|
\node(2)[state, accepting by arrow, right = of 1] {};
|
|
\path
|
|
(0) edge node {a} (1)
|
|
(1) edge node {b} (2)
|
|
;
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
\paragraph{Choix ($a+b$)}
|
|
|
|
C'est un aiguillage.
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[->, on grid, auto, node distance=2cm]
|
|
\node(0)[state, initial, initial text={}] {};
|
|
\node(1)[state, above right = of 0] {};
|
|
\node(2)[state, right = of 1] {};
|
|
\node(3)[state, , accepting by arrow, below right = of 2] {};
|
|
\node(4)[state, below right = of 0] {};
|
|
\node(5)[state, right = of 4] {};
|
|
\path
|
|
(0) edge node {$\varepsilon$} (1)
|
|
(0) edge node {$\varepsilon$} (4)
|
|
(1) edge node {a} (2)
|
|
(4) edge node {b} (5)
|
|
(2) edge node {$\varepsilon$} (3)
|
|
(5) edge node {$\varepsilon$} (3)
|
|
;
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
\paragraph{Répétition}
|
|
|
|
$a^*$
|
|
\begin{center}
|
|
\begin{tikzpicture}[->, on grid, auto, node distance=2cm]
|
|
\node(0)[state, initial, initial text={}] {};
|
|
\node(1)[state, right = of 0] {};
|
|
\node(2)[state, right = of 1] {};
|
|
\node(3)[state, accepting by arrow, right = of 2] {};
|
|
\path
|
|
(0) edge node {$\varepsilon$} (1)
|
|
(1) edge node {a} (2)
|
|
(2) edge node {$\varepsilon$} (3)
|
|
(2) edge [bend right=60] node {$\varepsilon$} (1)
|
|
(0) edge [bend right=30] node {$\varepsilon$} (3)
|
|
;
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
\paragraph{Exemples}
|
|
|
|
$(a+b)^*$
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[->, on grid, auto, node distance=2cm]
|
|
\node(0)[state, initial, initial text={}] {0};
|
|
\node(1)[state, right = of 0] {1};
|
|
\node(2)[state, above right = of 1] {2};
|
|
\node(3)[state, below right = of 1] {3};
|
|
\node(4)[state, right = of 2] {4};
|
|
\node(5)[state, right = of 3] {5};
|
|
\node(6)[state, below right = of 4] {6};
|
|
\node(7)[state, accepting by arrow, right = of 6] {7};
|
|
\path
|
|
(0) edge node {$\varepsilon$} (1)
|
|
(1) edge node {$\varepsilon$} (2)
|
|
(1) edge node {$\varepsilon$} (3)
|
|
(2) edge node {a} (4)
|
|
(3) edge node {b} (5)
|
|
(4) edge node {$\varepsilon$} (6)
|
|
(5) edge node {$\varepsilon$} (6)
|
|
(6) edge node {$\varepsilon$} (7)
|
|
(6) edge node {$\varepsilon$} (1)
|
|
(0) edge [bend right=50] node {$\varepsilon$} (7)
|
|
;
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
$(a^* + b^*)^*$
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[->, on grid, auto, node distance=2cm]
|
|
\node(0)[state, initial, initial text={}] {0};
|
|
\node(1)[state, right = of 0] {1};
|
|
\node(2)[state, above right = of 1] {2};
|
|
\node(3)[state, right = of 2] {3};
|
|
\node(4)[state, right = of 3] {4};
|
|
\node(5)[state, right = of 4] {5};
|
|
\node(6)[state, below right = of 5] {6};
|
|
\node(7)[state, accepting by arrow, right = of 6] {7};
|
|
\node(8)[state, below right = of 1] {8};
|
|
\node(9)[state, right = of 8] {9};
|
|
\node(10)[state, right = of 9] {10};
|
|
\node(11)[state, right = of 10] {11};
|
|
\path
|
|
(0) edge node {$\varepsilon$} (1)
|
|
(1) edge node {$\varepsilon$} (2)
|
|
(2) edge node {$\varepsilon$} (3)
|
|
(3) edge node {a} (4)
|
|
(4) edge node {$\varepsilon$} (5)
|
|
(5) edge node {$\varepsilon$} (6)
|
|
(1) edge node {$\varepsilon$} (8)
|
|
(8) edge node {$\varepsilon$} (9)
|
|
(9) edge node {b} (10)
|
|
(10) edge node {$\varepsilon$} (11)
|
|
(11) edge node {$\varepsilon$} (6)
|
|
(6) edge node {$\varepsilon$} (7)
|
|
|
|
(4) edge [bend right=60] node {$\varepsilon$} (3)
|
|
(2) edge [bend right=30] node {$\varepsilon$} (5)
|
|
(10) edge [bend right=60] node {$\varepsilon$} (9)
|
|
(8) edge [bend right=30] node {$\varepsilon$} (11)
|
|
|
|
(6) edge node {$\varepsilon$} (1)
|
|
(0) edge [bend right=60] node {$\varepsilon$} (7)
|
|
;
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
$ab^*(ba+ab)^*b$
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[->, on grid, auto, node distance=1.4cm]
|
|
\node(0)[state, initial, initial text={}] {0};
|
|
\node(1)[state, right = of 0] {1};
|
|
\node(2)[state, right = of 1] {2};
|
|
\node(3)[state, right = of 2] {3};
|
|
\node(4)[state, right = of 3] {4};
|
|
\node(5)[state, right = of 4] {5};
|
|
|
|
\node(9)[state, above right = of 5] {9};
|
|
\node(10)[state, right = of 9] {10};
|
|
\node(11)[state, right = of 10] {11};
|
|
|
|
\node(12)[state, below right = of 5] {12};
|
|
\node(13)[state, right = of 12] {13};
|
|
\node(14)[state, right = of 13] {14};
|
|
|
|
\node(6)[state, below right = of 11] {6};
|
|
\node(7)[state, right = of 6] {7};
|
|
\node(8)[state, accepting by arrow, right = of 7] {8};
|
|
\path
|
|
(0) edge node {a} (1)
|
|
(1) edge node {$\varepsilon$} (2)
|
|
(2) edge node {b} (3)
|
|
(3) edge node {$\varepsilon$} (4)
|
|
(4) edge node {$\varepsilon$} (5)
|
|
|
|
(3) edge [bend right=70] node {$\varepsilon$} (2)
|
|
(1) edge [bend right=40] node {$\varepsilon$} (4)
|
|
|
|
(5) edge node {$\varepsilon$} (9)
|
|
(9) edge node {b} (10)
|
|
(10) edge node {a} (11)
|
|
(11) edge node {$\varepsilon$} (6)
|
|
|
|
(6) edge node {$\varepsilon$} (5)
|
|
(4) edge [bend right=70] node {$\varepsilon$} (7)
|
|
|
|
(5) edge node {$\varepsilon$} (12)
|
|
(12) edge node {a} (13)
|
|
(13) edge node {b} (14)
|
|
(14) edge node {$\varepsilon$} (6)
|
|
|
|
(6) edge node {$\varepsilon$} (7)
|
|
(7) edge node {b} (8)
|
|
;
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
\section{Automates et expressions rationnelles}
|
|
|
|
\subsection{Automate vers expression rationnelle}
|
|
|
|
\subsubsection{Par élimination d'états}
|
|
|
|
Il s'agit de supprimer un par un tous les états, en remplaçant à chaque suppression les transitions attenant à l'état supprimé par une expression rationnelle équivalente.
|
|
|
|
La première étape est de \emph{rajouter} un état initial $\alpha$ avec sa transition $\varepsilon$ vers l'état initial.
|
|
De la même façon, on ajoute un état terminal $\omega$ avec les transitions $\varepsilon$ entre les états terminaux et $\omega$.
|
|
|
|
On peut maintenant supprimer les états un par un.
|
|
Pour s'aider, on peut créer un petit schéma centré sur l'état à supprimer, en indiquant toutes les transitions entrantes et sortantes vers cet état.
|
|
Ces transitions sont à ajouter à l'automate amputé de cet état.
|
|
|
|
Automate de départ~:
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[->, auto]
|
|
\node(1)[state, initial, initial text={}] at (3,2) {1};
|
|
\node(2)[state] at (5,2) {2};
|
|
\node(3)[state] at (7,3) {3};
|
|
\node(4)[state] at (7,1) {4};
|
|
\node(5)[state, accepting by arrow] at (9,2) {5};
|
|
|
|
\path
|
|
(1) edge node {a} (2)
|
|
(2) edge node {b} (3)
|
|
(2) edge node {c} (4)
|
|
(3) edge [loop above] node {d} (3)
|
|
(3) edge node {c} (5)
|
|
(4) edge node {b} (5)
|
|
;
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
Ajout des états inital / terminal~:
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[->, auto]
|
|
|
|
\node(alpha)[state, initial, initial text={}, red] at (1,2) {$\alpha$};
|
|
\node(1)[state] at (3,2) {1};
|
|
\node(2)[state] at (5,2) {2};
|
|
\node(3)[state] at (7,3) {3};
|
|
\node(4)[state] at (7,1) {4};
|
|
\node(5)[state] at (9,2) {5};
|
|
\node(omega)[state, accepting by arrow, red] at (11,2) {$\omega$};
|
|
|
|
\path
|
|
(alpha) edge [red] node {$\varepsilon$} (1)
|
|
(1) edge node {a} (2)
|
|
(2) edge node {b} (3)
|
|
(2) edge node {c} (4)
|
|
(3) edge [loop above] node {d} (3)
|
|
(3) edge node {c} (5)
|
|
(4) edge node {b} (5)
|
|
(5) edge [red] node {$\varepsilon$} (omega)
|
|
;
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
Suppressions~:
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[->, auto]
|
|
\node(alpha)[state, initial, initial text={}] at (1,2) {$\alpha$};
|
|
\node(1)[state] at (3,2) {1};
|
|
\node(2)[state] at (5,2) {2};
|
|
\node(4)[state] at (7,1) {4};
|
|
\node(5)[state] at (9,2) {5};
|
|
\node(omega)[state, accepting by arrow] at (11,2) {$\omega$};
|
|
|
|
\path
|
|
(alpha) edge node {$\varepsilon$} (1)
|
|
(1) edge node {a} (2)
|
|
(2) edge node {c} (4)
|
|
(2) edge [red] node {bd$^*$c} (5)
|
|
(4) edge node {b} (5)
|
|
(5) edge node {$\varepsilon$} (omega)
|
|
;
|
|
\end{tikzpicture}
|
|
|
|
\begin{tikzpicture}[->, auto]
|
|
\node(alpha)[state, initial, initial text={}] at (1,2) {$\alpha$};
|
|
\node(2)[state] at (5,2) {2};
|
|
\node(4)[state] at (7,1) {4};
|
|
\node(5)[state] at (9,2) {5};
|
|
\node(omega)[state, accepting by arrow] at (11,2) {$\omega$};
|
|
|
|
\path
|
|
(alpha) edge [red] node {a} (2)
|
|
(2) edge node {c} (4)
|
|
(2) edge node {bd$^*$c} (5)
|
|
(4) edge node {b} (5)
|
|
(5) edge node {$\varepsilon$} (omega)
|
|
;
|
|
\end{tikzpicture}
|
|
|
|
\begin{tikzpicture}[->, auto]
|
|
\node(alpha)[state, initial, initial text={}] at (1,2) {$\alpha$};
|
|
\node(4)[state] at (7,1) {4};
|
|
\node(5)[state] at (9,2) {5};
|
|
\node(omega)[state, accepting by arrow] at (11,2) {$\omega$};
|
|
|
|
\path
|
|
(alpha) edge [red] node {abd$^*$c} (5)
|
|
(alpha) edge [red] node {ac} (4)
|
|
(4) edge node {b} (5)
|
|
(5) edge node {$\varepsilon$} (omega)
|
|
;
|
|
\end{tikzpicture}
|
|
|
|
\begin{tikzpicture}[->, auto]
|
|
\node(alpha)[state, initial, initial text={}] at (1,2) {$\alpha$};
|
|
\node(5)[state] at (9,2) {5};
|
|
\node(omega)[state, accepting by arrow] at (11,2) {$\omega$};
|
|
|
|
\path
|
|
(alpha) edge [red] node {abd$^*$c + acb} (5)
|
|
(5) edge node {$\varepsilon$} (omega)
|
|
;
|
|
\end{tikzpicture}
|
|
|
|
\begin{tikzpicture}[->, auto]
|
|
\node(alpha)[state, initial, initial text={}] at (1,2) {$\alpha$};
|
|
\node(omega)[state, accepting by arrow] at (11,2) {$\omega$};
|
|
|
|
\path
|
|
(alpha) edge [red] node {abd$^*$c + acb} (omega)
|
|
;
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
\subsubsection{Système d'équations}
|
|
|
|
On note $X_{p,q}$ tous les mots faisant passer l'état $p$ à $q$.
|
|
Si l'automate contient plusieurs états initiaux ou plusieurs états terminaux, le langage reconnu peut être décrit par une somme (l'union) de toutes les expressions $X_{i,t}$ ($i$ état initial, $t$ état terminal).
|
|
|
|
On note alors $L$ cette somme~:
|
|
|
|
$L = X_{1,3} + X_{1,4} + X_{1,5} + X_{2,3} X_{2,4} + X_{2,5}$
|
|
|
|
Il faut ensuite réécrire toutes les expressions $X_{p,q}$ en n'utilisant que les symboles de l'alphabet.
|
|
|
|
Dans notre cas, nous passons d'un état initial à un état terminal.
|
|
L'expression $X_{p,q}$ se note donc $X_{i-}$ ou $X_{-t}$.
|
|
|
|
\paragraph{Méthode des préfixes (facteurs gauche)}
|
|
|
|
Il faut écrire l'expression en partant de l'union (la somme) des expressions partant d'un état initial ($X_{i-}$).
|
|
|
|
\begin{multicols}{2}
|
|
|
|
\begin{tikzpicture}[->, auto]
|
|
\node(1)[state, initial, initial text={}] at (0,0) {1};
|
|
\node(2)[state, initial, initial text={}] at (0,-2) {2};
|
|
\node(3)[state, accepting by arrow] at (4,1) {3};
|
|
\node(4)[state, accepting by arrow] at (4,-1) {4};
|
|
\node(5)[state, accepting by arrow] at (4,-3) {5};
|
|
\node(6)[state] at (2,0) {6};
|
|
\node(7)[state] at (2,-2) {7};
|
|
\path
|
|
(1) edge [loop above] node {a} (1)
|
|
(1) edge node {b} (6)
|
|
(2) edge node {g} (7)
|
|
(3) edge node {d} (4)
|
|
(4) edge node {f} (7)
|
|
(5) edge [loop below] node {i} (5)
|
|
(6) edge node {e} (2)
|
|
(6) edge node {c} (3)
|
|
(7) edge node {h} (5)
|
|
;
|
|
\end{tikzpicture}
|
|
|
|
\columnbreak
|
|
|
|
En écrivant les transitions \emph{sortantes} depuis chaque état, on a alors~:
|
|
\begin{align*}
|
|
L &= X_{1-} + X_{2-} \\
|
|
X_{1-} &= aX_{1-} + bX_{6-} \\
|
|
X_{2-} &= gX_{7-} \\
|
|
X_{3-} &= dX_{4-} + \varepsilon \\
|
|
X_{4-} &= fX_{7-} + \varepsilon \\
|
|
X_{5-} &= iX_{5-} + \varepsilon \\
|
|
X_{6-} &= cX_{3-} + eX_{2-} \\
|
|
X_{7-} &= hX_{5-}
|
|
\end{align*}
|
|
|
|
\end{multicols}
|
|
|
|
Il faut ensuite injecter les égalités dans l'expression de $L$, et simplifier ces expressions progressivement.
|
|
Quand on obtient une expression récursive, par exemple ici $X_{5-} = iX_{5-} + \varepsilon$, on applique le \emph{Lemme d'Arden}, qui permet de réécrire une expression sans sa composante récursive~:
|
|
\begin{equation*}
|
|
X = YX + Z \implies X = Y^*Z
|
|
\end{equation*}
|
|
|
|
\paragraph{Méthode des suffixes (facteurs droite)}
|
|
|
|
Il faut cette fois écrire l'expression en partant de l'union (la somme) des expressions arrivant sur un état terminal ($X_{-t}$).
|
|
|
|
\begin{multicols}{2}
|
|
|
|
\begin{tikzpicture}[->, auto]
|
|
\node(1)[state, initial, initial text={}] at (0,0) {1};
|
|
\node(2)[state, initial, initial text={}] at (0,-2) {2};
|
|
\node(3)[state, accepting by arrow] at (4,1) {3};
|
|
\node(4)[state, accepting by arrow] at (4,-1) {4};
|
|
\node(5)[state, accepting by arrow] at (4,-3) {5};
|
|
\node(6)[state] at (2,0) {6};
|
|
\node(7)[state] at (2,-2) {7};
|
|
\path
|
|
(1) edge [loop above] node {a} (1)
|
|
(1) edge node {b} (6)
|
|
(2) edge node {g} (7)
|
|
(3) edge node {d} (4)
|
|
(4) edge node {f} (7)
|
|
(5) edge [loop below] node {i} (5)
|
|
(6) edge node {e} (2)
|
|
(6) edge node {c} (3)
|
|
(7) edge node {h} (5)
|
|
;
|
|
\end{tikzpicture}
|
|
|
|
\columnbreak
|
|
|
|
En écrivant les transitions \emph{entrantes} vers chaque état, on a alors~:
|
|
\begin{align*}
|
|
L &= X_{-3} + X_{-4} + X_{-5} \\
|
|
X_{-1} &= X_{-1}a + \varepsilon \\
|
|
X_{-2} &= X_{-6}e + \varepsilon \\
|
|
X_{-3} &= X_{-6}c \\
|
|
X_{-4} &= X_{-4}d \\
|
|
X_{-5} &= X_{-5}i + X_{-7}h \\
|
|
X_{-6} &= X_{-1}b\\
|
|
X_{-7} &= X_{-2}g + X_{-4}f
|
|
\end{align*}
|
|
|
|
\end{multicols}
|
|
|
|
Ici les expressions peuvent être simplifiées par le \emph{Lemme d'Arden}~:
|
|
\begin{equation*}
|
|
X = XY + Z \implies X = ZY^*
|
|
\end{equation*}
|
|
|
|
\end{document}
|