# Module halting_problem

``` ```
 This work is a proof of the undecidability of the halting problem for Turing complete computation models. It is just a translation to Coq of the proof presented in Kristofer Johannisson's paper called Formalizing the Halting Problem in a Constructive Type Theory. (Vincent Cremet - mars 2003)
``` ```

``` ```

## The abstract computation model

``` ```

``` ```
 The set of programs.
``` ```

``` Variable Prog: Set. ```

``` ```
 The set of input and output values for programs with an associated equivalence relation.
``` ```

``` Variable Val: Set. ```

``` Variable eg: Val -> Val -> Prop. Hypothesis eg_refl: (x: Val) (eg x x). Hypothesis eg_sym: (x, y: Val) (eg x y) -> (eg y x). Hypothesis eg_trans: (x, y, z: Val) (eg x y) -> (eg y z) -> (eg x z). ```

``` ```
 Substitutivity of the equivalence relation.
``` ```

``` Definition isSubstitutive [A: Set; eg: A -> A -> Prop]: Prop :=  (a, b: A)(P: A -> Prop) (eg a b) -> (P a) -> (P b). ```

``` Hypothesis substEgVal: (isSubstitutive Val eg). ```

``` ```
 A partial function which maps a program and a input value to an output value.
``` ```

``` Hypothesis computes: Prog -> Val -> Val -> Prop. ```

``` Hypothesis pComputes: (p: Prog) (inp: Val) (out1: Val) (out2: Val)  (computes p inp out1) -> (computes p inp out2) -> (eg out1 out2). ```

``` ```
 Encoding of programs and pairs of values into values.
``` ```

``` Variable encode: Prog -> Val. Variable pairCode: Val -> Val -> Val. ```

``` ```
 Diagonalization program.
``` Variable diagonalize: Prog. ```

``` Hypothesis pDiagonalize: (n: Val) (computes diagonalize n (pairCode n n)). ```

``` ```
 Composition of programs.
``` ```

``` Variable compose: Prog -> Prog -> Prog. ```

``` Hypothesis pCompose: (p1, p2: Prog) (inp, out: Val)  (EX interm: Val | (computes p1 inp interm) /\ (computes p2 interm out))   <->  (computes (compose p1 p2) inp out). ```

``` ```
 Boolean Litterals.
``` Variable Vrai: Val. Variable Faux: Val. ```

``` Hypothesis pTrueIsNotFalse: ~(eg Vrai Faux). ```

``` ```
 Loop program.
``` ```

``` Variable loop: Prog. ```

``` Hypothesis pLoop: (inp: Val) ~(EX out: Val | (computes loop inp out)). ```

``` ```
 Constant programs.
``` ```

``` Variable const: Val -> Prog. ```

``` Hypothesis pConst: (c: Val) (inp: Val) (computes (const c) inp c). ```

``` Definition constInp [p: Prog; c: Val]: Prog := (compose (const c) p). ```

``` Theorem pConstInp: (p: Prog)(c, inp, out: Val) (computes (constInp p c) inp out) <-> (computes p c out). Intros. Unfold constInp. Case (pCompose (const c) p inp out). Intros. Split. Intro. Case (H0 H1). Clear H0. Clear H1. Intros. Case H0. Clear H0. Intros. Assert (eg x c). Apply pComputes with (const c) inp. Trivial. Apply pConst. Apply (substEgVal x c [y: Val] (computes p y out)). Trivial. Trivial. Clear H0. Intro. Apply H. Clear H. Exists c. Split. Apply pConst. Trivial. Qed. ```

``` ```
 Conditional program (if).
``` ```

``` Variable SI: Prog -> Prog -> Prog -> Prog. ```

``` Hypothesis pSI: (si, alors, sinon: Prog)(inp, out: Val)  ((computes (SI si alors sinon) inp out) <->    (((computes si inp Vrai) /\ (computes alors inp out)) \/      ((computes si inp Faux) /\ (computes sinon inp out)))). ```

``` ```

## Termination of a computation.

``` ```

``` Definition computation: Set := Prog * Val. ```

``` Definition results_in [c: computation; out: Val]: Prop :=  (computes (fst ? ? c) (snd ? ? c) out). ```

``` Definition terminates [c: computation]: Prop :=  (ex Val [out: Val] (results_in c out)). ```

``` Definition eqComp [c1, c2: computation]: Prop :=  (out: Val) (results_in c1 out) <-> (results_in c2 out). ```

``` Lemma eqComp_sym: (c1, c2: computation) (eqComp c1 c2) -> (eqComp c2 c1). Unfold eqComp. Intros. Pose (H out). Assert (A, B: Prop) (A <-> B) -> (B <-> A). Tauto. Apply H0. Assumption. Qed. ```

