From Undecidability.FOL.Incompleteness Require Import utils.
From Undecidability.Synthetic Require Import DecidabilityFacts EnumerabilityFacts.
Local Set Implicit Arguments.
Local Unset Strict Implicit.
From Undecidability.Synthetic Require Import DecidabilityFacts EnumerabilityFacts.
Local Set Implicit Arguments.
Local Unset Strict Implicit.
Definition is_universal {Y : Type} (theta : nat -> nat -\ Y) :=
forall f : nat -\ Y, exists c, forall x y, f x ▷ y <-> theta c x ▷ y.
Section epf.
Variable (theta : nat -> nat -\ bool).
Hypothesis theta_universal : is_universal theta.
Definition self_halting : nat -> Prop := fun x => exists y, theta x x ▷ y.
Theorem self_halting_diverge (f : nat -\ bool) :
(forall c, f c ▷ true <-> self_halting c) ->
exists c, forall y, ~f c ▷ y.
Proof.
intros H.
unshelve evar (g: nat -\ bool).
{ intros n. exists (fun k => match (f n).(core) k with
| Some true => None
| Some false => Some true
| None => None
end).
intros y1 y2 k1 k2 Hk1 Hk2.
destruct (core (f n) k1) as [[]|] eqn:Hf1, (core (f n) k2) as [[]|] eqn:Hf2.
all: congruence. }
destruct (theta_universal g) as [c Hc]. exists c.
intros [] Hf.
- pose proof (Hf' := Hf).
apply H in Hf.
destruct Hf as [b [k Hk]%Hc].
cbn in Hk. destruct (core (f c) k) as [[]|] eqn:Hf; try discriminate.
enough (true = false) by discriminate.
apply (@part_functional _ (f c)); firstorder.
- enough (f c ▷ true) as H1.
{ now pose proof (part_functional Hf H1). }
apply H. exists true. apply Hc.
destruct Hf as [k Hk]. exists k.
cbn. now rewrite Hk.
Qed.
Lemma self_halting_undec : ~decidable self_halting.
Proof.
intros [f Hf].
unshelve evar (g: nat -\ bool).
{ intros n. exists (fun _ => Some (f n)). congruence. }
destruct (@self_halting_diverge g).
{ intros c. split.
- now intros [k [=Hk%Hf]].
- intros H%Hf. exists 0. cbn. congruence. }
apply (H (f x)). now exists 0.
Qed.
Definition recursively_separates (P1 P2 : nat -> Prop) (f : nat -\ bool) :=
(forall x, P1 x -> f x ▷ true) /\
(forall x, P2 x -> f x ▷ false).
Definition theta_self_return (b : bool) : nat -> Prop :=
fun x => theta x x ▷ b.
Lemma theta_self_return_enumerable b : enumerable (theta_self_return b).
Proof.
apply semi_decidable_enumerable.
{ exists (fun n => Some n). intros n. now exists n. }
exists (fun c k => match core (theta c c) k, b with
| Some true, true => true
| Some false, false => true
| _, _ => false
end).
intros c. split; intros [k Hk]; exists k.
- rewrite Hk. destruct b; congruence.
- destruct (core _ _) as [[]|], b; congruence.
Qed.
Theorem recursively_separating_diverge (f : nat -\ bool):
(forall b c, theta_self_return b c -> f c ▷ b) ->
exists c, forall y, ~f c ▷ y.
Proof.
intros H.
unshelve evar (g : nat -\ bool).
{ intros x. exact (comp_part_total negb (f x)). }
destruct (theta_universal g) as [c Hc]. exists c.
intros y [k Hk].
assert (g c ▷ (negb y)) as Hg.
{ exists k. cbn. rewrite Hk. reflexivity. }
apply Hc in Hg. specialize (H _ _ Hg).
enough (y = negb y) by now destruct y.
apply (@part_functional _ (f c)).
- now exists k.
- assumption.
Qed.
Lemma no_recursively_separating (f : nat -> bool) :
~(forall b c, theta_self_return b c -> f c = b).
Proof.
intros H.
unshelve evar (g : nat -\ bool).
{ intros x. exists (fun _ => Some (f x)). congruence. }
destruct (@recursively_separating_diverge g) as [c Hc].
{ intros b c Hc%H. exists 0. cbn. congruence. }
apply (Hc (f c)). now exists 0.
Qed.
End epf.
Section epf_nat_bool.
Local Definition bool_to_nat (b : bool) := if b then 1 else 0.
Local Program Definition nat_to_bool : nat -\ bool.
Proof.
intros [|[|n]].
- exists (fun _ => Some false). congruence.
- exists (fun _ => Some true). congruence.
- exists (fun _ => None). congruence.
Defined.
Lemma epf_nat_bool : (exists theta : nat -> nat -\ nat, is_universal theta) -> (exists theta : nat -> nat -\ bool, is_universal theta).
Proof.
intros [theta theta_universal].
unshelve eexists.
{ intros c x. exact (comp_part_partial nat_to_bool (theta c x)). }
intros f.
unshelve edestruct theta_universal as [c Hc].
{ intros x. exact (comp_part_total bool_to_nat (f x)). }
exists c. intros x y. split; intros [k Hk].
- assert (theta c x ▷ bool_to_nat y) as [k' Hk'].
{ rewrite <-Hc. exists k. cbn. now rewrite Hk. }
exists k'. cbn. rewrite Hk'. now destruct y.
- assert (theta c x ▷ bool_to_nat y) as [k' Hk']%Hc.
{ exists k. cbn in Hk. destruct core; try congruence.
destruct y, n as [|[|n]]; cbn in *; try congruence. }
exists k'. cbn in Hk'. destruct (core (f x) k') as [[]|], y as []; cbn in *; congruence.
Qed.
End epf_nat_bool.