Recipes_neutralization.My_autosubst
Set Warnings "-notation-overridden, -notation-overriden".
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq zify.
From Coq Require Import ssrfun PeanoNat Lia Arith_base.
Set Warnings "notation-overridden, notation-overriden".
Require Import AutosubstSsr ARS My_tactics.
Require Import Recipes.
Section FPottierIdeas.
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq zify.
From Coq Require Import ssrfun PeanoNat Lia Arith_base.
Set Warnings "notation-overridden, notation-overriden".
Require Import AutosubstSsr ARS My_tactics.
Require Import Recipes.
Section FPottierIdeas.
The following way to manage free variables is taken from
Francois Pottier's personal extension of the autosubst library.
The predicate fv k t means that the free variables of the term t are
contained in the semi-open interval 0..k).
Definition fv (k: nat) (t: recipe) :=
forall σ, t.[upn k σ] = t.
Definition fv_t (k: nat) (t: term) :=
forall σ, t.[upn k σ] = t.
Definition fv_hsubst (k: nat) (t: recipe) :=
forall σ, t.|[upn k σ] = t.
Definition fv_old (k: nat) (t: recipe) :=
t.[upn k (ren (+1))] = t.
Definition fv_t_old (k: nat) (t: term) :=
t.[upn k (ren (+1))] = t.
Definition fv_hsubst_old (k: nat) (t: recipe) :=
t.|[upn k (ren (+1))] = t.
Lemma fv_to_fv_old k t :
fv k t -> fv_old k t.
Proof.
by apply.
Qed.
Lemma fvt_to_fvt_old k t :
fv_t k t -> fv_t_old k t.
Proof.
by apply.
Qed.
Lemma fv_hsubst_to_fv_hsubst_old k t :
fv_hsubst k t -> fv_hsubst_old k t.
Proof.
by apply.
Qed.
Lemma generalize_fv_subst_term (T: term) θ n :
T.[upn n (ren (+1))] = T
-> T.[upn n θ] = T.
Proof.
elim: T=>//=.
{ move=> x h.
case (boolP (x < n))=> [lt|ge].
by rewrite upnPh ifT.
have c: upn n (ren (+1)) x = TVar x.+1.
{ rewrite upnPh ifF=> /=.
by have->: (n + (x - n).+1)%coq_nat = x.+1 by lia.
by lia. }
rewrite h in c.
inversion c.
by lia. }
{ move=> S hS T hT h.
inversion h.
rewrite H1.
rewrite H0.
by rewrite (hS H0) (hT H1). }
Qed.
Lemma generalize_fv_hsubst (s: recipe) θ n :
s.|[upn n (ren (+1))] = s
-> s.|[upn n θ] = s.
Proof.
elim: s θ n=>//=.
{ move=> s hs t ht θ n h.
injection h=> h1 h2.
by rewrite (hs θ n h2) (ht θ n h1). }
{ move=> s hs t ht θ n h.
injection h=> h1 h2.
by rewrite (hs θ n h2) (ht θ n h1). }
{ move=> s hs S θ n h.
injection h=> h1 h2.
rewrite (hs θ n h2).
f_equal.
by apply generalize_fv_subst_term. }
{ move=> f t ht θ n h.
injection h=> h1.
by rewrite (ht θ n h1). }
{ move=> U t ht θ n h.
injection h=> h1.
by rewrite (ht θ n h1). }
{ move=> t ht θ n h.
injection h=> h1.
f_equal.
asimpl.
exact (ht θ n.+1 h1). }
{ move=> t ht θ n h.
injection h=> h1.
f_equal.
asimpl.
exact (ht θ n.+1 h1). }
Qed.
Lemma iterate_iterate {A} (f : A -> A) i j x :
iterate f i (iterate f j x) = iterate f (i + j) x.
Proof.
induction i; intros.
{ by rewrite iterate_0. }
{ have->: i.+1 + j = S (i + j) by lia.
by rewrite iterate_S IHi. }
Qed.
Lemma upn_upn:
forall i j σ,
upn i (upn j σ) = upn (i + j) σ.
Proof using .
eauto using iterate_iterate.
Qed.
Lemma upn_upn_t:
forall i j (σ: var -> term),
upn i (upn j σ) = upn (i + j) σ.
Proof using .
eauto using iterate_iterate.
Qed.
End FPottierIdeas.
Section MyLemmas.
Lemma fv_hsubst_upto_ge s n m :
n <= m ->
fv_hsubst n s ->
fv_hsubst m s.
Proof.
rewrite /fv_hsubst=> h1 h2 σ.
have[nn hnn]: exists nn, n + nn = m
by exists (m-n); lia.
rewrite -hnn.
(* Search upn. *)
rewrite -upn_upn_t.
by apply generalize_fv_hsubst.
Qed.
Lemma fv_hsubst_upto_ge_term (T : term) n m :
n <= m ->
fv_t n T ->
fv_t m T.
Proof.
rewrite /fv_t=> h1 h2 σ.
have[nn hnn]: exists nn, n + nn = m
by exists (m-n); lia.
rewrite -hnn.
rewrite -upn_upn_t.
by apply generalize_fv_subst_term.
Qed.
Lemma choose_last_n_subst (T: term) :
exists n, fv_t n T.
Proof.
elim: T.
{ move=> x. exists x.+1. rewrite /fv_t =>//= σ.
by rewrite upnPh ifT. }
{ exists 1. by rewrite /fv_t =>//=. }
{ move=> S [ns hs] T [nt ht].
rewrite /fv_t=>/= .
exists (max ns nt)=>σ.
f_equal.
apply fv_hsubst_upto_ge_term with ns=>//. by lia.
apply fv_hsubst_upto_ge_term with nt=>//. by lia. }
Qed.
Lemma choose_last_n_hsubst (s: recipe) :
exists n, fv_hsubst n s.
Proof.
elim: s.
{ by exists 1=>/=; rewrite /fv_hsubst; asimpl. }
{ by exists 1=>/=; rewrite /fv_hsubst; asimpl. }
{ rewrite /fv_hsubst=> s [ns h1] t [nt h2].
have ges: max ns nt >= ns by lia.
have get: max ns nt >= nt by lia.
exists (max ns nt)=>/= σ.
f_equal.
apply (fv_hsubst_upto_ge s ns (max ns nt) ges h1).
apply (fv_hsubst_upto_ge t nt (max ns nt) get h2). }
{ rewrite /fv_hsubst=> s [ns h1] t [nt h2].
have ges: max ns nt >= ns by lia.
have get: max ns nt >= nt by lia.
exists (max ns nt)=>/= σ.
f_equal.
apply (fv_hsubst_upto_ge s ns (max ns nt) ges h1).
apply (fv_hsubst_upto_ge t nt (max ns nt) get h2). }
{ rewrite /fv_hsubst=> s [ns h1] S /=.
destruct (choose_last_n_subst S) as [m h2].
exists (max ns m)=> σ.
have ges: max ns m >= ns by lia.
have gem: max ns m >= m by lia.
f_equal.
apply (fv_hsubst_upto_ge s ns (max ns m) ges h1).
apply (fv_hsubst_upto_ge_term S m (max ns m) gem h2). }
{ rewrite /fv_hsubst=> f s [ns h1] /=.
exists ns=>σ.
by rewrite h1. }
{ rewrite /fv_hsubst=> U s [ns h1] /=.
exists ns=>σ.
by rewrite h1. }
{ rewrite /fv_hsubst=> s [ns h1] /=.
exists (ns.-1)=>σ.
asimpl.
f_equal.
case: ns h1=>//= h.
by apply fv_hsubst_upto_ge with 0. }
{ rewrite /fv_hsubst=> s [ns h1] /=.
exists (ns.-1)=>σ.
asimpl.
f_equal.
case: ns h1=>//= h.
by apply fv_hsubst_upto_ge with 0. }
Qed.
Lemma free_above_n_t (T : term) (θ : var -> term) n :
fv_t n T ->
T.[fun i : nat => if i < n then θ i else TVar (i - n)] = T.[θ].
Proof.
elim: T θ=>//=.
{ move=> x θ h.
specialize (h (ren (+1))).
rewrite /= upnPh in h.
case (boolP (x < n))=>// h1.
rewrite ifF in h=>//=.
have: x = x.+1.
{ have e: (ren (+1) (x - n)).[ren (+n)] = TVar x.+1.
simpl.
have H: forall x, ids x = TVar x by autosubst.
rewrite H.
f_equal.
by lia.
rewrite e in h.
by injection h. }
by lia.
by lia. }
{ move=> S hS T hT θ h.
rewrite /fv_t/= in h.
(* specialize (h (ren (+1))). *)
(* injection h => h1 h2. *)
have h1: forall σ, S.[upn n σ] = S.
{ move=> σ.
specialize (h σ).
congruence. }
have h2: forall σ, T.[upn n σ] = T.
{ move=> σ.
specialize (h σ).
congruence. }
f_equal.
by rewrite (hS _ h1).
by rewrite (hT _ h2). }
Qed.
Lemma free_above_n_t_old (T : term) (θ : var -> term) n :
fv_t_old n T ->
T.[fun i : nat => if i < n then θ i else TVar (i - n)] = T.[θ].
Proof.
elim: T θ=>//=.
{ move=> x θ h.
rewrite /fv_t_old/= upnPh in h.
case (boolP (x < n))=>// h1.
rewrite ifF in h=>//=.
have: x = x.+1.
{ have e: (ren (+1) (x - n)).[ren (+n)] = TVar x.+1.
simpl.
have H: forall x, ids x = TVar x by autosubst.
rewrite H.
f_equal.
by lia.
rewrite e in h.
by injection h. }
by lia.
by lia. }
{ move=> S hS T hT θ h.
rewrite /fv_t/= in h.
injection h => h1 h2.
f_equal.
by rewrite (hS _ h2).
by rewrite (hT _ h1). }
Qed.
Lemma free_above_n (s : recipe) (θ : var -> term) n :
fv_hsubst n s ->
s.|[fun i : nat => if i < n then θ i else TVar (i - n)] = s.|[θ].
Proof.
move/fv_hsubst_to_fv_hsubst_old.
elim: s θ n=>//=.
{ move=> s hs t ht θ n h.
injection h=> h1 h2.
by rewrite (hs θ n h2) (ht θ n h1). }
{ move=> s hs t ht θ n h.
injection h=> h1 h2.
by rewrite (hs θ n h2) (ht θ n h1). }
{ move=> s hs S θ n h.
rewrite /fv_hsubst_old/= in h.
injection h=> h1 h2.
rewrite (hs θ n h2).
f_equal.
by apply free_above_n_t_old. }
{ move=> f s hs θ n h.
rewrite /fv_hsubst/= in h.
injection h=> h1.
by rewrite (hs θ n h1). }
{ move=> U s hs θ n h.
rewrite /fv_hsubst/= in h.
injection h=> h1.
by rewrite (hs θ n h1). }
{ move=> s hs θ n h.
rewrite /up=>/=.
have h2: fv_hsubst_old n.+1 s by injection h.
f_equal.
have->:
ids 0 .: (fun i : nat => if i < n then θ i else TVar (i - n)) >>> rename (+1)
= (fun i : nat => if i < n.+1 then up θ i else TVar (i - n)).
{ unfold ".:".
f_ext.
case=>//= x.
have->: x.+1 < n.+1 = (x < n) by lia.
case (boolP (x < n))=> [lt|ge]//=.
f_equal.
by lia. }
rewrite -(hs (up θ) n.+1 h2).
set θθ := fun i : nat => if i < n.+1 then up θ i else TVar (i - n).
specialize (hs θθ n.+1 h2).
rewrite -hs.
f_equal.
f_ext=>x.
case (boolP (x < n.+1))=>//= cmp.
rewrite /θθ ifT=>//. }
{ move=> s hs θ n h.
rewrite /up=>/=.
have h2: fv_hsubst_old n.+1 s by injection h.
f_equal.
have->:
ids 0 .: (fun i : nat => if i < n then θ i else TVar (i - n)) >>> rename (+1)
= (fun i : nat => if i < n.+1 then up θ i else TVar (i - n)).
{ unfold ".:".
f_ext.
case=>//= x.
have->: x.+1 < n.+1 = (x < n) by lia.
case (boolP (x < n))=> [lt|ge]//=.
f_equal.
by lia. }
rewrite -(hs (up θ) n.+1 h2).
set θθ := fun i : nat => if i < n.+1 then up θ i else TVar (i - n).
specialize (hs θθ n.+1 h2).
rewrite -hs.
f_equal.
f_ext=>x.
case (boolP (x < n.+1))=>//= cmp.
rewrite /θθ ifT=>//. }
Qed.
Definition closed := fv 0.
(* Lemma closed_subst_n s n :
fv n s -> forall σ, s = s.upn n σ.
Proof.
elim: s n=>//=.
{ rewrite/closed/fv.
asimpl=> h |n contra.
+ have e: upn 0 (ren (+1)) h = Var h.+1 by autosubst.
rewrite e in contra.
injection contra => hhh.
by lia.
+ rewrite upnP in contra.
case (boolP (h < n.+1))=> lt|ge σ.
* by rewrite upnP ifT.
* have ltb: (h < n.+1) = false by lia.
rewrite upnP ifF=>//.
rewrite ifF in contra=>//.
have e: (ren (+1) (h - n.+1)) = Var (h - n.+1).+1 by autosubst.
rewrite e in contra.
have {}e: Var (h - n.+1).+1 = Var (h - n) by f_equal; lia.
rewrite e in contra.
simpl in contra.
have {}e: ids (n + (h - n))coq_nat.+1 by autosubst.
rewrite e in contra.
have {}e: Var (n + (h - n))*)
(* rewrite e. *)
rewrite -{1}h2.
f_equal.
f_ext=>x.
f_equal. admit. }
(* by apply hs. } *)
admit.
Admitted. *)
Lemma closed_subst s :
closed s -> forall σ, s = s.[σ].
Proof.
move=> h σ.
by rewrite (h σ).
Qed.
End MyLemmas.