ProblĂšme de l'arrĂȘt et dĂ©cidabilitĂ©

Certains programmes utilisent comme données le code source d'autres programmes. Les compilateurs sont des bons exemples. Nous avons eu l'année derniÚre l'occasion de travailler sur le langage C, et nous avons vu que ce langage est un langage compilé : une fois le code source terminée, le compilateur (qui est un logiciel comme un autre) "transforme" ce code source en langage machine.

Il existe d'autres exemples de programmes qui utilisent comme données d'autres programmes :

  • un systĂšme d'exploitation peut ĂȘtre vu comme un programme qui fait "tourner" d'autres programme

  • pour tĂ©lĂ©charger un logiciel on utilise un gestionnaire de tĂ©lĂ©chargement qui est lui-mĂȘme un logiciel.

On trouve mĂȘme des programmes capables de dĂ©tecter certaines erreurs dans le code source d'autres programmes ou mĂȘme encore des programmes capables de prouver (mathĂ©matiquement parlant) qu'un autre programme est correct (qu'il fait bien ce pour quoi il a Ă©tĂ© conçu). Le dĂ©veloppement de programmes de "dĂ©tection d'erreurs" ou encore de "preuve de correction" a connu une forte croissance en France, notamment depuis l'accident du vol 501 d'Ariane 5 du 4 juin 1996 ou encore de la mise au point du mĂ©tro automatique Meteor (ligne 14 Ă  Paris).

Le "cauchemar" d'un programmeur est que son programme, dans certains cas, "tombe" dans une boucle infinie et ne s'arrĂȘte jamais. Dans ce cas, le logiciel est incapable de fournir la rĂ©ponse attendue par l'utilisateur. Un programme qui permettrait de tester si un autre programme va finir par s'arrĂȘter, quel que soit le cas traitĂ©, serait d'une grande aide pour tous les dĂ©veloppeurs du monde ! Pourtant, depuis 1937 et les travaux d'Alonzo Church et d'Alan Turing, on sait qu'un tel programme ne peut pas exister.

Alonzo Church (1903-1995)

Alonzo Church

Alan Turing (1912-1954)

Alan Turing

Nous allons essayer de dĂ©montrer qu'un programme capable de rĂ©pondre Ă  la question "ce programme va-t-il s'arrĂȘter" (rĂ©ponse oui/non) ne peut pas exister :

Soit un programme (ou un algorithme, cela revient au mĂȘme) que l'on va nommer "ArrĂȘt?", ce programme prend en entrĂ©e un programme P et des donnĂ©es x (les donnĂ©es x sont les donnĂ©es qui vont ĂȘtre utilisĂ©es par le programme P). Le programme "ArrĂȘt?" rĂ©pond "oui" si le programme P (qui utilise les donnĂ©es x) s'arrĂȘte. Le programme "ArrĂȘt?" rĂ©pond "non" si le programme P (qui utilise les donnĂ©es x) ne s'arrĂȘte jamais.

Partons du principe que ce programme "ArrĂȘt?" existe (raisonnement par l'absurde).

Imaginons un autre programme que nous appellerons D. D utilise, entre autres, le programme "ArrĂȘt?" :

D prend en entrée une donnée x (une chaine de caractÚres). La donnée x est d'abord dupliquée (on obtient (x,x)).

En sortie :

  • dans le cas oĂč le programme "ArrĂȘt?" renvoie "OUI", le programme D "tombe" dans une boucle infinie (il ne s'arrĂȘte jamais)

  • dans le cas oĂč le programme "ArrĂȘt?" renvoie "NON", le programme D s'arrĂȘte.

Le programme D possÚde un code source (une chaine de caractÚre), il est donc tout à fait possible de "placer" le code source de D à l'entrée du programme D :

Analysons ce qui se passe :

  • supposons que D s'arrĂȘte quand on lui donne D => "ArrĂȘt?" rĂ©pond "OUI", donc D tombe dans une boucle infinie, donc D ne s'arrĂȘte pas. Donc quand D s'arrĂȘte, D ne s'arrĂȘte pas... ce qui est une contradiction

  • supposons que D ne s'arrĂȘte pas quand on lui donne D => "ArrĂȘt?" rĂ©pond "NON", donc D s'arrĂȘte. Donc quand D ne s'arrĂȘte pas, D s'arrĂȘte...ici aussi nous avons une contradiction !

Dans les 2 cas, nous avons une contradiction, nous pouvons donc en conclure que le programme D ne peut pas exister. Mais du coup, si le programme D ne peut pas exister, cela signifie que le programme "ArrĂȘt?" ne peut pas exister (puisque le programme D se base sur le programme "ArrĂȘt?").

Nous venons donc bien de dĂ©montrer que le programme "ArrĂȘt?" ne peut pas exister.

Cette idĂ©e d'avoir un problĂšme (problĂšme de l'arrĂȘt) qui ne peut pas ĂȘtre rĂ©solu par un algorithme peut ĂȘtre gĂ©nĂ©ralisĂ©e : il existe en effet une sĂ©rie de problĂšmes qui ne peuvent pas ĂȘtre rĂ©solus par un algorithme. On dit que ces problĂšmes sont "indĂ©cidables". Le problĂšme de l'arrĂȘt est donc indĂ©cidable. A contrario, les problĂšmes qui peuvent ĂȘtre rĂ©solus par un algorithme sont dits dĂ©cidables.

Nous venons de voir qu'un algorithme peut permettre de résoudre des problÚmes (par exemple répondre à une question par oui ou non), à condition que le problÚme soit décidable. Un algorithme peut aussi réaliser des calculs et donner un résultat. Un algorithme peut donc aussi calculer l'image d'une valeur x par une fonction f (si on prend une fonction f telle que f(x)=5x+3, il est aisé de programmer un algorithme qui donnera l'image de x par f quel que soit x). Pourtant Church et Turing ont démontré que pour certaines fonctions il n'existait pas d'algorithme capable de calculer l'image de x. Ces fonctions sont dites non-calculables. Attention, ce n'est pas parce qu'une fonction f n'est pas calculable qu'il n'est possible de trouver l'image de x par f. Cela veut juste dire qu'il n'existe pas d'algorithme capable d'effectuer ce calcul. Au contraire, s'il existe un algorithme capable de calculer l'image de x par une fonction f, alors cette fonction f est dite calculable.

Les notions de décidabilité et de calculabilité sont étroitement liées, mais cela sort du cadre de ce cours.

source: https://informatique-lycee.forge.apps.education.fr/terminale_nsi/cours-terminale/c13c/