# HG changeset patch # User Cezary Kaliszyk # Date 1324280360 -32400 # Node ID abf147627b4bfacbc9ff85fd3f83fa67670282f9 # Parent df1055004f5294fec08848fc565634913f090a4c Retry Beta using a reduction relation and its reflexive-symmetric-transitive closure. diff -r df1055004f52 -r abf147627b4b Nominal/Ex/BetaCR.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal/Ex/BetaCR.thy Mon Dec 19 16:39:20 2011 +0900 @@ -0,0 +1,384 @@ +theory BetaCR +imports + "../Nominal2" +begin + +atom_decl name + +nominal_datatype lam = + Var "name" +| App "lam" "lam" +| Lam x::"name" l::"lam" binds x in l ("Lam [_]. _" [100, 100] 100) + +nominal_primrec + subst :: "lam \ name \ lam \ lam" ("_ [_ ::= _]" [90, 90, 90] 90) +where + "(Var x)[y ::= s] = (if x = y then s else (Var x))" +| "(App t1 t2)[y ::= s] = App (t1[y ::= s]) (t2[y ::= s])" +| "atom x \ (y, s) \ (Lam [x]. t)[y ::= s] = Lam [x].(t[y ::= s])" + unfolding eqvt_def subst_graph_def + apply (rule, perm_simp, rule) + apply(rule TrueI) + apply(auto simp add: lam.distinct lam.eq_iff) + apply(rule_tac y="a" and c="(aa, b)" in lam.strong_exhaust) + apply(blast)+ + apply(simp_all add: fresh_star_def fresh_Pair_elim) + apply (erule_tac c="(ya,sa)" in Abs_lst1_fcb2) + apply(simp_all add: Abs_fresh_iff) + apply(simp add: fresh_star_def fresh_Pair) + apply(simp add: eqvt_at_def atom_eqvt fresh_star_Pair perm_supp_eq) + apply(simp add: eqvt_at_def atom_eqvt fresh_star_Pair perm_supp_eq) +done + +termination (eqvt) + by lexicographic_order + +lemma fresh_fact: + fixes z::"name" + assumes a: "atom z \ s" + and b: "z = y \ atom z \ t" + shows "atom z \ t[y ::= s]" + using a b + by (nominal_induct t avoiding: z y s rule: lam.strong_induct) + (auto simp add: lam.fresh fresh_at_base) + +inductive + beta :: "lam \ lam \ bool" (" _ \b _" [80,80] 80) +where + b1[intro]: "t1 \b t2 \ App t1 s \b App t2 s" +| b2[intro]: "s1 \b s2 \ App t s1 \b App t s2" +| b3[intro]: "t1 \b t2 \ Lam [x]. t1 \b Lam [x]. t2" +| b4[intro]: "atom x \ s \ App (Lam [x]. t) s \b t[x ::= s]" + +equivariance beta + +(* HERE 1 *) +nominal_inductive beta + avoids b3: x + by (simp_all add: fresh_star_def fresh_Pair lam.fresh fresh_fact) + +(* This also works, but we cannot have them together: *) +(*nominal_inductive beta + avoids b4: x + by (simp_all add: fresh_star_def fresh_Pair lam.fresh fresh_fact)*) + +(* But I need a combination, possibly with an 'and' syntax: +nominal_inductive beta + avoids b3: x and b4: x + by (simp_all add: fresh_star_def fresh_Pair lam.fresh fresh_fact) +*) + +(* The combination should look like this: *) +lemma beta_strong_induct: + assumes "x1 \b x2" + and "\t1 t2 s c. \ t1 \b t2; \c. P c t1 t2\ \ P c (App t1 s) (App t2 s)" + and "\s1 s2 t c. \ s1 \b s2; \c. P c s1 s2\ \ P c (App t s1) (App t s2)" + and "\t1 t2 x c. \{atom x} \* c; t1 \b t2; \c. P c t1 t2\ \ P c (Lam [x]. t1) (Lam [x]. t2)" + and "\x s t c. \{atom x} \* c; atom x \ s\ \ P c (App (Lam [x]. t) s) (t [x ::= s])" + shows "P (c\'a\fs) x1 x2" + sorry + +inductive + beta_star :: "lam \ lam \ bool" (" _ \b* _" [80,80] 80) +where + bs1[intro, simp]: "M \b* M" +| bs2[intro]: "\M1\b* M2; M2 \b M3\ \ M1 \b* M3" + +lemma beta_star_trans: + assumes "A \b* B" + and "B \b* C" + shows "A \b* C" + using assms(2) assms(1) + by induct auto + +(* HERE 2: Does not work:*) + +(* equivariance beta_star *) + +(* proved manually below. *) + +lemma eqvt_helper: "x1 \b* x2 \ (p \ x1) \b* (p \ x2)" + apply (erule beta_star.induct) + apply auto + using eqvt(1) bs2 + by blast + +lemma [eqvt]: "p \ (x1 \b* x2) = ((p \ x1) \b* (p \ x2))" + apply rule + apply (drule permute_boolE) + apply (erule eqvt_helper) + apply (intro permute_boolI) + apply (drule_tac p="-p" in eqvt_helper) + by simp + +definition + equ :: "lam \ lam \ bool" ("_ \ _") +where + "t \ s \ (\r. t \b* r \ s \b* r)" + +lemma equ_refl: + shows "t \ t" + unfolding equ_def by auto + +lemma equ_sym: + assumes "t \ s" + shows "s \ t" + using assms unfolding equ_def + by auto + +(* can be ported from nominal1 *) +lemma cr: + assumes "t \b* t1" and "t \b* t2" shows "\t3. t1 \b* t3 \ t2 \b* t3" + sorry + +lemma equ_trans: + assumes "A \ B" "B \ C" + shows "A \ C" + using assms unfolding equ_def +proof (elim exE conjE) + fix D E + assume a: "A \b* D" "B \b* D" "B \b* E" "C \b* E" + then obtain F where "D \b* F" "E \b* F" using cr by blast + then have "A \b* F \ C \b* F" using a beta_star_trans by blast + then show "\F. A \b* F \ C \b* F" by blast +qed + +lemma App_beta: "A \b* B \ C \b* D \ App A C \b* App B D" + apply (erule beta_star.induct) + apply auto + apply (erule beta_star.induct) + apply auto + done + +lemma Lam_beta: "A \b* B \ Lam [x]. A \b* Lam [x]. B" + by (erule beta_star.induct) auto + +lemma [quot_respect]: + shows "(op = ===> equ) Var Var" + and "(equ ===> equ ===> equ) App App" + and "(op = ===> equ ===> equ) BetaCR.Lam BetaCR.Lam" + unfolding fun_rel_def equ_def + apply auto + apply (rule_tac x="App r ra" in exI) + apply (auto simp add: App_beta) + apply (rule_tac x="Lam [x]. r" in exI) + apply (auto simp add: Lam_beta) + done + +lemma beta_subst1_pre: "B \b C \ A [x ::= B] \b* A [x ::= C]" + by (nominal_induct A avoiding: x B C rule: lam.strong_induct) + (auto simp add: App_beta Lam_beta) + +lemma beta_subst1: "B \b* C \ A [x ::= B] \b* A [x ::= C]" + apply (erule beta_star.induct) + apply auto + apply (subgoal_tac "A [x ::= M2] \b* A [x ::= M3]") + apply (rotate_tac 1) + apply (erule beta_star_trans) + apply assumption + apply (simp add: beta_subst1_pre) + done + +lemma forget: + shows "atom x \ t \ t[x ::= s] = t" + by (nominal_induct t avoiding: x s rule: lam.strong_induct) + (auto simp add: lam.fresh fresh_at_base) + +lemma substitution_lemma: + assumes a: "x \ y" "atom x \ u" + shows "t[x ::= s][y ::= u] = t[y ::= u][x ::= s[y ::= u]]" + using a + by (nominal_induct t avoiding: x y s u rule: lam.strong_induct) + (auto simp add: fresh_fact forget) + +lemma beta_subst2_pre: + assumes "A \b B" shows "A [x ::= C] \b* B [x ::= C]" + using assms +(* HERE 3: nominal_induct doesn't work - leaves the assumption *) +(* apply (nominal_induct avoiding: x C rule: beta_strong_induct)*) + apply - + apply (erule beta_strong_induct[of A B "\c A B. A [(fst c) ::= (snd c)] \b* B [(fst c) ::= (snd c)]" "(x, C)", simplified]) + apply (auto simp add: App_beta fresh_star_def fresh_Pair Lam_beta)[3] + apply (subst substitution_lemma) + apply (auto simp add: fresh_star_def fresh_Pair fresh_at_base)[2] + apply (auto simp add: fresh_star_def fresh_Pair) + apply (rule beta_star.intros) + defer + apply (subst beta.intros) + apply (auto simp add: fresh_fact) + done + +lemma beta_subst2: "A \b* B \ A [x ::= C] \b* B [x ::= C]" + apply (erule beta_star.induct) + apply auto + apply (subgoal_tac "M2[x ::= C] \b* M3[x ::= C]") + apply (rotate_tac 1) + apply (erule beta_star_trans) + apply assumption + apply (simp add: beta_subst2_pre) + done + +lemma beta_subst: "A \b* B \ C \b* D \ A [x ::= C] \b* B [x ::= D]" + using beta_subst1 beta_subst2 beta_star_trans by metis + +lemma [quot_respect]: + shows "(equ ===> op = ===> equ ===> equ) subst subst" +unfolding fun_rel_def equ_def +apply auto +apply (rule_tac x="r [xa ::= ra]" in exI) +apply (simp add: beta_subst) +done + +lemma [quot_respect]: + shows "(op = ===> equ ===> equ) permute permute" + unfolding fun_rel_def equ_def + apply (auto intro: eqvts) + apply (rule_tac x="x \ r" in exI) + using eqvts(1) permute_boolI by metis + +quotient_type qlam = lam / equ + by (auto intro!: equivpI reflpI sympI transpI simp add: equ_refl equ_sym) + (erule equ_trans, assumption) + +quotient_definition "QVar::name \ qlam" is Var +quotient_definition "QApp::qlam \ qlam \ qlam" is App +quotient_definition QLam ("QLam [_]._") + where "QLam::name \ qlam \ qlam" is Beta.Lam + +lemmas qlam_strong_induct = lam.strong_induct[quot_lifted] +lemmas qlam_induct = lam.induct[quot_lifted] + +instantiation qlam :: pt +begin + +quotient_definition "permute_qlam::perm \ qlam \ qlam" + is "permute::perm \ lam \ lam" + +instance +apply default +apply(descending) +apply(simp) +apply(rule equ_refl) +apply(descending) +apply(simp) +apply(rule equ_refl) +done + +end + +lemma qlam_perm[simp, eqvt]: + shows "p \ (QVar x) = QVar (p \ x)" + and "p \ (QApp t s) = QApp (p \ t) (p \ s)" + and "p \ (QLam [x].t) = QLam [p \ x].(p \ t)" + by(descending, simp add: equ_refl)+ + +lemma qlam_supports: + shows "{atom x} supports (QVar x)" + and "supp (t, s) supports (QApp t s)" + and "supp (x, t) supports (QLam [x].t)" +unfolding supports_def fresh_def[symmetric] +by (auto simp add: swap_fresh_fresh) + +lemma qlam_fs: + fixes t::"qlam" + shows "finite (supp t)" +apply(induct t rule: qlam_induct) +apply(rule supports_finite) +apply(rule qlam_supports) +apply(simp) +apply(rule supports_finite) +apply(rule qlam_supports) +apply(simp add: supp_Pair) +apply(rule supports_finite) +apply(rule qlam_supports) +apply(simp add: supp_Pair finite_supp) +done + +instantiation qlam :: fs +begin + +instance +apply(default) +apply(rule qlam_fs) +done + +end + +quotient_definition subst_qlam ("_[_ ::q= _]") + where "subst_qlam::qlam \ name \ qlam \ qlam" is subst + +lemmas qsubst = subst.simps(1-2)[quot_lifted] + +definition + "Supp t = \{supp s | s. s \ t}" + +lemma [quot_respect]: + shows "(equ ===> op=) Supp Supp" + unfolding fun_rel_def Supp_def + apply(intro allI impI) + apply(rule_tac f="Inter" in arg_cong) + apply(auto) + apply (metis equ_trans) + by (metis equivp_def qlam_equivp) + +quotient_definition "supp_qlam::qlam \ atom set" + is "Supp::lam \ atom set" + +lemma Supp_supp: + "Supp t \ supp t" +unfolding Supp_def +apply(auto) +apply(drule_tac x="supp t" in spec) +apply(auto simp add: equ_refl) +done + +lemma Supp_Lam: + "atom a \ Supp (Lam [a].t)" +proof - + have "atom a \ supp (Lam [a].t)" by (simp add: lam.supp) + then show ?thesis using Supp_supp + by blast +qed + +lemma [eqvt]: "(p \ (a \ b)) = ((p \ a) \ (p \ b))" + unfolding equ_def + by perm_simp rule + +lemma [eqvt]: "p \ (Supp x) = Supp (p \ x)" + unfolding Supp_def + by perm_simp rule + +lemmas s = Supp_Lam[quot_lifted] + +lemma var_beta_pre: "s \b* r \ s = Var name \ r = Var name" + apply (induct rule: beta_star.induct) + apply simp + apply (subgoal_tac "M2 = Var name") + apply (thin_tac "M1 \b* M2") + apply (thin_tac "M1 = Var name") + apply (thin_tac "M1 = Var name \ M2 = Var name") + defer + apply simp + apply (erule_tac beta.cases) + apply simp_all + done + +lemma var_beta: "Var name \b* r \ r = Var name" + by (auto simp add: var_beta_pre) + +lemma qlam_eq_iff: + "(QVar n = QVar m) = (n = m)" + apply descending unfolding equ_def var_beta by auto + +lemma "supp (QVar n) = {atom n}" + unfolding supp_def + apply simp + unfolding qlam_eq_iff + apply (fold supp_def) + apply (simp add: supp_at_base) + done + +end + + +