Require Import Encodings.

Implicit Types s t u v : term.

Implicit Types p q : term -> Prop.


Decidable and recognisable classes

Definition of decidable classes


Definition decides u p := forall s, (p s /\ u (tenc s) T) \/ (~ p s /\ u (tenc s) F).

Definition decidable p :=
  exists u, proc u /\ decides u p.


Lemma decidable_spec u p : decides u p -> forall s, (p s <-> u (tenc s) T) /\ (~ p s <-> u (tenc s) F).

Proof.

  intros; split; destruct (H s); firstorder;
    rewrite H1 in H2; destruct T_equiv_F; now rewrite H2.

Qed.


Definition of recognisable classes


Definition pi s t := eva (s (tenc t)).


Definition recognisable p :=
  exists u, proc u /\ forall s, p s <-> eva (u (tenc s)).


(* * Complement, intersection and union of predicates *)

Definition complement p := fun t => ~ p t.

Definition intersection p q := fun t => p t /\ q t.

Definition union p q := fun t => p t \/ q t.


Decidable classes are closed under union, intersection and complement


Definition tcompl (u : term) : term := .\"x"; (!u "x") !F !T.


Definition tintersection u v : term := .\"x"; (!u "x") (!v "x") !F.


Definition tunion u v : term := .\"x"; (!u "x") !T (!v "x").


Lemma decidable_intersection p q : decidable p -> decidable q -> decidable (intersection p q).

Proof.

  intros [u [[cls_u lam_u] decp]] [v [[cls_v lam_v] decq]].

  exists (tintersection u v).
split; unfold tintersection; value.
  intros s.
destruct (decp s) as [[ps Hu ] | [nps Hu]], (decq s) as [[Qs Hv] | [nQs Hv]]; [left| right..]; firstorder; solvered.
Qed.


Lemma decidable_union p q : decidable p -> decidable q -> decidable (union p q).

Proof.

  intros [u [[cls_u lam_u] Hu]] [v [[cls_v lam_v] Hv]].

  exists (tunion u v).
split; unfold tunion; value.
  intros s.
destruct (Hu s) as [[A B] | [A B]], (Hv s) as [[C D] | [C D]]; [left .. | right]; firstorder; solvered.
Qed.


Lemma decidable_complement p : decidable p -> decidable (complement p).

Proof.

  intros [u [[cls_u lam_u] H]].

  exists (tcompl u).
split; unfold tcompl; value.
  intros s.
destruct (H s) as [[ps A] | [nps A]]; [right | left]; intuition; solveeq.
Qed.


There is an undecidable class


Lemma undecidable_russell : ~ decidable (fun s => ~ s (tenc s) T).

Proof.

  intros (u & proc_u & Hu).

  destruct (Hu u) as [ | [] ].

  - firstorder.

  - eapply T_equiv_F.
rewrite <- H0. exfalso. eapply H. intros H1.
    eapply T_equiv_F.
now rewrite <- H0, <- H1.
Qed.


Recognisable classes are closed under intersection


Definition recinter u v := lambda ((lambda (v 1)) (u 0) ).

Hint Unfold recinter : cbv.


Lemma recinter_correct u v s : closed u -> closed v -> eva (recinter u v (tenc s)) <-> eva ( u (tenc s)) /\ eva (v (tenc s)).

Proof.

  intros cls_u cls_q.

  split.

  - intros [x [Hx lx] % evaluates_equiv].

    assert (H : eva ((lambda (v (tenc s))) (u (tenc s)))).
exists x; eapply evaluates_equiv;split;auto. symmetry. symmetry in Hx. solvered.
    destruct (app_eva H) as [_ [y [Hy ly] % evaluates_equiv]].
split.
    + eexists; eapply evaluates_equiv; split;eassumption.

    + exists x; eapply evaluates_equiv; split;auto.
rewrite <- Hx. symmetry. clear Hx. solvered.
  - intros [[x [Hx ?] % evaluates_equiv] [y [Hy ?] % evaluates_equiv]].
exists y. eapply evaluates_equiv.
    split.
