From SyntheticComputability Require Import ArithmeticalHierarchySemantic PostsTheorem reductions SemiDec TuringJump OracleComputability Definitions partial Pigeonhole.
Require Import Vectors.VectorDef Arith.Compare_dec Lia.
Import Vector.VectorNotations.
Local Notation vec := Vector.t.
(* ##################################### *)
Require Import Vectors.VectorDef Arith.Compare_dec Lia.
Import Vector.VectorNotations.
Local Notation vec := Vector.t.
(* ##################################### *)
(* ##################################### *)
This file contains the definition of limit computable and proves the
Limit Lemma, i.e., limit computable is equivalence to reduciable to halting
problem.
Convention:
limit: limit computable
semi_dec(K): semi decidable (on K)
turing_red_K: turing reduciable to halting problem
char_X: extensionality of X
(* Definition of limit ciomputable *)
Definition limit_computable {X} (P: X -> Prop) :=
exists f: X -> nat -> bool, forall x,
(P x <-> exists N, forall n, n >= N -> f x n = true) /\
(~ P x <-> exists N, forall n, n >= N -> f x n = false).
Definition char_rel_limit_computable {X} (P: X -> bool -> Prop) :=
exists f: X -> nat -> bool, forall x y, P x y <-> exists N, forall n, n >= N -> f x n = y.
Definition char_rel_limit_computable' {X} (P: X -> bool -> Prop) :=
exists f: X -> nat -> bool, forall x y, P x y -> exists N, forall n, n >= N -> f x n = y.
Lemma char_rel_limit_equiv {X} (P: X -> Prop):
char_rel_limit_computable (char_rel P) <-> limit_computable P.
Proof.
split; intros [f Hf]; exists f; intros x.
- split; firstorder.
- intros []; destruct (Hf x) as [h1 h2]; eauto.
Qed.
Lemma char_rel_limit_equiv' {X} (P: X -> Prop):
definite P -> char_rel_limit_computable (char_rel P) <-> char_rel_limit_computable' (char_rel P) .
Proof.
intros HP; split.
- intros [f Hf]. exists f; intros.
destruct (Hf x y) as [Hf' _].
now apply Hf'.
- intros [f Hf]. exists f. intros x y.
split. intro H. now apply Hf.
intros [N HN]. destruct (HP x).
destruct y; [easy|].
destruct (Hf x true H) as [N' HfN].
intros _. enough (true = false) by congruence.
specialize (HN (max N N')).
specialize (HfN (max N N')).
rewrite <- HN, <- HfN; eauto; lia.
destruct y; [|easy].
destruct (Hf x false H) as [N' HfN].
enough (true = false) by congruence.
specialize (HN (max N N')).
specialize (HfN (max N N')).
rewrite <- HN, <- HfN; eauto; lia.
Qed.
(* Naming the halting problem as K *)
Notation K := ({0}^(1)).
Section LimitLemma1.
(* Limit computable predicate P is reduciable to K *)
Variable vec_to_nat : forall k, vec nat k -> nat.
Variable nat_to_vec : forall k, nat -> vec nat k.
Variable vec_nat_inv : forall k v, nat_to_vec k (vec_to_nat v) = v.
Variable nat_vec_inv : forall k n, vec_to_nat (nat_to_vec k n) = n.
Variable list_vec_to_nat : forall k, list (vec nat k) -> nat.
Variable nat_to_list_vec : forall k, nat -> list (vec nat k).
Variable list_vec_nat_inv : forall k v, nat_to_list_vec k (list_vec_to_nat v) = v.
Variable nat_list_vec_inv : forall k n, list_vec_to_nat (nat_to_list_vec k n) = n.
Variable nat_to_list_bool : nat -> list bool.
Variable list_bool_to_nat : list bool -> nat.
Variable list_bool_nat_inv : forall l, nat_to_list_bool (list_bool_to_nat l) = l.
Variable nat_list_bool_inv : forall n, list_bool_to_nat (nat_to_list_bool n) = n.
Section def_K.
Hypothesis LEM_Σ_1: LEM_Σ 1.
Lemma semi_dec_def {X} (p: X -> Prop):
semi_decidable p -> definite p.
Proof.
intros [f Hf]. unfold semi_decider in Hf.
destruct level1 as (_&H2&_).
assert principles.LPO as H by now rewrite <- H2.
intro x. destruct (H (f x)).
left. now rewrite Hf.
right. intros [k Hk]%Hf.
apply H0. now exists k.
Qed.
Lemma def_K: definite K.
Proof.
apply semi_dec_def.
assert (isΣsem 1 (@jumpNK _ 1 1)).
eapply jump_in_Σn; eauto.
assert (@jumpNK _ 1 1 ≡ₘ {0}^(1)).
apply jumpNKspec.
rewrite <- semi_dec_iff_Σ1 in H.
destruct H0 as [_ [f Hf]].
unfold reduces_m in Hf.
destruct H as [g Hg].
unfold semi_decider in Hg.
exists (fun x => g (f x)).
split. now intros H%Hf%Hg. now intros H%Hg%Hf.
Qed.
End def_K.
(* Extensionality of Σ2, i.e. P t iff ∃ x. ∀ y. f(x, y, t) = true *)
Lemma char_Σ2 {k: nat} (P: vec nat k -> Prop) :
(exists f: nat -> nat -> vec nat k -> bool, forall x, P x <-> (exists n, forall m, f n m x = true)) ->
isΣsem 2 P.
Proof.
intros [f H].
eapply isΣsemS_ with (p := fun v => forall y, f (hd v) y (tl v) = true).
eapply isΠsemS_ with (p := fun v => f (hd (tl v)) (hd v) (tl (tl v)) = true).
eapply isΣsem0. all: easy.
Qed.
Lemma limit_Σ2 {k: nat} (P: vec nat k -> Prop) :
limit_computable P -> isΣsem 2 P /\ isΣsem 2 (compl P).
Proof.
intros [f H]; split; eapply char_Σ2.
- exists (fun N n x => if lt_dec n N then true else f x n).
intro w. destruct (H w) as [-> _]; split; intros [N Hn]; exists N.
+ intro m. destruct (lt_dec m N); try apply Hn; lia.
+ intros n He. specialize (Hn n); destruct (lt_dec n N); auto; lia.
- exists (fun N n x => if lt_dec n N then true else negb (f x n)).
intro w. destruct (H w) as [_ ->]; split; intros [N Hn]; exists N.
+ intro m. destruct (lt_dec m N); [auto| rewrite (Hn m); lia].
+ intros n He. specialize (Hn n).
destruct (lt_dec n N); auto; [lia|destruct (f w n); easy].
Qed.
Lemma limit_semi_dec_K {k: nat} (P: vec nat k -> Prop) :
LEM_Σ 1 ->
limit_computable P ->
OracleSemiDecidable K P /\
OracleSemiDecidable K (compl P).
Proof.
intros LEM H%limit_Σ2.
rewrite <- !(Σ_semi_decidable_jump).
all: eauto.
Qed.
Lemma limit_turing_red_K' {k: nat} (P: vec nat k -> Prop) :
LEM_Σ 1 ->
definite K ->
limit_computable P ->
P ⪯ᴛ K.
Proof.
intros LEM D H % (limit_semi_dec_K LEM); destruct H as [h1 h2].
apply PT; try assumption.
apply Dec.nat_eq_dec.
Qed.
Fact elim_vec (P: nat -> Prop):
P ⪯ₘ (fun x: vec nat 1 => P (hd x)) .
Proof. exists (fun x => [x]). now intros x. Qed.
Lemma limit_turing_red_K {k: nat} (P: nat -> Prop) :
LEM_Σ 1 ->
limit_computable P ->
P ⪯ᴛ K.
Proof.
intros Hc [h Hh].
specialize (def_K Hc) as Hk.
eapply Turing_transitive; last eapply (@limit_turing_red_K' 1); eauto.
eapply red_m_impl_red_T. apply elim_vec.
exists (fun v n => h (hd v) n).
intros x; split;
destruct (Hh (hd x)) as [Hh1 Hh2]; eauto.
Qed.
End LimitLemma1.
Section Σ1Approximation.
(* Turing jump of a trivial decidable problem is semi decidable *)
Lemma semi_dec_halting : semi_decidable K.
Proof.
eapply OracleSemiDecidable_semi_decidable with (q := {0}).
- exists (fun n => match n with | O => true | _ => false end); intros [|n]; easy.
- eapply semidecidable_J.
Qed.
(* Stabilizing the semi decider allows the semi decider
to be used as a Σ1 approximation *)
Definition stable (f: nat -> bool) := forall n m, n <= m -> f n = true -> f m = true.
Fixpoint stabilize_step {X} (f: X -> nat -> bool) x n :=
match n with
| O => false
| S n => if f x n then true else stabilize_step f x n
end.
Lemma stabilize {X} (P: X -> Prop) :
semi_decidable P -> exists f, semi_decider f P /\ forall x, stable (f x).
Proof.
intros [f Hf].
exists (fun x n => stabilize_step f x n); split.
- intro x; split; intro h.
rewrite (Hf x) in h.
destruct h as [c Hc].
now exists (S c); cbn; rewrite Hc.
rewrite (Hf x).
destruct h as [c Hc].
induction c; cbn in Hc; [congruence|].
destruct (f x c) eqn: E; [now exists c|now apply IHc].
- intros x n m Lenm Hn.
induction Lenm; [trivial|].
cbn; destruct (f x m) eqn: E; [trivial|assumption].
Qed.
(* The Σ1 approximation output correct answers for arbitray list of questions *)
Definition approximation_list {A} (P: A -> Prop) (f: A -> bool) L :=
forall i, List.In i L -> P i <-> f i = true.
Definition approximation_Σ1 {A} (P: A -> Prop) :=
exists P_ : nat -> A -> bool,
forall L, exists c, forall c', c' >= c -> approximation_list P (P_ c') L.
Definition approximation_Σ1_strong {A} (P: A -> Prop) :=
exists P_ : nat -> A -> bool,
(forall L, exists c, forall c', c' >= c -> approximation_list P (P_ c') L) /\
(forall tau q a, @interrogation _ _ _ bool tau (char_rel P) q a -> exists n, forall m, m >= n -> interrogation tau (fun q a => P_ m q = a) q a).
Definition approximation_Σ1_weak {A} (P: A -> Prop) :=
exists P_ : nat -> A -> bool,
(forall tau q a, @interrogation _ _ _ bool tau (char_rel P) q a -> exists n, forall m, m >= n -> interrogation tau (fun q a => P_ m q = a) q a).
Lemma semi_dec_approximation_Σ1 {X} (P: X -> Prop) :
definite P ->
semi_decidable P -> approximation_Σ1 P.
Proof.
intros defP semiP; unfold approximation_Σ1, approximation_list.
destruct (stabilize semiP) as [h [Hh HS]].
exists (fun n x => h x n). intro l. induction l as [|a l [c Hc]].
- exists 42; eauto.
- destruct (defP a) as [h1| h2].
+ destruct (Hh a) as [H _].
destruct (H h1) as [N HN].
exists (max c N); intros c' Hc' e [->| He].
split; [intros _|easy].
eapply HS; [|eapply HN]; lia.
rewrite <- (Hc c'); [trivial|lia | assumption].
+ exists c; intros c' Hc' e [->| He].
split; [easy| intros h'].
unfold semi_decider in Hh.
now rewrite Hh; exists c'.
rewrite Hc; eauto.
Qed.
Lemma semi_dec_approximation_Σ1_strong {X} (P: X -> Prop) :
definite P ->
semi_decidable P -> approximation_Σ1_strong P.
Proof.
intros defP semiP.
destruct (semi_dec_approximation_Σ1 defP semiP) as [P_ HP_].
exists P_; split; [apply HP_|].
intros tau q ans Htau.
destruct (HP_ q) as [w Hw].
exists w. intros m Hm. rewrite interrogation_ext.
exact Htau. eauto.
intros q_ a H1.
specialize (Hw m Hm q_ H1).
unfold char_rel; cbn.
destruct a; eauto; split; intro h2.
intro h. rewrite Hw in h. congruence.
firstorder.
Qed.
Lemma approximation_Σ1_halting : definite K -> approximation_Σ1 K.
Proof. now intros H; apply semi_dec_approximation_Σ1, semi_dec_halting. Qed.
Lemma approximation_Σ1_halting_strong: definite K -> approximation_Σ1_strong K.
Proof. now intros H; apply semi_dec_approximation_Σ1_strong, semi_dec_halting. Qed.
End Σ1Approximation.
Section LimitLemma2.
(* A predicate P is reduciable to K if P is limit computable *)
Section Construction.
Variable f : nat -> nat -> bool.
Variable tau : nat -> tree nat bool bool.
Hypothesis Hf: forall L, exists c, forall c', c' >= c -> approximation_list K (f c') L.
Definition K_ n := fun i o => f n i = o.
Definition char_K_ n := fun i => ret (f n i).
Lemma dec_K_ n : decidable (fun i => f n i = true).
Proof.
exists (f n). easy.
Qed.
Lemma pcomputes_K_ n: pcomputes (char_K_ n) (fun i o => f n i = o).
Proof.
intros i o; split; intro H.
now apply ret_hasvalue_inv.
now apply ret_hasvalue'.
Qed.
End Construction.
Theorem turing_red_K_lim (P: nat -> Prop) :
P ⪯ᴛ K ->
definite K ->
definite P ->
limit_computable P.
Proof.
intros [F [H HF]] defK defP.
rewrite <- char_rel_limit_equiv.
destruct (approximation_Σ1_halting_strong defK) as [k_ [_ Hk_2]].
destruct H as [tau Htau].
pose (char_K_ n := char_K_ k_ n).
pose (K_ n := K_ k_ n).
pose (Phi x n := evalt_comp (tau x) (k_ n) n n).
assert (forall x y, char_rel P x y -> exists N : nat, forall n : nat, n >= N -> (evalt_comp (tau x) (k_ n)) n n = Some (inr y)) as HL.
{
intros x y H.
rewrite HF in H.
rewrite Htau in H.
destruct H as (qs & ans & Hint & Out).
specialize (Hk_2 (tau x) qs ans Hint).
destruct Hk_2 as [nth Hnth].
assert (interrogation (tau x)
(fun (q : nat) (a : bool) => (k_ nth) q = a) qs ans) as Hnthbase.
eapply Hnth. lia.
edestruct (interrogation_evalt_comp_limit (tau x) k_ qs ans y) as [L Hlimt].
exists nth. intros. eapply Hnth. easy.
eapply Out.
exists L. intros. now apply Hlimt.
}
assert (exists f, forall x y, char_rel P x y -> exists N : nat, forall n : nat, n >= N -> f x n = y) as [f HL'].
{
exists (fun x n => match (Phi x n) with
| Some (inr y) => y | _ => false end).
intros x y Hxy%HL.
destruct (Hxy) as [N HN].
exists N; intros.
unfold Phi. rewrite HN; eauto.
}
exists f. intros x y; split.
- now intros; apply HL'.
- intro H0. destruct y; cbn.
destruct (defP x); [easy|].
assert (char_rel P x false); [easy|].
apply HL' in H1.
destruct H0 as [N1 HN1].
destruct H1 as [N2 HN2].
specialize (HN1 (S (max N1 N2))).
specialize (HN2 (S (max N1 N2))).
enough (true = false) by congruence.
rewrite <- HN1, HN2; lia.
destruct (defP x); [|easy].
assert (char_rel P x true); [easy|].
apply HL' in H1.
destruct H0 as [N1 HN1].
destruct H1 as [N2 HN2].
specialize (HN1 (S (max N1 N2))).
specialize (HN2 (S (max N1 N2))).
enough (true = false) by congruence.
rewrite <- HN2, HN1; lia.
Qed.
End LimitLemma2.