Écrire un programme dont la non-terminaison est indépendante de l'arithmétique Peano

29

Défi

Écrivez un programme P, sans aucune entrée, de telle sorte que la proposition «l'exécution de P finit éventuellement» soit indépendante de l'arithmétique Peano .

Règles formelles

(Si vous êtes un logicien mathématique qui pense que la description ci-dessus est trop informelle.)

On peut, en principe, convertir une machine Universal Turing U (par exemple votre langage de programmation préféré) en une formule arithmétique Peano HALT sur la variable p , où HALT ( p ) encode la proposition « U se termine sur le programme ( codé par Gödel ) p ”. Le défi est de trouver p tel que ni HALT ( p ) ni ¬HALT ( p ) ne peuvent être prouvés en arithmétique Peano.

Vous pouvez supposer que votre programme s'exécute sur une machine idéale avec une mémoire illimitée et des entiers / pointeurs suffisamment grands pour y accéder.

Exemple

Pour voir que de tels programmes existent, un exemple est un programme qui recherche de manière exhaustive une preuve arithmétique Peano de 0 = 1. L'arithmétique Peano prouve que ce programme s'arrête si et seulement si l'arithmétique Peano est incohérente. Puisque l'arithmétique Peano est cohérente mais ne peut pas prouver sa propre cohérence , elle ne peut pas décider si ce programme s'arrête.

Cependant, il existe de nombreuses autres propositions indépendantes de l'arithmétique Peano sur lesquelles vous pouvez baser votre programme.

Motivation

Ce défi a été inspiré par un nouveau document de Yedidia et Aaronson (2016) présentant une machine de Turing à 7 918 états dont la non-terminaison est indépendante de ZFC , un système beaucoup plus puissant que l'arithmétique Peano. Vous pouvez être intéressé par sa citation [22]. Pour ce défi, bien sûr, vous pouvez utiliser le langage de programmation de votre choix à la place des machines Turing réelles.

Anders Kaseorg
la source
6
Quels systèmes d'axiomes peuvent être utilisés pour prouver que (a) le programme ne s'arrête pas, et (b) la non-interruption du programme n'est pas démontrable en PA?
feersum
5
Je ne pense pas qu'il soit raisonnable d'exiger que cette question contienne tous les antécédents nécessaires en logique mathématique. Il y en a beaucoup et il y a des liens vers les informations pertinentes. Ce n'est pas obscurci, c'est juste un sujet technique. Je pense qu'il serait utile pour l'accessibilité d'énoncer l'exigence d'un code distinct de la motivation impliquant les machines Turing et de se lier à un exemple de déclarations indépendantes de Peano à considérer, en particulier le théorème de Goodstein ( golf connexe )
xnor
Pour que cela ait du sens, nous devons supposer que le code s'exécute sur une machine idéalisée avec une mémoire illimitée. Peut-on également supposer que la machine a une précision réelle arbitraire?
xnor
1
@feersum Je ne m'attends pas à une preuve axiomatique de (a) et (b). Il suffit d'écrire un programme et de fournir suffisamment de description / arguments / citations pour être raisonnablement convaincant que les affirmations sont vraies, comme vous le feriez pour tout autre défi. Vous pouvez vous fier à tous les axiomes et théorèmes standardement acceptés dont vous avez besoin.
Anders Kaseorg
2
@xnor Vous pouvez supposer une mémoire illimitée et des pointeurs illimités pour y accéder. Mais je ne pense pas qu'il soit raisonnable de supposer une précision réelle arbitraire à moins que votre langue ne le fournisse réellement; dans la plupart des langues, un programme comme celui- x = 1.0; while (x) { x = x / 2.0; }ci s'arrêtera en fait très rapidement.
Anders Kaseorg

Réponses:

27

Haskell, 838 octets

"Si vous voulez que quelque chose soit fait, ..."