solvered. value.
Qed.


Lemma recognisable_intersection p q : recognisable p -> recognisable q -> recognisable (intersection p q).

Proof.

  intros [u1 [[? ?] Hu1]] [u2 [[? ?] Hu2]].

  exists (recinter u1 u2).
split. unfold recinter. value.
  intros; rewrite recinter_correct; firstorder.

Qed.


Decidable classes are recognisable and coregnisable


Lemma dec_recognisable p : decidable p -> recognisable p.

Proof.

  intros [u [[cls_u lam_u] dec_u_p]].

  exists (lambda (u 0 I (lambda Omega) I)); split; value.

    + intros t.
specialize (dec_u_p t).
      split; intros H; destruct dec_u_p; try tauto.

      * destruct H0 as [_ u_T].
eexists; eapply evaluates_equiv; split;[|eexists;reflexivity]. solvered.
      * destruct H.
destruct H0.
        assert ((lambda ((((u 0) I) (lambda Omega)) I)) (tenc t) Omega).
clear H. solveeq.
        rewrite H2 in H.
destruct (eva_Omega). eexists; eauto.
Qed.


Lemma dec_rec p : decidable p -> recognisable p /\ recognisable (complement p).

Proof.

  intros decp; split.

  - eapply (dec_recognisable decp).

  - eapply decidable_complement in decp.
eapply (dec_recognisable decp).
Qed.


Scott's theorem


Theorem SecondFixedPoint (s : term) : closed s -> exists t, closed t /\ s (tenc t) t.

Proof.

  intros cls_s.

  pose (A := (.\ "x"; !s (!App "x" (!Q "x"))) : term).
cbn in A.
  pose (t := A (tenc A)).

  exists t.
split; [subst t A; value|].
  symmetry.
unfold t, A.
  transitivity (s (App (tenc A) (Q (tenc A)))).
solvered.
  rewrite Q_correct, App_correct.
reflexivity.
Qed.


Theorem Scott p :
  (forall s t, closed s -> p s -> closed t -> t s -> p t) ->
  (exists t1, closed t1 /\ p t1) -> (exists t2, closed t2 /\ ~ p t2) ->
  ~ decidable p.

Proof.

  intros p_equiv [s1 [cls_s1 ps1]] [s2 [cls_s2 nps2]] [u [[cls_u lam_u] Hu]].

  pose (x := lambda(u 0 (lambda s2) (lambda s1) I)).

  destruct (SecondFixedPoint (s := x)) as [t [cls_t H]]; subst x; value.

  eapply eqTrans with (s := u (tenc t) (lambda s2) (lambda s1) I) in H.

  destruct (Hu t) as [ [pt Ht] | [npt Ht ]].

  - eapply nps2, p_equiv; eauto.

    rewrite <- H, Ht.
symmetry. solvered.
  - eapply npt,p_equiv with (s := s1); eauto.

    rewrite <- H, Ht; solvered.

  -symmetry.
now dobeta.
Qed.


Lemma eva_dec : ~ decidable eva.

Proof.

  eapply Scott.

  - intros s t cls_s [x [Hx lx] % evaluates_equiv] cls_t t_e_s.

    exists x; eapply evaluates_equiv; split;[|value].
now rewrite t_e_s.
  - exists I.
repeat split. exists I; eapply evaluates_equiv;split. reflexivity. value.
  - exists Omega.
repeat split. eapply eva_Omega.
Qed.


Lemma equiv_spec_decidable : forall t, closed t -> ~ decidable (fun x => x t).

Proof.

  intros t cls_t H.

  eapply Scott; try eassumption; cbn.

  - intros s t0 cls_s H0 cls_t0 H1.
rewrite H1. assumption.
  - exists t.
repeat split. value. reflexivity.
  - destruct H as (? & ? & ?).
destruct (H0 I) as [ [? ?] | [ ? ?] ]. exists Omega.
    split.
value. intros H3. eapply I_neq_Omega.
    rewrite H1, H3.
reflexivity.
    exists I.
split. value. eassumption.
Qed.