%% This is a LaTeX document. Hey, Emacs, -*- latex -*- , get it? \documentclass[12pt,a4paper]{article} \usepackage[francais]{babel} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} %\usepackage{ucs} \usepackage{times} % A tribute to the worthy AMS: \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \usepackage{amsthm} % \usepackage{mathrsfs} \usepackage{wasysym} \usepackage{url} % \usepackage{graphics} \usepackage[usenames,dvipsnames]{xcolor} \usepackage{tikz} \usetikzlibrary{matrix} \usepackage[hyperindex=false]{hyperref} % \theoremstyle{definition} \newtheorem{comcnt}{Tout}[subsection] \newcommand\thingy{% \refstepcounter{comcnt}\smallbreak\noindent\textbf{\thecomcnt.} } \newtheorem{defn}[comcnt]{Définition} \newtheorem{prop}[comcnt]{Proposition} \newtheorem{lem}[comcnt]{Lemme} \newtheorem{thm}[comcnt]{Théorème} \newtheorem{cor}[comcnt]{Corollaire} \newtheorem{scho}[comcnt]{Scholie} \newtheorem{algo}[comcnt]{Algorithme} \renewcommand{\qedsymbol}{\smiley} \renewcommand{\thefootnote}{\fnsymbol{footnote}} % \newcommand{\liff}{\mathrel{\Longleftrightarrow}\relax} % \DeclareUnicodeCharacter{00A0}{~} % \DeclareMathSymbol{\tiret}{\mathord}{operators}{"7C} \DeclareMathSymbol{\traitdunion}{\mathord}{operators}{"2D} % % \DeclareFontFamily{U}{manual}{} \DeclareFontShape{U}{manual}{m}{n}{ <-> manfnt }{} \newcommand{\manfntsymbol}[1]{% {\fontencoding{U}\fontfamily{manual}\selectfont\symbol{#1}}} \newcommand{\dbend}{\manfntsymbol{127}}% Z-shaped \newcommand{\danger}{\noindent\hangindent\parindent\hangafter=-2% \hbox to0pt{\hskip-\hangindent\dbend\hfill}} % % % \begin{document} \title{THL (Théorie des langages)\\Notes de cours \textcolor{red}{provisoires}} \author{David A. Madore} \maketitle \centerline{\textbf{INF105}} {\footnotesize \immediate\write18{sh ./vc > vcline.tex} \begin{center} Git: \input{vcline.tex} \end{center} \immediate\write18{echo ' (stale)' >> vcline.tex} \par} \pretolerance=8000 \tolerance=50000 % % % {\footnotesize \tableofcontents \par} \bigbreak \section{Alphabets, mots et langages} \subsection{Introduction, alphabets, mots et longueur} \thingy L'objet de ces notes, au confluent des mathématiques et de l'informatique, est l'étude des \textbf{langages} : un langage étant un ensemble de \textbf{mots}, eux-mêmes suites finies de \textbf{lettres} choisies dans un \textbf{alphabet}, on va commencer par définir ces différents termes avant de décrire plus précisément l'objet de l'étude. \thingy Le point de départ est donc ce que les mathématiciens appelleront un \textbf{alphabet}, et qui correspond pour les informaticiens à un \textbf{jeu de caractères}. Il s'agit d'un ensemble \emph{fini}, sans structure particulière, dont les éléments s'appellent \textbf{lettres}, ou encore \textbf{caractères} dans une terminologie plus informatique. Les exemples mathématiques seront souvent donnés sur un alphabet tel que l'alphabet à deux lettres $\{a,b\}$ ou à trois lettres $\{a,b,c\}$. On pourra aussi considérer l'alphabet $\{0,1\}$ appelé \textbf{binaire} (puisque l'alphabet n'a pas de structure particulière, cela ne fait guère de différence par rapport à n'importe quel autre alphabet à deux lettres). Dans un contexte informatique, des jeux de caractères (=alphabets) souvent importants sont ASCII, Latin-1 ou Unicode : en plus de former un ensemble, ces jeux de caractère attribuent un numéro à chacun de leurs éléments (par exemple, la lettre A majuscule porte le numéro 65 dans ces trois jeux de caractères), mais cette structure supplémentaire ne nous intéressera pas ici. Dans tous les cas, il est important pour la théorie que l'alphabet soit \emph{fini}. L'alphabet sera généralement fixé une fois pour toutes dans la discussion, et désigné par la lettre $\Sigma$ (sigma majuscule). \thingy Un \textbf{mot} sur l'alphabet $\Sigma$ est une suite finie de lettres (éléments de $\Sigma$) ; dans la terminologie informatique, on parle plutôt de \textbf{chaîne de caractères}, qui est une suite finie (=liste) de caractères. Le mot est désigné en écrivant les lettres les unes à la suite des autres : autrement dit, si $x_1,\ldots,x_n \in \Sigma$ sont des lettres, le mot formé par la suite finie $x_1,\ldots,x_n$ est simplement écrit $x_1\cdots x_n$. À titre d'exemple, $abbcab$ est un mot sur l'alphabet $\Sigma = \{a,b,c,d\}$, et \texttt{foobar} est un mot (=chaîne de caractères) sur l'alphabet ASCII. (Dans un contexte informatique, il est fréquent d'utiliser une sorte de guillemet pour délimiter les chaînes de caractères : on écrira donc \texttt{\char`\"foobar\char`\"} pour parler du mot en question. Dans ces notes, nous utiliserons peu cette convention.) L'ensemble des mots sur un alphabet $\Sigma$ est généralement désigné $\Sigma^*$ (on verra que l'étoile fait partie d'un usage plus général qui sera défini ci-dessous). Par exemple, si $\Sigma = \{0,1\}$, alors $\Sigma^*$ est l'ensemble (infini !) dont les éléments sont toutes les suites finies binaires (=suites finies de $0$ et de $1$). \thingy Le nombre $n$ de lettres dans un mot $w \in \Sigma^*$ est appelé la \textbf{longueur} du mot, et généralement notée $|w|$ ou bien $\ell(w)$ : autrement dit, si $x_1,\ldots,x_n \in \Sigma$, alors la longueur $\ell(x_1\cdots x_n)$ du mot $x_1\cdots x_n$, vaut $n$. Ceci coïncide bien avec la notion usuelle de longueur d'une chaîne de caractères en informatique. À titre d'exemple, sur l'alphabet $\Sigma=\{a,b,c,d\}$, la longueur du mot $abbcab$ vaut $6$ (on écrira $|abbcab|=6$ ou bien $\ell(abbcab)=6$). \thingy Quel que soit l'alphabet, il existe un unique mot de longueur $0$, c'est-à-dire un unique mot n'ayant aucune lettre, appelé le \textbf{mot vide} (ou la \textbf{chaîne [de caractères] vide}). Étant donné qu'il n'est pas commode de désigner un objet par une absence de symbole, on introduit un symbole spécial, généralement $\varepsilon$, pour désigner ce mot vide : on a donc $|\varepsilon|=0$. On souligne que le symbole $\varepsilon$ \underline{ne fait pas partie} de l'alphabet $\Sigma$, c'est un symbole \emph{spécial} qui a été introduit pour désigner le mot vide. (Lorsque les mots sont délimités par des guillemets, comme il est usage pour les chaînes de caractères en informatique, le mot vide n'a pas besoin d'un symbole spécial : il s'écrit juste \texttt{\char`\"\char`\"} — sans aucun caractère entre les guillemets.) {\footnotesize Lorsque l'alphabet $\Sigma$ est \emph{vide}, c'est-à-dire $\Sigma=\varnothing$, alors le mot vide est le seul mot qui existe : on a $\Sigma^*=\{\varepsilon\}$ dans ce cas. C'est la seule situation où l'ensemble $\Sigma^*$ des mots est un ensemble fini. Dans la suite, nous négligerons parfois ce cas particulier, qu'on pourra oublier : c'est-à-dire que nous ferons parfois l'hypothèse tacite que $\Sigma \neq \varnothing$.\par} La notation $\Sigma^+$ est parfois utilisée pour désigner l'ensemble des mots \emph{non vides} sur l'alphabet $\Sigma$ (par opposition à $\Sigma^*$ qui désigne l'ensemble de tous les mots, y compris le mot vide). \thingy Les mots d'une seule lettre sont naturellement en correspondance avec les lettres elles-mêmes : on identifiera souvent tacitement, quoique un peu abusivement, une lettre $x\in\Sigma$ et le mot de longueur $1$ formé de la seule lettre $x$. (En informatique, cette identification entre \emph{caractères} et \emph{chaînes de caractères de longueur $1$} est faite par certains langages de programmation, mais pas par tous : \textit{caveat programmator}.) Ceci permet d'écrire par exemple $\Sigma \subseteq \Sigma^*$ ou bien $|x|=1 \liff x\in\Sigma$. \thingy\label{number-of-words-of-length-n} Si le cardinal de l'alphabet $\Sigma$ vaut $\#\Sigma = N$, alors, pour chaque $n$, le nombre de mots de longueur exactement $n$ est égal à $N^n$ (combinatoire classique). Le nombre de mots de longueur $\leq n$ vaut donc $1 + N + \cdots + N^n = \frac{N^{n+1}-1}{N-1}$ (somme d'une série géométrique). \subsection{Concaténation de mots, préfixes, suffixes, facteurs, sous-mots} \thingy Si $u := x_1\cdots x_m$ et $v := y_1\cdots y_n$ sont deux mots, de longueurs respectives $m$ et $n$, sur un même alphabet $\Sigma$, alors on définit un mot $uv := x_1\cdots x_m y_1\cdots y_n$ de longueur $m+n$, dont les lettres sont obtenues en mettant bout à bout celles de $u$ puis celles de $v$ (dans cet ordre), et on l'appelle \textbf{concaténation} (ou, si cela ne prête pas à confusion, simplement \textbf{produit}) des mots $u$ et $v$. (Dans un contexte informatique, on parle de concaténation de chaînes de caractères.) \thingy Parmi les propriétés de la concaténation, signalons les faits suivants : \begin{itemize} \item le mot vide $\varepsilon$ est « \textbf{neutre} » pour la concaténation, ce qui signifie par définition : $\varepsilon w = w \varepsilon = w$ quel que soit le mot $w \in \Sigma^*$ ; \item la concaténation est « \textbf{associative} », ce qui signifie par définition : $u(vw) = (uv)w$ quels que soient les mots $u,v,w \in \Sigma^*$. \end{itemize} On peut traduire de façon savante ces deux propriétés en une phrase : l'ensemble $\Sigma^*$ est un \textbf{monoïde}, d'élément neutre $\varepsilon$, pour la concaténation (cela signifie exactement ce qui vient d'être dit). \thingy On a par ailleurs $|uv| = |u| + |v|$ (la longueur de la concaténation de deux mots est la somme des concaténations), et on rappelle par ailleurs que $|\varepsilon| = 0$ ; on peut traduire cela de manière savante : la longueur est un \textbf{morphisme de monoïdes} entre le monoïde $\Sigma^*$ des mots (pour la concaténation) et le monoïde $\mathbb{N}$ des entiers naturels (pour l'addition) (cela signifie exactement ce qui vient d'être dit). {\footnotesize\thingy \textbf{Complément :} Le monoïde $\Sigma^*$ possède la propriété suivante par rapport à l'ensemble $\Sigma$ : si $M$ est un monoïde quelconque (c'est-à-dire un ensemble muni d'une opération binaire associative $\cdot$ et d'un élément $e$ neutre pour cette opération), et si $\psi\colon \Sigma\to M$ est une application quelconque, alors il existe un unique morphisme de monoïdes $\hat\psi\colon \Sigma^* \to M$ (c'est-à-dire une application préservant le neutre et l'opération binaire) tel que $\hat\psi(x) = \psi(x)$ si $x\in\Sigma$. (Démonstration : on a nécessairement $\hat\psi(x_1\cdots x_n) = \psi(x_1)\cdots \psi(x_n)$, or ceci définit bien un morphisme comme annoncé.) On dit qu'il s'agit là d'une propriété « universelle », et plus précisément que $\Sigma^*$ est le \textbf{monoïde libre} sur l'ensemble $\Sigma$. Par exemple, le morphisme « longueur » $\ell\colon\Sigma^*\to\mathbb{N}$ est le $\ell = \hat\psi$ obtenu en appliquant cette propriété à la fonction $\psi(x) = 1$ pour tout $x\in\Sigma$.\par} \thingy\label{powers-of-a-word} Lorsque $w \in \Sigma^*$ et $r \in \mathbb{N}$, on définit un mot $w^r$ comme la concaténation de $r$ facteurs tous égaux au mot $w$, autrement dit, comme la répétition $r$ fois du mot $w$. Formellement, on définit par récurrence : \begin{itemize} \item $w^0 = \varepsilon$ (le mot vide), \item $w^{r+1} = w^r w$. \end{itemize} (Ces définitions valent, d'ailleurs, dans n'importe quel monoïde. On peut constater que $w^r w^s = w^{r+s}$ quels que soient $r,s\in\mathbb{N}$.) On a bien sûr $|w^r| = r|w|$. Cette définition sert notamment à désigner de façon concise les mots comportant des répétitions d'une même lettre : par exemple, le mot $aaaaa$ peut s'écrire tout simplement $a^5$, et le mot $aaabb$ peut s'écrire $a^3 b^2$. (De même que pour le mot vide, il faut souligner que ces exposants ne font pas partie de l'alphabet.) \thingy Lorsque $u,v,w \in \Sigma^*$ vérifient $w = uv$, autrement dit lorsque le mot $w$ est la concaténation des deux mots $u$ et $v$, on dira également : \begin{itemize} \item que $u$ est un \textbf{préfixe} de $w$, ou \item que $v$ est un \textbf{suffixe} de $w$. \end{itemize} De façon équivalente, si $w = x_1\cdots x_n$ (où $x_1,\ldots,x_n \in \Sigma$) est un mot de longueur $n$, et si $0\leq k\leq n$ est un entier quelconque compris entre $0$ et $n$, on dira que $u := x_1\cdots x_k$ (c'est-à-dire, le mot formé des $k$ premières lettres de $w$, dans le même ordre) est le \textbf{préfixe de longueur $k$} de $w$, et que $v := x_{k+1}\cdots x_n$ (mot formé des $n-k$ dernières lettres de $w$, dans le même ordre) est le \textbf{suffixe de longueur $n-k$} de $w$. Il est clair qu'il s'agit bien là de l'unique façon d'écrire $w = uv$ avec $|u|=k$ et $|v|=n-k$, ce qui fait le lien avec la définition donnée au paragraphe précédent ; parfois on dira que $v$ est le suffixe \textbf{correspondant} à $u$ ou que $u$ est le préfixe correspondant à $v$ (dans le mot $w$). Le mot vide est préfixe et suffixe de n'importe quel mot. Le mot $w$ lui-même est aussi un préfixe et un suffixe de lui-même. Entre les deux, pour n'importe quelle longueur $k$ donnée, il existe un unique préfixe et un unique suffixe de longueur $k$. (Il peut tout à fait se produire que le préfixe et le suffixe de longueur $k$ soient égaux pour d'autres $k$ que $0$ et $|w|$, comme le montre l'exemple qui suit.) À titre d'exemple, le mot $abbcab$ sur l'alphabet $\Sigma=\{a,b,c,d\}$ a les sept préfixes suivants, rangés par ordre croissant de longueur : $\varepsilon$ (le mot vide), $a$, $ab$, $abb$, $abbc$, $abbca$ et $abbcab$ lui-même ; il a les sept suffixes suivants, rangés par ordre croissant de longueur : $\varepsilon$ (le mot vide), $b$, $ab$, $cab$, $bcab$, $bbcab$ et $abbcab$ lui-même. Le suffixe correspondant au préfixe $abb$ est $bcab$ puisque $abbcab = (abb)(bcab)$. \thingy Comme généralisation à la fois de la notion de préfixe et de celle de suffixe, on a la notion de facteur : si $u_0,v,u_1 \in \Sigma^*$ sont trois mots quelconques sur un même alphabet $\Sigma$, et si $w = u_0 v u_1$ est leur concaténation, on dira que $v$ est un \textbf{facteur} de $w$. Alors qu'un préfixe ou suffixe du mot $w$ est déterminé simplement par sa longueur, un facteur est déterminé par sa longueur et l'emplacement à partir duquel il commence. À titre d'exemple, les facteurs du mot $abbcab$ sont : $\varepsilon$ (le mot vide), $a$, $b$, $c$, $ab$, $bb$, $bc$, $ca$, $abb$, $bbc$, $bca$, $cab$, $abbc$, $bbca$, $bcab$, $abbca$, $bbcab$ et $abbcab$ lui-même. Dans un contexte informatique, ce que nous appelons ici « facteur » est souvent appelé « sous-chaîne [de caractères] ». Il ne faut cependant pas confondre ce concept avec celui de sous-mot défini ci-dessous. \thingy Si $u_0,\ldots,u_r$ et $v_1,\ldots,v_r$ sont des mots sur un même alphabet $\Sigma$, on dira que $v := v_1\cdots v_r$ est un \textbf{sous-mot} du mot $w := u_0 v_1 u_1 v_2 \cdots u_{r-1} v_r u_r$. En plus clair, cela signifie que $v$ est obtenu en ne gardant que certaines lettres du mot $w$ (celles des $v_i$), dans le même ordre, mais en en effaçant d'autres (celles des $u_i$) ; à la différence du concept de facteur, celui de sous-mot n'exige pas que les lettres gardées soient consécutives. À titre d'exemple, le mot $acb$ est un sous-mot du mot $abbcab$ (obtenu en gardant les lettres soulignées ici : $\underline{a}bb\underline{c}a\underline{b}$ ; pour se rattacher à la définition ci-dessus, on pourra prendre $u_0 = \varepsilon$ et $v_1 = a$ et $u_1 = bb$ et $v_2 = c$ et $u_2 = a$ et $v_3 = b$ et $u_3 = \varepsilon$). \subsection{Langages et opérations sur les langages} \thingy Un \textbf{langage} $L$ sur l'alphabet $\Sigma$ est simplement un ensemble de mots sur $\Sigma$. Autrement dit, il s'agit d'un sous-ensemble (=une partie) de l'ensemble $\Sigma^*$ de tous les mots sur $\Sigma^*$ : en symboles, $L \subseteq \Sigma^*$. On souligne qu'on ne demande pas que $L$ soit fini (mais il peut l'être). \thingy À titre d'exemple, l'ensemble $\{d,dc,dcc,dccc,dcccc,\ldots\} = \{dc^r \colon r\in\mathbb{N}\}$ des mots formés d'un $d$ suivi d'un nombre quelconque (éventuellement nul) de $c$ est un langage sur l'alphabet $\Sigma = \{a,b,c,d\}$. On verra plus loin que ce langage est « rationnel » (et pourra être désigné par l'expression rationnelle $dc*$). Voici quelques autres exemples de langages : \begin{itemize} \item Le langage (fini) $\{foo,bar,baz\}$ formé des seuls trois mots $foo$, $bar$, $baz$ sur l'alphabet $\Sigma = \{a,b,f,o,r,z\}$. \item Le langage (fini) formé des mots de longueur exactement $42$ sur l'alphabet $\Sigma = \{p,q,r\}$. Comme on l'a vu en \ref{number-of-words-of-length-n}, cet ensemble a pour cardinal exactement $3^{42}$. \item Le langage (fini) formé du seul mot vide (=mot de longueur exactement $0$) sur l'alphabet, disons, $\Sigma = \{p,q,r\}$. Ce langage $\{\varepsilon\}$ a pour cardinal $1$ (ou $3^0$ si on veut). Il ne faut pas le confondre avec le suivant : \item Le langage vide, qui ne contient aucun mot (sur un alphabet quelconque). Ce langage a pour cardinal $0$. \item Le langage formé des mots de une seule lettre sur un alphabet $\Sigma$, qu'on peut identifier à $\Sigma$ lui-même (en identifiant un mot de une lettre à la lettre en question). \item Le langage sur l'alphabet $\Sigma=\{a,b\}$ formé des mots qui commencent par trois $a$ consécutifs : ou, si on préfère, qui ont le mot $aaa$ comme préfixe. \item Le langage sur l'alphabet $\Sigma=\{a,b\}$ formé des mots qui contiennent trois $a$ consécutifs ; ou, si on préfère, qui ont $aaa$ comme facteur. \item Le langage sur l'alphabet $\Sigma=\{a,b\}$ formé des mots qui contiennent au moins trois $a$, non nécessairement consécutifs ; ou, si on préfère, qui ont $aaa$ comme sous-mot. \item Le langage sur l'alphabet $\Sigma=\{a\}$ formé de tous les mots dont la longueur est un nombre premier ($L = \{aa, aaa, a^5, a^7, a^{11},\ldots\}$). Ce langage est infini. \item Le langage sur l'alphabet $\Sigma=\{0,1\}$ formé de tous les mots commençant par un $1$ et qui, interprétés comme un nombre écrit en binaire, désignent un nombre premier ($L = \{10, 11, 101, 111, 1011, \ldots\}$). \item Le langage sur l'alphabet Unicode formé de tous les mots qui constituent un document XML bien-formé d'après la spécification XML 1.0. \end{itemize} \thingy On pourrait aussi considérer un langage (sur l'alphabet $\Sigma$) comme une \emph{propriété} des mots (sur l'alphabet en question). Précisément, si $P$ est une propriété qu'un mot $w \in \Sigma^*$ peut ou ne pas avoir, on considère le langage $L_P = \{w \in \Sigma^* : w \text{~a la propriété~} P\}$, et inversement, si $L \subseteq \Sigma^*$ est un langage, on considère la propriété « appartenir à $L$ » : en identifiant la propriété et le langage qu'on vient d'associer l'un à l'autre (par exemple, le langage des mots commençant par $a$ et la propriété « commencer par $a$ »), un langage pourrait être considéré comme une propriété des mots. {\footnotesize(Ceci n'a rien de spécifique aux langages : une partie d'un ensemble $E$ quelconque peut être identifiée à une propriété que les éléments de $E$ peuvent ou ne pas avoir, à savoir, appartenir à la partie en question.)\par} On évitera de faire cette identification pour ne pas introduire de confusion, mais il est utile de la garder à l'esprit : par exemple, dans un langage de programmation fonctionnel, un « langage » au sens de ces notes peut être considéré comme une fonction (pure, c'est-à-dire, déterministe et sans effet de bord) prenant en entrée une chaîne de caractères et renvoyant un booléen. \thingy Si $L_1$ et $L_2$ sont deux langages sur un même alphabet $\Sigma$ (autrement dit, $L_1,L_2 \subseteq \Sigma^*$), on peut former les langages \textbf{union} $L_1\cup L_2$ et \textbf{intersection} $L_1\cap L_2$ qui sont simplement les opérations ensemblistes usuelles (entre parties de $\Sigma^*$). Les opérations correspondantes sur les propriétés de mots sont respectivement le « ou logique » (=disjonction) et le « et logique » (=conjonction) : à titre d'exemple, sur $\Sigma = \{a,b\}$ si $L_1$ est le langage des mots commençant par $a$ et $L_2$ le langage des mots finissant par $b$, alors $L_1 \cup L_2$ est le langage des mots commençant par $a$ \emph{ou bien} finissant par $b$, tandis que $L_1 \cap L_2$ est le langage des mots commençant par $a$ \emph{et} finissant par $b$. \thingy Si $L$ est un langage sur l'alphabet $\Sigma$, autrement dit $L \subseteq \Sigma^*$, on peut former le langage $\Sigma^*\setminus L$, parfois noté simplement $\overline L$ si ce n'est pas ambigu, dit \textbf{complémentaire} de $L$, et qui est simplement l'ensemble des mots sur $\Sigma$ \emph{n'appartenant pas} à $L$. L'opération correspondante sur les propriétés de mots est la négation logique. À titre d'exemple, sur $\Sigma=\{a,b\}$, si $L$ est le langage des mots commençant par $a$, alors $\overline{L}$ est le langage des mots ne commençant pas par $a$, c'est-à-dire, la réunion de $\{\varepsilon\}$ et du langage des mots commençant par $b$ (car sur $\Sigma=\{a,b\}$, un mot ne commençant pas par $a$ est vide ou bien commence par $b$). \thingy Si $L_1$ et $L_2$ sont deux langages sur un même alphabet $\Sigma$ (autrement dit, $L_1,L_2 \subseteq \Sigma^*$), on peut former le langage \textbf{concaténation} $L_1 L_2$ : il est défini comme l'ensemble des mots $w$ qui peuvent s'écrire comme concaténation d'un mot $w_1$ de $L_1$ et d'un mot $w_2$ de $L_2$, soit \[ \begin{aligned} L_1 L_2 &= \{w_1 w_2 : w_1 \in L_1,\, w_2 \in L_2\}\\ &= \{w \in \Sigma^* : \exists w_1 \in L_1\, \exists w_2 \in L_2\,(w = w_1 w_2)\}\\ \end{aligned} \] À titre d'exemple, sur l'alphabet $\Sigma = \{a,b,c,d\}$, si on a $L_1 = \{a,bb\}$ et $L_2 = \{bc, cd\}$ alors $L_1 L_2 = \{abc, acd, bbbc, bbcd\}$. \thingy Si $L$ est un langage sur l'alphabet $\Sigma$, autrement dit $L \subseteq \Sigma^*$, et si $r \in \mathbb{N}$, on peut définir un langage $L^r$, par analogie avec \ref{powers-of-a-word}, comme le langage $L^r = \{w_1\cdots w_r : w_1,\ldots,w_r \in L\}$ formé des concaténation de $r$ mots appartenant à $L$, ou si on préfère, par récurrence : \begin{itemize} \item $L^0 = \{\varepsilon\}$, \item $L^{r+1} = L^r L$. \end{itemize} À titre d'exemple, sur l'alphabet $\Sigma = \{a,b,c,d\}$, si on a $L = \{a,bb\}$, alors $L^2 = \{aa, abb, bba, bbbb\}$ et $L^3 = \{aaa, aabb, abba, abbbb, \penalty-100 bbaa, bbabb, bbbba, bbbbbb\}$. \emph{Attention}, $L^r$ n'est pas le langage $\{w^r : w\in L\}$ formé des répétitions $r$ fois ($w^r$) des mots $w$ de $L$ : c'est le langage des concaténations de $r$ mots appartenant à $L$ \emph{mais ces mots peuvent être différents}. À titre d'exemple, si $L = \{a,b\}$ alors $L^r$ est le langage formé des $2^r$ mots de longueur exactement $r$ sur $\{a,b\}$, ce n'est pas l'ensemble à deux éléments $\{a^r, b^r\}$ formé des seuls deux mots $a^r = aaa\cdots a$ et $b^r = bbb\cdots b$. \thingy Si $L$ est un langage sur l'alphabet $\Sigma$, on définit enfin l'\textbf{étoile de Kleene} $L^*$ de $L$ comme le langage formé des concaténations d'un nombre \emph{quelconque} de mots appartenant à $L$, c'est-à-dire \[ \begin{aligned} L^* &= \bigcup_{r=0}^{+\infty} L^r = \bigcup_{r\in\mathbb{N}} L^r\\ &= \{w_1\cdots w_r : r\in\mathbb{N},\, w_1,\ldots,w_r\in L\}\\ \end{aligned} \] Comme ci-dessus, il faut souligner que les mots $w_1,\ldots,w_r$ concaténés n'ont pas à être égaux : notamment, $\{a,b\}^*$ est le langage formé de tous les mots sur l'alphabet $\{a,b\}$, pas le langage $\{a\}^* \cup \{b\}^*$ formé des mots obtenus en répétant la lettre $a$ ou en répétant la lettre $b$. On remarquera que la définition de $L^*$ ci-dessus redonne bien, lorsqu'on l'applique à l'alphabet $\Sigma$ lui-même (considéré comme langage des mots de longueur $1$), l'ensemble $\Sigma^*$ de tous les mots : la notation $\Sigma^*$ est donc justifiée \textit{a posteriori}. Le mot vide appartient toujours à $L^*$ (quel que soit $L$) puisque $L^0 = \{\varepsilon\}$ et qu'on peut prendre $r=0$ ci-dessus (autrement dit, le mot vide est la concaténation de zéro mots de $L$). On introduit parfois la notation $L^+ = \bigcup_{r=1}^{+\infty} L^r = \{w_1\cdots w_r : r>0,\penalty-100\, w_1,\ldots,w_r\in L\}$ pour l'ensemble des mots formés par concaténation d'un nombre \emph{non nul} de mots de $L$. Lorsque le mot vide $\varepsilon$ n'appartient pas déjà à $L$, ce langage $L^+$ diffère de $L^*$ seulement en ce qu'il ne contient pas $\varepsilon$ ; tandis que si $\varepsilon$ appartient déjà à $L$, alors $L^+$ est égal à $L^*$. \subsection{Langages rationnels et expressions rationnelles} \thingy Soit $\Sigma$ un alphabet. On va considérer les langages de base triviaux suivants : \begin{itemize} \item le langage vide $\varnothing$, \item le langage formé du seul mot vide, $\{\varepsilon\}$, et \item les langages formés d'un seul mot lui-même formé d'une seule lettre, $\{a\}$ pour chaque $a\in\Sigma$, \end{itemize} et on va les combiner par les opérations dites « rationnelles » suivantes : \begin{itemize} \item la réunion $(L_1,L_2) \mapsto L_1 \cup L_2$, \item la concaténation $(L_1,L_2) \mapsto L_1 L_2$, et \item l'étoile de Kleene $L \mapsto L^*$. \end{itemize} On obtient ainsi une certaine famille de langages (cf. ci-dessous pour une définition plus précise), qu'on appelle \textbf{langages rationnels} : les langages rationnels sont exactement ceux qui peuvent s'obtenir à partir des langages de base énumérés ci-dessus par application des opérations qu'on vient de dire (i.e., la réunion de deux langages rationnels, ou la concaténation de deux langages rationnels, ou l'étoile de Kleene d'un langage rationnel, sont rationnels, et les langages rationnels sont exactement ceux qu'on obtient ainsi). À titre d'exemple, sur l'alphabet $\{a,b,c,d\}$, comme le langage $\{c\}$ (formé du seul mot $c$) est rationnel, son étoile de Kleene, c'est-à-dire $\{c\}^* = \{\varepsilon, c, cc, ccc, cccc,\ldots\}$, est rationnel, et comme $\{d\}$ l'est aussi, la concaténation $\{d\}(\{c\}^*) = \{d, dc, dcc, dccc, \ldots\}$ est encore un langage rationnel. \thingy Pour décrire la manière dont un langage rationnel est fabriqué (à partir des langages de base par les opérations rationnelles), comme il est malcommode d'écrire quelque chose comme $\{d\}(\{c\}^*)$, on introduit un nouvel objet, les \textbf{expressions rationnelles} (certains préfèrent le terme d'\textbf{expressions régulières}), qui sont des expressions servant à désigner un langage rationnel. Plus exactement, une expression rationnelle (sur un alphabet $\Sigma$) est un mot sur l'alphabet $\Sigma \cup \{\bot, \underline{\varepsilon}, {(}, {)}, {|}, {*}\}$, où $\bot, \underline{\varepsilon}, {(}, {)}, {|}, {*}$ sont de nouveaux caractères \emph{n'appartenant pas} à l'alphabet $\Sigma$, appelés \textbf{métacaractères}, et qui servent à marquer la manière dont est formée l'expression rationnelle. On définit simultanément la notion d'expression rationnelle $r$ et de \textbf{langage désigné} $L_r$ par l'expression $r$, de la manière suivante : \begin{itemize} \item $\bot$ est une expression rationnelle et son langage désigné est $L_\bot := \varnothing$, \item $\underline{\varepsilon}$ est une expression rationnelle et son langage désigné est $L_{\underline{\varepsilon}} := \{\varepsilon\}$, \item si $x\in\Sigma$ est une lettre de l'alphabet $\Sigma$, alors le mot $x$ est une expression rationnelle et son langage désigné est $L_x := \{x\}$, \item si $r_1,r_2$ sont deux expressions rationnelles et $L_1 = L_{r_1}$ et $L_2 = L_{r_2}$ les langages désignés correspondants, alors $r_1 r_2$ est une expression rationnelle et son langage désigné est $L_{r_1 r_2} := L_1 L_2$, \item si $r_1,r_2$ sont deux expressions rationnelles et $L_1 = L_{r_1}$ et $L_2 = L_{r_2}$ les langages désignés correspondants, alors $(r_1|r_2)$ est une expression rationnelle et son langage désigné est $L_{(r_1|r_2)} := L_1\cup L_2$, \item si $r$ est une expression rationnelle et $L = L_r$ les langage désigné correspondant, alors $(r)*$ est une expression rationnelle et son langage désigné est $L_{(r)*} := L^*$. \end{itemize} À titre d'exemple, sur l'alphabet $\Sigma = \{a,b,c,d\}$, $c$ est une expression rationnelle qui désigne le langage $\{c\}$, donc $(c)*$ en est une qui désigne le langage $\{c\}^* = \{\varepsilon, c, cc, ccc,\ldots\}$, et enfin $d(c)*$ en est une qui désigne le langage $\{d, dc, dcc, \ldots\}$ des mots formés d'un $d$ et d'une succession quelconques de $c$. Voici quelques autres exemples, toujours sur $\Sigma = \{a,b,c,d\}$ : \begin{itemize} \item l'expression rationnelle $(a|b)$ désigne le langage $\{a\} \cup \{b\} = \{a,b\}$ formé des deux mots d'une seule lettre $a$ et $b$ ; \item l'expression rationnelle $(a|b)c$ désigne le langage $\{a,b\}\{c\} = \{ac,bc\}$, de même que $(ac|bc)$ ; \item l'expression rationnelle $(bc)*$ désigne le langage $\{bc\}^* = \{\varepsilon, bc, bcbc, bcbcbc, \ldots\}$ ; \item l'expression rationnelle $(a|(bc)*)$ désigne le langage $\{a\} \cup \{bc\}^* = \{a, \varepsilon, bc, bcbc, bcbcbc, \ldots\}$ ; \item l'expression rationnelle $(a|(bc)*)d$ désigne le langage $\{a, d, bcd, bcbcd, bcbcbcd, \ldots\}$. \end{itemize} Un langage rationnel est par définition la même chose qu'un langage pour lequel il existe une expression rationnelle qui le désigne. On dira qu'un mot $w$ \textbf{vérifie} une expression rationnelle $r$ lorsque ce mot appartient au langage qu'elle désigne (i.e., $w \in L_r$). Par exemple, $dccc$ vérifie l'expression rationnelle $d(c)*$. La convention de parenthésage introduite ci-dessus est inambiguë mais parfois inutilement lourde : on se permettra parfois de l'alléger, par exemple d'écrire $(r_1|r_2|r_3)$ pour $((r_1|r_2)|r_3)$ (ou pour $(r_1|(r_2|r_3))$, ce qui n'a guère d'importance vu qu'elles désignent le même langage), ou encore $x*$ pour $(x)*$ lorsque $x$ est formé d'un seul caractère. La convention essentielle est que l'opération d'étoile $*$ est la plus prioritaire ($ab*$ se lit comme $a(b)*$ et non pas comme $(ab)*$), la concaténation vient après, et la barre de disjonction $|$ est la moins prioritaire ($ab|cd$ se lit comme $(ab|cd)$ et pas comme $a(b|c)d$). {\footnotesize Les métacaractères $\bot$ et $\underline{\varepsilon}$ sont introduits ici par souci de complétude mais font rarement utilisés dans les expressions rationnelles (le métacaractère $\underline{\varepsilon}$ a été souligné parce qu'il s'agit d'une vraie lettre et non pas du mot vide ; on peut ignorer cette subtilité qui n'a que très peu d'importance).\par} % % % \end{document}