import Control.Monad.State
data T=V Int|T:$T|A(T->T)
g=guard
r=runStateT
s!a@(V i)=maybe a id$lookup i s
s!(a:$b)=(s!a):$(s!b)
s@((i,_):_)!A f=A(\a->((i+1,a):s)!f(V$i+1))
c l=do(m,k)<-(`divMod`sum(1<$l)).pred<$>get;g$m>=0;put m;l!!fromEnum k
i&a=V i:$a
i%t=(:$).(i&)<$>t<*>t
x i=c$[4%x i,5%x i,(6&)<$>x i]++map(pure.V)[7..i-1]
y i=c[A<$>z i,1%y i,(2&)<$>y i,3%x i]
z i=(\a e->[(i,e)]!a)<$>y(i+1)
(i?h)p=c[g$any(p#i)h,do q<-y i;i?h$q;i?h$1&q:$p,do f<-z i;a<-x i;g$p#i$f a;c[i?h$A f,do b<-x i;i?h$3&b:$a;i?h$f b],case p of A f->c[(i+1)?h$f$V i,do i?h$f$V 7;(i+1)?(f(V i):h)$f$6&V i];V 1:$q:$r->c[i?(q:h)$r,i?(2&r:h)$V 2:$q];_->mzero]
(V a#i)(V b)=a==b
((a:$b)#i)(c:$d)=(a#i)c&&(b#i)d
(A f#i)(A g)=f(V i)#(i+1)$g$V i
(_#_)_=0<0
main=print$(r(8?map fst(r(y 8)=<<[497,8269,56106533,12033,123263749,10049,661072709])$3&V 7:$(6&V 7))=<<[0..])!!0

Explication

Ce programme recherche directement une preuve arithmétique Peano de 0 = 1. Puisque PA est cohérent, ce programme ne se termine jamais; mais comme l'AP ne peut pas prouver sa propre cohérence, la non-terminaison de ce programme est indépendante de l'AP.

T est le type d'expressions et de propositions:

  • A Preprésente la proposition ∀ x [ P ( x )].
  • (V 1 :$ P) :$ Qreprésente la proposition PQ .
  • V 2 :$ Preprésente la proposition ¬ P .
  • (V 3 :$ x) :$ yreprésente la proposition x = y .
  • (V 4 :$ x) :$ yreprésente le x + y naturel .
  • (V 5 :$ x) :$ yreprésente le xy naturel .
  • V 6 :$ xreprésente le S naturel ( x ) = x + 1.
  • V 7 représente le naturel 0.

Dans un environnement avec i variables libres, nous codons les expressions, propositions et preuves sous forme de matrices entières 2 × 2 [1, 0; a , b ], comme suit:

  • M ( i , ∀ x [ P ( x )]) = [1, 0; 1, 4] ⋅ M ( i , λ x [P (x)])
  • M ( i , λ x [ F ( x )]) = M ( i + 1, F ( x )) où M ( j , x ) = [1, 0; 5 + i , 4 + j ] pour tout j > i
  • M ( i , PQ ) = [1, 0; 2, 4] ⋅ M ( i , P ) ⋅ M ( i , Q )
  • M ( i , ¬ P ) = [1, 0; 3, 4] ⋅ M ( i , P )
  • M ( i , x = y ) = [1, 0; 4, 4] ⋅ M ( i , x ) ⋅ M ( i , y )
  • M ( i , x + y ) = [1, 0; 1, 4 + i ] ⋅ M ( i , x ) ⋅ M ( i , y )
  • M ( i , xy ) = [1, 0; 2, 4 + i ] ⋅ M ( i , x ) ⋅ M ( i , y )
  • M ( i , S x ) = [1, 0; 3, 4 + i ] ⋅ M ( i , x )
  • M ( i , 0) = [1, 0; 4, 4 + i ]
  • M ( i , ( Γ , P ) ⊢ P ) = [1, 0; 1, 4]
  • M ( i , ΓP ) = [1, 0; 2, 4] ⋅ M ( i , Q ) ⋅ M ( i , ΓQ ) ⋅ M ( i , ΓQP )
  • M ( i , ΓP ( x )) = [1, 0; 3, 4] ⋅ M ( i , λ x [P (x)]) ⋅ M ( i , x ) ⋅ [1, 0; 1, 2] ⋅ M ( i , Γ ⊢ ∀ x P (x))
  • M ( i , ΓP ( x )) = [1, 0; 3, 4] ⋅ M ( i , λ x [P (x)]) ⋅ M ( i , x ) ⋅ [1, 0; 2, 2] ⋅ M ( i , y ) ⋅ M ( i , Γy = x ) ⋅ M ( i , ΓP ( y ))
  • M ( i , Γ ⊢ ∀ x , P ( x )) = [1, 0; 8, 8] ⋅ M ( i , λ x [ ΓP ( x )])
  • M ( i , Γ ⊢ ∀ x , P ( x )) = [1, 0; 12, 8] ⋅ M ( i , ΓP (0)) ⋅ M ( i , λ x [( Γ , P ( x )) ⊢ P (S ( x ))]]
  • M ( i , ΓPQ ) = [1, 0; 8, 8] ⋅ M ( i , ( Γ , P ) ⊢ Q )
  • M ( i , ΓPQ ) = [1, 0; 12, 8] ⋅ M ( i , ( Γ , ¬ Q ) ⊢ ¬ P )

Les axiomes restants sont codés numériquement et inclus dans l'environnement initial Γ :

  • M (0, ∀ x [ x = x ]) = [1, 0; 497, 400]
  • M (0, ∀ x [¬ (S ( x ) = 0)]) = [1, 0; 8269, 8000]
  • M (0, ∀ xy [S ( x ) = S ( y ) → x = y ]) = [1, 0; 56106533, 47775744]
  • M (0, ∀ x [ x + 0 = x ]) = [1, 0; 12033, 10000]
  • M (0, ∀ y [ x + S ( y ) = S ( x + y )]) = [1, 0; 123263749, 107495424]
  • M (0, ∀ x [ x ⋅ 0 = 0]) = [1, 0; 10049, 10000]
  • M (0, ∀ xy [ x ⋅ S ( y ) = xy + x ]) = [1, 0; 661072709, 644972544]

Une preuve avec matrice [1, 0; a , b ] peut être vérifiée étant donné uniquement le coin inférieur gauche a (ou toute autre valeur congruente à un modulo b ); les autres valeurs sont là pour permettre la composition des épreuves.

Par exemple, voici une preuve que l'addition est commutative.

  • M (0, Γ ⊢ ∀ xy [ x + y = y + x]) = [1, 0; 6651439985424903472274778830412211286042729801174124932726010503641310445578492460637276210966154277204244776748283051731165114392766752978964153601068040044362776324924904132311711526476930755026298356469866717434090029353415862307981531900946916847172554628759434336793920402956876846292776619877110678804972343426850350512203833644, 14010499234317302152403198529613715336094817740448888109376168978138227692104106788277363562889534501599380268163213618740021570705080096139804941973102814335632180523847407060058534443254569282138051511292576687428837652027900127452656255880653718107444964680660904752950049505280000000000000000000000000000000000000000000000000000000]

Vous pouvez le vérifier avec le programme comme suit:

*Main> let p = A $ \x -> A $ \y -> V 3 :$ (V 4 :$ x :$ y) :$ (V 4 :$ y :$ x)
*Main> let a = 6651439985424903472274778830412211286042729801174124932726010503641310445578492460637276210966154277204244776748283051731165114392766752978964153601068040044362776324924904132311711526476930755026298356469866717434090029353415862307981531900946916847172554628759434336793920402956876846292776619877110678804972343426850350512203833644
*Main> r(8?map fst(r(y 8)=<<[497,8269,56106533,12033,123263749,10049,661072709])$p)a :: [((),Integer)]
[((),0)]

Si la preuve n'était pas valide, vous obtiendriez la liste vide à la place.

Anders Kaseorg
la source
1
Veuillez expliquer l'idée derrière les matrices.
fier haskeller
2
@proudhaskeller Ils ne sont qu'un moyen pratique et relativement compact de Gödel de numéroter tous les arbres de preuve possibles. Vous pouvez également les considérer comme des chiffres à radix mixtes qui sont décodés du côté le moins significatif en utilisant div et mod par le nombre de choix possibles à chaque étape.
Anders Kaseorg
Comment avez-vous codé les axiomes d'induction?
PyRulez
@PyRulez M (i, Γ ⊢ ∀x, P (x)) = [1, 0; 12, 8] ⋅ M (i, Γ ⊢ P (0)) ⋅ M (i, λx [(Γ, P (x)) ⊢ P (S (x))]) est l'axiome d'induction.
Anders Kaseorg
Je pense que vous pourriez réduire cela si vous utilisez plutôt le calcul des constructions (puisque le calcul des constructions a une logique de premier ordre intégrée et est très petit). Le calcul des constructions est à peu près aussi fort que ZFC, donc sa cohérence est sûrement indépendante de PA. Pour vérifier sa cohérence, il vous suffit de rechercher un terme de type vide.
PyRulez