Adloun

McCarthy 91 : le variant n'est pas un argument

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 9 — Ordres bien fondés et induction structurelle

Énoncé

Cette fonction termine-t-elle ? Que vaut-elle ?


let rec f n = if n > 100 then n - 10 else f (f (n + 11))

Corrigé

Elle termine, et pour tout — vérifié par le calcul pour tous les entiers de à . Au-delà, .

La difficulté est double, et il faut la nommer avant de la résoudre. L'argument augmente de à chaque appel interne : aucun variant décroissant ne peut porter sur tel quel. Et l'appel externe porte sur une valeur calculée : on ne connaît son argument qu'après avoir exécuté l'appel interne.

Le variant. On pose

à valeurs dans , muni de , qui est bien fondé.

L'appel interne avec : si , alors ; sinon , et l'appel se termine en une étape puisque . Le variant décroît, ou l'appel est immédiat.

L'appel externe où : il faut savoir que pour tout , ce qui est précisément le résultat qu'on démontre. Terminaison et valeur ne se séparent pas ici, et c'est ce qui rend cette fonction célèbre : on prouve les deux simultanément, par récurrence sur .

La preuve, en deux temps. Pour : est entre et , donc , et . Une récurrence descendante depuis donne sur tout cet intervalle. Pour : , l'hypothèse de récurrence sur donne , donc .

Les mesures qui accompagnent. Nombre d'appels : pour , pour , pour , pour , pour , pour . On lit la structure : deux appels de plus par unité en dessous de , tant qu'on reste au-dessus de ; puis un régime plus lent.

La leçon. Un variant n'est pas « l'argument », ni « un des arguments » : c'est n'importe quelle fonction des arguments à valeurs dans un ensemble bien fondé, et c'est au programmeur de l'inventer. Ici il fallait le chercher dans la distance à , une quantité qui n'apparaît nulle part dans le code.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.