Theory FRBCE_Rensets
section ‹Renset-based Recursion›
theory FRBCE_Rensets
imports Rensets
begin
text ‹In this theory we prove that lambda-terms (modulo alpha) form
the initial renset. This gives rise to a recursion principle, which we
further enhance with support for the Barendregt variable convention
(similarly to the nominal recursion). ›
section ‹Full-fledged, Barendregt-constrctor-enriched recursion›
locale FR_BCE_Renset = Renset vsubstA
for vsubstA :: "'A ⇒ var ⇒ var ⇒ 'A"
+
fixes
X :: "var set"
and VrA :: "var ⇒ 'A"
and ApA :: "trm ⇒ 'A ⇒ trm ⇒ 'A ⇒ 'A"
and LmA :: "var ⇒ trm ⇒ 'A ⇒ 'A"
assumes
finite_X[simp,intro!]: "finite X"
and
vsubstA_VrA: "⋀ x y z. {y,z} ∩ X = {} ⟹
vsubstA (VrA x) y z = (if x = z then VrA y else VrA x)"
and
vsubstA_ApA: "⋀ y z t1 a1 t2 a2. {y,z} ∩ X = {} ⟹
vsubstA (ApA t1 a1 t2 a2) y z =
ApA (vsubst t1 y z) (vsubstA a1 y z)
(vsubst t2 y z) (vsubstA a2 y z)"
and
vsubstA_LmA: "⋀ t a z x y. {x,y,z} ∩ X = {} ⟹
x ≠ y ⟹
vsubstA (LmA x t a) y z =
(if x = z then LmA x t a else LmA x (vsubst t y z) (vsubstA a y z))"
and
LmA_rename: "⋀ x y z t a. {x,y,z} ∩ X = {} ⟹
z ≠ y ⟹
LmA x (vsubst t z y) (vsubstA a z y) =
LmA y (vsubst (vsubst t z y) y x) (vsubstA (vsubstA a z y) y x)"
begin
lemma LmA_cong:
"{u,z,x,x'} ∩ X = {} ⟹
z ≠ u ⟹
z ≠ x ⟹ z ≠ x' ⟹
vsubst (vsubst t u z) z x = vsubst (vsubst t' u z) z x' ⟹
vsubstA (vsubstA a u z) z x = vsubstA (vsubstA a' u z) z x'
⟹ LmA x (vsubst t u z) (vsubstA a u z) =
LmA x' (vsubst t' u z) (vsubstA a' u z)"
using LmA_rename using Int_commute disjoint_insert(2) by metis
lemma vsubstA_LmA_same:
"{x,y} ∩ X = {} ⟹ vsubstA (LmA x t a) y x = LmA x t a"
by (metis insert_disjoint(1) vsubstA_LmA vsubstA_id)
lemma vsubstA_LmA_diff:
"{x,y,z} ∩ X = {} ⟹
x ≠ y ⟹ x ≠ z ⟹ vsubstA (LmA x t a) y z = LmA x (vsubst t y z) (vsubstA a y z)"
using vsubstA_LmA by meson
lemma freshA_2_vsubstA:
assumes "freshA z a" "freshA z a'"
shows "∃u. u ∉ X ∧ u ≠ z ∧ vsubstA a u z = a ∧ vsubstA a' u z = a'"
using assms unfolding freshA_def
by (metis assms exists_var finite.insertI finite_X insertCI freshA_vsubstA_idle)
lemma LmA_cong_freshA:
assumes "{z,x,x'} ∩ X = {}"
and "z ≠ x" "fresh z t" "freshA z a"
and "z ≠ x'" "fresh z t'" "freshA z a'"
and "vsubst t z x = vsubst t' z x'"
and "vsubstA a z x = vsubstA a' z x'"
shows "LmA x t a = LmA x' t' a'"
proof-
obtain u where 1: "u ∉ X ∪ {z}"
by (metis Un_insert_right boolean_algebra_cancel.sup0 exists_var finite_X finite_insert)
hence 0: "t = vsubst t u z" "a = vsubstA a u z"
"t' = vsubst t' u z" "a' = vsubstA a' u z"
using assms freshA_iff_all_vvsubstA_idle by auto
show ?thesis apply(subst 0(1), subst 0(2), subst 0(3), subst 0(4))
apply(rule LmA_cong) using assms 1 0 by auto
qed
lemma freshA_VrA: "z ∉ X ⟹ z ≠ x ⟹ freshA z (VrA x)"
using freshA_def vsubstA_VrA
by (metis Int_commute Int_insert_right_if0
freshA_iff_ex_vvsubstA_idle exists_fresh_set finite_X inf_bot_right insertI1 list.set(2))
lemma freshA_ApA: "z ∉ X ⟹
fresh z t1 ⟹ freshA z a1 ⟹
fresh z t2 ⟹ freshA z a2 ⟹
freshA z (ApA t1 a1 t2 a2)"
using freshA_2_vsubstA[of z a1 a2] freshA_vsubstA2 vsubstA_ApA
by (metis Diff_disjoint Diff_insert_absorb Int_insert_left_if0 fresh_subst_id)
lemma freshA_LmA_same:
assumes "x ∉ X"
shows "freshA x (LmA x t a)"
proof-
have "{y. vsubstA (LmA x t a) y x ≠ LmA x t a} ⊆ X"
using assms vsubstA_LmA_same[of x _ t a] by blast
thus ?thesis unfolding freshA_def finite_X
by (meson finite_X rev_finite_subset)
qed
lemma freshA_LmA':
assumes "{x,z} ∩ X = {}" "fresh z t" "freshA z a"
shows "freshA z (LmA x t a)"
proof(cases "x = z")
case True
thus ?thesis
using assms(1) freshA_LmA_same by auto
next
case False
hence "{y. vsubstA (LmA x t a) y z ≠ LmA x t a} ⊆
{y. vsubst t y z ≠ t} ∪ {y. vsubstA a y z ≠ a} ∪ {x} ∪ X"
using assms(1) vsubstA_LmA by force
hence "finite {y. vsubstA (LmA x t a) y z ≠ LmA x t a}"
by (smt (verit, best) Collect_empty_eq assms(2) assms(3)
fresh_subst_id finite.simps finite_UnI finite_X freshA_2_vsubstA rev_finite_subset vsubstA_idem)
thus ?thesis unfolding freshA_def by auto
qed
lemma LmA_rename_freshA:
assumes "{x,z} ∩ X = {}" "z ≠ x" "fresh z t" "freshA z a"
shows "LmA x t a = LmA z (vsubst t z x) (vsubstA a z x)"
using assms
by simp (smt (verit, ccfv_SIG) Int_insert_left LmA_rename assms(1)
freshA_iff_ex_vvsubstA_idle subst_Vr_id subst_chain
vsubstA_chain vsubstA_id)
lemma freshA_LmA:
"{x,z} ∩ X = {} ⟹ z = x ∨ (fresh z t ∧ freshA z a) ⟹ freshA z (LmA x t a)"
using freshA_LmA' freshA_LmA_same by (meson insert_disjoint(1))
end
subsection ‹The relational version of the recursor ›
context FR_BCE_Renset
begin
text ‹The recursor is first defined relationally. Then it will be proved to be functional. ›
inductive R :: "trm ⇒ 'A ⇒ bool" where
Vr: "R (Vr x) (VrA x)"
|
Ap: "R t1 a1 ⟹ R t2 a2 ⟹ R (Ap t1 t2) (ApA t1 a1 t2 a2)"
|
Lm: "R t a ⟹ x ∉ X ⟹ R (Lm x t) (LmA x t a)"
lemma F_Vr_elim[simp]: "R (Vr x) a ⟷ a = VrA x"
apply safe
subgoal using R.cases by fastforce
subgoal by (auto intro: R.intros) .
lemma F_Ap_elim:
assumes "R (Ap t1 t2) a"
shows "∃a1 a2. R t1 a1 ∧ R t2 a2 ∧ a = ApA t1 a1 t2 a2"
by (metis Ap_Lm_diff(1) Ap_inj R.cases Vr_Ap_diff(1) assms)
lemma F_Lm_elim:
assumes "R (Lm x t) a"
shows "∃x' t' e. R t' e ∧ x' ∉ X ∧ Lm x t = Lm x' t' ∧ a = LmA x' t' e"
using assms by (cases rule: R.cases) auto
lemma F_total: "∃a. R t a"
using finite_X apply(induct rule: fresh_induct) by (auto intro: R.intros)
text ‹The main lemma needed in the recursion theorem: It states that
the relational version of the recursor is (1) functional, (2) preserves freshness
and (3) preserves renaming. These three facts must be proved mutually recursively. ›
lemma F_main:
"(∀a a'. R t a ⟶ R t a' ⟶ a = a') ∧
(∀a x. x ∉ X ∧ fresh x t ∧ R t a ⟶ freshA x a) ∧
(∀a x y. x ∉ X ∧ y ∉ X ⟶ R t a ⟶ R (vsubst t y x) (vsubstA a y x))"
proof(induct t rule: substConnect_induct)
case (Vr x)
then show ?case by (auto simp: freshA_VrA vsubstA_VrA)
next
case (Ap t1 t2)
then show ?case apply safe
apply (metis F_Ap_elim)
apply (metis F_Ap_elim freshA_ApA fresh_Ap)
by (smt (verit, ccfv_SIG) Diff_disjoint Diff_insert_absorb R.simps F_Ap_elim Int_commute
Int_insert_right_if0 subst_Ap vsubstA_ApA)
next
case (Lm x t)
show ?case
proof safe
fix a1 a2 assume "R (Lm x t) a1" "R (Lm x t) a2"
then obtain x1' t1' a1' x2' t2' a2'
where 1: "x1' ∉ X" "R t1' a1'" "Lm x t = Lm x1' t1'" "a1 = LmA x1' t1' a1'"
and 2: "x2' ∉ X" "R t2' a2'" "Lm x t = Lm x2' t2'" "a2 = LmA x2' t2' a2'"
using F_Lm_elim by metis
define z where "z = ppickFreshS X [x,x1',x2'] [t,t1',t2']"
have z: "z ∉ {x,x1',x2'}" "fresh z t" "fresh z t1'" "fresh z t2'" "z ∉ X"
unfolding z_def using ppickFreshS[of X "[x,x1',x2']" "[t,t1',t2']"] by auto
have 11: "vsubst t z x = vsubst t1' z x1'"
using "1"(3) Lm_eq_elim_subst z by blast
hence tt1': "substConnect t t1'"
by (metis substConnect.simps subst_Vr_id subst_chain z(3))
have 22: "subst t (Vr z) x = subst t2' (Vr z) x2'"
using "2"(3) Lm_eq_elim_subst z by blast
hence tt2': "substConnect t t2'"
by (metis Refl Step subst_Vr_id subst_chain z(4))
show "a1 = a2" unfolding 1 2 apply(rule LmA_cong_freshA[of z])
subgoal using z by (simp add: "1"(1) "2"(1))
subgoal using z(1) by force
subgoal by (simp add: z)
subgoal apply(rule Lm[rule_format, OF tt1',
THEN conjunct2, THEN conjunct1, rule_format])
using 1 z by auto
subgoal using z by simp
subgoal by (simp add: z)
subgoal apply(rule Lm[rule_format, OF tt2',
THEN conjunct2, THEN conjunct1, rule_format])
using 2 z by auto
subgoal using "11" "22" by presburger
subgoal by (metis "1"(1) "1"(2) "11" "2"(1) "2"(2) "22" Lm.hyps Step tt1'
tt2' z(5)) .
next
fix a y assume yX: "y ∉ X"
and fr: "fresh y (Lm x t)" "R (Lm x t) a"
then obtain x' t' a'
where 0: "x' ∉ X" "R t' a'" "Lm x t = Lm x' t'" "a = LmA x' t' a'"
using F_Lm_elim by metis
define z where "z = ppickFreshS X [x,x'] [t,t']"
have z: "z ∉ {x,x'}" "fresh z t" "fresh z t'" "z ∉ X"
unfolding z_def using ppickFreshS[of X "[x,x']" "[t,t']"] by auto
have 00: "subst t (Vr z) x = subst t' (Vr z) x'"
using 0(3) Lm_eq_elim_subst z by blast
hence tt1': "substConnect t t'"
by (metis substConnect.simps subst_Vr_id subst_chain z(3))
show "freshA y a" unfolding 0
apply(rule freshA_LmA)
apply (simp add: "0"(1) yX)
apply(subst disj_commute, safe)
apply (metis "0"(3) fresh_Lm fr(1))
apply(rule Lm[rule_format,THEN conjunct2, THEN conjunct1, rule_format, of t'])
subgoal using tt1' .
subgoal apply safe
subgoal using yX by blast
subgoal using fr(1) unfolding 0 by simp
subgoal using 0(2) . . .
next
fix a yy y assume yy_y: "yy ∉ X" "y ∉ X" and "R (Lm x t) a"
then obtain x' t' a'
where 0: "x' ∉ X" "R t' a'" "Lm x t = Lm x' t'" "a = LmA x' t' a'"
using F_Lm_elim by metis
define z where "z = ppickFreshS X [x,x',y,yy] [t,t']"
have z: "z ∉ {x,x',y,yy}" "fresh z t" "fresh z t'" "z ∉ X"
unfolding z_def using ppickFreshS[of X "[x,x',y,yy]" "[t,t']"] by auto
have 00: "subst t (Vr z) x = subst t' (Vr z) x'"
using 0(3) Lm_eq_elim_subst z by blast
hence tt1': "substConnect t t'"
by (metis substConnect.simps subst_Vr_id subst_chain z(3))
define t'' where "t'' ≡ subst t' (Vr z) x'"
have 1: "Lm x' t' = Lm z t''" unfolding t''_def
by (simp add: Lm_subst_rename z(3))
have tt'': "substConnect t t''"
using Step t''_def tt1' by blast
define a'' where "a'' ≡ vsubstA a' z x'"
have 11: "LmA x' t' a' = LmA z t'' a''" unfolding a''_def
using "0"(1,2) LmA_rename_freshA Lm.hyps tt1' z(1) z(3,4)
unfolding t''_def by auto
show "R (subst (Lm x t) (Vr y) yy) (vsubstA a y yy)"
unfolding 0 1 11 using z apply (simp add: yy_y vsubstA_LmA)
apply(rule R.Lm)
apply(rule Lm[rule_format,THEN conjunct2, THEN conjunct2, rule_format])
subgoal using tt'' .
subgoal using yy_y(1) yy_y(2) by auto
subgoal unfolding t''_def a''_def
apply(rule Lm[rule_format,THEN conjunct2, THEN conjunct2, rule_format])
subgoal using tt1' .
subgoal using "0"(1) by blast
subgoal using 0(2) . .
subgoal using z(4) . .
qed
qed
lemmas F_functional = F_main[THEN conjunct1]
lemmas F_fresh = F_main[THEN conjunct2, THEN conjunct1]
lemmas F_subst = F_main[THEN conjunct2, THEN conjunct2]
subsection ‹The functional version of the recursor ›
definition f :: "trm ⇒ 'A" where "f t ≡ SOME a. R t a"
lemma F_f: "R t (f t)"
by (simp add: F_total f_def someI_ex)
lemma f_eq_F: "f t = a ⟷ R t a"
by (meson F_f F_functional)
subsection ‹The full-fledged recursion theorem ›
theorem f_Vr[simp]: "f (Vr x) = VrA x"
unfolding f_eq_F by (auto simp: F_f intro: R.intros)
theorem f_Ap[simp]: "f (Ap t1 t2) = ApA t1 (f t1) t2 (f t2)"
unfolding f_eq_F by (auto simp: F_f intro: R.intros)
theorem f_Lm[simp]:
"x ∉ X ⟹ f (Lm x t) = LmA x t (f t)"
unfolding f_eq_F by (auto simp: F_f intro: R.intros)
theorem f_subst:
"y ∉ X ⟹ z ∉ X ⟹ f (subst t (Vr y) z) = vsubstA (f t) y z"
using F_subst f_eq_F by blast
theorem f_fresh:
assumes "z ∉ X" "fresh z t"
shows "freshA z (f t)"
using F_f F_fresh assms by blast
theorem f_unique:
assumes [simp]: "⋀x. g (Vr x) = VrA x"
"⋀t1 t2. g (Ap t1 t2) = ApA t1 (g t1) t2 (g t2)"
"⋀x t. x ∉ X ⟹ g (Lm x t) = LmA x t (g t)"
shows "g = f"
apply(rule ext)
subgoal for t using finite_X by (induct t rule: fresh_induct, auto) .
end
subsection ‹The particular case of iteration ›
locale BCE_Renset = Renset vsubstA
for vsubstA :: "'A ⇒ var ⇒ var ⇒ 'A"
+
fixes
X :: "var set"
and VrA :: "var ⇒ 'A"
and ApA :: "'A ⇒ 'A ⇒ 'A"
and LmA :: "var ⇒ 'A ⇒ 'A"
assumes
finite_X'[simp,intro!]: "finite X"
and
vsubstA_VrA': "⋀ x y z. {y,z} ∩ X = {} ⟹
vsubstA (VrA x) y z = (if x = z then VrA y else VrA x)"
and
vsubstA_ApA': "⋀ y z a1 a2. {y,z} ∩ X = {} ⟹
vsubstA (ApA a1 a2) y z =
ApA (vsubstA a1 y z)
(vsubstA a2 y z)"
and
vsubstA_LmA': "⋀ a z x y. {x,y,z} ∩ X = {} ⟹
x ≠ y ⟹
vsubstA (LmA x a) y z = (if x = z then LmA x a else LmA x (vsubstA a y z))"
and
LmA_rename': "⋀ x y z a. {x,y,z} ∩ X = {} ⟹
z ≠ y ⟹ LmA x (vsubstA a z y) = LmA y (vsubstA (vsubstA a z y) y x)"
begin
sublocale FR_BCE_Renset where
VrA = VrA and
ApA = "λt1 a1 t2 a2. ApA a1 a2" and
LmA = "λx t a. LmA x a"
apply standard by (auto simp: vsubstA_VrA' vsubstA_ApA' vsubstA_LmA' LmA_rename')
lemmas f_clauses = f_Vr f_Ap f_Lm f_subst f_unique
end
locale CE_Renset = Renset vsubstA
for vsubstA :: "'A ⇒ var ⇒ var ⇒ 'A"
+
fixes
VrA :: "var ⇒ 'A"
and ApA :: "'A ⇒ 'A ⇒ 'A"
and LmA :: "var ⇒ 'A ⇒ 'A"
assumes
vsubstA_VrA'': "⋀ x y z.
vsubstA (VrA x) y z = (if x = z then VrA y else VrA x)"
and
vsubstA_ApA'': "⋀ y z a1 a2.
vsubstA (ApA a1 a2) y z =
ApA (vsubstA a1 y z)
(vsubstA a2 y z)"
and
vsubstA_LmA'': "⋀ a z x y.
x ≠ y ⟹
vsubstA (LmA x a) y z = (if x = z then LmA x a else LmA x (vsubstA a y z))"
and
LmA_rename'': "⋀ x y z a.
z ≠ y ⟹ LmA x (vsubstA a z y) = LmA y (vsubstA (vsubstA a z y) y x)"
begin
sublocale BCE_Renset where X = "{}"
apply standard by (auto simp: vsubstA_VrA'' vsubstA_ApA'' vsubstA_LmA'' LmA_rename'')
lemma triv: "x∉{}" by simp
text ‹The initiality theorem ›
lemmas f_clauses_init = f_Vr f_Ap f_Lm[OF triv] f_subst[OF triv triv] f_unique[simplified]
end
end