``` Theorem pDiagPair: (p: Prog)(n,r: Val)  (results_in ((compose diagonalize p), n) r) <->  (results_in (p, (pairCode n n)) r). Intros. Unfold results_in. Unfold fst snd. Split. Intro. Case (pCompose diagonalize p n r). Intros. Clear H0. Elim (H1 H). Clear H1. Clear H. Intros. Elim H. Clear H. Intros. Assert (eg x (pairCode n n)). Apply pComputes with diagonalize n. Trivial. Exact (pDiagonalize n). Clear H. Apply (substEgVal x (pairCode n n) [y: Val] (computes p y r)). Trivial. Trivial. ```

``` Intro. Case (pCompose diagonalize p n r). Intros. Clear H1. Apply H0. Clear H0. Apply ex_intro with (pairCode n n). Split. Apply pDiagonalize. Trivial. Qed. ```

``` ```

## Definition of decidability.

``` ```

``` Definition decides [pred: computation -> Prop; prog: Prog]: Prop := (c: computation) ((computes prog (pairCode (encode (fst ?? c)) (snd ?? c)) Vrai) \/ (computes prog (pairCode (encode (fst ?? c)) (snd ?? c)) Faux)) /\ ((computes prog (pairCode (encode (fst ?? c)) (snd ?? c)) Vrai) <-> (pred c)) /\ ((computes prog (pairCode (encode (fst ?? c)) (snd ?? c)) Faux) <-> ~(pred c)). ```

``` Definition decidable [pred: computation -> Prop]: Prop := (EX prog: Prog | (decides pred prog)). ```

``` ```

## Non trivial and substitutive predicates are undecidable.

``` ```

``` Definition isSubst [pred: computation -> Prop]: Prop := (c1, c2: computation) (eqComp c1 c2) -> (pred c1) -> (pred c2). ```

``` Theorem abstractHaltp:  (pred: computation -> Prop)  (isSubst pred) ->  (ex, nex: computation)  (pred ex) -> ~(pred nex) ->   ~(decidable pred). ```

``` Assert ssi_proj1: (A, B: Prop) (A <-> B) -> A -> B. Tauto. Assert ssi_proj2: (A, B: Prop) (A <-> B) -> B -> A. Tauto. ```

``` Intros. Unfold not. Intro. Unfold decidable in H2. Case H2. Clear H2. Intros. Pose liar :=  (SI (compose diagonalize x)    (constInp (fst ?? nex) (snd ?? nex))    (constInp (fst ?? ex) (snd ?? ex))  ). ```

``` ```
 Beginning pLiar1.
``` Assert pLiar1: (inp: Val) (computes x (pairCode inp inp) Vrai) -> ~(pred (liar, inp)). Intros. Assert (eqComp nex (liar, inp)). Unfold eqComp. Intro. Unfold results_in. Split. Intro. Unfold fst. Unfold snd. Unfold liar. Pose (pSI (compose diagonalize x)     (constInp (fst Prog Val nex) (snd Prog Val nex))     (constInp (fst Prog Val ex) (snd Prog Val ex)) inp out). ClearBody i. Case i. Clear i. Intros. Clear H5. Apply H6. Clear H6. Left. Split. Pose i:= (pDiagPair x inp Vrai). ClearBody i. Unfold results_in in i. Unfold fst in i. Unfold snd in i. Apply (ssi_proj2 (computes (compose diagonalize x) inp Vrai) (computes x (pairCode inp inp) Vrai) i). Trivial. Apply (ssi_proj2    (computes (constInp (fst Prog Val nex) (snd Prog Val nex)) inp out)    (computes (fst Prog Val nex) (snd Prog Val nex) out)    (pConstInp (fst Prog Val nex) (snd Prog Val nex) inp out)). Trivial. ```
 End step 1
``` ```

``` Intro. Unfold fst in H4. Unfold snd in H4. Unfold liar in H4. Pose (pSI (compose diagonalize x)     (constInp (fst Prog Val nex) (snd Prog Val nex))     (constInp (fst Prog Val ex) (snd Prog Val ex)) inp out). ClearBody i. Case i. Clear i. Intros. Clear H6. Elim (H5 H4). Clear H5. Clear H4. Intro. Case H4. Clear H4. Intros. Apply (ssi_proj1    (computes (constInp (fst Prog Val nex) (snd Prog Val nex)) inp out)    (computes (fst Prog Val nex) (snd Prog Val nex) out)    (pConstInp (fst Prog Val nex) (snd Prog Val nex) inp out)). Trivial. ```
 End step 2.
``` ```

``` Cut ~((computes (compose diagonalize x) inp Faux)). Tauto. Clear H4. Clear H5. Unfold not. Intro. Apply pTrueIsNotFalse. Assert (computes x (pairCode inp inp) Faux). Pose i := (pDiagPair x inp Faux). ClearBody i. Unfold results_in in i. Unfold fst in i. Unfold snd in i. Case i. Clear i. Intros. Clear H6. Apply (H5 H4). Apply pComputes with x (pairCode inp inp). Assumption. Assumption. ```
 End step 3.
``` ```

