informatique (MP2I/MPI) · Chapitre 9 · Exercice de TD
Problème — Les mots bien parenthésés, ou deux définitions pour une famille
Ordres bien fondés et induction structurelle · niveau 3 (difficile)
Énoncé
On note l'ensemble inductif de mots sur engendré par : le mot vide appartient à ; si alors ; si alors .
- Montrer par induction structurelle que tout mot de a autant de parenthèses ouvrantes que de fermantes, et que tout préfixe en a au moins autant d'ouvrantes.
- Écrire un reconnaisseur en un passage, et prouver sa correction par un invariant.
- Montrer la réciproque : tout mot vérifiant les deux conditions est dans .
- Combien contient-il de mots de longueur ?
Corrigé
Notons et les nombres de parenthèses ouvrantes et fermantes de , et son solde.
1. La condition est nécessaire. On prouve simultanément, par induction structurelle sur la construction de :
Prouver les deux ensemble est indispensable : la seconde ne se déduit pas de la première.
Assertion, . Le seul préfixe est , de solde .
Règle . par hypothèse d'induction. Un préfixe de est (solde ), ou avec préfixe de (solde ), ou entier (solde ). Tous positifs.
Règle . . Un préfixe de est soit un préfixe de , de solde , soit avec préfixe de , de solde . C'est ici que sert, et c'est pourquoi les deux propriétés voyagent ensemble.
2. Le reconnaisseur. L'invariant est la propriété , lue de gauche à droite.
(* Renvoie true ssi s est bien parenthese. Complexite : Theta(|s|) en temps,
Theta(1) en memoire. *)
let reconnait s =
let n = String.length s in
let rec aux i solde =
(* INVARIANT : solde = s(s[0..i-1]), et tout prefixe deja lu a un solde >= 0 *)
if solde < 0 then false
else if i = n then solde = 0
else aux (i+1) (if s.[i] = '(' then solde + 1 else solde - 1)
in aux 0 0
Terminaison : variant , qui décroît de à chaque appel et reste positif. Correction : l'invariant est vrai à l'entrée (, solde ) ; il se conserve, le solde étant mis à jour selon la lettre lue ; à la sortie, ou bien un solde négatif a été rencontré et le mot est rejeté, ou bien et l'on teste . La fonction rend donc vrai exactement quand est vraie. Elle est récursive terminale : le compilateur OCaml en fait une boucle, et la mémoire reste constante.
3. La réciproque, par récurrence forte sur . Soit de solde nul dont tous les préfixes ont un solde positif ou nul.
Si , il est dans . Sinon, commence par — sans quoi son préfixe de longueur aurait un solde . Soit le plus petit indice tel que le préfixe ait un solde nul ; il existe, puisque entier convient. Écrivons avec .
Alors : la première lettre est , la dernière est car le solde passe de à à cette position, et le mot intérieur a un solde nul. Ses préfixes ont un solde positif ou nul, car un préfixe de donne le préfixe de , de solde par minimalité de — c'est le choix du plus petit qui fait tout le travail. De même , de longueur , vérifie les deux conditions.
Par hypothèse de récurrence forte, et ; les deux règles donnent puis .
Vérification exhaustive. Pour allant de à , on a engendré tous les mots de et, séparément, filtré tous les mots de longueur par le reconnaisseur. Les deux ensembles sont identiques à chaque longueur. La longueur met mots à l'épreuve.
4. Le dénombrement, mesuré :
| longueur | |||||||
|---|---|---|---|---|---|---|---|
| mots de |
Ce sont les nombres de Catalan . La récurrence se lit sur la décomposition de la question 3, qui est unique : avec et , d'où
Les cinq mots de longueur : ((())), (()()), (())(), ()(()), ()()().
Ce que le problème a vraiment établi. Deux définitions d'apparence sans rapport — l'une constructive par des règles, l'autre déclarative par une condition sur les soldes — décrivent la même famille. C'est la situation la plus fréquente en informatique : la première dit comment fabriquer, la seconde comment vérifier, et il faut les deux. Les mêmes nombres de Catalan compteront les arbres binaires au chapitre chap:arbres — et ce n'est pas une coïncidence : la décomposition unique est exactement la décomposition d'un arbre en sa racine, son fils gauche et son fils droit.