Mathématiques pour l’Informatique 2 2016–17                  http://www.lri.fr/~blsk/MI2


5  Le paysage syntaxique

5.1  Ensemble des mots

Les mots sont une structure très utilisée en informatique. La théorie des langages classifie les ensembles de mots (langages réguliers ou algébriques) suivant leur propriétés, en particulier la manière de reconnaître qu’un mot appartient à un certain langage. Un programme donné à interpréter à un ordinateur est un mot. De la même manière, on peut représenter les actions réalisées par un programme par un mot, et donc certaines techniques d’analyse de programme s’appuient sur des résultats de théorie des langages.

Les mots sont aussi la notion sous-jacente aux structures séquentielles (tableaux, listes) qui servent dans de nombreux algorithmes en particulier pour représenter en machine des ensembles d’objets.

5.1.1  Définitions

On se donne un ensemble (en général fini) d’objets A que l’on appelle un alphabet. Les éléments d’un alphabet sont appelés des caractères.

Les mots sont des suites finies de caractères. On peut les représenter comme des couples formés d’un entier n (la taille du mot) et d’une application f de [0,n[ dans A. On notera A* l’ensemble des mots sur l’alphabet A.

Si m est un mot, on note |m| la longueur du mot et pour chaque i < |m|, on note m[i] le i-ème caractère du mot m (on commence à 0).

Pour définir un mot m, il suffit de se donner sa longueur n et une application de [0,n[ dans A.

On introduit les opérations suivantes sur les mots:

5.1.2  Propriétés

On montre les propriétés essentielles des opérations précédentes.

Proposition 1   Preuve:

Autres opérations sur les mots.

Un mot m qui n’est pas vide a un premier caractère a=m[0] et peut être décomposé m=am avec m le mot obtenu en retirant le premier caractère de m et défini par : |m′|=|m|−1 et m′[i]=m[i+1]. On introduit les notations hd(m) pour le caractère a et tl(m) pour le mot m.

5.1.3  Ensemble de mots

Un langage est un ensemble de mots. Il peut se définir par un système d’inférence.

Exercice 1   On se donne un alphabet formé de deux caractères a et b, on définit une propriété D(m) par les règles d’inférence suivantes:
 
D(є) 
      
D(m
D(amb
        
D(m
D(mb
  1. Dire si les mots suivants vérifient la condition D:
    aabb       abb       aab        abab
  2. Montrer que si D(m) est vérifié alors le nombre de caractères a dans m est inférieur ou égal au nombre de caractères b dans m.
Preuve:
  1. Les mots aabb et abb appartiennent au langage, on peut construire les arbres de dérivation:
     
     
      
     D(є)
     D(ab)
     D(aabb)
                     
     
     
      
     D(є)
     D(ab)
     D(abb)
    Le mot aab n’appartient pas à la relation (cf question suivante), le mot abab non plus car on pourrait montrer que si D(m) alors m est de la forme anbm avec mn.
  2. On prend pour propriété P(m) le fait que le nombre de b dans m est supérieur au nombre de a dans m et on vérifie que cette propriété est bien préservée par toutes les règles d’inférence.
Exercice 2   Donner une définition par clôture de l’ensemble des palindromes sur l’alphabet {a,b}, c’est-à-dire des mots qui sont les mêmes quel que soit le sens dans lequel on les lit.

5.1.4  Définitions de fonctions récursives sur les mots

Le schéma de définition récursive sur les entiers se généralise au cas des mots. Une manière naturelle de définir une application f dans A*B consiste à définir la valeur bB de l’application pour le mot vide, et pour un caractère aA arbitraire et un mot mA* de définir f(am) en fonction de a, de m et de f(m), c’est-à-dire se donner une application G dans A× A* × BB telle que f(am)=G(a,m,f(m)).

Exemple 1   On peut ainsi définir l’application qui à un mot associe sa longueur:
lg(є)=0       lg(am)=1+lg(m)
La définition du nombre d’occurrences d’une lettre b dans un mot est donnée par:
nb(b,є)=0       nb(b,am)=1+nb(b,msi  a=b        nb(b,am)=nb(b,msi  a≠ b

On remarque que l’on ne peut pas se servir de la concaténation de deux mots arbitraires comme construction d’équations fonctionnelles. En effet si on pose des équations:

f(є)=0     f(a)=1       f(m1 m2)=1+f(m1)+f(m2)

alors ces équations n’ont pas de solution en effet on devrait avoir f(aє)=1+f(a)+f(є)=2 et par ailleurs comme aє=a, on a aussi f(aє)=f(a)=1 ce qui ne peut se réaliser. On peut toujours utiliser une définition par cloture de la relation f(x,n) mais cette relation n’est pas fonctionnelle. Cela vient du fait que la décomposition d’un mot m sous la forme m1m2 n’est pas unique.

Exercice 3   Définir la fonction qui à un mot a1,… an associe le mot inverse ana1.

5.2  Arbres

Les mots sont des structures linéaires. Pour des raisons d’efficacité, on introduit des structures un peu plus complexes qui sont celles d’arbre. Ainsi les fichiers dans un ordinateur sont regroupés dans des répertoires. Un répertoire peut contenir des fichiers mais aussi d’autres répertoires créant ainsi une structure hiérarchique arborescente. Pour retrouver un fichier, il ne sera pas forcément nécessaire de les considérer dans leur globalité : si on sait reconnaitre à chaque étape dans quel sous-réperoire il peut se trouver, la recherche sera proportionnelle à la profondeur d’imbrication (et au nombre de fichiers dans le dernier répertoire), pas au nombre total de fichiers. Nous allons définir ce qu’est formellement un arbre.

5.2.1  Définitions des arbres

Il y a de nombreuses manières de définir la notion d’arbre. Une des plus courantes est de se ramener à la notion de graphe dirigé.

Définition 1 (Arbre)   Un arbre est un graphe dirigé qui possède de plus la propriété qu’il existe un sommet r appelé la racine tel que pour tout sommet x du graphe, il existe un unique chemin de r à x.

On appelle feuille de l’arbre un sommet dont le degré sortant est nul. Les autres sommets sont appelés des nœuds internes.

La profondeur d’un sommet de l’arbre est la longueur du chemin de la racine à ce sommet. La hauteur de l’arbre est la profondeur maximale d’un sommet (quand elle existe, car on peut construire des arbres ayant des branches infinies).

Exercice 4   Dire si les graphes suivants sont des arbres.

Proposition 2   Les arbres vérifient les propriétés suivantes: Preuve:
  1. Si l’arbre a un cycle, alors il existe un sommet x et un chemin c non vide de x à x. Comme x est dans l’arbre, il y a un chemin d de r à x, mais en concaténant d et c, on obtient un deuxièeme chemin r à x, ce qui contredit le fait que ce soit un arbre.
  2. Si x est un sommet différent de la racine r, alors il existe un chemin de r à x qui n’est pas vide, on a donc au moins une arête entrante sur x. Supposons qu’il y en ait 2 que l’on note e et f et soit a l’origine de e et b l’origine de f. On a un chemin de c de r à a et un chemin de d de r à b. On aurait donc deux chemins cex et dfx différents de r à x qui contredirait le fait que le graphe soit un arbre.
  3. On montre par récurrence sur le nombre de sommets dans le graphe que c’est un arbre.

    Il y a au moins un sommet de degré entrant 0, si c’est le seul sommet alors il n’y a pas d’arêtes et donc c’est un arbre.

    On suppose maintenant le résultat vrai pour un graphe avec n sommets et on le montre pour un graphe à n+1 sommets.

    La somme des degrés entrants est égale à la somme des degrés sortants. S’il y a n sommets, la somme des degrés entrants est n−1, dont il y a au moins un sommet x de degré sortant 0. Cela ne peut pas être le sommet de degré entrant 0 car sinon ce serait un point isolé et donc le graphe ne serait pas connecté. Le sommet x a donc un degré entrant de 1. On retire le sommet x du graphe ainsi que l’arête entrante, le graphe obtenu satisfait bien les hypothèses du graphe initial, on peut lui appliquer l’hypothèse de récurrence et c’est donc un arbre. Les seuls chemins qui passent par e sont les chemins qui se terminent par e pour arriver en x, on a donc bien que le graphe complet est un arbre.

Représentation graphique

On représente souvent les arbres avec une convention implicite sur le sens des flèches (du haut vers le bas ou du bas vers le haut ou encore de gauche à droite), en alignant verticalement ou horizontalement tous les sommets de même profondeur. On se dispense alors de représenter les “noms” des sommets, la position géométrique suffit à donner une représentation canonique de l’arbre.

Représentation à partir de chemins

On s’intéresse à des ensembles de mots formés d’entiers naturels non nuls, c’est-à-dire des sous-ensembles de ℕ\{0}*.

Définition 2 (Ensemble de positions)   Un sous-ensemble de mots P⊆ ℕ\{0}* est appelé un ensemble de positions s’il vérifie les propriétés suivantes

Si on se donne un ensemble de positions P alors on peut lui associer un graphe dirigé dont les sommets sont les éléments de P et dans lequel il y a une arète de m à mi pour tout miP.

La racine correspond au mot vide et est connectée à chacun des sommets m en passant par tous préfixes de m. Le chemin est unique car sinon un mot aurait dex préfixes différents.

Réciproquement, tout arbre ayant un ensemble dénombrable de sommets est isomorphe à un arbre construit à partir d’un ensemble de position.

Exercice 5   Donner l’ensemble des positions associées à l’arbre suivant :

Arbre annoté

Un arbre vu comme un graphe ou un ensemble de position représente uniquement un squelette. On a remarqué que les noms des sommets n’étaient pas une information très intéressante. L’arbre précédent se représentera tout aussi bien de la manière suivante, chaque nœud pouvant s’identifier grace à sa position.

En général, on a besoin d’associer des informations aux nœuds de l’arbre. On le fait en se donnant une application des sommets de l’arbre dans l’ensemble des informations A que l’on souhaite afficher dans l’arbre et on inscrit cette valeur comme étiquette du noeud. Par exemple pour un arbre de classification en biologie ou d’organisation de répertoires,

Parfois les annotations ne sont associées qu’aux nœuds internes et pas au feuilles qui sont vues comme des nœuds sans information (ceci est lié à la représentation syntaxique des arbres annotés et à leur représentation en machine).

5.3  Termes

Nous allons généraliser les constructions introduites précédemment pour les entiers ou les mots à des structures plus complexes. En effet en informatique, la machine manipule in fine des données assez simples à savoir des suites (finies) de 0 et de 1. Néanmoins, lorsqu’on veut modéliser une structure particulière comme une base de données ou une image, ces suites de 0 et de 1 sont organisées suivant des schémas très spécifiques. L’identification de ces schémas va nous permettre d’avoir des moyens de haut niveau pour construire ces objets et raisonner en faisant abstraction de la représentation physique.

On est amené par exemple à manipuler des structures d’arbres, que ce soit des arbres binaires pour représenter efficacement des ensembles finis d’objets ou bien des arbres de syntaxe abstraite pour représenter des programmes dans les compilateurs.

Dans cette section, on s’intéresse à des représentations syntaxiques, qu’il faut bien distinguer du modèle sous-jacent. Par exemple si on considère l’expression 2+3, le niveau syntaxique fait une différence entre cette expression et les expressions 5, 3+2 ou 2+(2+1) alors que toutes ces expressions correspondent au même modèle entier 5. Cette distinction entre syntaxe et modèle réel est importante en informatique où l’ordinateur effectue des manipulations symboliques sur des objets structurés qui représentent des notions complexes (des nombres flottants voir des rationnels ou des réels, des bases de données, des programmes, …).

5.3.1  Définitions

Définition 3 (Signature)   Une signature F est composée d’un ensemble fini d’objets que l’on appellera des symboles et d’une application arity dans F→ ℕ qui associe à chaque symbole f un entier arity(f) que l’on appellera l’arité de f.
Les symboles d’arité
0 sont appelés des constantes. Les autres symboles sont appelés des symboles de fonction et l’arité représente le nombre d’arguments attendus par ce symbole de fonction. On parle de symbole unaire pour une arité 1 et binaire pour une arité 2.
On notera
Fn l’ensemble des symboles d’arité n de la signature F.
Exemple 2 (Signature pour les entiers)   Une signature possible pour les expressions arithmétiques est constituée d’une constante 0 (arité 0) et un symbole S pour l’opération successeur d’arité 1. On peut aussi ajouter des symboles de fonctions binaires pour les opérations arithmétiques telles que l’addition (notée plus) et la multiplication (notée mult).
Définition 4 (Termes T( F))   Soit une signature F, on définit l’ensemble T( F) comme un ensemble de mots formés sur un alphabet composé des symboles de F et des caractères {(;);, } défini par les règles d’inférence suivantes (une pour chaque symbole) :
c F0 
c∈  T( F
     
f Fn    t1 T( F)  …   tn T( F
f(t1,…,tn) ∈  T( F
Exemple 3   Les mots suivants sont des termes sur la signature des entiers : S(0)    plus(S(0),0). On notera 1 le terme S(0), 2 le terme S(S(0))
Par contre les mots suivants ne sont pas des termes :
S    0(0)    S(0,0).

Notations.

On utilise parfois une notation infixe pour les symboles de fonctions binaires, c’est-à-dire que l’on écrira (t1 f t2) au lieu de f(t1,t2) de même on peut omettre certaines parenthèses en s’appuyant sur des conventions, mais il s’agit de facilités d’écriture qui ne changent pas la définition mathématique.

Termes avec variables.

En logique ou en informatique on a souvent besoin de considérer des termes généralisés dans lesquels apparaissent des variables. On l’a vu avec les formules quantifiées en logique. En informatique, les fonctions dans les langages de programmation correspondent à des termes avec des variables (pour les paramètres). Contrairement aux constantes dans les signatures, les variables peuvent être choisies dans un ensemble infini X (mais seulement un nombre fini de variables apparait dans chaque terme).

Définition 5 (Termes avec variables T( F, X))   Soit une signature F, un ensemble X de variables, on définit l’ensemble T( F, X) comme un ensemble de mots formés sur un alphabet composé des symboles de F, des variables X et des caractères (, ) et , défini par les règles d’inférence suivantes :
x X 
x∈  T( F, X
         
c F0 
c∈  T( F, X
     
f Fn    t1 T( F, X)  …   tn T( F, X
f(t1,…,tn) ∈  T( F, X

Les termes de T( F) sont un cas particulier de terme avec variables dans lesquels l’ensemble des variables X est vide. Dans la suite, on considèrera uniquement des termes sans variables.

Définition 6 (Terme clos)   Un terme de T( F, X) qui ne contient pas de variable est appelé un terme clos.

5.3.2  Egalité sur les termes

L’égalité sur les mots induit une égalité sur les termes. En particulier on peut dériver la propriété suivante :

t=u ⇔ 
(∃ c ∈  F0  , t=c ∧ u = c )
∨  (∃ f ∈  F1, ∃ t′ u′, t=f(t′) ∧ u = f(u′) ∧ t′=u′)
     … 
∨  (∃ f ∈  Fn, ∃ t1 … tn  u1… unt=f(t1,…,tn) ∧ u = f(ui,… un) ∧ t1=u1 ∧…∧ tn=un)
Exemple 4   On considère la signature des entiers avec 0, S et plus. On a x=yS(x)=S(y) mais on a aussi plus(x,y)=plus(z,t) ⇔ (x=zy=t) et plus(x,y)≠0 ainsi que plus(x,y)≠S(z). On pourra dériver plus(0,0)≠0 ou bien plus(S(0),0)≠plus(0,S(0)). Ce qui correspond au fait que les termes représentent l’enchainement des opérations (comme sur une calculatrice) et non pas le résultat.

5.4  Induction, récursion sur les termes

5.4.1  Définition récursive sur les termes

On peut généraliser la notion de définition récursive d’une application sur les entiers en définition récursive sur des termes arbitraires.

On suppose que l’on veut définir une application F dans T( F) → A. Pour cela on va se donner les objets suivants :

  1. Pour chaque constante c F0, un élément dcA
  2. Pour chaque symbole de fonction f Fn, une application Gf dans
     
     
     T( F)×… ×   T( F)


    n fois
    ×
     
     
    A×… × A


    n fois
     → A
    .

Il existe une unique application F dans T( F) → A qui vérifie :

F(c)=dc  (c F0)          F(f(t1,…,tn))=Gf(t1,…,tn,F(t1),…,F(tn))  (f Fn)

Le fait que l’on puisse définir une telle application est une conséquence de l’égalité sur les termes. En particulier, deux termes qui débutent par des symboles différents sont différents.

En effet ce schéma permet de définir une application f telle que f(c)=1 pour les constantes et f(t)=2 pour tous les termes qui commencent par un symbole de fonction. Si on avait plus(0,0)=0 alors on en déduirait f(plus(0,0))=f(0) et donc 2=1.

Exemple 5 (Taille d’un terme)   Le schéma de définition récursive précédent permet de définir l’application size qui compte le nombre de symboles dans un terme. Dans le cas de la signature sur les entiers, soit t le terme plus(0,S(0)), il vérifie size(t)=4.
Exemple 6 (Hauteur d’un terme)   Un autre exemple de définition récursive est l’application ht qui compte le nombre maximal de symboles imbriqués dans un terme. Pour le terme t précédent on a ht(t)=3.
Exercice 6   On suppose donnée la signature des entiers F qui contient les symboles 0, S, plus, mult. Définir une application de T( F) dans , qui à chaque terme associe sa valeur.

5.4.2  Induction sur les termes

L’induction généralisée associée à la définition par cloture de T( F) s’exprime de la manière suivante. Soit P(t) une propriété qui dépend d’un terme t T( F). On suppose :

  1. pour chaque constante c F0: P(c);
  2. pour chaque symbole f Fn : t1tn T( F), P(t1)⇒ ⋯ P(tn)⇒ P(f(t1,…,tn));

alors t T( F),P(t).

Exemple 7   On peut par exemple montrer la propriété suivante sur les termes :
∀ t ∈  T( F),ht(t) ≤ size(t)
Preuve: La preuve se fait par induction sur la structure du terme t.
constante
ht(c) ≤ size(c) vrai car ht(c)=1=size(c).
symbole
si f Fn: soit des termes arbitraires t1,…,tn T( F), on suppose que ht(ti) ≤ size(ti). on doit montrer ht(f(t1,…,tn)) ≤ size(f(t1,…,tn)).
ht(f(t1,…,tn))=
= 1+max(ht(t1),…,ht(tn)) 
 ≤ 1+ ht(t1)+⋯ + ht(tn
≤ 1+ size(t1)+⋯ + size(tn)
=size(f(t1,…,tn))

5.5  Généralisations

5.5.1  Termes vus comme des arbres

Nous avons défini les termes comme des mots en mettant en avant la structure séquentielle ce qui nous a amené à introduire les symboles parenthèses et virgule. La définition par cloture met l’accent sur la structure arborescente des termes. Une constante est vue comme une feuille de l’arbre, un terme f(t1,…,tn) est représenté comme un arbre dont la racine est étiquetée par f et qui a n fils, que l’on considère de manière ordonnée. Le i-ème sous-arbre est associé au terme ti.

Exemple 8   Soit le terme t=plus(mult(0,0),S(0)) sa représentation sous forme d’arbre est donnée par :

Positions dans un terme.

Un terme définit un ensemble de positions. Une position est une suite finie d’entiers compris entre 1 et l’arité maximale des éléments de la signature. La position décrit un chemin pour se déplacer dans l’arbre en partant de la racine, l’entier permet de choisir dans quel sous-terme continuer.

Définition 7 (Positions d’un terme pos(t))   On définit l’ensemble des positions d’un terme t par les règles d’inférence suivantes pour chaque symbole f Fn et chaque i tel que 1≤ in :
 
є∈pos(t
    
mpos(ti
im ∈ pos(f(t1,…,ti,…,tn)) 

On remarque que lorsque t est une constante alors: pos(t)={є }.

Définition 8 (Sous-terme à une position)   Soit ppos(t), on définit le sous-terme de t à la position p (noté t|p) comme une fonction récursive sur le mot p représentant la position :
t|є=t       f(t1,…,tn)|im=ti|m
On remarque que comme ppos(t) par inversion de la définition par cloture lorsque p=im on sait qu’il existe un symbole f d’arité n tel que 1≤ in et t=f(t1,…,tn) et mpos(ti) ce qui justifie la définition.
Exemple 9   On considère le terme t=plus(0,S(0)). L’ensemble des positions de t est défini par : pos(t)={є;1;2;21 } On a t|є=t, t|1=0, t|2=S(0), t|21=0.

5.5.2  Termes avec sortes

Lorsque l’on introduit des signatures complexes, il est souvent naturel de distinguer différentes catégories de termes.

Par exemple les termes correspondant aux suites finies peuvent se construire avec une constante nil et un symbole cons binaire pour ajouter un caractère en premier élément d’une suite. Il nous reste à introduire une signature pour représenter les éléments de la suite, par exemple des entiers avec une constante 0 et un symbole unaire S. Dans le cadre général, rien n’interdit de construire des termes comme S(cons(0,є)) qui n’ont pas d’interprétation naturelle.

Pour remédier à ce problème, on introduit des sortes qui permettent de distinguer les différentes classes de termes. Les sortes sont un ensemble fini (par exemple {nat,seq } pour représenter la sorte des entiers naturels et celle des séquences d’entiers). Au lieu d’être un simple entier décrivant le nombre d’arguments, une arité décrit la sorte des termes que le symbole prend en argument et la sorte du terme construit en résultat, on l’écrira s1×…× sns. Dans notre exemple de suite d’entiers :

On définit maintenant par cloture l’ensemble T( F,s) des termes de sorte s:

c ∈  F0  arity(c)=s 
c ∈  T( F,s
        
f ∈  Fn  arity(f)=s1× … × sn → s   t1 T( F,s1)… tn T( F,sn
f(t1,…,tn) ∈  T( F,s

5.6  Arbres binaires

Une structure importante en informatique est celle d’arbre binaire. On suppose que l’on souhaite stocker dans cet arbre des objets. On introduit une sorte elt pour représenter ce qui est stocké dans l’arbre avec par exemples des constantes a, b, c, d, e. On introduit également la sorte tree pour les arbres binaires.

Une signature (notée A) possible est donnée par :

L’arbre

est représenté par le terme :

node(node(node(leaf,c,leaf), b, node(leaf,d,leaf) ,a,node(leaf,e,node(leaf,c,leaf))))

qui lui même peut se représenter sous forme d’arbre :

On définit de nombreuses fonctions sur les arbres en suivant le schéma de définition récursive sur les termes.

Par exemple la hauteur:

ht(leaf) = 0              ht(node(l,a,r)) = 1 + max(ht(l),ht(r))

On peut aussi définir un parcours d’arbre qui construit la suite finie des éléments qui apparaissent dans l’arbre :

elts(leaf) = є               elts(node(l,a,r)) = elts(l)  a  elts(r)

De manière générale, le principe de définition récursive sur les arbres est donné par la définition suivante :

Proposition 3   Soit A la signature des arbres, soient T= T( A,tree) et E= T( A,elt) et deux ensembles X et Y quelconques.

Soit une fonction hXY et gT × E × T × Y × Y × XY alors il existe une unique fonction fT × XY telle que :

f(leaf,x)=h(x)       f(node(l,e,r),x)=g(l,e,r,f(l,x),f(r,x))

De plus la propriété suivante (schéma d’induction sur les arbres) est vérifiée pour toute propriété P sur les arbres :

Comme précédemment, le schéma peut être généralisé en autorisant dans les appels récursifs de f(l,x) et f(r,x) d’appliquer une transformation à x.

Exercice 7   En supposant que les élements associés aux arbres sont dans la sorte des entiers, écrire une fonction qui associe à chaque arbre la somme des éléments qui apparaissent dans cet arbre.

Preuve: La fonction demandée est la solution des équations :

sum(leaf)=0                 sum(node(l,e,r))=sum(l)+e+sum(r)