``` Unfold isSubst in H. Unfold not. Intro. Unfold not in H1. Apply H1. Apply H with (liar,inp). Apply eqComp_sym. Assumption. Assumption. ```
 End of pLiar1 proof.
``` ```

``` ```
 Beginning pLiar2: almost the same as pLiar1
``` Assert pLiar2: (inp: Val) (computes x (pairCode inp inp) Faux) -> (pred (liar, inp)). Clear pLiar1. Intros. Assert (eqComp ex (liar, inp)). Unfold eqComp. Intro. Unfold results_in. Split. Intro. Unfold fst. Unfold snd. Unfold liar. Pose (pSI (compose diagonalize x)     (constInp (fst Prog Val nex) (snd Prog Val nex))     (constInp (fst Prog Val ex) (snd Prog Val ex)) inp out). ClearBody i. Case i. Clear i. Intros. Clear H5. Apply H6. Clear H6. Right. Split. Pose i:= (pDiagPair x inp Faux). ClearBody i. Unfold results_in in i. Unfold fst in i. Unfold snd in i. Apply (ssi_proj2 (computes (compose diagonalize x) inp Faux) (computes x (pairCode inp inp) Faux) i). Trivial. Apply (ssi_proj2    (computes (constInp (fst Prog Val ex) (snd Prog Val ex)) inp out)    (computes (fst Prog Val ex) (snd Prog Val ex) out)    (pConstInp (fst Prog Val ex) (snd Prog Val ex) inp out)). Trivial. ```
 End step 1
``` ```

``` Intro. Unfold fst in H4. Unfold snd in H4. Unfold liar in H4. Pose (pSI (compose diagonalize x)     (constInp (fst Prog Val nex) (snd Prog Val nex))     (constInp (fst Prog Val ex) (snd Prog Val ex)) inp out). ClearBody i. Case i. Clear i. Intros. Clear H6. Elim (H5 H4). Clear H5. Clear H4. Intro. Case H4. Clear H4. Intros. Apply (ssi_proj1    (computes (constInp (fst Prog Val ex) (snd Prog Val ex)) inp out)    (computes (fst Prog Val ex) (snd Prog Val ex) out)    (pConstInp (fst Prog Val ex) (snd Prog Val ex) inp out)). Trivial. ```
 End step 2.
``` ```

``` Cut ~((computes (compose diagonalize x) inp Vrai)). Tauto. Clear H4. Clear H5. Unfold not. Intro. Apply pTrueIsNotFalse. Assert (computes x (pairCode inp inp) Vrai). Pose i := (pDiagPair x inp Vrai). ClearBody i. Unfold results_in in i. Unfold fst in i. Unfold snd in i. Case i. Clear i. Intros. Clear H6. Apply (H5 H4). Apply pComputes with x (pairCode inp inp). Assumption. Assumption. ```
 End step 3.
``` ```

``` Intro. Case H6. Clear H6. Clear H4. Clear H5. Intros. Clear H4. Case (pConstInp (fst Prog Val ex) (snd Prog Val ex) inp out). Intros. Tauto. ```
 End step 4.
``` ```

``` Unfold isSubst in H. Apply H with ex. Assumption. Assumption. ```
 End of pLiar2 proof.
``` ```

``` Pose liarliar := (liar, encode liar). Case (H2 liarliar). Clear H2. Intros. Case H2. Intro. Assert (pred liarliar) /\ ~(pred liarliar). Split. Clear H2. Clear pLiar1. Clear pLiar2. Tauto. Clear H2. Clear H3. Intro. Apply pLiar1 with (encode liar). Trivial. Trivial. Tauto. ```
 End step 1.
``` Intro. Clear H2. Clear pLiar1. Assert ~(pred liarliar) /\ (pred liarliar). Split. Clear pLiar2. Tauto. Clear H3. Unfold liarliar. Apply pLiar2. Exact H4. Tauto. ```
 End step 2.
``` Qed. ```

``` ```

## Proof of the halting problem.

``` ```

``` Definition c_terminates: computation := ((const Vrai), Vrai). Definition c_not_terminates: computation := (loop, Vrai). ```

``` Lemma isSubst_terminates: (isSubst terminates). Unfold isSubst. Intros. Unfold terminates. Unfold terminates in H0. Unfold eqComp in H. Case H0. Intros. Apply ex_intro with x. Cut (results_in c1 x)<->(results_in c2 x). Tauto. Apply H. Qed. Lemma terminates_constant: (terminates c_terminates). Unfold terminates. Apply ex_intro with Vrai. Unfold c_terminates. Unfold results_in. Unfold fst. Apply pConst. Qed. Lemma not_terminates_loop: ~(terminates c_not_terminates). Unfold c_not_terminates. Unfold terminates. Unfold results_in. Unfold fst. Apply pLoop. Qed. ```

``` Theorem halting_problem: ~(decidable terminates). Apply abstractHaltp with c_terminates c_not_terminates. Exact isSubst_terminates. Exact terminates_constant. Exact not_terminates_loop. Qed. ```

``` ```

Index