Une boucle sans variant connu
Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 3 — Algorithmes, programmes et complexité
Énoncé
Comparer ces deux boucles du point de vue de la terminaison.
/* A */ while (n > 0) { n = n / 2; }
/* B */ while (n != 1) { n = (n % 2 == 0) ? n / 2 : 3 * n + 1; }Corrigé
(A) termine, et la preuve tient en deux lignes. Variant : . Il est entier, minoré par tant que la condition tient, et il décroît strictement à chaque tour — pour , . La boucle s'arrête donc, en tours : mesuré, à partir de , elle en fait .
(B) est la suite de Syracuse, et personne ne sait la prouver. On mesure sans peine qu'elle s'arrête sur des cas particuliers :
n = 6 : 8 etapes, sommet atteint 16
n = 7 : 16 etapes, sommet atteint 52
n = 27 : 111 etapes, sommet atteint 9232
n = 871 : 178 etapes, sommet atteint 190996
pour tout n <= 10000 : au plus 261 etapes, atteintes en n = 6171
Ce qui ferme la porte à un variant simple est visible dans ces chiffres : partant de , la suite monte jusqu'à avant de redescendre. Aucune quantité évidente ne décroît. Et la conjecture de Collatz — « (B) termine pour tout » — est ouverte depuis 1937.
La terminaison n'est pas une évidence qu'on mentionne pour la forme. Voici deux boucles de deux lignes, d'apparence comparable : l'une se prouve en dix secondes, l'autre résiste depuis près d'un siècle. Trouver un variant est un vrai travail, et l'échouer n'est pas un défaut de méthode.
Le chapitre chap:decidabilite donne la raison profonde : il n'existe aucun algorithme capable de décider, en général, si un programme s'arrête. Le variant n'est pas une recette, c'est une preuve qu'on cherche au cas par cas.
Un test ne remplacerait pas la preuve. On peut vérifier (B) pour tous les jusqu'à — cela a été fait — sans rien démontrer. C'est la mise en garde du chapitre chap:discipline : « un test qui passe ne prouve rien ».
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.