Theory BetaNorm
section "Beta Normalization"
theory BetaNorm
imports Term
begin
inductive beta :: "term ⇒ term ⇒ bool" (infixl ‹→⇩β› 50)
where
beta [simp, intro!]: "Abs T s $ t →⇩β subst_bv2 s 0 t"
| appL [simp, intro!]: "s →⇩β t ⟹ s $ u →⇩β t $ u"
| appR [simp, intro!]: "s →⇩β t ⟹ u $ s →⇩β u $ t"
| abs [simp, intro!]: "s →⇩β t ⟹ Abs T s →⇩β Abs T t"
abbreviation
beta_reds :: "term ⇒ term ⇒ bool" (infixl ‹→⇩β⇧*› 50) where
"s →⇩β⇧* t == beta⇧*⇧* s t"
inductive_cases beta_cases [elim!]:
"Bv i →⇩β t"
"Fv idn S →⇩β t"
"Abs T r →⇩β s"
"s $ t →⇩β u"
declare if_not_P [simp] not_less_eq [simp]
lemma rtrancl_beta_Abs [intro!]:
"s →⇩β⇧* s' ⟹ Abs T s →⇩β⇧* Abs T s'"
by (induct set: rtranclp) (blast intro: rtranclp.rtrancl_into_rtrancl)+
lemma rtrancl_beta_AppL:
"s →⇩β⇧* s' ⟹ s $ t →⇩β⇧* s' $ t"
by (induct set: rtranclp) (blast intro: rtranclp.rtrancl_into_rtrancl)+
lemma rtrancl_beta_AppR:
"t →⇩β⇧* t' ⟹ s $ t →⇩β⇧* s $ t'"
by (induct set: rtranclp) (blast intro: rtranclp.rtrancl_into_rtrancl)+
lemma rtrancl_beta_App [intro]:
"s →⇩β⇧* s' ⟹ t →⇩β⇧* t' ⟹ s $ t →⇩β⇧* s' $ t'"
by (blast intro!: rtrancl_beta_AppL rtrancl_beta_AppR intro: rtranclp_trans)
theorem subst_bv2_preserves_beta [simp]:
"r →⇩β s ⟹ subst_bv2 r k u →⇩β subst_bv2 s k u"
by (induct arbitrary: k u set: beta) (simp_all add: subst_bv2_subst_bv2[symmetric])
theorem subst_bv2_preserves_beta': "r →⇩β⇧* s ⟹ subst_bv2 r i t →⇩β⇧* subst_bv2 s i t"
apply (induct set: rtranclp)
apply (rule rtranclp.rtrancl_refl)
apply (erule rtranclp.rtrancl_into_rtrancl)
apply (erule subst_bv2_preserves_beta)
done
theorem lift_preserves_beta [simp]:
"r →⇩β s ⟹ lift r i →⇩β lift s i"
proof (induction arbitrary: i set: beta)
case (beta T s t)
then show ?case
using lift_subst by force
qed auto
theorem lift_preserves_beta': "r →⇩β⇧* s ⟹ lift r i →⇩β⇧* lift s i"
apply (induct set: rtranclp)
apply (rule rtranclp.rtrancl_refl)
apply (erule rtranclp.rtrancl_into_rtrancl)
apply (erule lift_preserves_beta)
done
theorem subst_bv2_preserves_beta2 [simp]: "r →⇩β s ⟹ subst_bv2 t i r →⇩β⇧* subst_bv2 t i s"
apply (induct t arbitrary: r s i)
apply (solves ‹simp add: r_into_rtranclp›)+
using lift_preserves_beta by (auto simp add: rtrancl_beta_App)
theorem subst_bv2_preserves_beta2': "r →⇩β⇧* s ⟹ subst_bv2 t i r →⇩β⇧* subst_bv2 t i s"
apply (induct set: rtranclp)
apply (auto elim: rtranclp_trans subst_bv2_preserves_beta2)
done
lemma beta_preserves_typ_of1: "typ_of1 Ts r = Some T ⟹ r →⇩β s ⟹ typ_of1 Ts s = Some T"
proof (induction Ts r arbitrary: s T rule: typ_of1.induct)
case (4 Ts T body)
then show ?case
by (smt beta_cases(3) typ_of1.simps(4) typ_of_Abs_body_typ')
next
case (5 Ts f u)
from this obtain argT where argT: "typ_of1 Ts u = Some argT" and "typ_of1 Ts f = Some (argT → T)"
by (meson typ_of1_split_App_obtains)
from 5 show ?case apply -
apply (ind_cases "f $ u →⇩β s" for f u s)
using ‹typ_of1 Ts f = Some (argT → T)› argT typ_of1_subst_bv_gen'
typ_of_Abs_body_typ' by (fastforce simp add: substn_subst_n)+
qed (use beta.cases in ‹blast+›)
lemma beta_preserves_typ_of: "typ_of r = Some T ⟹ r →⇩β s ⟹ typ_of s = Some T"
by (metis beta_preserves_typ_of1 typ_of_def)
lemma beta_star_preserves_typ_of1: "r →⇩β⇧* s ⟹ typ_of1 Ts r = Some T ⟹ typ_of1 Ts s = Some T"
proof (induction rule: rtranclp.induct)
case (rtrancl_refl a)
then show ?case
by simp
next
case (rtrancl_into_rtrancl a b c)
then show ?case
using beta_preserves_typ_of1 by blast
qed
lemma beta_reducible_imp_beta_step: "beta_reducible t ⟹ ∃t'. t →⇩β t'"
proof (induction t)
case (App t1 t2)
then show ?case using App by (cases t1) auto
qed auto
lemma beta_step_imp_beta_reducible: "t →⇩β t' ⟹ beta_reducible t"
proof (induction t t' rule: beta.induct)
case (beta T s t)
then show ?case by simp
next
case (appL s t u)
then show ?case by (cases s) auto
next
case (appR s t u)
then show ?case using beta_reducible.elims by blast
next
case (abs s t T)
then show ?case by simp
qed
lemma beta_norm_imp_beta_reds: assumes "beta_norm t = Some t'" shows "t →⇩β⇧* t'"
using assms proof (induction arbitrary: t t' rule: beta_norm.fixp_induct)
case 1
then show ?case
by (smt Option.is_none_def ccpo.admissibleI chain_fun flat_lub_def flat_ord_def fun_lub_def
insertCI is_none_code(2) mem_Collect_eq option.lub_upper subsetI)
next
case 2
then show ?case
by simp
next
case (3 comp)
then show ?case
proof(cases t)
next
case (App f u)
note fu = App
then show ?thesis
proof (cases "comp f")
case None
show ?thesis
proof(cases f)
case (Abs B b)
then show ?thesis
by (metis (mono_tags, lifting) "3.IH" "3.prems" Core.subst_bv_def Core.term.simps(29)
Core.term.simps(30) beta fu rtranclp.rtrancl_into_rtrancl rtranclp.rtrancl_refl rtranclp_trans)
qed (use 3 None in ‹simp_all add: fu split: term.splits option.splits if_splits›)
next
case (Some fo)
then show ?thesis
proof(cases fo)
case (Ct n T)
then show ?thesis
proof(cases f)
case (Abs B b)
then show ?thesis
by (metis (no_types, lifting) "3.IH" "3.prems" Core.subst_bv_def Core.term.simps(29)
Core.term.simps(30) beta converse_rtranclp_into_rtranclp fu)
qed (use 3 Some in ‹auto simp add: fu split: term.splits option.splits if_split›)
next
case (Fv n T)
then show ?thesis
proof(cases f)
case (Abs B b)
then show ?thesis
by (metis (no_types, lifting) "3.IH" "3.prems" Core.subst_bv_def Core.term.simps(29)
Core.term.simps(30) beta converse_rtranclp_into_rtranclp fu)
qed (use 3 Some in ‹auto simp add: fu split: term.splits option.splits if_split›)
next
case (Bv n)
then show ?thesis
proof(cases f)
case (Abs B b)
then show ?thesis
by (metis (no_types, lifting) "3.IH" "3.prems" Core.subst_bv_def Core.term.simps(29)
Core.term.simps(30) beta converse_rtranclp_into_rtranclp fu)
qed (use 3 Some in ‹auto simp add: fu split: term.splits option.splits if_split›)
next
case (Abs T t)
then show ?thesis
proof(cases f)
case (Ct n C)
show ?thesis
by (metis "3.IH" Abs Core.term.simps(11) Ct Some beta_reducible.simps(7)
beta_step_imp_beta_reducible converse_rtranclpE)
next
case (Fv n C)
then show ?thesis
by (metis "3.IH" Abs Fv Some beta_reducible.simps(1,4,8) beta_step_imp_beta_reducible
converse_rtranclpE)
next
case (Bv n)
then show ?thesis
by (metis "3.IH" Abs Some beta_cases(1) converse_rtranclpE term.distinct(15))
next
case (Abs B b)
then show ?thesis
by (metis (no_types, lifting) "3.IH" "3.prems" Core.subst_bv_def Core.term.simps(29)
Core.term.simps(30) beta converse_rtranclp_into_rtranclp fu)
next
case (App a b)
then show ?thesis
using 3 apply (simp add: fu Some split: term.splits option.splits if_splits; fast?)
by (metis Core.subst_bv_def beta converse_rtranclp_into_rtranclp rtrancl_beta_AppL rtranclp_trans)
qed
next
case AppO: (App f u)
then show ?thesis
proof(cases f)
case (Ct n C)
show ?thesis
using 3 Some apply (simp add: Ct AppO fu split: term.splits option.splits if_split; fast?)
by (metis Core.subst_bv_def beta converse_rtranclp_into_rtranclp)
next
case (Fv n C)
then show ?thesis
using 3 Some apply (simp add: Fv AppO fu split: term.splits option.splits if_split; fast?)
by (metis Core.subst_bv_def beta converse_rtranclp_into_rtranclp)
next
case (Bv n)
then show ?thesis
using 3 Some apply (simp add: Bv AppO fu split: term.splits option.splits if_split; fast?)
by (metis Core.subst_bv_def beta converse_rtranclp_into_rtranclp)
next
case (Abs B b)
then show ?thesis
using 3 Some apply (simp add: Abs AppO fu split: term.splits option.splits if_split; fast?)
by (metis Core.subst_bv_def beta converse_rtranclp_into_rtranclp)
next
case (App a b)
then show ?thesis
using 3 Some apply (simp add: App AppO fu split: term.splits option.splits if_split; fast?)
by (metis Core.subst_bv_def beta converse_rtranclp_into_rtranclp)
qed
qed
qed
qed auto
qed
corollary "beta_norm t = Some t' ⟹ typ_of1 Ts t = Some T ⟹ typ_of1 Ts t' = Some T"
using beta_norm_imp_beta_reds beta_star_preserves_typ_of1 by blast
lemma beta_imp_beta_norm: assumes "t →⇩β t'" "¬ beta_reducible t'" shows "beta_norm t = Some t'"
using assms proof (induction rule: beta.induct)
case (beta T s t)
then show ?case using not_beta_reducible_imp_beta_norm_unchanged by (auto simp add: subst_bv_def substn_subst_n)
next
case (appL s t u)
hence t: "¬ beta_reducible t" by (fastforce elim: beta_reducible.elims)
hence IH: "beta_norm s = Some t" using appL.IH by simp
from appL have u: "¬ beta_reducible u"
using beta_reducible.elims by blast
show ?case
apply (cases s; cases t)
using not_beta_reducible_imp_beta_norm_unchanged IH t u appL.prems by auto
next
case (appR s t u)
hence t: "¬ beta_reducible t"
using beta_reducible.elims by blast
hence IH: "beta_norm s = Some t" using appR.IH by simp
from appR have u: "¬ beta_reducible u"
using beta_reducible.elims by blast
show ?case
apply (cases s; cases u)
using not_beta_reducible_imp_beta_norm_unchanged IH t u appR.prems by auto
next
case (abs s t T)
then show ?case by auto
qed
lemma beta_subst_bv1: "s →⇩β t ⟹ subst_bv1 s lev x →⇩β subst_bv1 t lev x"
proof (induction s t arbitrary: lev rule: beta.induct)
case (beta T s t)
then show ?case
using beta.beta subst_bv2_preserves_beta substn_subst_n by presburger
qed (auto simp add: subst_bv_def)
lemma beta_subst_bv: "s →⇩β t ⟹ subst_bv x s →⇩β subst_bv x t"
by (simp add: substn_subst_0')
lemma subst_bv1_beta:
"subst_bv1 s (length (T#Ts)) x →⇩β subst_bv1 t (length (T#Ts)) x
⟹ typ_of1 Ts s = Some ty
⟹ typ_of1 Ts t = Some ty
⟹ s →⇩β t"
proof (induction "subst_bv1 s (length (T#Ts)) x" "subst_bv1 t (length (T#Ts)) x"
arbitrary: s t T T Ts ty rule: beta.induct)
case (beta T s t)
then show ?case
by (metis beta.simps length_Cons loose_bvar_Suc no_loose_bvar_imp_no_subst_bv1 typ_of1_imp_no_loose_bvar)
next
case (appL s t u)
then show ?case
by (metis beta.appL length_Cons loose_bvar_Suc no_loose_bvar_imp_no_subst_bv1 typ_of1_imp_no_loose_bvar)
next
case (appR s t u)
then show ?case
by (metis beta.simps length_Cons loose_bvar_Suc no_loose_bvar_imp_no_subst_bv1 typ_of1_imp_no_loose_bvar)
next
case (abs s t bT sa ta T Ts rT )
obtain s' where "Abs bT s' = sa"
using abs.hyps(3) abs.prems loose_bvar_Suc no_loose_bvar_imp_no_subst_bv1 typ_of1_imp_no_loose_bvar
by (metis length_Cons)
moreover obtain t' where "Abs bT t' = ta"
using abs.hyps(4) abs.prems loose_bvar_Suc no_loose_bvar_imp_no_subst_bv1 typ_of1_imp_no_loose_bvar
by (metis length_Cons)
ultimately have "s' →⇩β t'"
by (metis abs.hyps(1) abs.hyps(3) abs.hyps(4) abs.prems(1) abs.prems(2) length_Cons
loose_bvar_Suc no_loose_bvar_imp_no_subst_bv1 term.inject(4) typ_of1_imp_no_loose_bvar)
then show ?case
using ‹Abs bT s' = sa› ‹Abs bT t' = ta› by blast
qed
fun subst_bvs1' :: "term ⇒ nat ⇒ term list ⇒ term" where
"subst_bvs1' (Bv i) lev args = (if i < lev then Bv i
else if i - lev < length args then (nth args (i-lev))
else Bv (i - length args))"
| "subst_bvs1' (Abs T body) lev args = Abs T (subst_bvs1' body (lev + 1) (map (λt. lift t 0) args))"
| "subst_bvs1' (f $ t) lev u = subst_bvs1' f lev u $ subst_bvs1' t lev u"
| "subst_bvs1' t _ _ = t"
lemma subst_bvs1'_empty [simp]: "subst_bvs1' t lev [] = t"
by (induction t lev "[]::term list" rule: subst_bvs1.induct)auto
lemma subst_bvs1'_eq [simp]: "args ≠ [] ⟹ subst_bvs1' (Bv k) k args = args ! 0"
by simp
lemma subst_bvs1'_eq' [simp]: "i < length args ⟹ subst_bvs1' (Bv (k+i)) k args = args ! i"
by auto
lemma subst_bvs1'_gt [simp]:
"i + length args < j ⟹ subst_bvs1' (Bv j) i args = Bv (j - length args)"
by auto
lemma subst_bv2_lt [simp]: "j < i ⟹ subst_bvs1' (Bv j) i u = Bv j"
by simp
lemma subst_bvs1'_App[simp]: "subst_bvs1' (s$t) k args
= subst_bvs1' s k args $ subst_bvs1' t k args"
by simp
lemma incr_bv_incr_bv:
"i < k + 1 ⟹ incr_bv inc2 (k+inc1) (incr_bv inc1 i t) = incr_bv inc1 i (incr_bv inc2 k t)"
proof (induction t arbitrary: i k)
case (Abs T t)
then show ?case
by (metis Suc_eq_plus1 add_Suc add_mono1 incr_bv.simps(2))
qed auto
lemma subst_bvs1_subst_bvs1': "subst_bvs1 t n s = subst_bvs1' t n (map (incr_bv n 0) s)"
proof (induction t arbitrary: n)
case (Abs T t)
then show ?case
by (simp add: incr_boundvars_def incr_bv_combine)
(metis One_nat_def comp_apply incr_bv_combine plus_1_eq_Suc)
qed (auto simp add: incr_boundvars_def incr_bv_combine)
theorem subst_bvs1_subst_bvs1'_0: "subst_bvs1 t 0 s = subst_bvs1' t 0 s"
proof-
have "subst_bvs1 t 0 s = subst_bvs1' t 0 (map (incr_bv 0 0) s)"
using subst_bvs1_subst_bvs1' by blast
moreover have "map (incr_bv 0 0) s = s"
by (induction s) auto
ultimately show ?thesis
by simp
qed
corollary subst_bvs_subst_bvs1': "subst_bvs s t = subst_bvs1' t 0 s"
using subst_bvs_def subst_bvs1_subst_bvs1'_0 by simp
lemma no_loose_bvar_subst_bvs1'_unchanged: "¬ loose_bvar t lev ⟹ subst_bvs1' t lev args = t"
by (induction t lev args rule: subst_bvs1'.induct) auto
lemma subst_bvs1'_step: "∀x ∈ set (a#args) . is_closed x ⟹
subst_bvs1' t lev (a#args) = subst_bvs1' (subst_bv2 t lev a) lev args"
proof (induction t lev args rule: subst_bvs1'.induct)
case (1 i lev args)
then show ?case
using no_loose_bvar_subst_bvs1'_unchanged
by (simp add: is_open_def)
(metis Suc_diff_Suc le_add1 le_add_same_cancel1 less_antisym loose_bvar_leq not_less_eq)
qed (auto simp add: is_open_def)
lemma not_loose_bvar_incr_bv: "¬ loose_bvar a lev ⟹ ¬ loose_bvar (incr_bv inc lev a) (lev+inc)"
by (induction a lev rule: loose_bvar.induct) auto
lemma not_loose_bvar_incr_bv_less:
"i < j ⟹ ¬ loose_bvar (incr_bv inc i a) (lev+inc) ⟹ ¬ loose_bvar (incr_bv inc j a) (lev+inc)"
proof (induction inc i a arbitrary: lev j rule: incr_bv.induct)
case (2 inc n T body)
then show ?case
by (metis Suc_eq_plus1 add_Suc add_mono1 incr_bv.simps(2) loose_bvar.simps(3))
qed (auto split: if_splits)
lemma subst_bvs1'_step_work: "∀x ∈ set args . is_closed x ⟹ ¬ loose_bvar (subst_bv2 t lev a) lev ⟹
subst_bvs1' t lev (a#args) = subst_bvs1' (subst_bv2 t lev a) lev args"
proof (induction t "lev" "args" arbitrary: a rule: subst_bvs1'.induct)
case (1 i )
then show ?case using no_loose_bvar_subst_bvs1'_unchanged
by (auto simp add: is_open_def)
next
case (2 T body lev args)
then show ?case using no_loose_bvar_subst_bvs1'_unchanged
by (auto simp add: is_open_def)
next
case (3 f t lev u)
then show ?case using no_loose_bvar_subst_bvs1'_unchanged
by (auto simp add: is_open_def)
next
case ("4_1" v va uu uv)
then show ?case using no_loose_bvar_subst_bvs1'_unchanged
by (auto simp add: is_open_def)
next
case ("4_2" v va uu uv)
then show ?case using no_loose_bvar_subst_bvs1'_unchanged
by (auto simp add: is_open_def)
qed
lemma is_closed_subst_bv2_unchanged: "is_closed t ⟹ subst_bv2 t n u = t"
by (metis is_open_def lift_def loose_bvar_Suc no_loose_bvar_no_incr subst_bv2_lift zero_induct)
lemma subst_bvs1'_step_extend_lower_level: "∀x ∈ set (a#args) . is_closed x ⟹
subst_bv2 (subst_bvs1' t (Suc lev) args) lev a
= subst_bvs1' t lev (a#args)"
proof (induction t lev "a#args" arbitrary: a args rule: subst_bvs1'.induct)
case (1 i lev)
have "subst_bv2 (subst_bvs1' (Bv i) (Suc lev) args) lev a =
subst_bvs1' (Bv i) lev (a # args)"
if "i < Suc lev"
using that by auto
moreover have "subst_bv2 (subst_bvs1' (Bv i) (Suc lev) args) lev a =
subst_bvs1' (Bv i) lev (a # args)"
if "i - Suc lev < length args" "¬ i < Suc lev"
proof-
have "subst_bv2 (subst_bvs1' (Bv i) (Suc lev) args) lev a = subst_bv2 (args ! (i - Suc lev)) lev a"
using that by simp
also have "… = args ! (i - Suc lev)"
using 1 that(1) by (auto simp add: is_closed_subst_bv2_unchanged)
also have "subst_bvs1' (Bv i) lev (a # args) = args ! (i - Suc lev)"
using that by auto
finally show ?thesis
by simp
qed
moreover have "subst_bv2(subst_bvs1' (Bv i) (Suc lev) args) lev a =
subst_bvs1' (Bv i) lev (a # args)"
if "i ≥ Suc lev" "i - lev ≥ length args" "¬ i < Suc lev"
using that 1 by (auto simp add: is_closed_subst_bv2_unchanged)
ultimately show ?case by (auto simp add: is_open_def split: if_splits)
qed (auto simp add: is_open_def)
corollary subst_bvs_extend_lower_level:
"∀x ∈ set (a#args) . is_closed x ⟹
subst_bv a (subst_bvs1' t 1 args) = subst_bvs (a#args) t"
using subst_bvs1'_step_extend_lower_level
by (simp add: subst_bvs_subst_bvs1' substn_subst_0')
lemma subst_bvs1'_preserves_beta:
"∀x ∈ set u . is_closed x ⟹ r →⇩β s ⟹ subst_bvs1' r k u →⇩β subst_bvs1' s k u"
proof (induction u arbitrary: r s )
case Nil
then show ?case by auto
next
case (Cons a u)
hence "subst_bv2 r k a →⇩β subst_bv2 s k a"
by simp
hence "subst_bvs1' (subst_bv2 r k a) k u →⇩β subst_bvs1' (subst_bv2 s k a) k u"
using Cons by simp
then show ?case
by (simp add: subst_bvs1'_step[symmetric] Cons.prems(1))
qed
lemma subst_bvs1'_fold: "∀x ∈ set args . is_closed x ⟹
subst_bvs1' t lev args = fold (λarg t . subst_bv2 t lev arg) args t"
by (induction args arbitrary: t) (simp_all add: subst_bvs1'_step)
lemma subst_bvs1'_Abs[simp]: "∀x ∈ set args . is_closed x ⟹
subst_bvs1' (Abs T t) lev args = Abs T (subst_bvs1' t (Suc lev) args)"
by (simp add: is_open_def map_idI)
lemma subst_bvs_Abs[simp]: "∀x ∈ set args . is_closed x ⟹
subst_bvs args (Abs T t) = Abs T (subst_bvs1' t 1 args)"
using subst_bvs1'_Abs subst_bvs_subst_bvs1' by auto
lemma subst_bvs1'_incr_bv [simp]:
"subst_bvs1' (incr_bv (length ss) k t) k ss = t"
proof (induct t arbitrary: k ss)
case (Abs T t)
then show ?case
by simp (metis length_map)
qed auto
lemma lift_subst_bvs1' [simp]:
"j < i + 1 ⟹ lift (subst_bvs1' t j ss) i
= subst_bvs1' (lift t (i + length ss)) j (map (λs . lift s i) ss)"
proof (induct t arbitrary: i j ss)
case (Abs T t)
hence I: "lift (subst_bvs1' t (Suc j) (map (λt. lift t 0) ss)) (Suc i) =
subst_bvs1' (lift t (Suc i + length (map (λt. lift t 0) ss))) (Suc j) (map (λa. lift a (Suc i)) (map (λt. lift t 0) ss))"
by auto
have "lift (subst_bvs1' (Abs T t) j ss) i
= Abs T (lift (subst_bvs1' t (Suc j) (map (λt. lift t 0) ss)) (Suc i))"
by simp
also have "… = Abs T
(subst_bvs1' (lift t (Suc i + length (map (incr_bv 1 0) ss))) (Suc j)
(map (incr_bv 1 (Suc i)) (map (incr_bv 1 0) ss)))"
using I by auto
also have "… = Abs T
(subst_bvs1' (lift t (Suc i + length (map (incr_bv 1 0) ss))) (Suc j)
(map (λt. lift t 0) (map (λt. lift t i) ss)))"
proof-
have "map (λt . lift t (Suc i)) (map (λt. lift t 0) ss) = map (λt. lift t 0) (map (λt. lift t i) ss)"
using lift_lift by auto
thus ?thesis unfolding lift_def
by argo
qed
also have "… = subst_bvs1' (Abs T (lift t (Suc i + length (map (incr_bv 1 0) ss)))) j
(map (λt. lift t i) ss)"
by auto
finally show ?case
by simp
qed (auto simp add: diff_Suc lift_lift split: nat.split)
lemma lift_subst_bvs1'_lt:
"i < j + 1 ⟹ lift (subst_bvs1' t j ss) i
= subst_bvs1' (lift t i) (j + 1) (map (λs . lift s i) ss)"
proof (induct t arbitrary: i j ss)
case (Abs T t)
then show ?case using lift_lift
by simp (smt comp_apply map_eq_conv zero_less_Suc)
qed auto
lemma subst_bvs1'_subst_bv2:
"i < j + 1 ⟹
subst_bv2(subst_bvs1' t (Suc j) (map (λv. lift v i) vs)) i (subst_bvs1' u j vs)
= subst_bvs1' (subst_bv2 t i u) j vs"
proof(induction t arbitrary: i j u vs)
case (Abs T t)
then show ?case
by simp (smt One_nat_def Suc_eq_plus1 Suc_less_eq comp_apply lift_lift lift_def
lift_subst_bvs1'_lt map_eq_conv map_map zero_less_Suc)
qed (use subst_bv2_lift in auto)
lemma fv_subst_bv2_upper_bound: "fv (subst_bv2 t lev u) ⊆ fv t ∪ fv u"
by (induction t lev u rule: subst_bv2.induct) auto
lemma beta_fv: "s →⇩β t ⟹ fv t ⊆ fv s"
by (induction rule: beta.induct) (use fv_subst_bv2_upper_bound in auto)
lemma loose_bvar1_subst_bvs1'_closeds: "¬ loose_bvar1 t lev ⟹ lev < k ⟹ ∀x∈set us . is_closed x
⟹ ¬ loose_bvar1 (subst_bvs1' t k us) lev"
by (induction t k us arbitrary: lev rule: subst_bvs1'.induct)
(use is_open_def loose_bvar_iff_exist_loose_bvar1 in ‹auto simp add: is_open_def›)
lemma is_closed_subst_bvs1'_closeds: "¬ is_dependent t ⟹ ∀x∈set us . is_closed x
⟹ ¬ is_dependent (subst_bvs1' t (Suc k) us)"
by (simp add: is_dependent_def loose_bvar1_subst_bvs1'_closeds)
end