Library SATnat
Saturated sets constructions related to natural numbers: interpreting constructors,
dependent pattern-matching and fixpoint. Also support size annotations.
Set Implicit Arguments.
Require Import basic Can Sat.
Require Import ZF ZFind_nat.
Module Lc:=Lambda.
A family is a realizability relation for natural numbers
Record family := mkFam {
fam :> set -> SAT;
fam_mrph : ∀ x y, x ∈ NAT -> x == y -> eqSAT (fam x) (fam y)
}.
Definition dflt_family : family.
exists (fun _ => snSAT).
reflexivity.
Defined.
Definition eqfam (A B:family) :=
∀ x y, x ∈ NAT -> x == y -> eqSAT (A x) (B y).
fam :> set -> SAT;
fam_mrph : ∀ x y, x ∈ NAT -> x == y -> eqSAT (fam x) (fam y)
}.
Definition dflt_family : family.
exists (fun _ => snSAT).
reflexivity.
Defined.
Definition eqfam (A B:family) :=
∀ x y, x ∈ NAT -> x == y -> eqSAT (A x) (B y).
Denotation of the intersection of (F(n)) expressions when n:Nat
Definition piNAT F :=
interSAT (fun p:{n|n ∈ NAT} => F (proj1_sig p)).
Lemma piNAT_ax t F :
inSAT t (piNAT F) <-> sn t /\ ∀ n, n ∈ NAT -> inSAT t (F n).
split; intros.
split.
apply sat_sn in H; trivial.
intros.
apply interSAT_elim with (x:=exist (fun n=>n ∈ NAT) n H0) in H; trivial.
destruct H.
split; trivial.
destruct x; simpl; intros.
apply H0; trivial.
Qed.
interSAT (fun p:{n|n ∈ NAT} => F (proj1_sig p)).
Lemma piNAT_ax t F :
inSAT t (piNAT F) <-> sn t /\ ∀ n, n ∈ NAT -> inSAT t (F n).
split; intros.
split.
apply sat_sn in H; trivial.
intros.
apply interSAT_elim with (x:=exist (fun n=>n ∈ NAT) n H0) in H; trivial.
destruct H.
split; trivial.
destruct x; simpl; intros.
apply H0; trivial.
Qed.
Quantification over families
Definition piFAM F :=
interSAT (fun P:family => F P).
Lemma piFAM_ax t F :
inSAT t (piFAM F) <-> ∀ P:family, inSAT t (F P).
split; intros.
apply interSAT_elim with (x:=P) in H; trivial.
apply interSAT_intro; auto.
exact dflt_family.
Qed.
interSAT (fun P:family => F P).
Lemma piFAM_ax t F :
inSAT t (piFAM F) <-> ∀ P:family, inSAT t (F P).
split; intros.
apply interSAT_elim with (x:=P) in H; trivial.
apply interSAT_intro; auto.
exact dflt_family.
Qed.
Definition fNAT (A:family) (k:set) :=
piFAM(fun P =>
prodSAT (P ZERO)
(prodSAT (piNAT(fun n => prodSAT (A n) (prodSAT (P n) (P (SUCC n)))))
(P k))).
Lemma fNAT_morph : ∀ A B, eqfam A B ->
∀ x y, x ∈ NAT -> x == y -> eqSAT (fNAT A x) (fNAT B y).
intros.
unfold fNAT.
apply interSAT_morph.
apply indexed_relation_id; intros.
apply prodSAT_morph.
reflexivity.
apply prodSAT_morph.
apply interSAT_morph_subset; simpl proj1_sig; intros; auto with *.
apply prodSAT_morph; auto with *.
apply fam_mrph; trivial.
Qed.
Definition fNATf (A:family) : family.
exists (fNAT A).
intros.
apply fNAT_morph; trivial.
exact (fam_mrph A).
Defined.
Lemma fNAT_def : ∀ t A k,
inSAT t (fNAT A k) <->
∀ (P:family) f g,
inSAT f (P ZERO) ->
inSAT g (piNAT(fun n => prodSAT (A n) (prodSAT (P n) (P (SUCC n))))) ->
inSAT (Lc.App2 t f g) (P k).
intros.
unfold fNAT.
rewrite piFAM_ax.
apply fa_morph; intros P.
split; intros.
apply prodSAT_elim with (2:=H0) in H.
apply prodSAT_elim with (1:=H); trivial.
intros f satf g satg.
apply H; trivial.
Qed.
Lemma fNAT_mono : ∀ (A B:family),
(∀ k, inclSAT (A k) (B k)) -> ∀ k, inclSAT (fNAT A k) (fNAT B k).
unfold fNAT; intros.
apply interSAT_mono; intro P.
apply prodSAT_mono; auto with *.
apply prodSAT_mono; auto with *.
apply interSAT_mono; intros (n,tyn); simpl proj1_sig.
apply prodSAT_mono; auto with *.
apply H.
Qed.
Realizability relation of Nat: fixpoint of fNAT
Definition cNAT : family.
exists (fun n =>
interSAT (fun P:{P:family|∀ k, inclSAT (fNAT P k) (P k)} =>
proj1_sig P n)).
intros.
apply interSAT_morph.
split; intros.
exists x0.
apply (fam_mrph (proj1_sig x0)); trivial.
exists y0.
apply (fam_mrph (proj1_sig y0)); trivial.
Defined.
Lemma cNAT_post : ∀ k, inclSAT (fNAT cNAT k) (cNAT k).
red; intros.
unfold cNAT.
apply interSAT_intro; intros.
exists dflt_family; red; intros.
apply sat_sn in H0; trivial.
apply (proj2_sig x).
revert t H.
apply fNAT_mono.
red; intros.
apply interSAT_elim with (1:=H) (x:=x).
Qed.
Lemma cNAT_pre : ∀ k, inclSAT (cNAT k) (fNAT cNAT k).
red; intros.
apply interSAT_elim with (1:=H)
(x:=exist (fun P => ∀ k, inclSAT (fNAT P k) (P k))
(fNATf cNAT) (@fNAT_mono (fNATf cNAT) cNAT cNAT_post)).
Qed.
exists (fun n =>
interSAT (fun P:{P:family|∀ k, inclSAT (fNAT P k) (P k)} =>
proj1_sig P n)).
intros.
apply interSAT_morph.
split; intros.
exists x0.
apply (fam_mrph (proj1_sig x0)); trivial.
exists y0.
apply (fam_mrph (proj1_sig y0)); trivial.
Defined.
Lemma cNAT_post : ∀ k, inclSAT (fNAT cNAT k) (cNAT k).
red; intros.
unfold cNAT.
apply interSAT_intro; intros.
exists dflt_family; red; intros.
apply sat_sn in H0; trivial.
apply (proj2_sig x).
revert t H.
apply fNAT_mono.
red; intros.
apply interSAT_elim with (1:=H) (x:=x).
Qed.
Lemma cNAT_pre : ∀ k, inclSAT (cNAT k) (fNAT cNAT k).
red; intros.
apply interSAT_elim with (1:=H)
(x:=exist (fun P => ∀ k, inclSAT (fNAT P k) (P k))
(fNATf cNAT) (@fNAT_mono (fNATf cNAT) cNAT cNAT_post)).
Qed.
Fixpoint equation
Definition ZE := Lc.Abs (Lc.Abs (Lc.Ref 1)).
Lemma fNAT_ZE : ∀ A, inSAT ZE (fNAT A ZERO).
intros.
rewrite fNAT_def; intros.
unfold ZE.
eapply prodSAT_elim;[|eexact H0].
apply prodSAT_elim with (2:=H).
apply prodSAT_intro; intros.
unfold Lc.subst; simpl Lc.subst_rec.
apply prodSAT_intro; intros.
unfold Lc.subst; rewrite Lc.simpl_subst; auto.
rewrite Lc.lift0; auto.
Qed.
Lemma fNAT_ZE : ∀ A, inSAT ZE (fNAT A ZERO).
intros.
rewrite fNAT_def; intros.
unfold ZE.
eapply prodSAT_elim;[|eexact H0].
apply prodSAT_elim with (2:=H).
apply prodSAT_intro; intros.
unfold Lc.subst; simpl Lc.subst_rec.
apply prodSAT_intro; intros.
unfold Lc.subst; rewrite Lc.simpl_subst; auto.
rewrite Lc.lift0; auto.
Qed.
ZE realizes 0
Interp of successor. Unlike in system F the function corresponding to the successor
expects two arguments: the predecessor and the usual result of recursive call.
S(n) is (fun f g => g n (n f g)) instead of the usual (fun f g => g (n f g)).
Definition SU := Lc.Abs (Lc.Abs (Lc.Abs
(Lc.App2 (Lc.Ref 0) (Lc.Ref 2) (Lc.App2 (Lc.Ref 2) (Lc.Ref 1) (Lc.Ref 0))))).
Lemma fNAT_SU : ∀ (A:family) n t,
n ∈ NAT ->
inSAT t (A n) ->
inSAT t (fNAT A n) ->
inSAT (Lc.App SU t) (fNAT A (SUCC n)).
intros A n t tyn H H0.
unfold SU.
apply inSAT_exp;[right|].
apply sat_sn in H0; trivial.
unfold Lc.subst; simpl Lc.subst_rec.
rewrite fNAT_def; intros.
eapply inSAT_context.
intros.
apply inSAT_exp; [right|].
apply sat_sn in H1; trivial.
eexact H3.
unfold Lc.subst; simpl Lc.subst_rec.
apply inSAT_exp.
right; apply sat_sn in H2; trivial.
unfold Lc.subst; simpl Lc.subst_rec.
repeat rewrite Lc.simpl_subst; auto.
repeat rewrite Lc.lift0.
apply prodSAT_elim with (P n).
apply prodSAT_elim with (2:=H).
rewrite piNAT_ax in H2; auto.
destruct H2; auto.
rewrite fNAT_def in H0.
apply H0; trivial.
Qed.
SU realizes the successor
Lemma cNAT_SU : ∀ n t, n ∈ NAT -> inSAT t (cNAT n) -> inSAT (Lc.App SU t) (cNAT (SUCC n)).
intros.
rewrite cNAT_eq.
apply fNAT_SU; trivial.
rewrite <- cNAT_eq; trivial.
Qed.
intros.
rewrite cNAT_eq.
apply fNAT_SU; trivial.
rewrite <- cNAT_eq; trivial.
Qed.
Definition NCASE f g n :=
Lc.App2 n f (Lc.Abs (Lc.Abs (Lc.App (Lc.lift 2 g) (Lc.Ref 1)))).
Lemma NCASE_sim_0 f g :
Lc.redp (NCASE f g ZE) f.
unfold NCASE, ZE.
eapply t_trans;[apply t_step|].
apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
apply t_step.
apply Lc.red1_beta.
unfold Lc.subst; rewrite Lc.simpl_subst; auto.
rewrite Lc.lift0; trivial.
Qed.
Lemma NCASE_sim_S f g n :
Lc.redp (NCASE f g (Lc.App SU n)) (Lc.App g n).
unfold NCASE, SU.
eapply t_trans;[apply t_step|].
do 2 apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
eapply t_trans;[apply t_step|].
apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
rewrite Lc.simpl_subst; trivial.
eapply t_trans;[apply t_step|].
apply beta.
unfold Lc.subst; simpl.
do 2 (rewrite Lc.simpl_subst; trivial).
repeat rewrite Lc.lift0.
eapply t_trans;[apply t_step|].
apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
rewrite Lc.simpl_subst; trivial.
apply t_step.
apply Lc.red1_beta.
unfold Lc.subst; simpl.
do 2 (rewrite Lc.simpl_subst; auto).
repeat rewrite Lc.lift0; trivial.
Qed.
Lemma NCASE_fNAT f g n k (A B:family) :
k ∈ NAT ->
inSAT n (fNAT A k) ->
inSAT f (B ZERO) ->
inSAT g (piNAT(fun m => prodSAT (A m) (B (SUCC m)))) ->
inSAT (NCASE f g n) (B k).
unfold NCASE; intros.
rewrite fNAT_def in H0.
apply H0 with (P:=B); intros; trivial.
rewrite piNAT_ax in H2|-*; intros.
destruct H2 as (sng,H2).
split; intros.
do 2 apply Lc.sn_abs.
apply Lc.sn_app_var.
apply Lc.sn_lift; trivial.
apply prodSAT_intro; intros.
unfold Lc.subst; simpl Lc.subst_rec.
apply prodSAT_intro; intros.
unfold Lc.subst; simpl Lc.subst_rec.
repeat rewrite Lc.simpl_subst; trivial.
do 2 rewrite Lc.lift0.
apply prodSAT_elim with (2:=H4); auto.
Qed.
Structural fixpoint:
Definition G m :=
Lc.Abs (Lc.App2 (Lc.App2 (Lc.Ref 0) (Lc.lift 1 m) (Lc.Abs (Lc.Abs (Lc.lift 3 m)))) (Lc.lift 1 m) (Lc.Ref 0)).
Lc.Abs (Lc.App2 (Lc.App2 (Lc.Ref 0) (Lc.lift 1 m) (Lc.Abs (Lc.Abs (Lc.lift 3 m)))) (Lc.lift 1 m) (Lc.Ref 0)).
(G m n) reduces to (m m n) when n is a constructor. Note that
n need not be closed.
Lemma G_sim : ∀ m n,
n = ZE \/ (exists t1 t2, n = Lc.Abs (Lc.Abs (Lc.App2 (Lc.Ref 0) t1 t2))) ->
Lc.redp (Lc.App (G m) n) (Lc.App2 m m n).
intros.
unfold G.
eapply t_trans.
apply t_step.
apply Lc.beta.
unfold Lc.subst; simpl.
rewrite Lc.simpl_subst; auto.
repeat rewrite Lc.lift0.
unfold Lc.lift; rewrite Lc.simpl_subst_rec; auto.
apply Lc.redp_app_l.
apply Lc.redp_app_l.
destruct H as [eqn|(t1,(t2,eqn))]; rewrite eqn.
eapply t_trans.
apply t_step.
apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
apply t_step.
apply red1_beta.
unfold Lc.subst; rewrite Lc.simpl_subst; auto with *.
rewrite Lc.lift0; trivial.
eapply t_trans.
apply t_step.
apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
eapply t_trans.
apply t_step; apply beta.
unfold Lc.subst; simpl.
rewrite Lc.lift0.
eapply t_trans.
apply t_step.
apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
rewrite Lc.simpl_subst_rec; auto.
apply t_step.
apply Lc.red1_beta.
unfold Lc.subst.
rewrite Lc.simpl_subst_rec; auto.
rewrite Lc.lift_rec0; trivial.
Qed.
Lemma G_sat A k m t X :
k ∈ NAT ->
inSAT t (fNAT A k) ->
inSAT (Lc.App2 m m t) X ->
inSAT (Lc.App (G m) t) X.
intros.
unfold G.
apply inSAT_exp; intros.
right; apply sat_sn in H0; trivial.
unfold Lc.subst; simpl Lc.subst_rec.
repeat rewrite Lc.simpl_subst; auto.
repeat rewrite Lc.lift0.
assert (tsat := H0).
rewrite fNAT_def in tsat.
eapply inSAT_context.
intros.
eapply inSAT_context.
intros.
assert (rS0 : eqSAT S0 S0) by reflexivity.
pose (G:=mkFam (fun _ => S0) (fun _ _ _ _ => rS0)).
apply tsat with (P:=G).
unfold G; simpl.
eexact H3.
rewrite piNAT_ax; intros.
split; intros.
do 2 apply Lc.sn_abs.
apply Lc.sn_lift.
apply sat_sn in H3; trivial.
apply prodSAT_intro; intros.
unfold Lc.subst; simpl Lc.subst_rec.
apply prodSAT_intro; intros.
unfold Lc.subst; repeat rewrite Lc.simpl_subst; auto.
rewrite Lc.lift0; trivial.
eexact H2.
trivial.
Qed.
Lemma sn_G_inv m : Lc.sn (G m) -> Lc.sn m.
intros.
unfold G in H.
eapply subterm_sn in H;[|constructor].
eapply subterm_sn in H;[|apply sbtrm_app_l].
eapply subterm_sn in H;[|apply sbtrm_app_r].
apply sn_lift_inv with (1:=H) (2:=eq_refl).
Qed.
Definition NATFIX m :=
G (Lc.Abs (Lc.App (Lc.lift 1 m) (G (Lc.Ref 0)))).
n = ZE \/ (exists t1 t2, n = Lc.Abs (Lc.Abs (Lc.App2 (Lc.Ref 0) t1 t2))) ->
Lc.redp (Lc.App (G m) n) (Lc.App2 m m n).
intros.
unfold G.
eapply t_trans.
apply t_step.
apply Lc.beta.
unfold Lc.subst; simpl.
rewrite Lc.simpl_subst; auto.
repeat rewrite Lc.lift0.
unfold Lc.lift; rewrite Lc.simpl_subst_rec; auto.
apply Lc.redp_app_l.
apply Lc.redp_app_l.
destruct H as [eqn|(t1,(t2,eqn))]; rewrite eqn.
eapply t_trans.
apply t_step.
apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
apply t_step.
apply red1_beta.
unfold Lc.subst; rewrite Lc.simpl_subst; auto with *.
rewrite Lc.lift0; trivial.
eapply t_trans.
apply t_step.
apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
eapply t_trans.
apply t_step; apply beta.
unfold Lc.subst; simpl.
rewrite Lc.lift0.
eapply t_trans.
apply t_step.
apply Lc.app_red_l.
apply beta.
unfold Lc.subst; simpl.
rewrite Lc.simpl_subst_rec; auto.
apply t_step.
apply Lc.red1_beta.
unfold Lc.subst.
rewrite Lc.simpl_subst_rec; auto.
rewrite Lc.lift_rec0; trivial.
Qed.
Lemma G_sat A k m t X :
k ∈ NAT ->
inSAT t (fNAT A k) ->
inSAT (Lc.App2 m m t) X ->
inSAT (Lc.App (G m) t) X.
intros.
unfold G.
apply inSAT_exp; intros.
right; apply sat_sn in H0; trivial.
unfold Lc.subst; simpl Lc.subst_rec.
repeat rewrite Lc.simpl_subst; auto.
repeat rewrite Lc.lift0.
assert (tsat := H0).
rewrite fNAT_def in tsat.
eapply inSAT_context.
intros.
eapply inSAT_context.
intros.
assert (rS0 : eqSAT S0 S0) by reflexivity.
pose (G:=mkFam (fun _ => S0) (fun _ _ _ _ => rS0)).
apply tsat with (P:=G).
unfold G; simpl.
eexact H3.
rewrite piNAT_ax; intros.
split; intros.
do 2 apply Lc.sn_abs.
apply Lc.sn_lift.
apply sat_sn in H3; trivial.
apply prodSAT_intro; intros.
unfold Lc.subst; simpl Lc.subst_rec.
apply prodSAT_intro; intros.
unfold Lc.subst; repeat rewrite Lc.simpl_subst; auto.
rewrite Lc.lift0; trivial.
eexact H2.
trivial.
Qed.
Lemma sn_G_inv m : Lc.sn (G m) -> Lc.sn m.
intros.
unfold G in H.
eapply subterm_sn in H;[|constructor].
eapply subterm_sn in H;[|apply sbtrm_app_l].
eapply subterm_sn in H;[|apply sbtrm_app_r].
apply sn_lift_inv with (1:=H) (2:=eq_refl).
Qed.
Definition NATFIX m :=
G (Lc.Abs (Lc.App (Lc.lift 1 m) (G (Lc.Ref 0)))).
NATFIX reduces as a fixpoint combinator when applied to a constructor
Lemma NATFIX_sim : ∀ m n,
n = ZE \/ (exists t1 t2, n = Lc.Abs (Lc.Abs (Lc.App2 (Lc.Ref 0) t1 t2))) ->
Lc.redp (Lc.App (NATFIX m) n) (Lc.App2 m (NATFIX m) n).
intros.
unfold NATFIX at 1.
eapply t_trans.
apply G_sim; trivial.
apply Lc.redp_app_l.
apply t_step.
apply Lc.red1_beta.
set (t1 := Lc.Abs (Lc.App (Lc.lift 1 m) (G (Lc.Ref 0)))).
unfold Lc.subst; simpl.
rewrite Lc.simpl_subst; auto.
rewrite Lc.lift0.
reflexivity.
Qed.
Definition piNATi F o :=
interSAT (fun p:{n|n ∈ NATi o} => F (proj1_sig p)).
Lemma piNATi_ax t F o :
inSAT t (piNATi F o) <-> sn t /\ ∀ n, n ∈ NATi o -> inSAT t (F n).
split; intros.
split; intros.
apply sat_sn in H; trivial.
apply interSAT_elim with (x:=exist (fun n=>n ∈ NATi o) n H0) in H; trivial.
destruct H.
split; intros; trivial.
destruct x; simpl; auto.
apply H0; trivial.
Qed.
Require Import ZFord.
n = ZE \/ (exists t1 t2, n = Lc.Abs (Lc.Abs (Lc.App2 (Lc.Ref 0) t1 t2))) ->
Lc.redp (Lc.App (NATFIX m) n) (Lc.App2 m (NATFIX m) n).
intros.
unfold NATFIX at 1.
eapply t_trans.
apply G_sim; trivial.
apply Lc.redp_app_l.
apply t_step.
apply Lc.red1_beta.
set (t1 := Lc.Abs (Lc.App (Lc.lift 1 m) (G (Lc.Ref 0)))).
unfold Lc.subst; simpl.
rewrite Lc.simpl_subst; auto.
rewrite Lc.lift0.
reflexivity.
Qed.
Definition piNATi F o :=
interSAT (fun p:{n|n ∈ NATi o} => F (proj1_sig p)).
Lemma piNATi_ax t F o :
inSAT t (piNATi F o) <-> sn t /\ ∀ n, n ∈ NATi o -> inSAT t (F n).
split; intros.
split; intros.
apply sat_sn in H; trivial.
apply interSAT_elim with (x:=exist (fun n=>n ∈ NATi o) n H0) in H; trivial.
destruct H.
split; intros; trivial.
destruct x; simpl; auto.
apply H0; trivial.
Qed.
Require Import ZFord.
The guard is needed mainly here: NATFIX m does not reduce
Lemma sn_natfix o m X :
isOrd o ->
inSAT m (interSAT (fun o':{o'|o' ∈ osucc o} => let o':=proj1_sig o' in
prodSAT (piNATi(fun n => prodSAT (cNAT n) (X o' n)) o')
(piNATi(fun n => prodSAT (cNAT n) (X (osucc o') n)) (osucc o')))) ->
sn (NATFIX m).
intros.
assert (empty ∈ osucc o).
apply isOrd_plump with o; auto with *.
red; intros.
apply empty_ax in H1; contradiction.
apply lt_osucc; trivial.
apply interSAT_elim with (x:=exist (fun o'=>o'∈ osucc o) empty H1) in H0.
simpl proj1_sig in H0.
unfold NATFIX.
assert (sn (Lc.Abs (Lc.App (Lc.lift 1 m) (G (Lc.Ref 0))))).
apply sn_abs.
assert (inSAT (G (Lc.Ref 0)) (piNATi(fun n => prodSAT (cNAT n) (X empty n)) empty)).
rewrite piNATi_ax.
split; intros.
apply sn_abs.
constructor; intros.
apply nf_norm in H2; try contradiction.
repeat constructor.
intros ? ?.
eapply G_sat with (A:=cNAT) (k:=n).
revert H2; apply NATi_NAT; auto with *.
apply cNAT_pre; trivial.
apply prodSAT_elim with (A:=snSAT).
2:apply sat_sn in H3; trivial.
apply prodSAT_elim with (A:=snSAT).
apply varSAT.
apply varSAT.
specialize prodSAT_elim with (1:=H0)(2:=H2); intro.
apply sat_sn in H3; trivial.
apply sn_subst with (Ref 0).
unfold Lc.subst; simpl.
rewrite simpl_subst; auto.
rewrite lift0; auto.
apply sn_abs.
apply prodSAT_elim with (A:=snSAT) (B:=snSAT).
2:simpl; auto with *.
apply prodSAT_elim with (A:=snSAT).
apply prodSAT_elim with (A:=snSAT).
apply prodSAT_elim with (A:=snSAT).
apply varSAT.
simpl; apply sn_lift; trivial.
apply sn_abs; apply sn_abs.
apply sn_lift; trivial.
simpl; apply sn_lift; trivial.
Qed.
Lemma NATFIX_sat : ∀ o m X,
isOrd o ->
(∀ y y' n, isOrd y -> isOrd y' -> y ⊆ y' -> y' ⊆ o -> n ∈ NATi y ->
inclSAT (X y n) (X y' n)) ->
inSAT m (interSAT (fun o':{o'|o' ∈ osucc o} => let o':=proj1_sig o' in
prodSAT (piNATi(fun n => prodSAT (cNAT n) (X o' n)) o')
(piNATi(fun n => prodSAT (cNAT n) (X (osucc o') n)) (osucc o')))) ->
inSAT (NATFIX m) (piNATi(fun n => prodSAT (cNAT n) (X o n)) o).
intros o m X H Xmono H0.
elim H using isOrd_ind; intros.
rewrite piNATi_ax.
split.
apply sn_natfix with (2:=H0); trivial.
intros x i.
assert (tyx : x ∈ NAT).
apply NATi_NAT with y; trivial.
apply TI_elim in i; auto with *.
destruct i as (z,?,?).
unfold NATFIX.
intros t tty.
apply cNAT_pre in tty.
apply G_sat with (2:=tty); trivial.
eapply inSAT_context; intros.
apply inSAT_exp.
left; simpl.
apply Bool.orb_true_r.
unfold Lc.subst; simpl Lc.subst_rec.
repeat rewrite Lc.simpl_subst; auto.
rewrite Lc.lift0.
change (inSAT (Lc.App m (NATFIX m)) S).
eexact H6.
apply Xmono with (osucc z); eauto using isOrd_inv.
red; intros.
apply isOrd_plump with z; trivial.
eauto using isOrd_inv.
apply olts_le; trivial.
unfold NATi; rewrite ZFfix.TI_mono_succ; auto with *.
eauto using isOrd_inv.
apply prodSAT_elim with (cNAT x).
2:apply cNAT_post; trivial.
assert (z ∈ osucc o).
apply isOrd_trans with o; auto.
apply H2; trivial.
apply interSAT_elim with (x:=exist (fun o'=>o' ∈ osucc o) z H6) in H0.
simpl proj1_sig in H0.
specialize H3 with (1:=H4).
specialize prodSAT_elim with (1:=H0) (2:=H3); intro.
rewrite piNATi_ax in H7.
destruct H7 as (_,H7); apply H7.
assert (isOrd z).
apply isOrd_inv with y; trivial.
apply TI_intro with z; auto with *.
Qed.
isOrd o ->
inSAT m (interSAT (fun o':{o'|o' ∈ osucc o} => let o':=proj1_sig o' in
prodSAT (piNATi(fun n => prodSAT (cNAT n) (X o' n)) o')
(piNATi(fun n => prodSAT (cNAT n) (X (osucc o') n)) (osucc o')))) ->
sn (NATFIX m).
intros.
assert (empty ∈ osucc o).
apply isOrd_plump with o; auto with *.
red; intros.
apply empty_ax in H1; contradiction.
apply lt_osucc; trivial.
apply interSAT_elim with (x:=exist (fun o'=>o'∈ osucc o) empty H1) in H0.
simpl proj1_sig in H0.
unfold NATFIX.
assert (sn (Lc.Abs (Lc.App (Lc.lift 1 m) (G (Lc.Ref 0))))).
apply sn_abs.
assert (inSAT (G (Lc.Ref 0)) (piNATi(fun n => prodSAT (cNAT n) (X empty n)) empty)).
rewrite piNATi_ax.
split; intros.
apply sn_abs.
constructor; intros.
apply nf_norm in H2; try contradiction.
repeat constructor.
intros ? ?.
eapply G_sat with (A:=cNAT) (k:=n).
revert H2; apply NATi_NAT; auto with *.
apply cNAT_pre; trivial.
apply prodSAT_elim with (A:=snSAT).
2:apply sat_sn in H3; trivial.
apply prodSAT_elim with (A:=snSAT).
apply varSAT.
apply varSAT.
specialize prodSAT_elim with (1:=H0)(2:=H2); intro.
apply sat_sn in H3; trivial.
apply sn_subst with (Ref 0).
unfold Lc.subst; simpl.
rewrite simpl_subst; auto.
rewrite lift0; auto.
apply sn_abs.
apply prodSAT_elim with (A:=snSAT) (B:=snSAT).
2:simpl; auto with *.
apply prodSAT_elim with (A:=snSAT).
apply prodSAT_elim with (A:=snSAT).
apply prodSAT_elim with (A:=snSAT).
apply varSAT.
simpl; apply sn_lift; trivial.
apply sn_abs; apply sn_abs.
apply sn_lift; trivial.
simpl; apply sn_lift; trivial.
Qed.
Lemma NATFIX_sat : ∀ o m X,
isOrd o ->
(∀ y y' n, isOrd y -> isOrd y' -> y ⊆ y' -> y' ⊆ o -> n ∈ NATi y ->
inclSAT (X y n) (X y' n)) ->
inSAT m (interSAT (fun o':{o'|o' ∈ osucc o} => let o':=proj1_sig o' in
prodSAT (piNATi(fun n => prodSAT (cNAT n) (X o' n)) o')
(piNATi(fun n => prodSAT (cNAT n) (X (osucc o') n)) (osucc o')))) ->
inSAT (NATFIX m) (piNATi(fun n => prodSAT (cNAT n) (X o n)) o).
intros o m X H Xmono H0.
elim H using isOrd_ind; intros.
rewrite piNATi_ax.
split.
apply sn_natfix with (2:=H0); trivial.
intros x i.
assert (tyx : x ∈ NAT).
apply NATi_NAT with y; trivial.
apply TI_elim in i; auto with *.
destruct i as (z,?,?).
unfold NATFIX.
intros t tty.
apply cNAT_pre in tty.
apply G_sat with (2:=tty); trivial.
eapply inSAT_context; intros.
apply inSAT_exp.
left; simpl.
apply Bool.orb_true_r.
unfold Lc.subst; simpl Lc.subst_rec.
repeat rewrite Lc.simpl_subst; auto.
rewrite Lc.lift0.
change (inSAT (Lc.App m (NATFIX m)) S).
eexact H6.
apply Xmono with (osucc z); eauto using isOrd_inv.
red; intros.
apply isOrd_plump with z; trivial.
eauto using isOrd_inv.
apply olts_le; trivial.
unfold NATi; rewrite ZFfix.TI_mono_succ; auto with *.
eauto using isOrd_inv.
apply prodSAT_elim with (cNAT x).
2:apply cNAT_post; trivial.
assert (z ∈ osucc o).
apply isOrd_trans with o; auto.
apply H2; trivial.
apply interSAT_elim with (x:=exist (fun o'=>o' ∈ osucc o) z H6) in H0.
simpl proj1_sig in H0.
specialize H3 with (1:=H4).
specialize prodSAT_elim with (1:=H0) (2:=H3); intro.
rewrite piNATi_ax in H7.
destruct H7 as (_,H7); apply H7.
assert (isOrd z).
apply isOrd_inv with y; trivial.
apply TI_intro with z; auto with *.
Qed.