From PostTheorem.external.Shared Require Import embed_nat.
From PostTheorem Require Import OracleComputability TuringJump ArithmeticalHierarchySemantic.
Require Import Lia List Vector PeanoNat.
Import Vector.VectorNotations.
Local Notation vec := Vector.t.
From PostTheorem.external Require Import partial.
From Equations Require Import Equations.
Require Import Equations.Prop.DepElim.
Section PostsTheorem.
Axiom LEM : forall p, p \/ ~p.
Lemma DN p : ~~p -> p. Proof. now destruct (LEM p). Qed.
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 k v) = v.
Variable nat_vec_inv : forall k n, vec_to_nat k (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 k v) = v.
Variable nat_list_vec_inv : forall k n, list_vec_to_nat k (nat_to_list_vec k n) = n.
Lemma dec_vec {k} (v v' : vec nat k) :
{v = v'} + {v <> v'}.
Proof.
specialize (Nat.eq_dec (vec_to_nat k v) (vec_to_nat k v')) as [eq | neq].
- left. rewrite <- (vec_nat_inv k v). rewrite <- (vec_nat_inv k v'). now f_equal.
- right. now intros ->.
Qed.
Definition jumpNK (n : nat) {k : nat} (v : vec nat (S k)) :=
(fix jumpNK {k} (v : vec nat k) :=
match v with
| [] => False
| x::[] => ∅^(n) x
| x::v' => jumpNK v'
end) (S k) v.
Notation "'∅^[' n ',' k ']'" := (@jumpNK n k) (at level 25, format "∅^[ n , k ]").
Notation "'∅^[' n ']'" := (jumpNK n) (at level 25, format "∅^[ n ]").
Lemma jumpNKspec n {k} :
∅^[n,k] ⪯ₘ ∅^(n) /\ ∅^(n) ⪯ₘ ∅^[n,k].
Proof.
induction k as [|k IH].
- split.
+ exists (fun v => hd v). intros v. now repeat dependent destruction v.
+ now exists (fun x => x::[]).
- split.
+ eapply red_m_transitive. 2: apply IH.
exists tl. intros v. now do 2 dependent destruction v.
+ eapply red_m_transitive. 1: apply IH.
exists (fun v => 27::v). intros v. now do 2 dependent destruction v.
Qed.
Lemma jumpNK0 {k} (v : vec nat (S k)):
∅^[0] v <-> False.
Proof.
induction k.
- now repeat dependent destruction v.
- do 2 dependent destruction v.
now rewrite <- (IHk (h0::v)).
Qed.
Lemma jumpNKSemiDec n {k1 k2}:
oracle_semi_decidable (∅^[n,k1]) (∅^[S n,k2]).
Proof.
eapply semi_decidable_m_red. 1: apply jumpNKspec.
eapply semi_dec_turing_red_trans.
- apply semidecidable_J.
- apply red_m_impl_red_T, jumpNKspec.
Qed.
Lemma Σ_semi_decidable_in_Π1 {k} (p: (vec nat k) -> Prop) n:
isΣsem (S n) p -> exists (p': vec nat (S k) -> Prop), isΠsem n p' /\ oracle_semi_decidable p' p.
Proof.
intros H. inversion H as [| n' k' p' Hp' eqN eqk eqp]; subst.
exists p'. split;[easy|].
unshelve eapply mk_semi_dec with
(r := fun R v => exists n, R (n::v) true)
(r' := fun f v => mkpart (fun! ⟨x,m⟩ => match seval (f (x::v)) m with
| Some true => Some I
| _ => None
end)).
+ intros f R Hf v. rewrite mkpart_hasvalue;[|intros ? ? [] []; reflexivity].
split.
* intros [em H']. destruct unembed as [x m]. exists x.
destruct seval as [[]|] eqn:eq; try congruence.
apply Hf. apply seval_hasvalue. eauto.
* intros [x H'%Hf].
apply seval_hasvalue in H' as [m Hf'].
exists (embed (x, m)).
rewrite embedP.
destruct seval as [[]|] eqn:eq; congruence.
+ intros R v [x Hx]. exists (List.cons (x::v) List.nil).
split; [exists true|]; firstorder congruence.
+ now apply Eqdep.EqdepTheory.inj_pair2 in eqp as <-.
Qed.
Lemma Σ_semi_decidable_in_Π2 {k} (p: (vec nat k) -> Prop) n:
(exists (p': vec nat (S k) -> Prop), isΠsem n p' /\ oracle_semi_decidable p' p) -> isΣsem (S n) p.
Proof.
intros [p' [Πp' [om Hom]]].
erewrite PredExt. 2: apply Hom.
erewrite PredExt. 2: intros v; apply (oracle_iff_exists_LT_LF dec_vec). destruct om as [r r' Hr cont]. cbn in *.
unshelve erewrite PredExt. { intros v. apply (exists LTLFx : nat,
(fun v =>
((fun v => let (LT, LFx) := unembed (hd v) in let (LF, x) := unembed LFx in let v := (tl v) in
List.Forall p' (nat_to_list_vec (S k) LT)) v) /\
((fun v => let (LT, LFx) := unembed (hd v) in let (LF, x) := unembed LFx in let v := (tl v) in
List.Forall (fun y => ~p' y) (nat_to_list_vec (S k) LF)) v) /\
(fun v => let (LT, LFx) := unembed (hd v) in let (LF, x) := unembed LFx in let v := (tl v) in
seval (r' (oracle_from_lists dec_vec (nat_to_list_vec (S k) LT) (nat_to_list_vec (S k) LF)) v) x = Some I) v) (LTLFx::v)). }
2: {
setoid_rewrite seval_hasvalue.
intros v. split.
- intros [LT [LF [H1 [H2 [x H3]]]]].
exists (embed ((list_vec_to_nat _ LT), embed((list_vec_to_nat _ LF), x))).
rewrite eqhd. repeat rewrite embedP. rewrite eqtl. cbn.
repeat rewrite List.Forall_forall.
now repeat rewrite (list_vec_nat_inv).
- intros [LTLFx H]. rewrite eqhd in H. rewrite eqtl in H.
destruct (unembed LTLFx) as [LT LFx].
destruct (unembed LFx) as [LF x].
exists (nat_to_list_vec _ LT), (nat_to_list_vec _ LF).
repeat rewrite <- List.Forall_forall.
repeat split. 3: eexists. all: apply H.
} apply isΣsemE.
repeat apply isΣsem_and_closed.
- eapply isΣsem_m_red_closed. { apply isΣΠn_In_ΠΣSn in Πp'. eapply (isΣsemListΣ vec_nat_inv), Πp'. }
exists (fun v => let (LT, LFx) := unembed (hd v) in LT::(tl v)).
intros v. dependent destruction v. rewrite eqhd. now destruct unembed; destruct unembed.
- eapply isΣsem_m_red_closed. { apply (negΣinΠsem DN), (isΣΠn_In_ΣΠSn 1) in Πp'. apply (isΣsemListΣ vec_nat_inv), Πp'. }
exists (fun v => let (_, LFx) := unembed (hd v) in let (LF, _) := unembed LFx in LF::(tl v)).
intros v. dependent destruction v. rewrite eqhd. now destruct unembed; destruct unembed.
- erewrite PredExt with (g := fun v => (fun v => let (LT, LFx) := unembed (hd v) in
let (LF, x) := unembed LFx in
let v0 := tl v in
match seval (A:=True)
(r' (oracle_from_lists dec_vec (nat_to_list_vec (S k) LT)
(nat_to_list_vec (S k) LF)) v0) x
with Some _ => true | None => false end) v = true).
+ apply isΣΠsem0.
+ intros v. dependent destruction v. rewrite eqhd. rewrite eqtl.
destruct unembed. destruct unembed. destruct seval; split; now destruct t + intros [=].
Qed.
Lemma Σ_semi_decidable_in_Π {k} (p: (vec nat k) -> Prop) n:
isΣsem (S n) p <-> exists (p': vec nat (S k) -> Prop), isΠsem n p' /\ oracle_semi_decidable p' p.
Proof.
split; apply Σ_semi_decidable_in_Π1 + apply Σ_semi_decidable_in_Π2.
Qed.
Lemma Σ_semi_decidable_in_Σ {k} (p: (vec nat k) -> Prop) n:
isΣsem (S n) p <-> exists (p': vec nat (S k) -> Prop), isΣsem n p' /\ oracle_semi_decidable p' p.
Proof.
rewrite Σ_semi_decidable_in_Π.
split.
- intros [p' [H%(negΣinΠsem DN) S]].
eexists. split;[apply H|].
now rewrite <- (oracle_semi_decidable_complement_iff _ _ DN).
- intros [p' [H%(negΣinΠsem DN) S]].
eexists. split;[apply H|].
now rewrite <- (oracle_semi_decidable_complement_iff _ _ DN).
Qed.
Lemma jump_in_Σn n {k} :
@isΣsem n (S k) (∅^[n]).
Proof.
induction n as [|n IH] in k |-*.
- rewrite PredExt with (g := fun _ => false=true). { apply isΣsem0. } setoid_rewrite jumpNK0. clear. firstorder congruence.
- apply Σ_semi_decidable_in_Σ.
exists (jumpNK n). split; [apply IH|].
apply jumpNKSemiDec.
Qed.
Lemma jump_Σn_complete n :
forall k (p : vec nat k -> Prop), isΣsem (S n) p -> p ⪯ₘ (∅^(S n)).
Proof.
induction n as [|n IH].
- intros k p H.
apply (red_m_iff_semidec_jump_vec vec_to_nat nat_to_vec vec_nat_inv).
apply no_oracle_semi_decidable. { exists (fun _ => false). split; [intros [] |intros [=]]. }
now apply semi_dec_iff_Σ1.
- intros k p [p' [Σp' Sp']]%Σ_semi_decidable_in_Σ.
apply (red_m_iff_semidec_jump_vec vec_to_nat nat_to_vec vec_nat_inv).
eapply (semi_dec_turing_red_trans Sp').
apply red_m_impl_red_T, (IH _ p' Σp').
Qed.
Lemma jump_Σn_complete_redT n :
forall k (p : vec nat k -> Prop), isΣsem n p -> p ⪯ᴛ (∅^(n)).
Proof.
intros k p H. destruct n.
- dependent destruction H.
unshelve eexists. {
unshelve econstructor.
- intros _. apply (@Build_FunRel _ _ (fun v b => f v = b)). { now intros ? ? ? -> ->. }
- intros _ v. apply ret, f, v.
- intros f' ? _ x b. cbn. now rewrite ret_hasvalue_iff.
- intros ? ? ?. now exists List.nil.
} cbn. intros x []. reflexivity. now destruct f.
- apply red_m_impl_red_T. now apply jump_Σn_complete.
Qed.
Lemma Σ_semi_decidable_jump {k} (p: (vec nat k) -> Prop) n:
isΣsem (S n) p <-> oracle_semi_decidable (∅^(n)) p.
Proof.
split.
- intros [p' [Σp' Sp']]%Σ_semi_decidable_in_Σ.
eapply (semi_dec_turing_red_trans Sp').
now apply jump_Σn_complete_redT.
- intros H. apply Σ_semi_decidable_in_Σ.
exists (∅^[n]). split.
+ apply jump_in_Σn.
+ apply (semi_dec_turing_red_trans H), red_m_impl_red_T, jumpNKspec.
Qed.
Theorem PostsTheorem {k} (p: (vec nat k) -> Prop) n :
(isΣsem (S n) p <-> exists (p': vec nat (S k) -> Prop), isΠsem n p' /\ oracle_semi_decidable p' p)
/\ (isΣsem (S n) p <-> exists (p': vec nat (S k) -> Prop), isΣsem n p' /\ oracle_semi_decidable p' p)
/\ (@isΣsem n (S k) (∅^[n]))
/\ (isΣsem (S n) p -> p ⪯ₘ (∅^(S n)))
/\ (isΣsem n p -> p ⪯ᴛ (∅^(n)))
/\ (isΣsem (S n) p <-> oracle_semi_decidable (∅^(n)) p).
Proof.
split; [|split]; [| |split]; [| | |split]; [| | | |split].
- apply Σ_semi_decidable_in_Π.
- apply Σ_semi_decidable_in_Σ.
- apply jump_in_Σn.
- apply jump_Σn_complete.
- apply jump_Σn_complete_redT.
- apply Σ_semi_decidable_jump.
Qed.
End PostsTheorem.