# HG changeset patch # User urbanc # Date 1131373143 -3600 # Node ID 836135c8acb27efc0af3cb0a8a42538532e40a57 # Parent 4c9c081a416b8adbc2f8380c0092e2ca66e66155 Initial commit. diff -r 4c9c081a416b -r 836135c8acb2 src/HOL/Nominal/Examples/CR.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Nominal/Examples/CR.thy Mon Nov 07 15:19:03 2005 +0100 @@ -0,0 +1,952 @@ + +theory cr +imports lam_substs +begin + +lemma forget[rule_format]: + shows "a\t1 \ t1[a::=t2] = t1" +proof (nominal_induct t1 rule: lam_induct) + case (Var a t2 b) + show ?case by (simp, simp add: fresh_atm) +next + case App + thus ?case by (simp add: fresh_prod) +next + case (Lam a t2 c t) + have i: "\a b. a\t \ t[a::=b] = t" by fact + have "c\(a,t2)" by fact + hence a: "a\c" and b: "c\t2" by (auto simp add: fresh_prod fresh_atm) + show ?case + proof + assume "a\Lam [c].t" + hence "a\t" using a by (force simp add: abs_fresh) + hence "t[a::=t2] = t" using i by simp + thus "(Lam [c].t)[a::=t2] = Lam [c].t" using a b by (simp add: alpha) + qed +qed + +lemma forget[rule_format]: + shows "a\t1 \ t1[a::=t2] = t1" +apply (nominal_induct t1 rule: lam_induct) +apply(auto simp add: abs_fresh fresh_atm fresh_prod) +done + +lemma fresh_fact[rule_format]: + fixes b :: "name" + and a :: "name" + and t1 :: "lam" + and t2 :: "lam" + shows "a\t1\a\t2\a\(t1[b::=t2])" +proof (nominal_induct t1 rule: lam_induct) + case (Var a b t2 c) + show ?case by (simp) +next + case App + thus ?case by (simp add: fresh_prod) +next + case (Lam a b t2 c t) + have i: "\(a::name) b t2. a\t\a\t2\a\(t[b::=t2])" by fact + have "c\(a,b,t2)" by fact + hence b: "c\a \ c\b \ c\t2" by (simp add: fresh_prod fresh_atm) + show ?case + proof (intro strip) + assume a1: "a\t2" + assume a2: "a\Lam [c].t" + hence "a\t" using b by (force simp add: abs_fresh) + hence "a\t[b::=t2]" using a1 i by simp + thus "a\(Lam [c].t)[b::=t2]" using b by (simp add: abs_fresh) + qed +qed + +lemma fresh_fact[rule_format]: + fixes b :: "name" + and a :: "name" + and t1 :: "lam" + and t2 :: "lam" + shows "a\t1\a\t2\a\(t1[b::=t2])" +apply(nominal_induct t1 rule: lam_induct) +apply(auto simp add: abs_fresh fresh_prod fresh_atm) +done + +lemma subs_lemma: + fixes x::"name" + and y::"name" + and L::"lam" + and M::"lam" + and N::"lam" + shows "x\y\x\L\M[x::=N][y::=L] = M[y::=L][x::=N[y::=L]]" +proof (nominal_induct M rule: lam_induct) + case (Var L N x y z) (* case 1: Variables*) + show ?case + proof (intro strip) + assume a1: "x\y" + and a2: "x\L" + show "Var z[x::=N][y::=L] = Var z[y::=L][x::=N[y::=L]]" (is "?LHS = ?RHS") + proof - + have "z=x \ (z\x \ z=y) \ (z\x \ z\y)" by force + moreover (*Case 1.1*) + { assume c1: "z=x" + have c1l: "?LHS = N[y::=L]" using c1 by simp + have c1r: "?RHS = N[y::=L]" using c1 a1 by simp + from c1l and c1r have "?LHS = ?RHS" by simp + } + moreover (*Case 1.2*) + { assume c2: "z\x \ z=y" + have c2l: "?LHS = L" using c2 by force + have c2r: "?RHS = L[x::=N[y::=L]]" using c2 by force + have c2x: "L[x::=N[y::=L]] = L" using a2 by (simp add: forget) + from c2l and c2r and c2x have "?LHS = ?RHS" by simp + } + moreover (*Case 1.3*) + { assume c3: "z\x \ z\y" + have c3l: "?LHS = Var z" using c3 by force + have c3r: "?RHS = Var z" using c3 by force + from c3l and c3r have "?LHS = ?RHS" by simp + } + ultimately show "?LHS = ?RHS" by blast + qed + qed +next + case (Lam L N x y z M1) (* case 2: lambdas *) + assume f1: "z\(L,N,x,y)" + from f1 have f2: "z \ N[y::=L]" by (simp add: fresh_fact fresh_prod) + show ?case + proof (intro strip) + assume a1: "x\y" + and a2: "x\L" + show "(Lam [z].M1)[x::=N][y::=L] = (Lam [z].M1)[y::=L][x::=N[y::=L]]" (is "?LHS=?RHS") + proof - + have "?LHS = Lam [z].(M1[x::=N][y::=L])" using f1 + by (simp add: fresh_prod fresh_atm) + also have "\ = Lam [z].(M1[y::=L][x::=N[y::=L]])" using a1 a2 Lam(2) by simp + also have "\ = (Lam [z].(M1[y::=L]))[x::=N[y::=L]]" using f1 f2 + by (simp add: fresh_prod fresh_atm) + also have "\ = ?RHS" using f1 by (simp add: fresh_prod fresh_atm) + finally show "?LHS = ?RHS" . + qed + qed +next + case (App L N x y M1 M2) (* case 3: applications *) + show ?case + proof (intro strip) + assume a1: "x\y" + and a2: "x\L" + from a1 a2 App show "(App M1 M2)[x::=N][y::=L] = (App M1 M2)[y::=L][x::=N[y::=L]]" by simp + qed +qed + +lemma subs_lemma: + fixes x::"name" + and y::"name" + and L::"lam" + and M::"lam" + and N::"lam" + shows "x\y\x\L\M[x::=N][y::=L] = M[y::=L][x::=N[y::=L]]" +proof (nominal_induct M rule: lam_induct) + case (Var L N x y z) (* case 1: Variables*) + show ?case + proof - + have "z=x \ (z\x \ z=y) \ (z\x \ z\y)" by force + thus "x\y\x\L\Var z[x::=N][y::=L] = Var z[y::=L][x::=N[y::=L]]" + using forget by force + qed +next + case (Lam L N x y z M1) (* case 2: lambdas *) + assume f1: "z\(L,N,x,y)" + hence f2: "z\N[y::=L]" by (simp add: fresh_fact fresh_prod) + show ?case + proof (intro strip) + assume a1: "x\y" + and a2: "x\L" + show "(Lam [z].M1)[x::=N][y::=L] = (Lam [z].M1)[y::=L][x::=N[y::=L]]" (is "?LHS=?RHS") + proof - + have "?LHS = Lam [z].(M1[x::=N][y::=L])" using f1 by (simp add: fresh_prod fresh_atm) + also have "\ = Lam [z].(M1[y::=L][x::=N[y::=L]])" using a1 a2 Lam(2) by simp + also have "\ = ?RHS" using f1 f2 by (simp add: fresh_prod fresh_atm) + finally show "?LHS = ?RHS" . + qed + qed +next + case (App L N x y M1 M2) (* case 3: applications *) + thus "x\y\x\L\(App M1 M2)[x::=N][y::=L] = (App M1 M2)[y::=L][x::=N[y::=L]]" by simp +qed + +lemma subs_lemma: + fixes x::"name" + and y::"name" + and L::"lam" + and M::"lam" + and N::"lam" + shows "x\y\x\L\M[x::=N][y::=L] = M[y::=L][x::=N[y::=L]]" +apply(nominal_induct M rule: lam_induct) +apply(auto simp add: fresh_fact forget fresh_prod fresh_atm) +done + +lemma subst_rename[rule_format]: + fixes c :: "name" + and a :: "name" + and t1 :: "lam" + and t2 :: "lam" + shows "c\t1 \ (t1[a::=t2] = ([(c,a)]\t1)[c::=t2])" +proof (nominal_induct t1 rule: lam_induct) + case (Var a c t2 b) + show "c\(Var b) \ (Var b)[a::=t2] = ([(c,a)]\(Var b))[c::=t2]" by (simp add: calc_atm fresh_atm) +next + case App thus ?case by (force simp add: fresh_prod) +next + case (Lam a c t2 b s) + have i: "\a c t2. c\s \ (s[a::=t2] = ([(c,a)]\s)[c::=t2])" by fact + have f: "b\(a,c,t2)" by fact + from f have a:"b\c" and b: "b\a" and c: "b\t2" by (simp add: fresh_prod fresh_atm)+ + show "c\Lam [b].s \ (Lam [b].s)[a::=t2] = ([(c,a)]\(Lam [b].s))[c::=t2]" (is "_ \ ?LHS = ?RHS") + proof + assume "c\Lam [b].s" + hence "c\s" using a by (force simp add: abs_fresh) + hence d: "s[a::=t2] = ([(c,a)]\s)[c::=t2]" using i by simp + have "?LHS = Lam [b].(s[a::=t2])" using b c by simp + also have "\ = Lam [b].(([(c,a)]\s)[c::=t2])" using d by simp + also have "\ = (Lam [b].([(c,a)]\s))[c::=t2]" using a c by simp + also have "\ = ?RHS" using a b by (force simp add: calc_atm) + finally show "?LHS = ?RHS" by simp + qed +qed + +lemma subst_rename[rule_format]: + fixes c :: "name" + and a :: "name" + and t1 :: "lam" + and t2 :: "lam" + shows "c\t1 \ (t1[a::=t2] = ([(c,a)]\t1)[c::=t2])" +apply(nominal_induct t1 rule: lam_induct) +apply(auto simp add: calc_atm fresh_atm fresh_prod abs_fresh) +done + +section {* Beta Reduction *} + +consts + Beta :: "(lam\lam) set" +syntax + "_Beta" :: "lam\lam\bool" (" _ \\<^isub>\ _" [80,80] 80) + "_Beta_star" :: "lam\lam\bool" (" _ \\<^isub>\\<^sup>* _" [80,80] 80) +translations + "t1 \\<^isub>\ t2" \ "(t1,t2) \ Beta" + "t1 \\<^isub>\\<^sup>* t2" \ "(t1,t2) \ Beta\<^sup>*" +inductive Beta + intros + b1[intro!]: "s1\\<^isub>\s2 \ (App s1 t)\\<^isub>\(App s2 t)" + b2[intro!]: "s1\\<^isub>\s2 \ (App t s1)\\<^isub>\(App t s2)" + b3[intro!]: "s1\\<^isub>\s2 \ (Lam [a].s1)\\<^isub>\ (Lam [(a::name)].s2)" + b4[intro!]: "(App (Lam [(a::name)].s1) s2)\\<^isub>\(s1[a::=s2])" + +lemma eqvt_beta: + fixes pi :: "name prm" + and t :: "lam" + and s :: "lam" + shows "t\\<^isub>\s \ (pi\t)\\<^isub>\(pi\s)" + apply(erule Beta.induct) + apply(auto) + done + +lemma beta_induct_aux[rule_format]: + fixes P :: "lam \ lam \'a::fs_name\bool" + and t :: "lam" + and s :: "lam" + assumes a: "t\\<^isub>\s" + and a1: "\x t s1 s2. + s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (App s1 t) (App s2 t) x" + and a2: "\x t s1 s2. + s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (App t s1) (App t s2) x" + and a3: "\x (a::name) s1 s2. + a\x \ s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (Lam [a].s1) (Lam [a].s2) x" + and a4: "\x (a::name) t1 s1. a\(s1,x) \ P (App (Lam [a].t1) s1) (t1[a::=s1]) x" + shows "\x (pi::name prm). P (pi\t) (pi\s) x" +using a +proof (induct) + case b1 thus ?case using a1 by (simp, blast intro: eqvt_beta) +next + case b2 thus ?case using a2 by (simp, blast intro: eqvt_beta) +next + case (b3 a s1 s2) + assume j1: "s1 \\<^isub>\ s2" + assume j2: "\x (pi::name prm). P (pi\s1) (pi\s2) x" + show ?case + proof (simp, intro strip) + fix pi::"name prm" and x::"'a::fs_name" + have f: "\c::name. c\(pi\a,pi\s1,pi\s2,x)" + by (rule at_exists_fresh[OF at_name_inst], simp add: fs_name1) + then obtain c::"name" + where f1: "c\(pi\a)" and f2: "c\x" and f3: "c\(pi\s1)" and f4: "c\(pi\s2)" + by (force simp add: fresh_prod fresh_atm) + have x: "P (Lam [c].(([(c,pi\a)]@pi)\s1)) (Lam [c].(([(c,pi\a)]@pi)\s2)) x" + using a3 f2 j1 j2 by (simp, blast intro: eqvt_beta) + have alpha1: "(Lam [c].([(c,pi\a)]\(pi\s1))) = (Lam [(pi\a)].(pi\s1))" using f1 f3 + by (simp add: lam.inject alpha) + have alpha2: "(Lam [c].([(c,pi\a)]\(pi\s2))) = (Lam [(pi\a)].(pi\s2))" using f1 f3 + by (simp add: lam.inject alpha) + show " P (Lam [(pi\a)].(pi\s1)) (Lam [(pi\a)].(pi\s2)) x" + using x alpha1 alpha2 by (simp only: pt_name2) + qed +next + case (b4 a s1 s2) + show ?case + proof (simp add: subst_eqvt, intro strip) + fix pi::"name prm" and x::"'a::fs_name" + have f: "\c::name. c\(pi\a,pi\s1,pi\s2,x)" + by (rule at_exists_fresh[OF at_name_inst], simp add: fs_name1) + then obtain c::"name" + where f1: "c\(pi\a)" and f2: "c\(pi\s2,x)" and f3: "c\(pi\s1)" and f4: "c\(pi\s2)" + by (force simp add: fresh_prod fresh_atm) + have x: "P (App (Lam [c].(([(c,pi\a)]@pi)\s1)) (pi\s2)) ((([(c,pi\a)]@pi)\s1)[c::=(pi\s2)]) x" + using a4 f2 by (blast intro!: eqvt_beta) + have alpha1: "(Lam [c].([(c,pi\a)]\(pi\s1))) = (Lam [(pi\a)].(pi\s1))" using f1 f3 + by (simp add: lam.inject alpha) + have alpha2: "(([(c,pi\a)]@pi)\s1)[c::=(pi\s2)] = (pi\s1)[(pi\a)::=(pi\s2)]" + using f3 by (simp only: subst_rename[symmetric] pt_name2) + show "P (App (Lam [(pi\a)].(pi\s1)) (pi\s2)) ((pi\s1)[(pi\a)::=(pi\s2)]) x" + using x alpha1 alpha2 by (simp only: pt_name2) + qed +qed + + +lemma beta_induct[case_names b1 b2 b3 b4]: + fixes P :: "lam \ lam \'a::fs_name\bool" + and t :: "lam" + and s :: "lam" + and x :: "'a::fs_name" + assumes a: "t\\<^isub>\s" + and a1: "\x t s1 s2. + s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (App s1 t) (App s2 t) x" + and a2: "\x t s1 s2. + s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (App t s1) (App t s2) x" + and a3: "\x (a::name) s1 s2. + a\x \ s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (Lam [a].s1) (Lam [a].s2) x" + and a4: "\x (a::name) t1 s1. + a\(s1,x) \ P (App (Lam [a].t1) s1) (t1[a::=s1]) x" + shows "P t s x" +using a a1 a2 a3 a4 +by (auto intro!: beta_induct_aux[of "t" "s" "P" "[]" "x", simplified]) + +section {* One-Reduction *} + +consts + One :: "(lam\lam) set" +syntax + "_One" :: "lam\lam\bool" (" _ \\<^isub>1 _" [80,80] 80) + "_One_star" :: "lam\lam\bool" (" _ \\<^isub>1\<^sup>* _" [80,80] 80) +translations + "t1 \\<^isub>1 t2" \ "(t1,t2) \ One" + "t1 \\<^isub>1\<^sup>* t2" \ "(t1,t2) \ One\<^sup>*" +inductive One + intros + o1[intro!]: "M\\<^isub>1M" + o2[simp,intro!]: "\t1\\<^isub>1t2;s1\\<^isub>1s2\ \ (App t1 s1)\\<^isub>1(App t2 s2)" + o3[simp,intro!]: "s1\\<^isub>1s2 \ (Lam [(a::name)].s1)\\<^isub>1(Lam [a].s2)" + o4[simp,intro!]: "\s1\\<^isub>1s2;t1\\<^isub>1t2\ \ (App (Lam [(a::name)].t1) s1)\\<^isub>1(t2[a::=s2])" + +lemma eqvt_one: + fixes pi :: "name prm" + and t :: "lam" + and s :: "lam" + shows "t\\<^isub>1s \ (pi\t)\\<^isub>1(pi\s)" + apply(erule One.induct) + apply(auto) + done + +lemma one_induct_aux[rule_format]: + fixes P :: "lam \ lam \'a::fs_name\bool" + and t :: "lam" + and s :: "lam" + assumes a: "t\\<^isub>1s" + and a1: "\x t. P t t x" + and a2: "\x t1 t2 s1 s2. + (t1\\<^isub>1t2 \ (\z. P t1 t2 z) \ s1\\<^isub>1s2 \ (\z. P s1 s2 z)) + \ P (App t1 s1) (App t2 s2) x" + and a3: "\x (a::name) s1 s2. (a\x \ s1\\<^isub>1s2 \ (\z. P s1 s2 z)) + \ P (Lam [a].s1) (Lam [a].s2) x" + and a4: "\x (a::name) t1 t2 s1 s2. + (a\(s1,s2,x) \ t1\\<^isub>1t2 \ (\z. P t1 t2 z) \ s1\\<^isub>1s2 \ (\z. P s1 s2 z)) + \ P (App (Lam [a].t1) s1) (t2[a::=s2]) x" + shows "\x (pi::name prm). P (pi\t) (pi\s) x" +using a +proof (induct) + case o1 show ?case using a1 by force +next + case (o2 s1 s2 t1 t2) + thus ?case using a2 by (simp, blast intro: eqvt_one) +next + case (o3 a t1 t2) + assume j1: "t1 \\<^isub>1 t2" + assume j2: "\x (pi::name prm). P (pi\t1) (pi\t2) x" + show ?case + proof (simp, intro strip) + fix pi::"name prm" and x::"'a::fs_name" + have f: "\c::name. c\(pi\a,pi\t1,pi\t2,x)" + by (rule at_exists_fresh[OF at_name_inst], simp add: fs_name1) + then obtain c::"name" + where f1: "c\(pi\a)" and f2: "c\x" and f3: "c\(pi\t1)" and f4: "c\(pi\t2)" + by (force simp add: fresh_prod fresh_atm) + have x: "P (Lam [c].(([(c,pi\a)]@pi)\t1)) (Lam [c].(([(c,pi\a)]@pi)\t2)) x" + using a3 f2 j1 j2 by (simp, blast intro: eqvt_one) + have alpha1: "(Lam [c].([(c,pi\a)]\(pi\t1))) = (Lam [(pi\a)].(pi\t1))" using f1 f3 + by (simp add: lam.inject alpha) + have alpha2: "(Lam [c].([(c,pi\a)]\(pi\t2))) = (Lam [(pi\a)].(pi\t2))" using f1 f3 + by (simp add: lam.inject alpha) + show " P (Lam [(pi\a)].(pi\t1)) (Lam [(pi\a)].(pi\t2)) x" + using x alpha1 alpha2 by (simp only: pt_name2) + qed +next +case (o4 a s1 s2 t1 t2) + assume j0: "t1 \\<^isub>1 t2" + assume j1: "s1 \\<^isub>1 s2" + assume j2: "\x (pi::name prm). P (pi\t1) (pi\t2) x" + assume j3: "\x (pi::name prm). P (pi\s1) (pi\s2) x" + show ?case + proof (simp, intro strip) + fix pi::"name prm" and x::"'a::fs_name" + have f: "\c::name. c\(pi\a,pi\t1,pi\t2,pi\s1,pi\s2,x)" + by (rule at_exists_fresh[OF at_name_inst], simp add: fs_name1) + then obtain c::"name" + where f1: "c\(pi\a)" and f2: "c\(pi\s1,pi\s2,x)" and f3: "c\(pi\t1)" and f4: "c\(pi\t2)" + by (force simp add: fresh_prod at_fresh[OF at_name_inst]) + have x: "P (App (Lam [c].(([(c,pi\a)]@pi)\t1)) (pi\s1)) ((([(c,pi\a)]@pi)\t2)[c::=(pi\s2)]) x" + using a4 f2 j0 j1 j2 j3 by (simp, blast intro!: eqvt_one) + have alpha1: "(Lam [c].([(c,pi\a)]\(pi\t1))) = (Lam [(pi\a)].(pi\t1))" using f1 f3 + by (simp add: lam.inject alpha) + have alpha2: "(([(c,pi\a)]@pi)\t2)[c::=(pi\s2)] = (pi\t2)[(pi\a)::=(pi\s2)]" + using f4 by (simp only: subst_rename[symmetric] pt_name2) + show "P (App (Lam [(pi\a)].(pi\t1)) (pi\s1)) ((pi\t2)[(pi\a)::=(pi\s2)]) x" + using x alpha1 alpha2 by (simp only: pt_name2) + qed +qed + +lemma one_induct[rule_format, case_names o1 o2 o3 o4]: + fixes P :: "lam \ lam \'a::fs_name\bool" + and t :: "lam" + and s :: "lam" + and x :: "'a::fs_name" + assumes a: "t\\<^isub>1s" + and a1: "\x t. P t t x" + and a2: "\x t1 t2 s1 s2. + t1\\<^isub>1t2 \ (\z. P t1 t2 z) \ s1\\<^isub>1s2 \ (\z. P s1 s2 z) \ + P (App t1 s1) (App t2 s2) x" + and a3: "\x (a::name) s1 s2. a\x \ s1\\<^isub>1s2 \ (\z. P s1 s2 z) + \ P (Lam [a].s1) (Lam [a].s2) x" + and a4: "\x (a::name) t1 t2 s1 s2. + a\(s1,s2,x) \ t1\\<^isub>1t2 \ (\z. P t1 t2 z) \ s1\\<^isub>1s2 \ (\z. P s1 s2 z) + \ P (App (Lam [a].t1) s1) (t2[a::=s2]) x" + shows "P t s x" +using a a1 a2 a3 a4 +by (auto intro!: one_induct_aux[of "t" "s" "P" "[]" "x", simplified]) + +lemma fresh_fact'[rule_format]: + shows "a\t2 \ a\(t1[a::=t2])" +proof (nominal_induct t1 rule: lam_induct) + case (Var a t2 b) + show ?case by (cases "b=a") (force simp add: at_fresh[OF at_name_inst])+ +next + case App + thus ?case by (simp add: fresh_prod) +next + case (Lam a t2 c t) + from Lam(1) have "c\a \ c\t2" by (simp add: fresh_prod fresh_atm) + thus ?case using Lam(2) by (force simp add: abs_fresh) +qed + +lemma one_fresh_preserv[rule_format]: + fixes t :: "lam" + and s :: "lam" + and a :: "name" + assumes a: "t\\<^isub>1s" + shows "a\t \ a\s" +using a +proof (induct) + case o1 show ?case by simp +next + case o2 thus ?case by (simp add: fresh_prod) +next + case (o3 c s1 s2) + assume i: "a\s1 \ a\s2" + show ?case + proof (intro strip, cases "a=c") + assume "a=c" + thus "a\Lam [c].s2" by (simp add: abs_fresh) + next + assume b: "a\c" and "a\Lam [c].s1" + hence "a\s1" by (simp add: abs_fresh) + hence "a\s2" using i by simp + thus "a\Lam [c].s2" using b by (simp add: abs_fresh) + qed +next + case (o4 c t1 t2 s1 s2) + assume i1: "a\t1 \ a\t2" + and i2: "a\s1 \ a\s2" + show "a\App (Lam [c].s1) t1 \ a\s2[c::=t2]" + proof + assume "a\App (Lam [c].s1) t1" + hence c1: "a\Lam [c].s1" and c2: "a\t1" by (simp add: fresh_prod)+ + from c2 i1 have c3: "a\t2" by simp + show "a\s2[c::=t2]" + proof (cases "a=c") + assume "a=c" + thus "a\s2[c::=t2]" using c3 by (simp add: fresh_fact') + next + assume d1: "a\c" + from c1 d1 have "a\s1" by (simp add: abs_fresh) + hence "a\s2" using i2 by simp + thus "a\s2[c::=t2]" using c3 by (simp add: fresh_fact) + qed + qed +qed + +lemma one_abs: + fixes t :: "lam" + and t':: "lam" + and a :: "name" + shows "(Lam [a].t)\\<^isub>1t'\\t''. t'=Lam [a].t'' \ t\\<^isub>1t''" + apply(ind_cases "(Lam [a].t)\\<^isub>1t'") + apply(auto simp add: lam.distinct lam.inject alpha) + apply(rule_tac x="[(a,aa)]\s2" in exI) + apply(rule conjI) + apply(rule pt_bij2[OF pt_name_inst, OF at_name_inst, symmetric]) + apply(simp) + apply(rule pt_name3) + apply(rule at_ds5[OF at_name_inst]) + apply(frule_tac a="a" in one_fresh_preserv) + apply(assumption) + apply(rule conjI) + apply(simp add: pt_fresh_left[OF pt_name_inst, OF at_name_inst]) + apply(simp add: calc_atm) + apply(force intro!: eqvt_one) + done + +lemma one_app: + "App t1 t2 \\<^isub>1 t' \ + (\s1 s2. t' = App s1 s2 \ t1 \\<^isub>1 s1 \ t2 \\<^isub>1 s2) \ + (\a s s1 s2. t1 = Lam [a].s \ t' = s1[a::=s2] \ s \\<^isub>1 s1 \ t2 \\<^isub>1 s2)" + apply(ind_cases "App t1 s1 \\<^isub>1 t'") + apply(auto simp add: lam.distinct lam.inject) + done + +lemma one_red: + "App (Lam [a].t1) t2 \\<^isub>1 M \ + (\s1 s2. M = App (Lam [a].s1) s2 \ t1 \\<^isub>1 s1 \ t2 \\<^isub>1 s2) \ + (\s1 s2. M = s1[a::=s2] \ t1 \\<^isub>1 s1 \ t2 \\<^isub>1 s2)" + apply(ind_cases "App (Lam [a].t1) s1 \\<^isub>1 M") + apply(simp_all add: lam.inject) + apply(force) + apply(erule conjE) + apply(drule sym[of "Lam [a].t1"]) + apply(simp) + apply(drule one_abs) + apply(erule exE) + apply(simp) + apply(force simp add: alpha) + apply(erule conjE) + apply(simp add: lam.inject alpha) + apply(erule disjE) + apply(simp) + apply(force) + apply(simp) + apply(rule disjI2) + apply(rule_tac x="[(a,aa)]\t2a" in exI) + apply(rule_tac x="s2" in exI) + apply(auto) + apply(subgoal_tac "a\t2a")(*A*) + apply(simp add: subst_rename) + (*A*) + apply(force intro: one_fresh_preserv) + apply(force intro: eqvt_one) + done + +(* first case in Lemma 3.2.4*) + +lemma one_subst_aux[rule_format]: + fixes M :: "lam" + and N :: "lam" + and N':: "lam" + and x :: "name" + shows "N\\<^isub>1N'\M[x::=N] \\<^isub>1 M[x::=N']" +proof (nominal_induct M rule: lam_induct) + case (Var N N' x y) + show "N\\<^isub>1N' \ Var y[x::=N] \\<^isub>1 Var y[x::=N']" by (cases "x=y", auto) +next + case (App N N' x P Q) (* application case - third line *) + thus "N\\<^isub>1N' \ (App P Q)[x::=N] \\<^isub>1 (App P Q)[x::=N']" using o2 by simp +next + case (Lam N N' x y P) (* abstraction case - fourth line *) + thus "N\\<^isub>1N' \ (Lam [y].P)[x::=N] \\<^isub>1 (Lam [y].P)[x::=N']" using o3 + by (simp add: fresh_prod fresh_atm) +qed + +lemma one_subst_aux[rule_format]: + fixes M :: "lam" + and N :: "lam" + and N':: "lam" + and x :: "name" + shows "N\\<^isub>1N'\M[x::=N] \\<^isub>1 M[x::=N']" +apply(nominal_induct M rule: lam_induct) +apply(auto simp add: fresh_prod fresh_atm) +done + +lemma one_subst[rule_format]: + fixes M :: "lam" + and M':: "lam" + and N :: "lam" + and N':: "lam" + and x :: "name" + assumes a: "M\\<^isub>1M'" + shows "N\\<^isub>1N' \ M[x::=N]\\<^isub>1M'[x::=N']" +using a +proof (nominal_induct M M' rule: one_induct) + case (o1 x N N' M) + show ?case by (simp add: one_subst_aux) +next + case (o2 x N N' M1 M2 N1 N2) + thus ?case by simp +next + case (o3 x N N' a M1 M2) + thus ?case by (simp add: fresh_prod fresh_atm) +next + case (o4 N N' x a M1 M2 N1 N2) + assume e3: "a\(N1,N2,N,N',x)" + show ?case + proof + assume a1: "N\\<^isub>1N'" + have "(App (Lam [a].M1) N1)[x::=N] = App (Lam [a].(M1[x::=N])) (N1[x::=N])" + using e3 by (simp add: fresh_prod fresh_atm) + also have "App (Lam [a].(M1[x::=N])) (N1[x::=N]) \\<^isub>1 M2[x::=N'][a::=N2[x::=N']]" + using o4 a1 by force + also have "M2[x::=N'][a::=N2[x::=N']] = M2[a::=N2][x::=N']" + using e3 by (simp add: subs_lemma fresh_prod fresh_atm) + ultimately show "(App (Lam [a].M1) N1)[x::=N] \\<^isub>1 M2[a::=N2][x::=N']" by simp + qed +qed + +lemma one_subst[rule_format]: + assumes a: "M\\<^isub>1M'" + shows "N\\<^isub>1N' \ M[x::=N]\\<^isub>1M'[x::=N']" +using a +apply(nominal_induct M M' rule: one_induct) +apply(auto simp add: one_subst_aux subs_lemma fresh_prod fresh_atm) +done + +lemma diamond[rule_format]: + fixes M :: "lam" + and M1:: "lam" + assumes a: "M\\<^isub>1M1" + shows "\M2. (M\\<^isub>1M2) \ (\M3. M1\\<^isub>1M3 \ M2\\<^isub>1M3)" + using a +proof (induct) + case (o1 M) (* case 1 --- M1 = M *) + show "\M2. M\\<^isub>1M2 \ (\M3. M\\<^isub>1M3 \ M2\\<^isub>1M3)" by force +next + case (o4 x Q Q' P P') (* case 2 --- a beta-reduction occurs*) + assume i1: "\M2. Q \\<^isub>1M2 \ (\M3. Q'\\<^isub>1M3 \ M2\\<^isub>1M3)" + assume i2: "\M2. P \\<^isub>1M2 \ (\M3. P'\\<^isub>1M3 \ M2\\<^isub>1M3)" + show "\M2. App (Lam [x].P) Q\\<^isub>1M2 \ (\M3. P'[x::=Q']\\<^isub>1M3 \ M2\\<^isub>1M3)" + proof (intro strip) + fix M2 + assume "App (Lam [x].P) Q \\<^isub>1 M2" + hence "(\P' Q'. M2 = App (Lam [x].P') Q' \ P\\<^isub>1P' \ Q\\<^isub>1Q') \ + (\P' Q'. M2 = P'[x::=Q'] \ P\\<^isub>1P' \ Q\\<^isub>1Q')" by (simp add: one_red) + moreover (* subcase 2.1 *) + { assume "\P' Q'. M2 = App (Lam [x].P') Q' \ P\\<^isub>1P' \ Q\\<^isub>1Q'" + then obtain P'' and Q'' where + b1: "M2=App (Lam [x].P'') Q''" and b2: "P\\<^isub>1P''" and b3: "Q\\<^isub>1Q''" by force + from b2 i2 have "(\M3. P'\\<^isub>1M3 \ P''\\<^isub>1M3)" by simp + then obtain P''' where + c1: "P'\\<^isub>1P'''" and c2: "P''\\<^isub>1P'''" by force + from b3 i1 have "(\M3. Q'\\<^isub>1M3 \ Q''\\<^isub>1M3)" by simp + then obtain Q''' where + d1: "Q'\\<^isub>1Q'''" and d2: "Q''\\<^isub>1Q'''" by force + from c1 c2 d1 d2 + have "P'[x::=Q']\\<^isub>1P'''[x::=Q'''] \ App (Lam [x].P'') Q'' \\<^isub>1 P'''[x::=Q''']" + by (force simp add: one_subst) + hence "\M3. P'[x::=Q']\\<^isub>1M3 \ M2\\<^isub>1M3" using b1 by force + } + moreover (* subcase 2.2 *) + { assume "\P' Q'. M2 = P'[x::=Q'] \ P\\<^isub>1P' \ Q\\<^isub>1Q'" + then obtain P'' Q'' where + b1: "M2=P''[x::=Q'']" and b2: "P\\<^isub>1P''" and b3: "Q\\<^isub>1Q''" by force + from b2 i2 have "(\M3. P'\\<^isub>1M3 \ P''\\<^isub>1M3)" by simp + then obtain P''' where + c1: "P'\\<^isub>1P'''" and c2: "P''\\<^isub>1P'''" by force + from b3 i1 have "(\M3. Q'\\<^isub>1M3 \ Q''\\<^isub>1M3)" by simp + then obtain Q''' where + d1: "Q'\\<^isub>1Q'''" and d2: "Q''\\<^isub>1Q'''" by force + from c1 c2 d1 d2 + have "P'[x::=Q']\\<^isub>1P'''[x::=Q'''] \ P''[x::=Q'']\\<^isub>1P'''[x::=Q''']" + by (force simp add: one_subst) + hence "\M3. P'[x::=Q']\\<^isub>1M3 \ M2\\<^isub>1M3" using b1 by force + } + ultimately show "\M3. P'[x::=Q']\\<^isub>1M3 \ M2\\<^isub>1M3" by blast + qed +next + case (o2 Q Q' P P') (* case 3 *) + assume i0: "P\\<^isub>1P'" + assume i1: "\M2. Q \\<^isub>1M2 \ (\M3. Q'\\<^isub>1M3 \ M2\\<^isub>1M3)" + assume i2: "\M2. P \\<^isub>1M2 \ (\M3. P'\\<^isub>1M3 \ M2\\<^isub>1M3)" + show "\M2. App P Q\\<^isub>1M2 \ (\M3. App P' Q'\\<^isub>1M3 \ M2\\<^isub>1M3)" + proof (intro strip) + fix M2 + assume "App P Q \\<^isub>1 M2" + hence "(\P'' Q''. M2 = App P'' Q'' \ P\\<^isub>1P'' \ Q\\<^isub>1Q'') \ + (\x P' P'' Q'. P = Lam [x].P' \ M2 = P''[x::=Q'] \ P'\\<^isub>1 P'' \ Q\\<^isub>1Q')" + by (simp add: one_app[simplified]) + moreover (* subcase 3.1 *) + { assume "\P'' Q''. M2 = App P'' Q'' \ P\\<^isub>1P'' \ Q\\<^isub>1Q''" + then obtain P'' and Q'' where + b1: "M2=App P'' Q''" and b2: "P\\<^isub>1P''" and b3: "Q\\<^isub>1Q''" by force + from b2 i2 have "(\M3. P'\\<^isub>1M3 \ P''\\<^isub>1M3)" by simp + then obtain P''' where + c1: "P'\\<^isub>1P'''" and c2: "P''\\<^isub>1P'''" by force + from b3 i1 have "(\M3. Q'\\<^isub>1M3 \ Q''\\<^isub>1M3)" by simp + then obtain Q''' where + d1: "Q'\\<^isub>1Q'''" and d2: "Q''\\<^isub>1Q'''" by force + from c1 c2 d1 d2 + have "App P' Q'\\<^isub>1App P''' Q''' \ App P'' Q'' \\<^isub>1 App P''' Q'''" by force + hence "\M3. App P' Q'\\<^isub>1M3 \ M2\\<^isub>1M3" using b1 by force + } + moreover (* subcase 3.2 *) + { assume "\x P1 P'' Q''. P = Lam [x].P1 \ M2 = P''[x::=Q''] \ P1\\<^isub>1 P'' \ Q\\<^isub>1Q''" + then obtain x P1 P1'' Q'' where + b0: "P=Lam [x].P1" and b1: "M2=P1''[x::=Q'']" and + b2: "P1\\<^isub>1P1''" and b3: "Q\\<^isub>1Q''" by force + from b0 i0 have "\P1'. P'=Lam [x].P1' \ P1\\<^isub>1P1'" by (simp add: one_abs) + then obtain P1' where g1: "P'=Lam [x].P1'" and g2: "P1\\<^isub>1P1'" by force + from g1 b0 b2 i2 have "(\M3. (Lam [x].P1')\\<^isub>1M3 \ (Lam [x].P1'')\\<^isub>1M3)" by simp + then obtain P1''' where + c1: "(Lam [x].P1')\\<^isub>1P1'''" and c2: "(Lam [x].P1'')\\<^isub>1P1'''" by force + from c1 have "\R1. P1'''=Lam [x].R1 \ P1'\\<^isub>1R1" by (simp add: one_abs) + then obtain R1 where r1: "P1'''=Lam [x].R1" and r2: "P1'\\<^isub>1R1" by force + from c2 have "\R2. P1'''=Lam [x].R2 \ P1''\\<^isub>1R2" by (simp add: one_abs) + then obtain R2 where r3: "P1'''=Lam [x].R2" and r4: "P1''\\<^isub>1R2" by force + from r1 r3 have r5: "R1=R2" + by (simp add: lam.inject alpha) + from b3 i1 have "(\M3. Q'\\<^isub>1M3 \ Q''\\<^isub>1M3)" by simp + then obtain Q''' where + d1: "Q'\\<^isub>1Q'''" and d2: "Q''\\<^isub>1Q'''" by force + from g1 r2 d1 r4 r5 d2 + have "App P' Q'\\<^isub>1R1[x::=Q'''] \ P1''[x::=Q'']\\<^isub>1R1[x::=Q''']" by (simp add: one_subst) + hence "\M3. App P' Q'\\<^isub>1M3 \ M2\\<^isub>1M3" using b1 by force + } + ultimately show "\M3. App P' Q'\\<^isub>1M3 \ M2\\<^isub>1M3" by blast + qed +next + case (o3 x P P') (* case 4 *) + assume i1: "P\\<^isub>1P'" + assume i2: "\M2. P \\<^isub>1M2 \ (\M3. P'\\<^isub>1M3 \ M2\\<^isub>1M3)" + show "\M2. (Lam [x].P)\\<^isub>1M2 \ (\M3. (Lam [x].P')\\<^isub>1M3 \ M2\\<^isub>1M3)" + proof (intro strip) + fix M2 + assume "(Lam [x].P)\\<^isub>1 M2" + hence "\P''. M2=Lam [x].P'' \ P\\<^isub>1P''" by (simp add: one_abs) + then obtain P'' where b1: "M2=Lam [x].P''" and b2: "P\\<^isub>1P''" by force + from i2 b1 b2 have "\M3. (Lam [x].P')\\<^isub>1M3 \ (Lam [x].P'')\\<^isub>1M3" by force + then obtain M3 where c1: "(Lam [x].P')\\<^isub>1M3" and c2: "(Lam [x].P'')\\<^isub>1M3" by force + from c1 have "\R1. M3=Lam [x].R1 \ P'\\<^isub>1R1" by (simp add: one_abs) + then obtain R1 where r1: "M3=Lam [x].R1" and r2: "P'\\<^isub>1R1" by force + from c2 have "\R2. M3=Lam [x].R2 \ P''\\<^isub>1R2" by (simp add: one_abs) + then obtain R2 where r3: "M3=Lam [x].R2" and r4: "P''\\<^isub>1R2" by force + from r1 r3 have r5: "R1=R2" + by (simp add: lam.inject alpha) + from r2 r4 have "(Lam [x].P')\\<^isub>1(Lam [x].R1) \ (Lam [x].P'')\\<^isub>1(Lam [x].R2)" + by (simp add: one_subst) + thus "\M3. (Lam [x].P')\\<^isub>1M3 \ M2\\<^isub>1M3" using b1 r5 by force + qed +qed + +lemma one_abs_cong: + fixes a :: "name" + assumes a: "t1\\<^isub>\\<^sup>*t2" + shows "(Lam [a].t1)\\<^isub>\\<^sup>*(Lam [a].t2)" + using a +proof induct + case 1 thus ?case by force +next + case (2 y z) + thus ?case by (force dest: b3 intro: rtrancl_trans) +qed + +lemma one_pr_congL: + assumes a: "t1\\<^isub>\\<^sup>*t2" + shows "App t1 s\\<^isub>\\<^sup>* App t2 s" + using a +proof induct + case 1 thus ?case by (force) +next + case 2 thus ?case by (force dest: b1 intro: rtrancl_trans) +qed + +lemma one_pr_congR: + assumes a: "t1\\<^isub>\\<^sup>*t2" + shows "App s t1 \\<^isub>\\<^sup>* App s t2" +using a +proof induct + case 1 thus ?case by (force) +next + case 2 thus ?case by (force dest: b2 intro: rtrancl_trans) +qed + +lemma one_pr_cong: + assumes a1: "t1\\<^isub>\\<^sup>*t2" + and a2: "s1\\<^isub>\\<^sup>*s2" + shows "App t1 s1\\<^isub>\\<^sup>* App t2 s2" +proof - + have b1: "App t1 s1 \\<^isub>\\<^sup>* App t2 s1" using a1 by (rule one_pr_congL) + have b2: "App t2 s1 \\<^isub>\\<^sup>* App t2 s2" using a2 by (rule one_pr_congR) + show ?thesis using b1 and b2 by (force intro: rtrancl_trans) +qed + +lemma one_beta_star: + assumes a: "(t1\\<^isub>1t2)" + shows "(t1\\<^isub>\\<^sup>*t2)" + using a +proof induct + case o1 thus ?case by (force) +next + case o2 thus ?case by (force intro!: one_pr_cong) +next + case o3 thus ?case by (force intro!: one_abs_cong) +next + case (o4 a s1 s2 t1 t2) + have a1: "t1\\<^isub>\\<^sup>*t2" and a2: "s1\\<^isub>\\<^sup>*s2" . + have c1: "(App (Lam [a].t2) s2) \\<^isub>\ (t2 [a::= s2])" by (rule b4) + from a1 a2 have c2: "App (Lam [a].t1 ) s1 \\<^isub>\\<^sup>* App (Lam [a].t2 ) s2" + by (force intro!: one_pr_cong one_abs_cong) + show ?case using c1 c2 by (force intro: rtrancl_trans) +qed + +lemma one_star_abs_cong: + fixes a :: "name" + assumes a: "t1\\<^isub>1\<^sup>*t2" + shows "(Lam [a].t1)\\<^isub>1\<^sup>* (Lam [a].t2)" + using a +proof induct + case 1 thus ?case by (force) +next + case 2 thus ?case by (force intro: rtrancl_trans) +qed + +lemma one_star_pr_congL: + assumes a: "t1\\<^isub>1\<^sup>*t2" + shows "App t1 s\\<^isub>1\<^sup>* App t2 s" + using a +proof induct + case 1 thus ?case by (force) +next + case 2 thus ?case by (force intro: rtrancl_trans) +qed + +lemma one_star_pr_congR: + assumes a: "t1\\<^isub>1\<^sup>*t2" + shows "App s t1 \\<^isub>1\<^sup>* App s t2" + using a +proof induct + case 1 thus ?case by (force) +next + case 2 thus ?case by (force intro: rtrancl_trans) +qed + +lemma beta_one_star: + assumes a: "t1\\<^isub>\t2" + shows "t1\\<^isub>1\<^sup>*t2" + using a +proof induct + case b1 thus ?case by (force intro!: one_star_pr_congL) +next + case b2 thus ?case by (force intro!: one_star_pr_congR) +next + case b3 thus ?case by (force intro!: one_star_abs_cong) +next + case b4 thus ?case by (force) +qed + +lemma trans_closure: + shows "(t1\\<^isub>1\<^sup>*t2) = (t1\\<^isub>\\<^sup>*t2)" +proof + assume "t1 \\<^isub>1\<^sup>* t2" + thus "t1\\<^isub>\\<^sup>*t2" + proof induct + case 1 thus ?case by (force) + next + case 2 thus ?case by (force intro: rtrancl_trans simp add: one_beta_star) + qed +next + assume "t1 \\<^isub>\\<^sup>* t2" + thus "t1\\<^isub>1\<^sup>*t2" + proof induct + case 1 thus ?case by (force) + next + case 2 thus ?case by (force intro: rtrancl_trans simp add: beta_one_star) + qed +qed + +lemma cr_one: + assumes a: "t\\<^isub>1\<^sup>*t1" + and b: "t\\<^isub>1t2" + shows "\t3. t1\\<^isub>1t3 \ t2\\<^isub>1\<^sup>*t3" +proof - + have stronger: "\t2. t\\<^isub>1t2\(\t3. t1\\<^isub>1t3\t2\\<^isub>1\<^sup>*t3)" + using a + proof induct + case 1 show ?case by (force) + next + case (2 s1 s2) + assume b: "s1 \\<^isub>1 s2" + assume h: "\t2. t \\<^isub>1 t2 \ (\t3. s1 \\<^isub>1 t3 \ t2 \\<^isub>1\<^sup>* t3)" + show ?case + proof (rule allI, rule impI) + fix t2 + assume c: "t \\<^isub>1 t2" + show "(\t3. s2 \\<^isub>1 t3 \ t2 \\<^isub>1\<^sup>* t3)" + proof - + from c h have "(\t3. s1 \\<^isub>1 t3 \ t2 \\<^isub>1\<^sup>* t3)" by force + then obtain t3 where c1: "s1 \\<^isub>1 t3" + and c2: "t2 \\<^isub>1\<^sup>* t3" by (force) + have "(\t4. s2 \\<^isub>1 t4 \ t3 \\<^isub>1 t4)" using b c1 by (force intro: diamond) + thus ?thesis using c2 by (force intro: rtrancl_trans) + qed + qed + qed + from a b stronger show ?thesis by force +qed + + +lemma cr_one_star: + assumes a: "t\\<^isub>1\<^sup>*t2" + and b: "t\\<^isub>1\<^sup>*t1" + shows "(\t3. t1\\<^isub>1\<^sup>*t3\t2\\<^isub>1\<^sup>*t3)" +using a +proof induct + case 1 + show ?case using b by force +next + case (2 s1 s2) + assume d: "s1 \\<^isub>1 s2" + assume "\t3. t1 \\<^isub>1\<^sup>* t3 \ s1 \\<^isub>1\<^sup>* t3" + then obtain t3 where f1: "t1 \\<^isub>1\<^sup>* t3" + and f2: "s1 \\<^isub>1\<^sup>* t3" by force + from cr_one d f2 have "\t4. t3\\<^isub>1t4 \ s2\\<^isub>1\<^sup>*t4" by force + then obtain t4 where g1: "t3\\<^isub>1t4" + and g2: "s2\\<^isub>1\<^sup>*t4" by force + have "t1\\<^isub>1\<^sup>*t4" using f1 g1 by (force intro: rtrancl_trans) + thus ?case using g2 by (force) +qed + +lemma cr_beta_star: + assumes a1: "t\\<^isub>\\<^sup>*t1" + and a2: "t\\<^isub>\\<^sup>*t2" + shows "(\t3. t1\\<^isub>\\<^sup>*t3\t2\\<^isub>\\<^sup>*t3)" +proof - + from a1 have b1: "t\\<^isub>1\<^sup>*t1" by (simp add: trans_closure[symmetric]) + from a2 have b2: "t\\<^isub>1\<^sup>*t2" by (simp add: trans_closure[symmetric]) + from b1 and b2 have c: "\t3. (t1\\<^isub>1\<^sup>*t3 \ t2\\<^isub>1\<^sup>*t3)" by (force intro!: cr_one_star) + from c obtain t3 where d1: "t1\\<^isub>1\<^sup>*t3" and d2: "t2\\<^isub>1\<^sup>*t3" by force + from d1 have e1: "t1\\<^isub>\\<^sup>*t3" by (simp add: trans_closure) + from d2 have e2: "t2\\<^isub>\\<^sup>*t3" by (simp add: trans_closure) + show ?thesis using e1 and e2 by (force) +qed + +end + diff -r 4c9c081a416b -r 836135c8acb2 src/HOL/Nominal/Examples/Lam_substs.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Nominal/Examples/Lam_substs.thy Mon Nov 07 15:19:03 2005 +0100 @@ -0,0 +1,1561 @@ + +theory lam_substs +imports "../nominal" +begin + +atom_decl name + +nominal_datatype lam = Var "name" + | App "lam" "lam" + | Lam "\name\lam" ("Lam [_]._" [100,100] 100) + +section {* strong induction principles for lam *} + +lemma lam_induct_aux: + fixes P :: "lam \ 'a \ bool" + and f :: "'a \ name set" + assumes fs: "\x. finite (f x)" + and h1: "\x a. P (Var a) x" + and h2: "\x t1 t2. (\z. P t1 z) \ (\z. P t2 z) \ P (App t1 t2) x" + and h3: "\x a t. a\f x \ (\z. P t z) \ P (Lam [a].t) x" + shows "\(pi::name prm) x. P (pi\t) x" +proof (induct rule: lam.induct_weak) + case (Lam a t) + assume i1: "\(pi::name prm) x. P (pi\t) x" + show ?case + proof (intro strip, simp add: abs_perm) + fix x::"'a" and pi::"name prm" + have f: "\c::name. c\(f x,pi\a,pi\t)" + by (rule at_exists_fresh[OF at_name_inst], simp add: supp_prod fs_name1 + at_fin_set_supp[OF at_name_inst, OF fs] fs) + then obtain c::"name" + where f1: "c\(pi\a)" and f2: "c\(f x)" and f3: "c\(pi\t)" + by (force simp add: fresh_prod at_fresh[OF at_name_inst]) + have g: "Lam [c].([(c,pi\a)]\(pi\t)) = Lam [(pi\a)].(pi\t)" using f1 f3 + by (simp add: lam.inject alpha) + from i1 have "\x. P (([(c,pi\a)]@pi)\t) x" by force + hence i1b: "\x. P ([(c,pi\a)]\(pi\t)) x" by (simp add: pt_name2[symmetric]) + with h3 f2 have "P (Lam [c].([(c,pi\a)]\(pi\t))) x" + by (auto simp add: fresh_def at_fin_set_supp[OF at_name_inst, OF fs]) + with g show "P (Lam [(pi\a)].(pi\t)) x" by simp + qed +qed (auto intro: h1 h2) + +lemma lam_induct'[case_names Fin Var App Lam]: + fixes P :: "lam \ 'a \ bool" + and x :: "'a" + and t :: "lam" + and f :: "'a \ name set" + assumes fs: "\x. finite (f x)" + and h1: "\x a. P (Var a) x" + and h2: "\x t1 t2. (\z. P t1 z)\(\z. P t2 z)\P (App t1 t2) x" + and h3: "\x a t. a\f x \ (\z. P t z)\ P (Lam [a].t) x" + shows "P t x" +proof - + from fs h1 h2 h3 have "\(pi::name prm) x. P (pi\t) x" by (rule lam_induct_aux, auto) + hence "P (([]::name prm)\t) x" by blast + thus "P t x" by simp +qed + +lemma lam_induct[case_names Var App Lam]: + fixes P :: "lam \ ('a::fs_name) \ bool" + and x :: "'a::fs_name" + and t :: "lam" + assumes h1: "\x a. P (Var a) x" + and h2: "\x t1 t2. (\z. P t1 z)\(\z. P t2 z)\P (App t1 t2) x" + and h3: "\x a t. a\x \ (\z. P t z)\ P (Lam [a].t) x" + shows "P t x" +by (rule lam_induct'[of "\x. ((supp x)::name set)" "P"], + simp_all add: fs_name1 fresh_def[symmetric], auto intro: h1 h2 h3) + +types 'a f1_ty = "name\('a::pt_name)" + 'a f2_ty = "'a\'a\('a::pt_name)" + 'a f3_ty = "name\'a\('a::pt_name)" + +lemma f3_freshness_conditions: + fixes f3::"('a::pt_name) f3_ty" + and y ::"name prm \ 'a::pt_name" + and a ::"name" + and pi1::"name prm" + and pi2::"name prm" + assumes a: "finite ((supp f3)::name set)" + and b: "finite ((supp y)::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "\(a''::name). a''\(\a'. f3 a' (y (pi1@[(a,pi2\a')]))) \ + a''\(\a'. f3 a' (y (pi1@[(a,pi2\a')]))) a''" +proof - + from c obtain a' where d0: "a'\f3" and d1: "\(y::'a::pt_name). a'\f3 a' y" by force + have "\(a''::name). a''\(f3,a,a',pi1,pi2,y)" + by (rule at_exists_fresh[OF at_name_inst], simp add: supp_prod fs_name1 a b) + then obtain a'' where d2: "a''\f3" and d3: "a''\a'" and d3b: "a''\(f3,a,pi1,pi2,y)" + by (auto simp add: fresh_prod at_fresh[OF at_name_inst]) + have d3c: "a''\((supp (f3,a,pi1,pi2,y))::name set)" using d3b by (simp add: fresh_def) + have d4: "a''\f3 a'' (y (pi1@[(a,pi2\a'')]))" + proof - + have d5: "[(a'',a')]\f3 = f3" + by (rule pt_fresh_fresh[OF pt_name_inst, OF at_name_inst, OF d2, OF d0]) + from d1 have "\(y::'a::pt_name). ([(a'',a')]\a')\([(a'',a')]\(f3 a' y))" + by (simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst]) + hence "\(y::'a::pt_name). a''\(f3 a'' ([(a'',a')]\y))" using d3 d5 + by (simp add: at_calc[OF at_name_inst] pt_fun_app_eq[OF pt_name_inst, OF at_name_inst]) + hence "a''\(f3 a'' ([(a'',a')]\((rev [(a'',a')])\(y (pi1@[(a,pi2\a'')])))))" by force + thus ?thesis by (simp only: pt_pi_rev[OF pt_name_inst, OF at_name_inst]) + qed + have d6: "a''\(\a'. f3 a' (y (pi1@[(a,pi2\a')])))" + proof - + from a b have d7: "finite ((supp (f3,a,pi1,pi2,y))::name set)" by (simp add: supp_prod fs_name1) + have e: "((supp (f3,a,pi1,pi2,y))::name set) supports (\a'. f3 a' (y (pi1@[(a,pi2\a')])))" + by (supports_simp add: perm_append) + from e d7 d3c show ?thesis by (rule supports_fresh) + qed + from d6 d4 show ?thesis by force +qed + +lemma f3_freshness_conditions_simple: + fixes f3::"('a::pt_name) f3_ty" + and y ::"name prm \ 'a::pt_name" + and a ::"name" + and pi::"name prm" + assumes a: "finite ((supp f3)::name set)" + and b: "finite ((supp y)::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "\(a''::name). a''\(\a'. f3 a' (y (pi@[(a,a')]))) \ a''\(\a'. f3 a' (y (pi@[(a,a')]))) a''" +proof - + from c obtain a' where d0: "a'\f3" and d1: "\(y::'a::pt_name). a'\f3 a' y" by force + have "\(a''::name). a''\(f3,a,a',pi,y)" + by (rule at_exists_fresh[OF at_name_inst], simp add: supp_prod fs_name1 a b) + then obtain a'' where d2: "a''\f3" and d3: "a''\a'" and d3b: "a''\(f3,a,pi,y)" + by (auto simp add: fresh_prod at_fresh[OF at_name_inst]) + have d3c: "a''\((supp (f3,a,pi,y))::name set)" using d3b by (simp add: fresh_def) + have d4: "a''\f3 a'' (y (pi@[(a,a'')]))" + proof - + have d5: "[(a'',a')]\f3 = f3" + by (rule pt_fresh_fresh[OF pt_name_inst, OF at_name_inst, OF d2, OF d0]) + from d1 have "\(y::'a::pt_name). ([(a'',a')]\a')\([(a'',a')]\(f3 a' y))" + by (simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst]) + hence "\(y::'a::pt_name). a''\(f3 a'' ([(a'',a')]\y))" using d3 d5 + by (simp add: at_calc[OF at_name_inst] pt_fun_app_eq[OF pt_name_inst, OF at_name_inst]) + hence "a''\(f3 a'' ([(a'',a')]\((rev [(a'',a')])\(y (pi@[(a,a'')])))))" by force + thus ?thesis by (simp only: pt_pi_rev[OF pt_name_inst, OF at_name_inst]) + qed + have d6: "a''\(\a'. f3 a' (y (pi@[(a,a')])))" + proof - + from a b have d7: "finite ((supp (f3,a,pi,y))::name set)" by (simp add: supp_prod fs_name1) + have "((supp (f3,a,pi,y))::name set) supports (\a'. f3 a' (y (pi@[(a,a')])))" + by (supports_simp add: perm_append) + with d7 d3c show ?thesis by (simp add: supports_fresh) + qed + from d6 d4 show ?thesis by force +qed + +lemma f3_fresh_fun_supports: + fixes f3::"('a::pt_name) f3_ty" + and a ::"name" + and pi1::"name prm" + and y ::"name prm \ 'a::pt_name" + assumes a: "finite ((supp f3)::name set)" + and b: "finite ((supp y)::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "((supp (f3,a,y))::name set) supports (\pi. fresh_fun (\a'. f3 a' (y (pi@[(a,a')]))))" +proof (auto simp add: "op supports_def" perm_fun_def expand_fun_eq fresh_def[symmetric]) + fix b::"name" and c::"name" and pi::"name prm" + assume b1: "b\(f3,a,y)" + and b2: "c\(f3,a,y)" + from b1 b2 have b3: "[(b,c)]\f3=f3" and t4: "[(b,c)]\a=a" and t5: "[(b,c)]\y=y" + by (simp_all add: pt_fresh_fresh[OF pt_name_inst, OF at_name_inst] fresh_prod) + let ?g = "\a'. f3 a' (y (([(b,c)]\pi)@[(a,a')]))" + and ?h = "\a'. f3 a' (y (pi@[(a,a')]))" + have a0: "finite ((supp (f3,a,[(b,c)]\pi,y))::name set)" using a b + by (simp add: supp_prod fs_name1) + have a1: "((supp (f3,a,[(b,c)]\pi,y))::name set) supports ?g" by (supports_simp add: perm_append) + hence a2: "finite ((supp ?g)::name set)" using a0 by (rule supports_finite) + have a3: "\(a''::name). a''\?g \ a''\(?g a'')" + by (rule f3_freshness_conditions_simple[OF a, OF b, OF c]) + have "((supp (f3,a,y))::name set) \ (supp (f3,a,[(b,c)]\pi,y))" by (force simp add: supp_prod) + have a4: "[(b,c)]\?g = ?h" using b1 b2 + by (simp add: fresh_prod, perm_simp add: perm_append) + have "[(b,c)]\(fresh_fun ?g) = fresh_fun ([(b,c)]\?g)" + by (simp add: fresh_fun_equiv[OF pt_name_inst, OF at_name_inst, OF a2, OF a3]) + also have "\ = fresh_fun ?h" using a4 by simp + finally show "[(b,c)]\(fresh_fun ?g) = fresh_fun ?h" . +qed + +lemma f3_fresh_fun_supp_finite: + fixes f3::"('a::pt_name) f3_ty" + and a ::"name" + and pi1::"name prm" + and y ::"name prm \ 'a::pt_name" + assumes a: "finite ((supp f3)::name set)" + and b: "finite ((supp y)::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "finite ((supp (\pi. fresh_fun (\a'. f3 a' (y (pi@[(a,a')])))))::name set)" +proof - + have "((supp (f3,a,y))::name set) supports (\pi. fresh_fun (\a'. f3 a' (y (pi@[(a,a')]))))" + using a b c by (rule f3_fresh_fun_supports) + moreover + have "finite ((supp (f3,a,y))::name set)" using a b by (simp add: supp_prod fs_name1) + ultimately show ?thesis by (rule supports_finite) +qed + +(* +types 'a recT = "'a f1_ty \ 'a f2_ty \ 'a f3_ty \ ((lam\name prm\('a::pt_name)) set)" + +consts + rec :: "('a::pt_name) recT" + +inductive "rec f1 f2 f3" +intros +r1: "(Var a,pi,f1 (pi\a))\rec f1 f2 f3" +r2: "\finite ((supp y1)::name set);(t1,pi,y1)\rec f1 f2 f3; + finite ((supp y2)::name set);(t2,pi,y2)\rec f1 f2 f3\ + \ (App t1 t2,pi,f2 y1 y2)\rec f1 f2 f3" +r3: "\finite ((supp y)::name set);\a'. ((t,pi@[(a,a')],y)\rec f1 f2 f3)\ + \ (Lam [a].t,pi,fresh_fun (\a'. f3 a' y))\rec f1 f2 f3" + +*) + +(* +types 'a recT = "'a f1_ty \ 'a f2_ty \ 'a f3_ty \ (lam\(name prm \ ('a::pt_name))) set" + +consts + rec :: "('a::pt_name) recT" + +inductive "rec f1 f2 f3" +intros +r1: "(Var a,\pi. f1 (pi\a))\rec f1 f2 f3" +r2: "\finite ((supp y1)::name set);(t1,y1)\rec f1 f2 f3; + finite ((supp y2)::name set);(t2,y2)\rec f1 f2 f3\ + \ (App t1 t2,\pi. f2 (y1 pi) (y2 pi))\rec f1 f2 f3" +r3: "\finite ((supp y)::name set);(t,y)\rec f1 f2 f3\ + \ (Lam [a].t,fresh_fun (\a' pi. f3 a' (y (pi@[(a,a')]))))\rec f1 f2 f3" +*) + +term lam_Rep.Var +term lam_Rep.Lam + +consts nthe :: "'a nOption \ 'a" +primrec + "nthe (nSome x) = x" + +types 'a recT = "'a f1_ty \ 'a f2_ty \ 'a f3_ty \ (lam\(name prm \ ('a::pt_name))) set" + +(* +consts fn :: "'a f1_ty \ 'a f2_ty \ 'a f3_ty \ lam_Rep \ ('a::pt_name)" + +primrec +"fn f1 f2 f3 (lam_Rep.Var a) = f1 a" +"fn f1 f2 f3 (lam_Rep.App t1 t2) = f2 (fn f1 f2 f3 t1) (fn f1 f2 f3 t2)" +"fn f1 f2 f3 (lam_Rep.Lam f) = fresh_fun (\a'. f3 a' (fn f1 f2 f3 (fn' (f a'))))" +*) + +consts + rec :: "('a::pt_name) recT" + +inductive "rec f1 f2 f3" +intros +r1: "(Var a,\pi. f1 (pi\a))\rec f1 f2 f3" +r2: "\finite ((supp y1)::name set);(t1,y1)\rec f1 f2 f3; + finite ((supp y2)::name set);(t2,y2)\rec f1 f2 f3\ + \ (App t1 t2,\pi. f2 (y1 pi) (y2 pi))\rec f1 f2 f3" +r3: "\finite ((supp y)::name set);(t,y)\rec f1 f2 f3\ + \ (Lam [a].t,\pi. fresh_fun (\a'. f3 a' (y (pi@[(a,a')]))))\rec f1 f2 f3" + +constdefs + rfun' :: "'a f1_ty \ 'a f2_ty \ 'a f3_ty \ lam \ name prm \ ('a::pt_name)" + "rfun' f1 f2 f3 t \ (THE y. (t,y)\rec f1 f2 f3)" + + rfun :: "'a f1_ty \ 'a f2_ty \ 'a f3_ty \ lam \ ('a::pt_name)" + "rfun f1 f2 f3 t \ rfun' f1 f2 f3 t ([]::name prm)" + +lemma rec_prm_eq[rule_format]: + fixes f1 ::"('a::pt_name) f1_ty" + and f2 ::"('a::pt_name) f2_ty" + and f3 ::"('a::pt_name) f3_ty" + and t ::"lam" + and y ::"name prm \ ('a::pt_name)" + shows "(t,y)\rec f1 f2 f3 \ (\(pi1::name prm) (pi2::name prm). pi1 \ pi2 \ (y pi1 = y pi2))" +apply(erule rec.induct) +apply(auto simp add: pt3[OF pt_name_inst]) +apply(rule_tac f="fresh_fun" in arg_cong) +apply(auto simp add: expand_fun_eq) +apply(drule_tac x="pi1@[(a,x)]" in spec) +apply(drule_tac x="pi2@[(a,x)]" in spec) +apply(force simp add: prm_eq_def pt2[OF pt_name_inst]) +done + +(* silly helper lemma *) +lemma rec_trans: + fixes f1 ::"('a::pt_name) f1_ty" + and f2 ::"('a::pt_name) f2_ty" + and f3 ::"('a::pt_name) f3_ty" + and t ::"lam" + and y ::"name prm \ ('a::pt_name)" + assumes a: "(t,y)\rec f1 f2 f3" + and b: "y=y'" + shows "(t,y')\rec f1 f2 f3" +using a b by simp + + +lemma rec_prm_equiv: + fixes f1 ::"('a::pt_name) f1_ty" + and f2 ::"('a::pt_name) f2_ty" + and f3 ::"('a::pt_name) f3_ty" + and t ::"lam" + and y ::"name prm \ ('a::pt_name)" + and pi ::"name prm" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + and a: "(t,y)\rec f1 f2 f3" + shows "(pi\t,pi\y)\rec (pi\f1) (pi\f2) (pi\f3)" +using a +proof (induct) + case (r1 c) + let ?g ="pi\(\(pi'::name prm). f1 (pi'\c))" + and ?g'="\(pi'::name prm). (pi\f1) (pi'\(pi\c))" + have "?g'=?g" + proof (auto simp only: expand_fun_eq perm_fun_def) + fix pi'::"name prm" + let ?h = "((rev pi)\(pi'\(pi\c)))" + and ?h'= "(((rev pi)\pi')\c)" + have "?h' = ((rev pi)\pi')\((rev pi)\(pi\c))" + by (simp add: pt_rev_pi[OF pt_name_inst, OF at_name_inst]) + also have "\ = ?h" + by (simp add: pt_perm_compose[OF pt_name_inst, OF at_name_inst,symmetric]) + finally show "pi\(f1 ?h) = pi\(f1 ?h')" by simp + qed + thus ?case by (force intro: rec_trans rec.r1) +next + case (r2 t1 t2 y1 y2) + assume a1: "finite ((supp y1)::name set)" + and a2: "finite ((supp y2)::name set)" + and a3: "(pi\t1,pi\y1) \ rec (pi\f1) (pi\f2) (pi\f3)" + and a4: "(pi\t2,pi\y2) \ rec (pi\f1) (pi\f2) (pi\f3)" + from a1 a2 have a1': "finite ((supp (pi\y1))::name set)" and a2': "finite ((supp (pi\y2))::name set)" + by (simp_all add: pt_supp_finite_pi[OF pt_name_inst, OF at_name_inst]) + let ?g ="pi\(\(pi'::name prm). f2 (y1 pi') (y2 pi'))" + and ?g'="\(pi'::name prm). (pi\f2) ((pi\y1) pi') ((pi\y2) pi')" + have "?g'=?g" by (simp add: expand_fun_eq perm_fun_def pt_rev_pi[OF pt_name_inst, OF at_name_inst]) + thus ?case using a1' a2' a3 a4 by (force intro: rec.r2 rec_trans) +next + case (r3 a t y) + assume a1: "finite ((supp y)::name set)" + and a2: "(pi\t,pi\y) \ rec (pi\f1) (pi\f2) (pi\f3)" + from a1 have a1': "finite ((supp (pi\y))::name set)" + by (simp add: pt_supp_finite_pi[OF pt_name_inst, OF at_name_inst]) + let ?g ="pi\(\(pi'::name prm). fresh_fun (\a'. f3 a' (y (pi'@[(a,a')]))))" + and ?g'="(\(pi'::name prm). fresh_fun (\a'. (pi\f3) a' ((pi\y) (pi'@[((pi\a),a')]))))" + have "?g'=?g" + proof (auto simp add: expand_fun_eq perm_fun_def pt_rev_pi[OF pt_name_inst, OF at_name_inst] + perm_append) + fix pi'::"name prm" + let ?h = "\a'. pi\(f3 ((rev pi)\a') (y (((rev pi)\pi')@[(a,(rev pi)\a')])))" + and ?h' = "\a'. f3 a' (y (((rev pi)\pi')@[(a,a')]))" + have fs_f3: "finite ((supp f3)::name set)" using f by (simp add: supp_prod) + have fs_h': "finite ((supp ?h')::name set)" + proof - + have "((supp (f3,a,(rev pi)\pi',y))::name set) supports ?h'" + by (supports_simp add: perm_append) + moreover + have "finite ((supp (f3,a,(rev pi)\pi',y))::name set)" using a1 fs_f3 + by (simp add: supp_prod fs_name1) + ultimately show ?thesis by (rule supports_finite) + qed + have fcond: "\(a''::name). a''\?h' \ a''\(?h' a'')" + by (rule f3_freshness_conditions_simple[OF fs_f3, OF a1, OF c]) + have "fresh_fun ?h = fresh_fun (pi\?h')" + by (simp add: perm_fun_def pt_rev_pi[OF pt_name_inst, OF at_name_inst]) + also have "\ = pi\(fresh_fun ?h')" + by (simp add: fresh_fun_equiv[OF pt_name_inst, OF at_name_inst, OF fs_h', OF fcond]) + finally show "fresh_fun ?h = pi\(fresh_fun ?h')" . + qed + thus ?case using a1' a2 by (force intro: rec.r3 rec_trans) +qed + +lemma rec_perm: + fixes f1 ::"('a::pt_name) f1_ty" + and f2 ::"('a::pt_name) f2_ty" + and f3 ::"('a::pt_name) f3_ty" + and pi1::"name prm" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + and a: "(t,y)\rec f1 f2 f3" + shows "(pi1\t, \pi2. y (pi2@pi1))\rec f1 f2 f3" +proof - + have lem: "\(y::name prm\('a::pt_name))(pi::name prm). + finite ((supp y)::name set) \ finite ((supp (\pi'. y (pi'@pi)))::name set)" + proof (intro strip) + fix y::"name prm\('a::pt_name)" and pi::"name prm" + assume "finite ((supp y)::name set)" + hence "finite ((supp (y,pi))::name set)" by (simp add: supp_prod fs_name1) + moreover + have "((supp (y,pi))::name set) supports (\pi'. y (pi'@pi))" + by (supports_simp add: perm_append) + ultimately show "finite ((supp (\pi'. y (pi'@pi)))::name set)" by (simp add: supports_finite) + qed +from a +show ?thesis +proof (induct) + case (r1 c) + show ?case + by (auto simp add: pt2[OF pt_name_inst], rule rec.r1) +next + case (r2 t1 t2 y1 y2) + thus ?case using lem by (auto intro!: rec.r2) +next + case (r3 c t y) + assume a0: "(t,y)\rec f1 f2 f3" + and a1: "finite ((supp y)::name set)" + and a2: "(pi1\t,\pi2. y (pi2@pi1))\rec f1 f2 f3" + from f have f': "finite ((supp f3)::name set)" by (simp add: supp_prod) + show ?case + proof(simp) + have a3: "finite ((supp (\pi2. y (pi2@pi1)))::name set)" using lem a1 by force + let ?g' = "\(pi::name prm). fresh_fun (\a'. f3 a' ((\pi2. y (pi2@pi1)) (pi@[(pi1\c,a')])))" + and ?g = "\(pi::name prm). fresh_fun (\a'. f3 a' (y (pi@[(pi1\c,a')]@pi1)))" + and ?h = "\(pi::name prm). fresh_fun (\a'. f3 a' (y (pi@pi1@[(c,a')])))" + have eq1: "?g = ?g'" by simp + have eq2: "?g'= ?h" + proof (auto simp only: expand_fun_eq) + fix pi::"name prm" + let ?q = "\a'. f3 a' (y ((pi@[(pi1\c,a')])@pi1))" + and ?q' = "\a'. f3 a' (y (((pi@pi1)@[(c,(rev pi1)\a')])))" + and ?r = "\a'. f3 a' (y ((pi@pi1)@[(c,a')]))" + and ?r' = "\a'. f3 a' (y (pi@(pi1@[(c,a')])))" + have eq3a: "?r = ?r'" by simp + have eq3: "?q = ?q'" + proof (auto simp only: expand_fun_eq) + fix a'::"name" + have "(y ((pi@[(pi1\c,a')])@pi1)) = (y (((pi@pi1)@[(c,(rev pi1)\a')])))" + proof - + have "((pi@[(pi1\c,a')])@pi1) \ ((pi@pi1)@[(c,(rev pi1)\a')])" + by (force simp add: prm_eq_def at_append[OF at_name_inst] + at_calc[OF at_name_inst] at_bij[OF at_name_inst] + at_pi_rev[OF at_name_inst] at_rev_pi[OF at_name_inst]) + with a0 show ?thesis by (rule rec_prm_eq) + qed + thus "f3 a' (y ((pi@[(pi1\c,a')])@pi1)) = f3 a' (y (((pi@pi1)@[(c,(rev pi1)\a')])))" by simp + qed + have fs_a: "finite ((supp ?q')::name set)" + proof - + have "((supp (f3,c,(pi@pi1),(rev pi1),y))::name set) supports ?q'" + by (supports_simp add: perm_append fresh_list_append fresh_list_rev) + moreover + have "finite ((supp (f3,c,(pi@pi1),(rev pi1),y))::name set)" using f' a1 + by (simp add: supp_prod fs_name1) + ultimately show ?thesis by (rule supports_finite) + qed + have fs_b: "finite ((supp ?r)::name set)" + proof - + have "((supp (f3,c,(pi@pi1),y))::name set) supports ?r" + by (supports_simp add: perm_append fresh_list_append) + moreover + have "finite ((supp (f3,c,(pi@pi1),y))::name set)" using f' a1 + by (simp add: supp_prod fs_name1) + ultimately show ?thesis by (rule supports_finite) + qed + have c1: "\(a''::name). a''\?q' \ a''\(?q' a'')" + by (rule f3_freshness_conditions[OF f', OF a1, OF c]) + have c2: "\(a''::name). a''\?r \ a''\(?r a'')" + by (rule f3_freshness_conditions_simple[OF f', OF a1, OF c]) + have c3: "\(d::name). d\(?q',?r,(rev pi1))" + by (rule at_exists_fresh[OF at_name_inst], + simp only: finite_Un supp_prod fs_a fs_b fs_name1, simp) + then obtain d::"name" where d1: "d\?q'" and d2: "d\?r" and d3: "d\(rev pi1)" + by (auto simp only: fresh_prod) + have eq4: "(rev pi1)\d = d" using d3 by (simp add: at_prm_fresh[OF at_name_inst]) + have "fresh_fun ?q = fresh_fun ?q'" using eq3 by simp + also have "\ = ?q' d" using fs_a c1 d1 + by (simp add: fresh_fun_app[OF pt_name_inst, OF at_name_inst]) + also have "\ = ?r d" using fs_b c2 d2 eq4 + by (simp add: fresh_fun_app[OF pt_name_inst, OF at_name_inst]) + also have "\ = fresh_fun ?r" using fs_b c2 d2 + by (simp add: fresh_fun_app[OF pt_name_inst, OF at_name_inst]) + finally show "fresh_fun ?q = fresh_fun ?r'" by simp + qed + from a3 a2 have "(Lam [(pi1\c)].(pi1\t), ?g')\rec f1 f2 f3" by (rule rec.r3) + thus "(Lam [(pi1\c)].(pi1\t), ?h)\rec f1 f2 f3" using eq2 by simp + qed +qed +qed + +lemma rec_perm_rev: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + and a: "(pi\t,y)\rec f1 f2 f3" + shows "(t, \pi2. y (pi2@(rev pi)))\rec f1 f2 f3" +proof - + from a have "((rev pi)\(pi\t),\pi2. y (pi2@(rev pi)))\rec f1 f2 f3" + by (rule rec_perm[OF f, OF c]) + thus ?thesis by (simp add: pt_rev_pi[OF pt_name_inst, OF at_name_inst]) +qed + + +lemma rec_unique: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + and a: "(t,y)\rec f1 f2 f3" + shows "\(y'::name prm\('a::pt_name))(pi::name prm). + (t,y')\rec f1 f2 f3 \ y pi = y' pi" +using a +proof (induct) + case (r1 c) + show ?case + apply(auto) + apply(ind_cases "(Var c, y') \ rec f1 f2 f3") + apply(simp_all add: lam.distinct lam.inject) + done +next + case (r2 t1 t2 y1 y2) + thus ?case + apply(clarify) + apply(ind_cases "(App t1 t2, y') \ rec f1 f2 f3") + apply(simp_all (no_asm_use) only: lam.distinct lam.inject) + apply(clarify) + apply(drule_tac x="y1" in spec) + apply(drule_tac x="y2" in spec) + apply(auto) + done +next + case (r3 c t y) + assume i1: "finite ((supp y)::name set)" + and i2: "(t,y)\rec f1 f2 f3" + and i3: "\(y'::name prm\('a::pt_name))(pi::name prm). + (t,y')\rec f1 f2 f3 \ y pi = y' pi" + from f have f': "finite ((supp f3)::name set)" by (simp add: supp_prod) + show ?case + proof (auto) + fix y'::"name prm\('a::pt_name)" and pi::"name prm" + assume i4: "(Lam [c].t, y') \ rec f1 f2 f3" + from i4 show "fresh_fun (\a'. f3 a' (y (pi@[(c,a')]))) = y' pi" + proof (cases, simp_all add: lam.distinct lam.inject, auto) + fix a::"name" and t'::"lam" and y''::"name prm\('a::pt_name)" + assume i5: "[c].t = [a].t'" + and i6: "(t',y'')\rec f1 f2 f3" + and i6':"finite ((supp y'')::name set)" + let ?g = "\a'. f3 a' (y (pi@[(c,a')]))" + and ?h = "\a'. f3 a' (y'' (pi@[(a,a')]))" + show "fresh_fun ?g = fresh_fun ?h" using i5 + proof (cases "a=c") + case True + assume i7: "a=c" + with i5 have i8: "t=t'" by (simp add: alpha) + show "fresh_fun ?g = fresh_fun ?h" using i3 i6 i7 i8 by simp + next + case False + assume i9: "a\c" + with i5[symmetric] have i10: "t'=[(a,c)]\t" and i11: "a\t" by (simp_all add: alpha) + have r1: "finite ((supp ?g)::name set)" + proof - + have "((supp (f3,c,pi,y))::name set) supports ?g" + by (supports_simp add: perm_append) + moreover + have "finite ((supp (f3,c,pi,y))::name set)" using f' i1 + by (simp add: supp_prod fs_name1) + ultimately show ?thesis by (rule supports_finite) + qed + have r2: "finite ((supp ?h)::name set)" + proof - + have "((supp (f3,a,pi,y''))::name set) supports ?h" + by (supports_simp add: perm_append) + moreover + have "finite ((supp (f3,a,pi,y''))::name set)" using f' i6' + by (simp add: supp_prod fs_name1) + ultimately show ?thesis by (rule supports_finite) + qed + have c1: "\(a''::name). a''\?g \ a''\(?g a'')" + by (rule f3_freshness_conditions_simple[OF f', OF i1, OF c]) + have c2: "\(a''::name). a''\?h \ a''\(?h a'')" + by (rule f3_freshness_conditions_simple[OF f', OF i6', OF c]) + have "\(d::name). d\(?g,?h,t,a,c)" + by (rule at_exists_fresh[OF at_name_inst], + simp only: finite_Un supp_prod r1 r2 fs_name1, simp) + then obtain d::"name" + where f1: "d\?g" and f2: "d\?h" and f3: "d\t" and f4: "d\a" and f5: "d\c" + by (force simp add: fresh_prod at_fresh[OF at_name_inst] at_fresh[OF at_name_inst]) + have g1: "[(a,d)]\t = t" + by (rule pt_fresh_fresh[OF pt_name_inst, OF at_name_inst, OF i11, OF f3]) + from i6 have "(([(a,c)]@[(a,d)])\t,y'')\rec f1 f2 f3" using g1 i10 by (simp only: pt_name2) + hence "(t, \pi2. y'' (pi2@(rev ([(a,c)]@[(a,d)]))))\rec f1 f2 f3" + by (simp only: rec_perm_rev[OF f, OF c]) + hence g2: "(t, \pi2. y'' (pi2@([(a,d)]@[(a,c)])))\rec f1 f2 f3" by simp + have "distinct [a,c,d]" using i9 f4 f5 by force + hence g3: "(pi@[(c,d)]@[(a,d)]@[(a,c)]) \ (pi@[(a,d)])" + by (force simp add: prm_eq_def at_calc[OF at_name_inst] at_append[OF at_name_inst]) + have "fresh_fun ?g = ?g d" using r1 c1 f1 + by (simp add: fresh_fun_app[OF pt_name_inst, OF at_name_inst]) + also have "\ = f3 d ((\pi2. y'' (pi2@([(a,d)]@[(a,c)]))) (pi@[(c,d)]))" using i3 g2 by simp + also have "\ = f3 d (y'' (pi@[(c,d)]@[(a,d)]@[(a,c)]))" by simp + also have "\ = f3 d (y'' (pi@[(a,d)]))" using i6 g3 by (simp add: rec_prm_eq) + also have "\ = fresh_fun ?h" using r2 c2 f2 + by (simp add: fresh_fun_app[OF pt_name_inst, OF at_name_inst]) + finally show "fresh_fun ?g = fresh_fun ?h" . + qed + qed + qed +qed + +lemma rec_total_aux: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "\(y::name prm\('a::pt_name)). ((t,y)\rec f1 f2 f3) \ (finite ((supp y)::name set))" +proof (induct t rule: lam.induct_weak) + case (Var c) + have a1: "(Var c,\(pi::name prm). f1 (pi\c))\rec f1 f2 f3" by (rule rec.r1) + have a2: "finite ((supp (\(pi::name prm). f1 (pi\c)))::name set)" + proof - + have "((supp (f1,c))::name set) supports (\(pi::name prm). f1 (pi\c))" by (supports_simp) + moreover have "finite ((supp (f1,c))::name set)" using f by (simp add: supp_prod fs_name1) + ultimately show ?thesis by (rule supports_finite) + qed + from a1 a2 show ?case by force +next + case (App t1 t2) + assume "\y1. (t1,y1)\rec f1 f2 f3 \ finite ((supp y1)::name set)" + then obtain y1::"name prm \ ('a::pt_name)" + where a11: "(t1,y1)\rec f1 f2 f3" and a12: "finite ((supp y1)::name set)" by force + assume "\y2. (t2,y2)\rec f1 f2 f3 \ finite ((supp y2)::name set)" + then obtain y2::"name prm \ ('a::pt_name)" + where a21: "(t2,y2)\rec f1 f2 f3" and a22: "finite ((supp y2)::name set)" by force + + have a1: "(App t1 t2,\(pi::name prm). f2 (y1 pi) (y2 pi))\rec f1 f2 f3" + using a12 a11 a22 a21 by (rule rec.r2) + have a2: "finite ((supp (\(pi::name prm). f2 (y1 pi) (y2 pi)))::name set)" + proof - + have "((supp (f2,y1,y2))::name set) supports (\(pi::name prm). f2 (y1 pi) (y2 pi))" + by (supports_simp) + moreover have "finite ((supp (f2,y1,y2))::name set)" using f a21 a22 + by (simp add: supp_prod fs_name1) + ultimately show ?thesis by (rule supports_finite) + qed + from a1 a2 show ?case by force +next + case (Lam a t) + assume "\y. (t,y)\rec f1 f2 f3 \ finite ((supp y)::name set)" + then obtain y::"name prm \ ('a::pt_name)" + where a11: "(t,y)\rec f1 f2 f3" and a12: "finite ((supp y)::name set)" by force + from f have f': "finite ((supp f3)::name set)" by (simp add: supp_prod) + have a1: "(Lam [a].t,\(pi::name prm). fresh_fun (\a'. f3 a' (y (pi@[(a,a')]))))\rec f1 f2 f3" + using a12 a11 by (rule rec.r3) + have a2: "finite ((supp (\pi. fresh_fun (\a'. f3 a' (y (pi@[(a,a')])))))::name set)" + using f' a12 c by (rule f3_fresh_fun_supp_finite) + from a1 a2 show ?case by force +qed + +lemma rec_total: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "\(y::name prm\('a::pt_name)). ((t,y)\rec f1 f2 f3)" +proof - + have "\y. ((t,y)\rec f1 f2 f3) \ (finite ((supp y)::name set))" + by (rule rec_total_aux[OF f, OF c]) + thus ?thesis by force +qed + +lemma rec_function: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "\!y. (t,y)\rec f1 f2 f3" +proof + case goal1 + show ?case by (rule rec_total[OF f, OF c]) +next + case (goal2 y1 y2) + assume a1: "(t,y1)\rec f1 f2 f3" and a2: "(t,y2)\rec f1 f2 f3" + hence "\pi. y1 pi = y2 pi" using rec_unique[OF f, OF c] by force + thus ?case by (force simp add: expand_fun_eq) +qed + +lemma theI2': + assumes a1: "P a" + and a2: "\!x. P x" + and a3: "P a \ Q a" + shows "Q (THE x. P x)" +apply(rule theI2) +apply(rule a1) +apply(subgoal_tac "\!x. P x") +apply(auto intro: a1 simp add: Ex1_def) +apply(fold Ex1_def) +apply(rule a2) +apply(subgoal_tac "x=a") +apply(simp) +apply(rule a3) +apply(assumption) +apply(subgoal_tac "\!x. P x") +apply(auto intro: a1 simp add: Ex1_def) +apply(fold Ex1_def) +apply(rule a2) +done + +lemma rfun'_equiv: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + and pi::"name prm" + and t ::"lam" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "pi\(rfun' f1 f2 f3 t) = rfun' (pi\f1) (pi\f2) (pi\f3) (pi\t)" +apply(auto simp add: rfun'_def) +apply(subgoal_tac "\y. (t,y)\rec f1 f2 f3 \ finite ((supp y)::name set)") +apply(auto) +apply(rule sym) +apply(rule_tac a="y" in theI2') +apply(assumption) +apply(rule rec_function[OF f, OF c]) +apply(rule the1_equality) +apply(rule rec_function) +apply(subgoal_tac "finite ((supp (f1,f2,f3))::name set)") +apply(simp add: supp_prod) +apply(simp add: pt_supp_finite_pi[OF pt_name_inst, OF at_name_inst]) +apply(rule f) +apply(subgoal_tac "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)") +apply(auto) +apply(rule_tac x="pi\a" in exI) +apply(auto) +apply(simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst]) +apply(drule_tac x="(rev pi)\x" in spec) +apply(subgoal_tac "(pi\f3) (pi\a) x = pi\(f3 a ((rev pi)\x))") +apply(simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst]) +apply(subgoal_tac "pi\(f3 a ((rev pi)\x)) = (pi\f3) (pi\a) (pi\((rev pi)\x))") +apply(simp) +apply(simp add: pt_pi_rev[OF pt_name_inst, OF at_name_inst]) +apply(simp add: pt_fun_app_eq[OF pt_name_inst, OF at_name_inst]) +apply(rule c) +apply(rule rec_prm_equiv) +apply(rule f, rule c, assumption) +apply(rule rec_total_aux) +apply(rule f) +apply(rule c) +done + +lemma rfun'_supports: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "((supp (f1,f2,f3,t))::name set) supports (rfun' f1 f2 f3 t)" +proof (auto simp add: "op supports_def" fresh_def[symmetric]) + fix a::"name" and b::"name" + assume a1: "a\(f1,f2,f3,t)" + and a2: "b\(f1,f2,f3,t)" + from a1 a2 have "[(a,b)]\f1=f1" and "[(a,b)]\f2=f2" and "[(a,b)]\f3=f3" and "[(a,b)]\t=t" + by (simp_all add: pt_fresh_fresh[OF pt_name_inst, OF at_name_inst] fresh_prod) + thus "[(a,b)]\(rfun' f1 f2 f3 t) = rfun' f1 f2 f3 t" + by (simp add: rfun'_equiv[OF f, OF c]) +qed + +lemma rfun'_finite_supp: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "finite ((supp (rfun' f1 f2 f3 t))::name set)" +apply(rule supports_finite) +apply(rule rfun'_supports[OF f, OF c]) +apply(subgoal_tac "finite ((supp (f1,f2,f3))::name set)") +apply(simp add: supp_prod fs_name1) +apply(rule f) +done + +lemma rfun'_prm: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + and pi1::"name prm" + and pi2::"name prm" + and t ::"lam" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "rfun' f1 f2 f3 (pi1\t) pi2 = rfun' f1 f2 f3 t (pi2@pi1)" +apply(auto simp add: rfun'_def) +apply(subgoal_tac "\y. (t,y)\rec f1 f2 f3 \ finite ((supp y)::name set)") +apply(auto) +apply(rule_tac a="y" in theI2') +apply(assumption) +apply(rule rec_function[OF f, OF c]) +apply(rule_tac a="\pi2. y (pi2@pi1)" in theI2') +apply(rule rec_perm) +apply(rule f, rule c) +apply(assumption) +apply(rule rec_function) +apply(rule f) +apply(rule c) +apply(simp) +apply(rule rec_total_aux) +apply(rule f) +apply(rule c) +done + +lemma rfun_Var: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "rfun f1 f2 f3 (Var c) = (f1 c)" +apply(auto simp add: rfun_def rfun'_def) +apply(subgoal_tac "(THE y. (Var c, y) \ rec f1 f2 f3) = (\(pi::name prm). f1 (pi\c))")(*A*) +apply(simp) +apply(rule the1_equality) +apply(rule rec_function) +apply(rule f) +apply(rule c) +apply(rule rec.r1) +done + +lemma rfun_App: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "rfun f1 f2 f3 (App t1 t2) = (f2 (rfun f1 f2 f3 t1) (rfun f1 f2 f3 t2))" +apply(auto simp add: rfun_def rfun'_def) +apply(subgoal_tac "(THE y. (App t1 t2, y)\rec f1 f2 f3) = + (\(pi::name prm). f2 ((rfun' f1 f2 f3 t1) pi) ((rfun' f1 f2 f3 t2) pi))")(*A*) +apply(simp add: rfun'_def) +apply(rule the1_equality) +apply(rule rec_function[OF f, OF c]) +apply(rule rec.r2) +apply(rule rfun'_finite_supp[OF f, OF c]) +apply(subgoal_tac "\y. (t1,y)\rec f1 f2 f3") +apply(erule exE, simp add: rfun'_def) +apply(rule_tac a="y" in theI2') +apply(assumption) +apply(rule rec_function[OF f, OF c]) +apply(assumption) +apply(rule rec_total[OF f, OF c]) +apply(rule rfun'_finite_supp[OF f, OF c]) +apply(subgoal_tac "\y. (t2,y)\rec f1 f2 f3") +apply(auto simp add: rfun'_def) +apply(rule_tac a="y" in theI2') +apply(assumption) +apply(rule rec_function[OF f, OF c]) +apply(assumption) +apply(rule rec_total[OF f, OF c]) +done + +lemma rfun_Lam_aux1: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "rfun f1 f2 f3 (Lam [a].t) = fresh_fun (\a'. f3 a' (rfun' f1 f2 f3 t ([]@[(a,a')])))" +apply(simp add: rfun_def rfun'_def) +apply(subgoal_tac "(THE y. (Lam [a].t, y)\rec f1 f2 f3) = + (\(pi::name prm). fresh_fun(\a'. f3 a' ((rfun' f1 f2 f3 t) (pi@[(a,a')]))))")(*A*) +apply(simp add: rfun'_def[symmetric]) +apply(rule the1_equality) +apply(rule rec_function[OF f, OF c]) +apply(rule rec.r3) +apply(rule rfun'_finite_supp[OF f, OF c]) +apply(subgoal_tac "\y. (t,y)\rec f1 f2 f3") +apply(erule exE, simp add: rfun'_def) +apply(rule_tac a="y" in theI2') +apply(assumption) +apply(rule rec_function[OF f, OF c]) +apply(assumption) +apply(rule rec_total[OF f, OF c]) +done + +lemma rfun_Lam_aux2: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + and a: "b\(a,t,f1,f2,f3)" + shows "rfun f1 f2 f3 (Lam [b].([(a,b)]\t)) = f3 b (rfun f1 f2 f3 ([(a,b)]\t))" +proof - + from f have f': "finite ((supp f3)::name set)" by (simp add: supp_prod) + have eq1: "rfun f1 f2 f3 (Lam [b].([(a,b)]\t)) = rfun f1 f2 f3 (Lam [a].t)" + proof - + have "Lam [a].t = Lam [b].([(a,b)]\t)" using a + by (force simp add: lam.inject alpha fresh_prod at_fresh[OF at_name_inst] + pt_swap_bij[OF pt_name_inst, OF at_name_inst] + pt_fresh_left[OF pt_name_inst, OF at_name_inst] at_calc[OF at_name_inst]) + thus ?thesis by simp + qed + let ?g = "(\a'. f3 a' (rfun' f1 f2 f3 t ([]@[(a,a')])))" + have a0: "((supp (f3,a,([]::name prm),rfun' f1 f2 f3 t))::name set) supports ?g" + by (supports_simp add: perm_append) + have a1: "finite ((supp (f3,a,([]::name prm),rfun' f1 f2 f3 t))::name set)" + using f' by (simp add: supp_prod fs_name1 rfun'_finite_supp[OF f, OF c]) + from a0 a1 have a2: "finite ((supp ?g)::name set)" + by (rule supports_finite) + have c0: "finite ((supp (rfun' f1 f2 f3 t))::name set)" + by (rule rfun'_finite_supp[OF f, OF c]) + have c1: "\(a''::name). a''\?g \ a''\(?g a'')" + by (rule f3_freshness_conditions_simple[OF f', OF c0, OF c]) + have c2: "b\?g" + proof - + have fs_g: "finite ((supp (f1,f2,f3,t))::name set)" using f + by (simp add: supp_prod fs_name1) + have "((supp (f1,f2,f3,t))::name set) supports (rfun' f1 f2 f3 t)" + by (simp add: rfun'_supports[OF f, OF c]) + hence c3: "b\(rfun' f1 f2 f3 t)" using fs_g + proof(rule supports_fresh, simp add: fresh_def[symmetric]) + show "b\(f1,f2,f3,t)" using a by (simp add: fresh_prod) + qed + show ?thesis + proof(rule supports_fresh[OF a0, OF a1], simp add: fresh_def[symmetric]) + show "b\(f3,a,([]::name prm),rfun' f1 f2 f3 t)" using a c3 + by (simp add: fresh_prod fresh_list_nil) + qed + qed + (* main proof *) + have "rfun f1 f2 f3 (Lam [b].([(a,b)]\t)) = rfun f1 f2 f3 (Lam [a].t)" by (simp add: eq1) + also have "\ = fresh_fun ?g" by (rule rfun_Lam_aux1[OF f, OF c]) + also have "\ = ?g b" using c2 + by (rule fresh_fun_app[OF pt_name_inst, OF at_name_inst, OF a2, OF c1]) + also have "\ = f3 b (rfun f1 f2 f3 ([(a,b)]\t))" + by (simp add: rfun_def rfun'_prm[OF f, OF c]) + finally show "rfun f1 f2 f3 (Lam [b].([(a,b)]\t)) = f3 b (rfun f1 f2 f3 ([(a,b)]\t))" . +qed + + +lemma rfun_Lam: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + and a: "b\(f1,f2,f3)" + shows "rfun f1 f2 f3 (Lam [b].t) = f3 b (rfun f1 f2 f3 t)" +proof - + have "\(a::name). a\(b,t)" + by (rule at_exists_fresh[OF at_name_inst], simp add: supp_prod fs_name1) + then obtain a::"name" where a1: "a\b" and a2: "a\t" by (force simp add: fresh_prod) + have "rfun f1 f2 f3 (Lam [b].t) = rfun f1 f2 f3 (Lam [b].(([(a,b)])\([(a,b)]\t)))" + by (simp add: pt_swap_bij[OF pt_name_inst, OF at_name_inst]) + also have "\ = f3 b (rfun f1 f2 f3 (([(a,b)])\([(a,b)]\t)))" + proof(rule rfun_Lam_aux2[OF f, OF c]) + have "b\([(a,b)]\t)" using a1 a2 + by (simp add: pt_fresh_left[OF pt_name_inst, OF at_name_inst] at_calc[OF at_name_inst] + at_fresh[OF at_name_inst]) + thus "b\(a,[(a,b)]\t,f1,f2,f3)" using a a1 by (force simp add: fresh_prod at_fresh[OF at_name_inst]) + qed + also have "\ = f3 b (rfun f1 f2 f3 t)" by (simp add: pt_swap_bij[OF pt_name_inst, OF at_name_inst]) + finally show ?thesis . +qed + +lemma rec_unique: + fixes fun::"lam \ ('a::pt_name)" + and f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + and a1: "\c. fun (Var c) = f1 c" + and a2: "\t1 t2. fun (App t1 t2) = f2 (fun t1) (fun t2)" + and a3: "\a t. a\(f1,f2,f3) \ fun (Lam [a].t) = f3 a (fun t)" + shows "fun t = rfun f1 f2 f3 t" +(*apply(nominal_induct t rule: lam_induct')*) +apply (rule lam_induct'[of "\_. ((supp (f1,f2,f3))::name set)" "\t _. fun t = rfun f1 f2 f3 t"]) +(* finite support *) +apply(rule f) +(* VAR *) +apply(simp add: a1 rfun_Var[OF f, OF c, symmetric]) +(* APP *) +apply(simp add: a2 rfun_App[OF f, OF c, symmetric]) +(* LAM *) +apply(fold fresh_def) +apply(simp add: a3 rfun_Lam[OF f, OF c, symmetric]) +done + +lemma rec_function: + fixes f1::"('a::pt_name) f1_ty" + and f2::"('a::pt_name) f2_ty" + and f3::"('a::pt_name) f3_ty" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name). a\f3 a y)" + shows "(\!(fun::lam \ ('a::pt_name)). + (\c. fun (Var c) = f1 c) \ + (\t1 t2. fun (App t1 t2) = f2 (fun t1) (fun t2)) \ + (\a t. a\(f1,f2,f3) \ fun (Lam [a].t) = f3 a (fun t)))" +apply(rule_tac a="\t. rfun f1 f2 f3 t" in ex1I) +(* existence *) +apply(simp add: rfun_Var[OF f, OF c]) +apply(simp add: rfun_App[OF f, OF c]) +apply(simp add: rfun_Lam[OF f, OF c]) +(* uniqueness *) +apply(auto simp add: expand_fun_eq) +apply(rule rec_unique[OF f, OF c]) +apply(force)+ +done + +(* "real" recursion *) + +types 'a f1_ty' = "name\('a::pt_name)" + 'a f2_ty' = "lam\lam\'a\'a\('a::pt_name)" + 'a f3_ty' = "lam\name\'a\('a::pt_name)" + +constdefs + rfun_gen' :: "'a f1_ty' \ 'a f2_ty' \ 'a f3_ty' \ lam \ (lam\'a::pt_name)" + "rfun_gen' f1 f2 f3 t \ (rfun + (\(a::name). (Var a,f1 a)) + (\r1 r2. (App (fst r1) (fst r2), f2 (fst r1) (fst r2) (snd r1) (snd r2))) + (\(a::name) r. (Lam [a].(fst r),f3 (fst r) a (snd r))) + t)" + + rfun_gen :: "'a f1_ty' \ 'a f2_ty' \ 'a f3_ty' \ lam \ 'a::pt_name" + "rfun_gen f1 f2 f3 t \ snd(rfun_gen' f1 f2 f3 t)" + + + +lemma f1'_supports: + fixes f1::"('a::pt_name) f1_ty'" + shows "((supp f1)::name set) supports (\(a::name). (Var a,f1 a))" + by (supports_simp) + +lemma f2'_supports: + fixes f2::"('a::pt_name) f2_ty'" + shows "((supp f2)::name set) supports + (\r1 r2. (App (fst r1) (fst r2), f2 (fst r1) (fst r2) (snd r1) (snd r2)))" + by (supports_simp add: perm_fst perm_snd) + +lemma f3'_supports: + fixes f3::"('a::pt_name) f3_ty'" + shows "((supp f3)::name set) supports (\(a::name) r. (Lam [a].(fst r),f3 (fst r) a (snd r)))" +by (supports_simp add: perm_fst perm_snd) + +lemma fcb': + fixes f3::"('a::pt_name) f3_ty'" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name) t. a\f3 t a y)" + shows "\a. a \ (\a r. (Lam [a].fst r, f3 (fst r) a (snd r))) \ + (\y. a \ (Lam [a].fst y, f3 (fst y) a (snd y)))" +using c f +apply(auto) +apply(rule_tac x="a" in exI) +apply(auto simp add: abs_fresh fresh_prod) +apply(rule supports_fresh) +apply(rule f3'_supports) +apply(simp add: supp_prod) +apply(simp add: fresh_def) +done + +lemma fsupp': + fixes f1::"('a::pt_name) f1_ty'" + and f2::"('a::pt_name) f2_ty'" + and f3::"('a::pt_name) f3_ty'" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + shows "finite((supp + (\a. (Var a, f1 a), + \r1 r2. + (App (fst r1) (fst r2), + f2 (fst r1) (fst r2) (snd r1) (snd r2)), + \a r. (Lam [a].fst r, f3 (fst r) a (snd r))))::name set)" +using f +apply(auto simp add: supp_prod) +apply(rule supports_finite) +apply(rule f1'_supports) +apply(assumption) +apply(rule supports_finite) +apply(rule f2'_supports) +apply(assumption) +apply(rule supports_finite) +apply(rule f3'_supports) +apply(assumption) +done + +lemma rfun_gen'_fst: + fixes f1::"('a::pt_name) f1_ty'" + and f2::"('a::pt_name) f2_ty'" + and f3::"('a::pt_name) f3_ty'" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "(\(a::name). a\f3 \ (\(y::'a::pt_name) t. a\f3 t a y))" + shows "fst (rfun_gen' f1 f2 f3 t) = t" +apply (rule lam_induct'[of "\_. ((supp (f1,f2,f3))::name set)" "\t _. fst (rfun_gen' f1 f2 f3 t) = t"]) +apply(simp add: f) +apply(unfold rfun_gen'_def) +apply(simp only: rfun_Var[OF fsupp'[OF f],OF fcb'[OF f, OF c]]) +apply(simp) +apply(simp only: rfun_App[OF fsupp'[OF f],OF fcb'[OF f, OF c]]) +apply(simp) +apply(fold fresh_def) +apply(auto) +apply(rule trans) +apply(rule_tac f="fst" in arg_cong) +apply(rule rfun_Lam[OF fsupp'[OF f],OF fcb'[OF f, OF c]]) +apply(auto simp add: fresh_prod) +apply(rule supports_fresh) +apply(rule f1'_supports) +apply(subgoal_tac "finite ((supp (f1,f2,f3))::name set)") +apply(simp add: supp_prod) +apply(rule f) +apply(simp add: fresh_def) +apply(rule supports_fresh) +apply(rule f2'_supports) +apply(subgoal_tac "finite ((supp (f1,f2,f3))::name set)") +apply(simp add: supp_prod) +apply(rule f) +apply(simp add: fresh_def) +apply(rule supports_fresh) +apply(rule f3'_supports) +apply(subgoal_tac "finite ((supp (f1,f2,f3))::name set)") +apply(simp add: supp_prod) +apply(rule f) +apply(simp add: fresh_def) +done + +lemma rfun_gen'_Var: + fixes f1::"('a::pt_name) f1_ty'" + and f2::"('a::pt_name) f2_ty'" + and f3::"('a::pt_name) f3_ty'" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name) t. a\f3 t a y)" + shows "rfun_gen' f1 f2 f3 (Var c) = (Var c, f1 c)" +apply(simp add: rfun_gen'_def) +apply(simp add: rfun_Var[OF fsupp'[OF f],OF fcb'[OF f, OF c]]) +done + +lemma rfun_gen'_App: + fixes f1::"('a::pt_name) f1_ty'" + and f2::"('a::pt_name) f2_ty'" + and f3::"('a::pt_name) f3_ty'" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name) t. a\f3 t a y)" + shows "rfun_gen' f1 f2 f3 (App t1 t2) = + (App t1 t2, f2 t1 t2 (rfun_gen f1 f2 f3 t1) (rfun_gen f1 f2 f3 t2))" +apply(simp add: rfun_gen'_def) +apply(rule trans) +apply(rule rfun_App[OF fsupp'[OF f],OF fcb'[OF f, OF c]]) +apply(fold rfun_gen'_def) +apply(simp_all add: rfun_gen'_fst[OF f, OF c]) +apply(simp_all add: rfun_gen_def) +done + +lemma rfun_gen'_Lam: + fixes f1::"('a::pt_name) f1_ty'" + and f2::"('a::pt_name) f2_ty'" + and f3::"('a::pt_name) f3_ty'" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name) t. a\f3 t a y)" + and a: "b\(f1,f2,f3)" + shows "rfun_gen' f1 f2 f3 (Lam [b].t) = (Lam [b].t, f3 t b (rfun_gen f1 f2 f3 t))" +using a f +apply(simp add: rfun_gen'_def) +apply(rule trans) +apply(rule rfun_Lam[OF fsupp'[OF f],OF fcb'[OF f, OF c]]) +apply(auto simp add: fresh_prod) +apply(rule supports_fresh) +apply(rule f1'_supports) +apply(simp add: supp_prod) +apply(simp add: fresh_def) +apply(rule supports_fresh) +apply(rule f2'_supports) +apply(simp add: supp_prod) +apply(simp add: fresh_def) +apply(rule supports_fresh) +apply(rule f3'_supports) +apply(simp add: supp_prod) +apply(simp add: fresh_def) +apply(fold rfun_gen'_def) +apply(simp_all add: rfun_gen'_fst[OF f, OF c]) +apply(simp_all add: rfun_gen_def) +done + +lemma rfun_gen_Var: + fixes f1::"('a::pt_name) f1_ty'" + and f2::"('a::pt_name) f2_ty'" + and f3::"('a::pt_name) f3_ty'" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name) t. a\f3 t a y)" + shows "rfun_gen f1 f2 f3 (Var c) = f1 c" +apply(unfold rfun_gen_def) +apply(simp add: rfun_gen'_Var[OF f, OF c]) +done + +lemma rfun_gen_App: + fixes f1::"('a::pt_name) f1_ty'" + and f2::"('a::pt_name) f2_ty'" + and f3::"('a::pt_name) f3_ty'" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name) t. a\f3 t a y)" + shows "rfun_gen f1 f2 f3 (App t1 t2) = f2 t1 t2 (rfun_gen f1 f2 f3 t1) (rfun_gen f1 f2 f3 t2)" +apply(unfold rfun_gen_def) +apply(simp add: rfun_gen'_App[OF f, OF c]) +apply(simp add: rfun_gen_def) +done + +lemma rfun_gen_Lam: + fixes f1::"('a::pt_name) f1_ty'" + and f2::"('a::pt_name) f2_ty'" + and f3::"('a::pt_name) f3_ty'" + assumes f: "finite ((supp (f1,f2,f3))::name set)" + and c: "\(a::name). a\f3 \ (\(y::'a::pt_name) t. a\f3 t a y)" + and a: "b\(f1,f2,f3)" + shows "rfun_gen f1 f2 f3 (Lam [b].t) = f3 t b (rfun_gen f1 f2 f3 t)" +using a +apply(unfold rfun_gen_def) +apply(simp add: rfun_gen'_Lam[OF f, OF c]) +apply(simp add: rfun_gen_def) +done + +instance nat :: pt_name +apply(intro_classes) +apply(simp_all add: perm_nat_def) +done + +constdefs + depth_Var :: "name \ nat" + "depth_Var \ \(a::name). 1" + + depth_App :: "nat \ nat \ nat" + "depth_App \ \n1 n2. (max n1 n2)+1" + + depth_Lam :: "name \ nat \ nat" + "depth_Lam \ \(a::name) n. n+1" + + depth_lam :: "lam \ nat" + "depth_lam \ rfun depth_Var depth_App depth_Lam" + +lemma supp_depth_Var: + shows "((supp depth_Var)::name set)={}" + apply(simp add: depth_Var_def) + apply(simp add: supp_def) + apply(simp add: perm_fun_def) + apply(simp add: perm_nat_def) + done + +lemma supp_depth_App: + shows "((supp depth_App)::name set)={}" + apply(simp add: depth_App_def) + apply(simp add: supp_def) + apply(simp add: perm_fun_def) + apply(simp add: perm_nat_def) + done + +lemma supp_depth_Lam: + shows "((supp depth_Lam)::name set)={}" + apply(simp add: depth_Lam_def) + apply(simp add: supp_def) + apply(simp add: perm_fun_def) + apply(simp add: perm_nat_def) + done + + +lemma fin_supp_depth: + shows "finite ((supp (depth_Var,depth_App,depth_Lam))::name set)" + using supp_depth_Var supp_depth_Lam supp_depth_App +by (simp add: supp_prod) + +lemma fresh_depth_Lam: + shows "\(a::name). a\depth_Lam \ (\n. a\depth_Lam a n)" +apply(rule exI) +apply(rule conjI) +apply(simp add: fresh_def supp_depth_Lam) +apply(auto simp add: depth_Lam_def) +apply(unfold fresh_def) +apply(simp add: supp_def) +apply(simp add: perm_nat_def) +done + +lemma depth_Var: + shows "depth_lam (Var c) = 1" +apply(simp add: depth_lam_def) +apply(simp add: rfun_Var[OF fin_supp_depth, OF fresh_depth_Lam]) +apply(simp add: depth_Var_def) +done + +lemma depth_App: + shows "depth_lam (App t1 t2) = (max (depth_lam t1) (depth_lam t2))+1" +apply(simp add: depth_lam_def) +apply(simp add: rfun_App[OF fin_supp_depth, OF fresh_depth_Lam]) +apply(simp add: depth_App_def) +done + +lemma depth_Lam: + shows "depth_lam (Lam [a].t) = (depth_lam t)+1" +apply(simp add: depth_lam_def) +apply(rule trans) +apply(rule rfun_Lam[OF fin_supp_depth, OF fresh_depth_Lam]) +apply(simp add: fresh_def supp_prod supp_depth_Var supp_depth_App supp_depth_Lam) +apply(simp add: depth_Lam_def) +done + + +(* substitution *) + +constdefs + subst_Var :: "name \lam \ name \ lam" + "subst_Var b t \ \a. (if a=b then t else (Var a))" + + subst_App :: "name \ lam \ lam \ lam \ lam" + "subst_App b t \ \r1 r2. App r1 r2" + + subst_Lam :: "name \ lam \ name \ lam \ lam" + "subst_Lam b t \ \a r. Lam [a].r" + + subst_lam :: "name \ lam \ lam \ lam" + "subst_lam b t \ rfun (subst_Var b t) (subst_App b t) (subst_Lam b t)" + + +lemma supports_subst_Var: + shows "((supp (b,t))::name set) supports (subst_Var b t)" +apply(supports_simp add: subst_Var_def) +apply(rule impI) +apply(drule pt_bij1[OF pt_name_inst, OF at_name_inst]) +apply(simp add: pt_fresh_fresh[OF pt_name_inst, OF at_name_inst]) +done + +lemma supports_subst_App: + shows "((supp (b,t))::name set) supports subst_App b t" +by (supports_simp add: subst_App_def) + +lemma supports_subst_Lam: + shows "((supp (b,t))::name set) supports subst_Lam b t" + by (supports_simp add: subst_Lam_def) + + +lemma fin_supp_subst: + shows "finite ((supp (subst_Var b t,subst_App b t,subst_Lam b t))::name set)" +apply(auto simp add: supp_prod) +apply(rule supports_finite) +apply(rule supports_subst_Var) +apply(simp add: fs_name1) +apply(rule supports_finite) +apply(rule supports_subst_App) +apply(simp add: fs_name1) +apply(rule supports_finite) +apply(rule supports_subst_Lam) +apply(simp add: fs_name1) +done + +lemma fresh_subst_Lam: + shows "\(a::name). a\(subst_Lam b t)\ (\y. a\(subst_Lam b t) a y)" +apply(subgoal_tac "\(c::name). c\(b,t)") +apply(auto) +apply(rule_tac x="c" in exI) +apply(auto) +apply(rule supports_fresh) +apply(rule supports_subst_Lam) +apply(simp_all add: fresh_def[symmetric] fs_name1) +apply(simp add: subst_Lam_def) +apply(simp add: abs_fresh) +apply(rule at_exists_fresh[OF at_name_inst]) +apply(simp add: fs_name1) +done + +lemma subst_Var: + shows "subst_lam b t (Var a) = (if a=b then t else (Var a))" +apply(simp add: subst_lam_def) +apply(auto simp add: rfun_Var[OF fin_supp_subst, OF fresh_subst_Lam]) +apply(auto simp add: subst_Var_def) +done + +lemma subst_App: + shows "subst_lam b t (App t1 t2) = App (subst_lam b t t1) (subst_lam b t t2)" +apply(simp add: subst_lam_def) +apply(auto simp add: rfun_App[OF fin_supp_subst, OF fresh_subst_Lam]) +apply(auto simp add: subst_App_def) +done + +lemma subst_Lam: + assumes a: "a\(b,t)" + shows "subst_lam b t (Lam [a].t1) = Lam [a].(subst_lam b t t1)" +using a +apply(simp add: subst_lam_def) +apply(subgoal_tac "a\(subst_Var b t,subst_App b t,subst_Lam b t)") +apply(auto simp add: rfun_Lam[OF fin_supp_subst, OF fresh_subst_Lam]) +apply(simp (no_asm) add: subst_Lam_def) +apply(auto simp add: fresh_prod) +apply(rule supports_fresh) +apply(rule supports_subst_Var) +apply(simp_all add: fs_name1 fresh_def[symmetric] fresh_prod) +apply(rule supports_fresh) +apply(rule supports_subst_App) +apply(simp_all add: fs_name1 fresh_def[symmetric] fresh_prod) +apply(rule supports_fresh) +apply(rule supports_subst_Lam) +apply(simp_all add: fs_name1 fresh_def[symmetric] fresh_prod) +done + +lemma subst_Lam': + assumes a: "a\b" + and b: "a\t" + shows "subst_lam b t (Lam [a].t1) = Lam [a].(subst_lam b t t1)" +apply(rule subst_Lam) +apply(simp add: fresh_prod a b fresh_atm) +done + +consts + subst_syn :: "lam \ name \ lam \ lam" ("_[_::=_]" [100,100,100] 900) +translations + "t1[a::=t2]" \ "subst_lam a t2 t1" + +declare subst_Var[simp] +declare subst_App[simp] +declare subst_Lam[simp] +declare subst_Lam'[simp] + +lemma subst_eqvt[simp]: + fixes pi:: "name prm" + and t1:: "lam" + and t2:: "lam" + and a :: "name" + shows "pi\(t1[a::=t2]) = (pi\t1)[(pi\a)::=(pi\t2)]" +apply(nominal_induct t1 rule: lam_induct) +apply(auto) +apply(auto simp add: perm_bij fresh_prod fresh_atm) +apply(subgoal_tac "(aa\ab)\(aa\a,aa\b)")(*A*) +apply(simp) +apply(simp add: perm_bij fresh_prod fresh_atm pt_fresh_bij[OF pt_name_inst, OF at_name_inst]) +done + +lemma subst_supp: "supp(t1[a::=t2])\(((supp(t1)-{a})\supp(t2))::name set)" +apply(nominal_induct t1 rule: lam_induct) +apply(auto simp add: lam.supp supp_atm fresh_prod abs_supp) +apply(blast) +apply(blast) +done + +(* parallel substitution *) + + +consts + "dom_sss" :: "(name\lam) list \ (name list)" +primrec + "dom_sss [] = []" + "dom_sss (x#\) = (fst x)#(dom_sss \)" + +consts + "apply_sss" :: "(name\lam) list \ name \ lam" (" _ < _ >" [80,80] 80) +primrec +"(x#\) = (if (a = fst x) then (snd x) else \)" + + +lemma apply_sss_eqvt[rule_format]: + fixes pi::"name prm" + shows "a\set (dom_sss \) \ pi\(\) = (pi\\)a>" +apply(induct_tac \) +apply(auto) +apply(simp add: pt_bij[OF pt_name_inst, OF at_name_inst]) +done + +lemma dom_sss_eqvt[rule_format]: + fixes pi::"name prm" + shows "((pi\a)\set (dom_sss \)) = (a\set (dom_sss ((rev pi)\\)))" +apply(induct_tac \) +apply(auto) +apply(simp_all add: pt_rev_pi[OF pt_name_inst, OF at_name_inst]) +apply(simp_all add: pt_pi_rev[OF pt_name_inst, OF at_name_inst]) +done + +constdefs + psubst_Var :: "(name\lam) list \ name \ lam" + "psubst_Var \ \ \a. (if a\set (dom_sss \) then \ else (Var a))" + + psubst_App :: "(name\lam) list \ lam \ lam \ lam" + "psubst_App \ \ \r1 r2. App r1 r2" + + psubst_Lam :: "(name\lam) list \ name \ lam \ lam" + "psubst_Lam \ \ \a r. Lam [a].r" + + psubst_lam :: "(name\lam) list \ lam \ lam" + "psubst_lam \ \ rfun (psubst_Var \) (psubst_App \) (psubst_Lam \)" + +lemma supports_psubst_Var: + shows "((supp \)::name set) supports (psubst_Var \)" + by (supports_simp add: psubst_Var_def apply_sss_eqvt dom_sss_eqvt) + +lemma supports_psubst_App: + shows "((supp \)::name set) supports psubst_App \" + by (supports_simp add: psubst_App_def) + +lemma supports_psubst_Lam: + shows "((supp \)::name set) supports psubst_Lam \" + by (supports_simp add: psubst_Lam_def) + +lemma fin_supp_psubst: + shows "finite ((supp (psubst_Var \,psubst_App \,psubst_Lam \))::name set)" +apply(auto simp add: supp_prod) +apply(rule supports_finite) +apply(rule supports_psubst_Var) +apply(simp add: fs_name1) +apply(rule supports_finite) +apply(rule supports_psubst_App) +apply(simp add: fs_name1) +apply(rule supports_finite) +apply(rule supports_psubst_Lam) +apply(simp add: fs_name1) +done + +lemma fresh_psubst_Lam: + shows "\(a::name). a\(psubst_Lam \)\ (\y. a\(psubst_Lam \) a y)" +apply(subgoal_tac "\(c::name). c\\") +apply(auto) +apply(rule_tac x="c" in exI) +apply(auto) +apply(rule supports_fresh) +apply(rule supports_psubst_Lam) +apply(simp_all add: fresh_def[symmetric] fs_name1) +apply(simp add: psubst_Lam_def) +apply(simp add: abs_fresh) +apply(rule at_exists_fresh[OF at_name_inst]) +apply(simp add: fs_name1) +done + +lemma psubst_Var: + shows "psubst_lam \ (Var a) = (if a\set (dom_sss \) then \ else (Var a))" +apply(simp add: psubst_lam_def) +apply(auto simp add: rfun_Var[OF fin_supp_psubst, OF fresh_psubst_Lam]) +apply(auto simp add: psubst_Var_def) +done + +lemma psubst_App: + shows "psubst_lam \ (App t1 t2) = App (psubst_lam \ t1) (psubst_lam \ t2)" +apply(simp add: psubst_lam_def) +apply(auto simp add: rfun_App[OF fin_supp_psubst, OF fresh_psubst_Lam]) +apply(auto simp add: psubst_App_def) +done + +lemma psubst_Lam: + assumes a: "a\\" + shows "psubst_lam \ (Lam [a].t1) = Lam [a].(psubst_lam \ t1)" +using a +apply(simp add: psubst_lam_def) +apply(subgoal_tac "a\(psubst_Var \,psubst_App \,psubst_Lam \)") +apply(auto simp add: rfun_Lam[OF fin_supp_psubst, OF fresh_psubst_Lam]) +apply(simp (no_asm) add: psubst_Lam_def) +apply(auto simp add: fresh_prod) +apply(rule supports_fresh) +apply(rule supports_psubst_Var) +apply(simp_all add: fs_name1 fresh_def[symmetric] fresh_prod) +apply(rule supports_fresh) +apply(rule supports_psubst_App) +apply(simp_all add: fs_name1 fresh_def[symmetric] fresh_prod) +apply(rule supports_fresh) +apply(rule supports_psubst_Lam) +apply(simp_all add: fs_name1 fresh_def[symmetric] fresh_prod) +done + +declare psubst_Var[simp] +declare psubst_App[simp] +declare psubst_Lam[simp] + +consts + psubst_syn :: "lam \ (name\lam) list \ lam" ("_[<_>]" [100,100] 900) +translations + "t[<\>]" \ "psubst_lam \ t" + +end \ No newline at end of file diff -r 4c9c081a416b -r 836135c8acb2 src/HOL/Nominal/Examples/Lambda_mu.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Nominal/Examples/Lambda_mu.thy Mon Nov 07 15:19:03 2005 +0100 @@ -0,0 +1,122 @@ + +theory lambda_mu +imports "../nominal" +begin + +section {* Mu-Calculus from Gavin's cilmu-Paper*} + +atom_decl var mvar + +nominal_datatype trm = Var "var" + | Lam "\var\trm" ("Lam [_]._" [100,100] 100) + | App "trm" "trm" + | Pss "mvar" "trm" + | Act "\mvar\trm" ("Act [_]._" [100,100] 100) + +section {* strong induction principle *} + +lemma trm_induct_aux: + fixes P :: "trm \ 'a \ bool" + and f1 :: "'a \ var set" + and f2 :: "'a \ mvar set" + assumes fs1: "\x. finite (f1 x)" + and fs2: "\x. finite (f2 x)" + and h1: "\k x. P (Var x) k" + and h2: "\k x t. x\f1 k \ (\l. P t l) \ P (Lam [x].t) k" + and h3: "\k t1 t2. (\l. P t1 l) \ (\l. P t2 l) \ P (App t1 t2) k" + and h4: "\k a t1. (\l. P t1 l) \ P (Pss a t1) k" + and h5: "\k a t1. a\f2 k \ (\l. P t1 l) \ P (Act [a].t1) k" + shows "\(pi1::var prm) (pi2::mvar prm) k. P (pi1\(pi2\t)) k" +proof (induct rule: trm.induct_weak) + case (goal1 a) + show ?case using h1 by simp +next + case (goal2 x t) + assume i1: "\(pi1::var prm)(pi2::mvar prm) k. P (pi1\(pi2\t)) k" + show ?case + proof (intro strip, simp add: abs_perm) + fix pi1::"var prm" and pi2::"mvar prm" and k::"'a" + have f: "\c::var. c\(f1 k,pi1\(pi2\x),pi1\(pi2\t))" + by (rule at_exists_fresh[OF at_var_inst], simp add: supp_prod fs_var1 + at_fin_set_supp[OF at_var_inst, OF fs1] fs1) + then obtain c::"var" + where f1: "c\(pi1\(pi2\x))" and f2: "c\(f1 k)" and f3: "c\(pi1\(pi2\t))" + by (force simp add: fresh_prod at_fresh[OF at_var_inst]) + have g: "Lam [c].([(c,pi1\(pi2\x))]\(pi1\(pi2\t))) = Lam [(pi1\(pi2\x))].(pi1\(pi2\t))" using f1 f3 + by (simp add: trm.inject alpha) + from i1 have "\k. P (([(c,pi1\(pi2\x))]@pi1)\(pi2\t)) k" by force + hence i1b: "\k. P ([(c,pi1\(pi2\x))]\(pi1\(pi2\t))) k" by (simp add: pt_var2[symmetric]) + with h3 f2 have "P (Lam [c].([(c,pi1\(pi2\x))]\(pi1\(pi2\t)))) k" + by (auto simp add: fresh_def at_fin_set_supp[OF at_var_inst, OF fs1]) + with g show "P (Lam [(pi1\(pi2\x))].(pi1\(pi2\t))) k" by simp + qed +next + case (goal3 t1 t2) + assume i1: "\(pi1::var prm)(pi2::mvar prm) k. P (pi1\(pi2\t1)) k" + assume i2: "\(pi1::var prm)(pi2::mvar prm) k. P (pi1\(pi2\t2)) k" + show ?case + proof (intro strip) + fix pi1::"var prm" and pi2::"mvar prm" and k::"'a" + from h3 i1 i2 have "P (App (pi1\(pi2\t1)) (pi1\(pi2\t2))) k" by force + thus "P (pi1\(pi2\(App t1 t2))) k" by simp + qed +next + case (goal4 b t) + assume i1: "\(pi1::var prm)(pi2::mvar prm) k. P (pi1\(pi2\t)) k" + show ?case + proof (intro strip) + fix pi1::"var prm" and pi2::"mvar prm" and k::"'a" + from h4 i1 have "P (Pss (pi1\(pi2\b)) (pi1\(pi2\t))) k" by force + thus "P (pi1\(pi2\(Pss b t))) k" by simp + qed +next + case (goal5 b t) + assume i1: "\(pi1::var prm)(pi2::mvar prm) k. P (pi1\(pi2\t)) k" + show ?case + proof (intro strip, simp add: abs_perm) + fix pi1::"var prm" and pi2::"mvar prm" and k::"'a" + have f: "\c::mvar. c\(f2 k,pi1\(pi2\b),pi1\(pi2\t))" + by (rule at_exists_fresh[OF at_mvar_inst], simp add: supp_prod fs_mvar1 + at_fin_set_supp[OF at_mvar_inst, OF fs2] fs2) + then obtain c::"mvar" + where f1: "c\(pi1\(pi2\b))" and f2: "c\(f2 k)" and f3: "c\(pi1\(pi2\t))" + by (force simp add: fresh_prod at_fresh[OF at_mvar_inst]) + have g: "Act [c].(pi1\([(c,pi1\(pi2\b))]\(pi2\t))) = Act [(pi1\(pi2\b))].(pi1\(pi2\t))" using f1 f3 + by (simp add: trm.inject alpha, simp add: dj_cp[OF cp_mvar_var_inst, OF dj_var_mvar]) + from i1 have "\k. P (pi1\(([(c,pi1\(pi2\b))]@pi2)\t)) k" by force + hence i1b: "\k. P (pi1\([(c,pi1\(pi2\b))]\(pi2\t))) k" by (simp add: pt_mvar2[symmetric]) + with h5 f2 have "P (Act [c].(pi1\([(c,pi1\(pi2\b))]\(pi2\t)))) k" + by (auto simp add: fresh_def at_fin_set_supp[OF at_mvar_inst, OF fs2]) + with g show "P (Act [(pi1\(pi2\b))].(pi1\(pi2\t))) k" by simp + qed +qed + +lemma trm_induct'[case_names Var Lam App Pss Act]: + fixes P :: "trm \ 'a \ bool" + and f1 :: "'a \ var set" + and f2 :: "'a \ mvar set" + assumes fs1: "\x. finite (f1 x)" + and fs2: "\x. finite (f2 x)" + and h1: "\k x. P (Var x) k" + and h2: "\k x t. x\f1 k \ (\l. P t l) \ P (Lam [x].t) k" + and h3: "\k t1 t2. (\l. P t1 l) \ (\l. P t2 l) \ P (App t1 t2) k" + and h4: "\k a t1. (\l. P t1 l) \ P (Pss a t1) k" + and h5: "\k a t1. a\f2 k \ (\l. P t1 l) \ P (Act [a].t1) k" + shows "P t k" +proof - + have "\(pi1::var prm)(pi2::mvar prm) k. P (pi1\(pi2\t)) k" + using fs1 fs2 h1 h2 h3 h4 h5 by (rule trm_induct_aux, auto) + hence "P (([]::var prm)\(([]::mvar prm)\t)) k" by blast + thus "P t k" by simp +qed + +lemma trm_induct[case_names Var Lam App Pss Act]: + fixes P :: "trm \ ('a::{fs_var,fs_mvar}) \ bool" + assumes h1: "\k x. P (Var x) k" + and h2: "\k x t. x\k \ (\l. P t l) \ P (Lam [x].t) k" + and h3: "\k t1 t2. (\l. P t1 l) \ (\l. P t2 l) \ P (App t1 t2) k" + and h4: "\k a t1. (\l. P t1 l) \ P (Pss a t1) k" + and h5: "\k a t1. a\k \ (\l. P t1 l) \ P (Act [a].t1) k" + shows "P t k" +by (rule trm_induct'[of "\x. ((supp x)::var set)" "\x. ((supp x)::mvar set)" "P"], + simp_all add: fs_var1 fs_mvar1 fresh_def[symmetric], auto intro: h1 h2 h3 h4 h5) diff -r 4c9c081a416b -r 836135c8acb2 src/HOL/Nominal/Examples/SN.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Nominal/Examples/SN.thy Mon Nov 07 15:19:03 2005 +0100 @@ -0,0 +1,902 @@ + +theory sn +imports lam_substs Accessible_Part +begin + +(* Strong normalisation according to the P&T book by Girard et al *) + +section {* Beta Reduction *} + +lemma subst_rename[rule_format]: + fixes c :: "name" + and a :: "name" + and t1 :: "lam" + and t2 :: "lam" + shows "c\t1 \ (t1[a::=t2] = ([(c,a)]\t1)[c::=t2])" +apply(nominal_induct t1 rule: lam_induct) +apply(auto simp add: calc_atm fresh_atm fresh_prod abs_fresh) +done + +lemma forget[rule_format]: + shows "a\t1 \ t1[a::=t2] = t1" +apply (nominal_induct t1 rule: lam_induct) +apply(auto simp add: abs_fresh fresh_atm fresh_prod) +done + +lemma fresh_fact[rule_format]: + fixes b :: "name" + and a :: "name" + and t1 :: "lam" + and t2 :: "lam" + shows "a\t1\a\t2\a\(t1[b::=t2])" +apply(nominal_induct t1 rule: lam_induct) +apply(auto simp add: abs_fresh fresh_prod fresh_atm) +done + +lemma subs_lemma: + fixes x::"name" + and y::"name" + and L::"lam" + and M::"lam" + and N::"lam" + shows "x\y\x\L\M[x::=N][y::=L] = M[y::=L][x::=N[y::=L]]" +apply(nominal_induct M rule: lam_induct) +apply(auto simp add: fresh_fact forget fresh_prod fresh_atm) +done + +lemma id_subs: "t[x::=Var x] = t" +apply(nominal_induct t rule: lam_induct) +apply(simp_all add: fresh_atm) +done + +consts + Beta :: "(lam\lam) set" +syntax + "_Beta" :: "lam\lam\bool" (" _ \\<^isub>\ _" [80,80] 80) + "_Beta_star" :: "lam\lam\bool" (" _ \\<^isub>\\<^sup>* _" [80,80] 80) +translations + "t1 \\<^isub>\ t2" \ "(t1,t2) \ Beta" + "t1 \\<^isub>\\<^sup>* t2" \ "(t1,t2) \ Beta\<^sup>*" +inductive Beta + intros + b1[intro!]: "s1\\<^isub>\s2 \ (App s1 t)\\<^isub>\(App s2 t)" + b2[intro!]: "s1\\<^isub>\s2 \ (App t s1)\\<^isub>\(App t s2)" + b3[intro!]: "s1\\<^isub>\s2 \ (Lam [a].s1)\\<^isub>\ (Lam [(a::name)].s2)" + b4[intro!]: "(App (Lam [(a::name)].s1) s2)\\<^isub>\(s1[a::=s2])" + +lemma eqvt_beta: + fixes pi :: "name prm" + and t :: "lam" + and s :: "lam" + shows "t\\<^isub>\s \ (pi\t)\\<^isub>\(pi\s)" + apply(erule Beta.induct) + apply(auto) + done + +lemma beta_induct_aux[rule_format]: + fixes P :: "lam \ lam \'a::fs_name\bool" + and t :: "lam" + and s :: "lam" + assumes a: "t\\<^isub>\s" + and a1: "\x t s1 s2. + s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (App s1 t) (App s2 t) x" + and a2: "\x t s1 s2. + s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (App t s1) (App t s2) x" + and a3: "\x (a::name) s1 s2. + a\x \ s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (Lam [a].s1) (Lam [a].s2) x" + and a4: "\x (a::name) t1 s1. a\(s1,x) \ P (App (Lam [a].t1) s1) (t1[a::=s1]) x" + shows "\x (pi::name prm). P (pi\t) (pi\s) x" +using a +proof (induct) + case b1 thus ?case using a1 by (simp, blast intro: eqvt_beta) +next + case b2 thus ?case using a2 by (simp, blast intro: eqvt_beta) +next + case (b3 a s1 s2) + assume j1: "s1 \\<^isub>\ s2" + assume j2: "\x (pi::name prm). P (pi\s1) (pi\s2) x" + show ?case + proof (simp, intro strip) + fix pi::"name prm" and x::"'a::fs_name" + have f: "\c::name. c\(pi\a,pi\s1,pi\s2,x)" + by (rule at_exists_fresh[OF at_name_inst], simp add: fs_name1) + then obtain c::"name" + where f1: "c\(pi\a)" and f2: "c\x" and f3: "c\(pi\s1)" and f4: "c\(pi\s2)" + by (force simp add: fresh_prod fresh_atm) + have x: "P (Lam [c].(([(c,pi\a)]@pi)\s1)) (Lam [c].(([(c,pi\a)]@pi)\s2)) x" + using a3 f2 j1 j2 by (simp, blast intro: eqvt_beta) + have alpha1: "(Lam [c].([(c,pi\a)]\(pi\s1))) = (Lam [(pi\a)].(pi\s1))" using f1 f3 + by (simp add: lam.inject alpha) + have alpha2: "(Lam [c].([(c,pi\a)]\(pi\s2))) = (Lam [(pi\a)].(pi\s2))" using f1 f3 + by (simp add: lam.inject alpha) + show " P (Lam [(pi\a)].(pi\s1)) (Lam [(pi\a)].(pi\s2)) x" + using x alpha1 alpha2 by (simp only: pt_name2) + qed +next + case (b4 a s1 s2) + show ?case + proof (simp add: subst_eqvt, intro strip) + fix pi::"name prm" and x::"'a::fs_name" + have f: "\c::name. c\(pi\a,pi\s1,pi\s2,x)" + by (rule at_exists_fresh[OF at_name_inst], simp add: fs_name1) + then obtain c::"name" + where f1: "c\(pi\a)" and f2: "c\(pi\s2,x)" and f3: "c\(pi\s1)" and f4: "c\(pi\s2)" + by (force simp add: fresh_prod fresh_atm) + have x: "P (App (Lam [c].(([(c,pi\a)]@pi)\s1)) (pi\s2)) ((([(c,pi\a)]@pi)\s1)[c::=(pi\s2)]) x" + using a4 f2 by (blast intro!: eqvt_beta) + have alpha1: "(Lam [c].([(c,pi\a)]\(pi\s1))) = (Lam [(pi\a)].(pi\s1))" using f1 f3 + by (simp add: lam.inject alpha) + have alpha2: "(([(c,pi\a)]@pi)\s1)[c::=(pi\s2)] = (pi\s1)[(pi\a)::=(pi\s2)]" + using f3 by (simp only: subst_rename[symmetric] pt_name2) + show "P (App (Lam [(pi\a)].(pi\s1)) (pi\s2)) ((pi\s1)[(pi\a)::=(pi\s2)]) x" + using x alpha1 alpha2 by (simp only: pt_name2) + qed +qed + +lemma beta_induct[case_names b1 b2 b3 b4]: + fixes P :: "lam \ lam \'a::fs_name\bool" + and t :: "lam" + and s :: "lam" + and x :: "'a::fs_name" + assumes a: "t\\<^isub>\s" + and a1: "\x t s1 s2. + s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (App s1 t) (App s2 t) x" + and a2: "\x t s1 s2. + s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (App t s1) (App t s2) x" + and a3: "\x (a::name) s1 s2. + a\x \ s1\\<^isub>\s2 \ (\z. P s1 s2 z) \ P (Lam [a].s1) (Lam [a].s2) x" + and a4: "\x (a::name) t1 s1. + a\(s1,x) \ P (App (Lam [a].t1) s1) (t1[a::=s1]) x" + shows "P t s x" +using a a1 a2 a3 a4 +by (auto intro!: beta_induct_aux[of "t" "s" "P" "[]" "x", simplified]) + +lemma supp_beta: "t\\<^isub>\ s\(supp s)\((supp t)::name set)" +apply(erule Beta.induct) +apply(auto intro!: simp add: abs_supp lam.supp subst_supp) +done +lemma beta_abs: "Lam [a].t\\<^isub>\ t'\\t''. t'=Lam [a].t'' \ t\\<^isub>\ t''" +apply(ind_cases "Lam [a].t \\<^isub>\ t'") +apply(auto simp add: lam.distinct lam.inject) +apply(auto simp add: alpha) +apply(rule_tac x="[(a,aa)]\s2" in exI) +apply(rule conjI) +apply(rule sym) +apply(rule pt_bij2[OF pt_name_inst, OF at_name_inst]) +apply(simp) +apply(rule pt_name3) +apply(simp add: at_ds5[OF at_name_inst]) +apply(rule conjI) +apply(simp add: pt_fresh_left[OF pt_name_inst, OF at_name_inst] calc_atm) +apply(force dest!: supp_beta simp add: fresh_def) +apply(force intro!: eqvt_beta) +done + +lemma beta_subst[rule_format]: + assumes a: "M \\<^isub>\ M'" + shows "M[x::=N]\\<^isub>\ M'[x::=N]" +using a +apply(nominal_induct M M' rule: beta_induct) +apply(auto simp add: fresh_prod fresh_atm subs_lemma) +done + +instance nat :: fs_name +apply(intro_classes) +apply(simp_all add: supp_def perm_nat_def) +done + +datatype ty = + TVar "string" + | TArr "ty" "ty" (infix "\" 200) + +primrec + "pi\(TVar s) = TVar s" + "pi\(\ \ \) = (\ \ \)" + +lemma perm_ty[simp]: + fixes pi ::"name prm" + and \ ::"ty" + shows "pi\\ = \" + by (cases \, simp_all) + +lemma fresh_ty: + fixes a ::"name" + and \ ::"ty" + shows "a\\" + by (simp add: fresh_def supp_def) + +instance ty :: pt_name +apply(intro_classes) +apply(simp_all) +done + +instance ty :: fs_name +apply(intro_classes) +apply(simp add: supp_def) +done + +(* valid contexts *) + +consts + "dom_ty" :: "(name\ty) list \ (name list)" +primrec + "dom_ty [] = []" + "dom_ty (x#\) = (fst x)#(dom_ty \)" + +consts + ctxts :: "((name\ty) list) set" + valid :: "(name\ty) list \ bool" +translations + "valid \" \ "\ \ ctxts" +inductive ctxts +intros +v1[intro]: "valid []" +v2[intro]: "\valid \;a\\\\ valid ((a,\)#\)" + +lemma valid_eqvt: + fixes pi:: "name prm" + assumes a: "valid \" + shows "valid (pi\\)" +using a +apply(induct) +apply(auto simp add: pt_fresh_bij[OF pt_name_inst, OF at_name_inst]) +done + +(* typing judgements *) + +lemma fresh_context[rule_format]: + fixes \ :: "(name\ty)list" + and a :: "name" + shows "a\\\\(\\::ty. (a,\)\set \)" +apply(induct_tac \) +apply(auto simp add: fresh_prod fresh_list_cons fresh_atm) +done + +lemma valid_elim: + fixes \ :: "(name\ty)list" + and pi:: "name prm" + and a :: "name" + and \ :: "ty" + shows "valid ((a,\)#\) \ valid \ \ a\\" +apply(ind_cases "valid ((a,\)#\)", simp) +done + +lemma valid_unicity[rule_format]: + shows "valid \\(c,\)\set \\(c,\)\set \\\=\" +apply(induct_tac \) +apply(auto dest!: valid_elim fresh_context) +done + +consts + typing :: "(((name\ty) list)\lam\ty) set" +syntax + "_typing_judge" :: "(name\ty) list\lam\ty\bool" (" _ \ _ : _ " [80,80,80] 80) +translations + "\ \ t : \" \ "(\,t,\) \ typing" + +inductive typing +intros +t1[intro]: "\valid \; (a,\)\set \\\ \ \ Var a : \" +t2[intro]: "\\ \ t1 : \\\; \ \ t2 : \\\ \ \ App t1 t2 : \" +t3[intro]: "\a\\;((a,\)#\) \ t : \\ \ \ \ Lam [a].t : \\\" + +lemma typing_eqvt: + fixes \ :: "(name\ty) list" + and t :: "lam" + and \ :: "ty" + and pi:: "name prm" + assumes a: "\ \ t : \" + shows "(pi\\) \ (pi\t) : \" +using a +proof (induct) + case (t1 \ \ a) + have "valid (pi\\)" by (rule valid_eqvt) + moreover + have "(pi\(a,\))\((pi::name prm)\set \)" by (rule pt_set_bij2[OF pt_name_inst, OF at_name_inst]) + ultimately show "(pi\\) \ (pi\Var a) : \" + using typing.intros by (auto simp add: pt_list_set_pi[OF pt_name_inst]) +next + case (t3 \ \ \ a t) + moreover have "(pi\a)\(pi\\)" by (rule pt_fresh_bij1[OF pt_name_inst, OF at_name_inst]) + ultimately show "(pi\\) \ (pi\Lam [a].t) : \\\" + using typing.intros by (force) +qed (auto) + +lemma typing_induct_aux[rule_format]: + fixes P :: "(name\ty) list \ lam \ ty \'a::fs_name\bool" + and \ :: "(name\ty) list" + and t :: "lam" + and \ :: "ty" + assumes a: "\ \ t : \" + and a1: "\x \ (a::name) \. valid \ \ (a,\) \ set \ \ P \ (Var a) \ x" + and a2: "\x \ \ \ t1 t2. + \ \ t1 : \\\ \ (\z. P \ t1 (\\\) z) \ \ \ t2 : \ \ (\z. P \ t2 \ z) + \ P \ (App t1 t2) \ x" + and a3: "\x (a::name) \ \ \ t. + a\x \ a\\ \ ((a,\) # \) \ t : \ \ (\z. P ((a,\)#\) t \ z) + \ P \ (Lam [a].t) (\\\) x" + shows "\(pi::name prm) (x::'a::fs_name). P (pi\\) (pi\t) \ x" +using a +proof (induct) + case (t1 \ \ a) + assume j1: "valid \" + assume j2: "(a,\)\set \" + show ?case + proof (intro strip, simp) + fix pi::"name prm" and x::"'a::fs_name" + from j1 have j3: "valid (pi\\)" by (rule valid_eqvt) + from j2 have "pi\(a,\)\pi\(set \)" by (simp only: pt_set_bij[OF pt_name_inst, OF at_name_inst]) + hence j4: "(pi\a,\)\set (pi\\)" by (simp add: pt_list_set_pi[OF pt_name_inst]) + show "P (pi\\) (Var (pi\a)) \ x" using a1 j3 j4 by force + qed +next + case (t2 \ \ \ t1 t2) + thus ?case using a2 by (simp, blast intro: typing_eqvt) +next + case (t3 \ \ \ a t) + have k1: "a\\" by fact + have k2: "((a,\)#\)\t:\" by fact + have k3: "\(pi::name prm) (x::'a::fs_name). P (pi \ ((a,\)#\)) (pi\t) \ x" by fact + show ?case + proof (intro strip, simp) + fix pi::"name prm" and x::"'a::fs_name" + have f: "\c::name. c\(pi\a,pi\t,pi\\,x)" + by (rule at_exists_fresh[OF at_name_inst], simp add: fs_name1) + then obtain c::"name" + where f1: "c\(pi\a)" and f2: "c\x" and f3: "c\(pi\t)" and f4: "c\(pi\\)" + by (force simp add: fresh_prod fresh_atm) + from k1 have k1a: "(pi\a)\(pi\\)" + by (simp add: pt_fresh_left[OF pt_name_inst, OF at_name_inst] + pt_rev_pi[OF pt_name_inst, OF at_name_inst]) + have l1: "(([(c,pi\a)]@pi)\\) = (pi\\)" using f4 k1a + by (simp only: pt_name2, rule pt_fresh_fresh[OF pt_name_inst, OF at_name_inst]) + have "\x. P (([(c,pi\a)]@pi)\((a,\)#\)) (([(c,pi\a)]@pi)\t) \ x" using k3 by force + hence l2: "\x. P ((c, \)#(pi\\)) (([(c,pi\a)]@pi)\t) \ x" using f1 l1 + by (force simp add: pt_name2 calc_atm split: if_splits) + have "(([(c,pi\a)]@pi)\((a,\)#\)) \ (([(c,pi\a)]@pi)\t) : \" using k2 by (rule typing_eqvt) + hence l3: "((c, \)#(pi\\)) \ (([(c,pi\a)]@pi)\t) : \" using l1 f1 + by (force simp add: pt_name2 calc_atm split: if_splits) + have l4: "P (pi\\) (Lam [c].(([(c,pi\a)]@pi)\t)) (\ \ \) x" using f2 f4 l2 l3 a3 by auto + have alpha: "(Lam [c].([(c,pi\a)]\(pi\t))) = (Lam [(pi\a)].(pi\t))" using f1 f3 + by (simp add: lam.inject alpha) + show "P (pi\\) (Lam [(pi\a)].(pi\t)) (\ \ \) x" using l4 alpha + by (simp only: pt_name2) + qed +qed + +lemma typing_induct[case_names t1 t2 t3]: + fixes P :: "(name\ty) list \ lam \ ty \'a::fs_name\bool" + and \ :: "(name\ty) list" + and t :: "lam" + and \ :: "ty" + and x :: "'a::fs_name" + assumes a: "\ \ t : \" + and a1: "\x \ (a::name) \. valid \ \ (a,\) \ set \ \ P \ (Var a) \ x" + and a2: "\x \ \ \ t1 t2. + \ \ t1 : \\\ \ (\z. P \ t1 (\\\) z) \ \ \ t2 : \ \ (\z. P \ t2 \ z) + \ P \ (App t1 t2) \ x" + and a3: "\x (a::name) \ \ \ t. + a\x \ a\\ \ ((a,\) # \) \ t : \ \ (\z. P ((a,\)#\) t \ z) + \ P \ (Lam [a].t) (\\\) x" + shows "P \ t \ x" +using a a1 a2 a3 typing_induct_aux[of "\" "t" "\" "P" "[]" "x", simplified] by force + +constdefs + "sub" :: "(name\ty) list \ (name\ty) list \ bool" (" _ \ _ " [80,80] 80) + "\1 \ \2 \ \a \. (a,\)\set \1 \ (a,\)\set \2" + +lemma weakening[rule_format]: + assumes a: "\1 \ t : \" + shows "valid \2 \ \1 \ \2 \ \2 \ t:\" +using a +apply(nominal_induct \1 t \ rule: typing_induct) +apply(auto simp add: sub_def) +done + +lemma in_ctxt[rule_format]: "(a,\)\set \ \ (a\set(dom_ty \))" +apply(induct_tac \) +apply(auto) +done + +lemma free_vars: + assumes a: "\ \ t : \" + shows " (supp t)\set(dom_ty \)" +using a +apply(nominal_induct \ t \ rule: typing_induct) +apply(auto simp add: lam.supp abs_supp supp_atm in_ctxt) +done + +lemma t1_elim: "\ \ Var a : \ \ valid \ \ (a,\) \ set \" +apply(ind_cases "\ \ Var a : \") +apply(auto simp add: lam.inject lam.distinct) +done + +lemma t2_elim: "\ \ App t1 t2 : \ \ \\. (\ \ t1 : \\\ \ \ \ t2 : \)" +apply(ind_cases "\ \ App t1 t2 : \") +apply(auto simp add: lam.inject lam.distinct) +done + +lemma t3_elim: "\\ \ Lam [a].t : \;a\\\\ \\ \'. \=\\\' \ ((a,\)#\) \ t : \'" +apply(ind_cases "\ \ Lam [a].t : \") +apply(auto simp add: lam.distinct lam.inject alpha) +apply(drule_tac pi="[(a,aa)]::name prm" in typing_eqvt) +apply(simp) +apply(subgoal_tac "([(a,aa)]::name prm)\\ = \")(*A*) +apply(force simp add: calc_atm) +(*A*) +apply(force intro!: pt_fresh_fresh[OF pt_name_inst, OF at_name_inst]) +done + +lemma typing_valid: + assumes a: "\ \ t : \" + shows "valid \" +using a by (induct, auto dest!: valid_elim) + +lemma ty_subs[rule_format]: + fixes \ ::"(name\ty) list" + and t1 ::"lam" + and t2 ::"lam" + and \ ::"ty" + and \ ::"ty" + and c ::"name" + shows "((c,\)#\) \ t1:\\ \\ t2:\\ \ \ t1[c::=t2]:\" +proof(nominal_induct t1 rule: lam_induct) + case (Var \ \ \ c t2 a) + show ?case + proof(intro strip) + assume a1: "\ \t2:\" + assume a2: "((c,\)#\) \ Var a:\" + hence a21: "(a,\)\set((c,\)#\)" and a22: "valid((c,\)#\)" by (auto dest: t1_elim) + from a22 have a23: "valid \" and a24: "c\\" by (auto dest: valid_elim) + from a24 have a25: "\(\\. (c,\)\set \)" by (rule fresh_context) + show "\\(Var a)[c::=t2] : \" + proof (cases "a=c", simp_all) + assume case1: "a=c" + show "\ \ t2:\" using a1 + proof (cases "\=\") + assume "\=\" thus ?thesis using a1 by simp + next + assume a3: "\\\" + show ?thesis + proof (rule ccontr) + from a3 a21 have "(a,\)\set \" by force + with case1 a25 show False by force + qed + qed + next + assume case2: "a\c" + with a21 have a26: "(a,\)\set \" by force + from a23 a26 show "\ \ Var a:\" by force + qed + qed +next + case (App \ \ \ c t2 s1 s2) + show ?case + proof (intro strip, simp) + assume b1: "\ \t2:\" + assume b2: " ((c,\)#\)\App s1 s2 : \" + hence "\\'. (((c,\)#\)\s1:\'\\ \ ((c,\)#\)\s2:\')" by (rule t2_elim) + then obtain \' where b3a: "((c,\)#\)\s1:\'\\" and b3b: "((c,\)#\)\s2:\'" by force + show "\ \ App (s1[c::=t2]) (s2[c::=t2]) : \" + using b1 b3a b3b App by (rule_tac \="\'" in t2, auto) + qed +next + case (Lam \ \ \ c t2 a s) + assume "a\(\,\,\,c,t2)" + hence f1: "a\\" and f2: "a\c" and f2': "c\a" and f3: "a\t2" and f4: "a\((c,\)#\)" + by (auto simp add: fresh_atm fresh_prod fresh_list_cons) + show ?case using f2 f3 + proof(intro strip, simp) + assume c1: "((c,\)#\)\Lam [a].s : \" + hence "\\1 \2. \=\1\\2 \ ((a,\1)#(c,\)#\) \ s : \2" using f4 by (auto dest: t3_elim) + then obtain \1 \2 where c11: "\=\1\\2" and c12: "((a,\1)#(c,\)#\) \ s : \2" by force + from c12 have "valid ((a,\1)#(c,\)#\)" by (rule typing_valid) + hence ca: "valid \" and cb: "a\\" and cc: "c\\" + by (auto dest: valid_elim simp add: fresh_list_cons) + from c12 have c14: "((c,\)#(a,\1)#\) \ s : \2" + proof - + have c2: "((a,\1)#(c,\)#\) \ ((c,\)#(a,\1)#\)" by (force simp add: sub_def) + have c3: "valid ((c,\)#(a,\1)#\)" + by (rule v2, rule v2, auto simp add: fresh_list_cons fresh_prod ca cb cc f2' fresh_ty) + from c12 c2 c3 show ?thesis by (force intro: weakening) + qed + assume c8: "\ \ t2 : \" + have c81: "((a,\1)#\)\t2 :\" + proof - + have c82: "\ \ ((a,\1)#\)" by (force simp add: sub_def) + have c83: "valid ((a,\1)#\)" using f1 ca by force + with c8 c82 c83 show ?thesis by (force intro: weakening) + qed + show "\ \ Lam [a].(s[c::=t2]) : \" + using c11 Lam c14 c81 f1 by force + qed +qed + +lemma subject[rule_format]: + fixes \ ::"(name\ty) list" + and t1 ::"lam" + and t2 ::"lam" + and \ ::"ty" + assumes a: "t1\\<^isub>\t2" + shows "(\ \ t1:\) \ (\ \ t2:\)" +using a +proof (nominal_induct t1 t2 rule: beta_induct, auto) + case (b1 \ \ t s1 s2) + assume i: "\\ \. \ \ s1 : \ \ \ \ s2 : \" + assume "\ \ App s1 t : \" + hence "\\. (\ \ s1 : \\\ \ \ \ t : \)" by (rule t2_elim) + then obtain \ where a1: "\ \ s1 : \\\" and a2: "\ \ t : \" by force + thus "\ \ App s2 t : \" using i by force +next + case (b2 \ \ t s1 s2) + assume i: "\\ \. \ \ s1 : \ \ \ \ s2 : \" + assume "\ \ App t s1 : \" + hence "\\. (\ \ t : \\\ \ \ \ s1 : \)" by (rule t2_elim) + then obtain \ where a1: "\ \ t : \\\" and a2: "\ \ s1 : \" by force + thus "\ \ App t s2 : \" using i by force +next + case (b3 \ \ a s1 s2) + assume "a\(\,\)" + hence f: "a\\" by (simp add: fresh_prod) + assume i: "\\ \. \ \ s1 : \ \ \ \ s2 : \" + assume "\ \ Lam [a].s1 : \" + with f have "\\1 \2. \=\1\\2 \ ((a,\1)#\) \ s1 : \2" by (force dest: t3_elim) + then obtain \1 \2 where a1: "\=\1\\2" and a2: "((a,\1)#\) \ s1 : \2" by force + thus "\ \ Lam [a].s2 : \" using f i by force +next + case (b4 \ \ a s1 s2) + have "a\(s2,\,\)" by fact + hence f: "a\\" by (simp add: fresh_prod) + assume "\ \ App (Lam [a].s1) s2 : \" + hence "\\. (\ \ (Lam [a].s1) : \\\ \ \ \ s2 : \)" by (rule t2_elim) + then obtain \ where a1: "\ \ (Lam [(a::name)].s1) : \\\" and a2: "\ \ s2 : \" by force + have "((a,\)#\) \ s1 : \" using a1 f by (auto dest!: t3_elim) + with a2 show "\ \ s1[a::=s2] : \" by (force intro: ty_subs) +qed + + +lemma subject[rule_format]: + fixes \ ::"(name\ty) list" + and t1 ::"lam" + and t2 ::"lam" + and \ ::"ty" + assumes a: "t1\\<^isub>\t2" + shows "\ \ t1:\ \ \ \ t2:\" +using a +apply(nominal_induct t1 t2 rule: beta_induct) +apply(auto dest!: t2_elim t3_elim intro: ty_subs simp add: fresh_prod) +done + + + +subsection {* some facts about beta *} + +constdefs + "NORMAL" :: "lam \ bool" + "NORMAL t \ \(\t'. t\\<^isub>\ t')" + +constdefs + "SN" :: "lam \ bool" + "SN t \ t\termi Beta" + +lemma qq1: "\SN(t1);t1\\<^isub>\ t2\\SN(t2)" +apply(simp add: SN_def) +apply(drule_tac a="t2" in acc_downward) +apply(auto) +done + +lemma qq2: "(\t2. t1\\<^isub>\t2 \ SN(t2))\SN(t1)" +apply(simp add: SN_def) +apply(rule accI) +apply(auto) +done + + +section {* Candidates *} + +consts + RED :: "ty \ lam set" +primrec + "RED (TVar X) = {t. SN(t)}" + "RED (\\\) = {t. \u. (u\RED \ \ (App t u)\RED \)}" + +constdefs + NEUT :: "lam \ bool" + "NEUT t \ (\a. t=Var a)\(\t1 t2. t=App t1 t2)" + +(* a slight hack to get the first element of applications *) +consts + FST :: "(lam\lam) set" +syntax + "FST_judge" :: "lam\lam\bool" (" _ \ _" [80,80] 80) +translations + "t1 \ t2" \ "(t1,t2) \ FST" +inductive FST +intros +fst[intro!]: "(App t s) \ t" + +lemma fst_elim[elim!]: "(App t s) \ t' \ t=t'" +apply(ind_cases "App t s \ t'") +apply(simp add: lam.inject) +done + +lemma qq3: "SN(App t s)\SN(t)" +apply(simp add: SN_def) +apply(subgoal_tac "\z. (App t s \ z) \ z\termi Beta")(*A*) +apply(force) +(*A*) +apply(erule acc_induct) +apply(clarify) +apply(ind_cases "x \ z") +apply(clarify) +apply(rule accI) +apply(auto intro: b1) +done + +constdefs + "CR1" :: "ty \ bool" + "CR1 \ \ \ t. (t\RED \ \ SN(t))" + + "CR2" :: "ty \ bool" + "CR2 \ \ \t t'. ((t\RED \ \ t \\<^isub>\ t') \ t'\RED \)" + + "CR3_RED" :: "lam \ ty \ bool" + "CR3_RED t \ \ \t'. (t\\<^isub>\ t' \ t'\RED \)" + + "CR3" :: "ty \ bool" + "CR3 \ \ \t. (NEUT t \ CR3_RED t \) \ t\RED \" + + "CR4" :: "ty \ bool" + "CR4 \ \ \t. (NEUT t \ NORMAL t) \t\RED \" + +lemma CR3_CR4: "CR3 \ \ CR4 \" +apply(simp (no_asm_use) add: CR3_def CR3_RED_def CR4_def NORMAL_def) +apply(blast) +done + +lemma sub_ind: + "SN(u)\(u\RED \\(\t. (NEUT t\CR2 \\CR3 \\CR3_RED t (\\\))\(App t u)\RED \))" +apply(simp add: SN_def) +apply(erule acc_induct) +apply(auto) +apply(simp add: CR3_def) +apply(rotate_tac 5) +apply(drule_tac x="App t x" in spec) +apply(drule mp) +apply(rule conjI) +apply(force simp only: NEUT_def) +apply(simp (no_asm) add: CR3_RED_def) +apply(clarify) +apply(ind_cases "App t x \\<^isub>\ t'") +apply(simp_all add: lam.inject) +apply(simp only: CR3_RED_def) +apply(drule_tac x="s2" in spec) +apply(simp) +apply(drule_tac x="s2" in spec) +apply(simp) +apply(drule mp) +apply(simp (no_asm_use) add: CR2_def) +apply(blast) +apply(drule_tac x="ta" in spec) +apply(force) +apply(auto simp only: NEUT_def lam.inject lam.distinct) +done + +lemma RED_props: "CR1 \ \ CR2 \ \ CR3 \" +apply(induct_tac \) +apply(auto) +(* atom types *) +(* C1 *) +apply(simp add: CR1_def) +(* C2 *) +apply(simp add: CR2_def) +apply(clarify) +apply(drule_tac ?t2.0="t'" in qq1) +apply(assumption)+ +(* C3 *) +apply(simp add: CR3_def CR3_RED_def) +apply(clarify) +apply(rule qq2) +apply(assumption) +(* arrow types *) +(* C1 *) +apply(simp (no_asm) add: CR1_def) +apply(clarify) +apply(subgoal_tac "NEUT (Var a)")(*A*) +apply(subgoal_tac "(Var a)\RED ty1")(*C*) +apply(drule_tac x="Var a" in spec) +apply(simp) +apply(simp add: CR1_def) +apply(rotate_tac 1) +apply(drule_tac x="App t (Var a)" in spec) +apply(simp) +apply(drule qq3) +apply(assumption) +(*C*) +apply(simp (no_asm_use) add: CR3_def CR3_RED_def) +apply(drule_tac x="Var a" in spec) +apply(drule mp) +apply(clarify) +apply(ind_cases " Var a \\<^isub>\ t'") +apply(simp (no_asm_use) add: lam.distinct)+ +(*A*) +apply(simp (no_asm) only: NEUT_def) +apply(rule disjCI) +apply(rule_tac x="a" in exI) +apply(simp (no_asm)) +(* C2 *) +apply(simp (no_asm) add: CR2_def) +apply(clarify) +apply(drule_tac x="u" in spec) +apply(simp) +apply(subgoal_tac "App t u \\<^isub>\ App t' u")(*X*) +apply(simp (no_asm_use) only: CR2_def) +apply(blast) +(*X*) +apply(force intro!: b1) +(* C3 *) +apply(unfold CR3_def) +apply(rule allI) +apply(rule impI) +apply(erule conjE) +apply(simp (no_asm)) +apply(rule allI) +apply(rule impI) +apply(subgoal_tac "SN(u)")(*Z*) +apply(fold CR3_def) +apply(drule_tac \="ty1" and \="ty2" in sub_ind) +apply(simp) +(*Z*) +apply(simp add: CR1_def) +done + +lemma double_acc_aux: + assumes a_acc: "a \ acc r" + and b_acc: "b \ acc r" + and hyp: "\x z. + (\y. (y, x) \ r \ y \ acc r) \ + (\y. (y, x) \ r \ P y z) \ + (\u. (u, z) \ r \ u \ acc r) \ + (\u. (u, z) \ r \ P x u) \ P x z" + shows "P a b" +proof - + from a_acc + have r: "\b. b \ acc r \ P a b" + proof (induct a rule: acc.induct) + case (accI x) + note accI' = accI + have "b \ acc r" . + thus ?case + proof (induct b rule: acc.induct) + case (accI y) + show ?case + apply (rule hyp) + apply (erule accI') + apply (erule accI') + apply (rule acc.accI) + apply (erule accI) + apply (erule accI) + apply (erule accI) + done + qed + qed + from b_acc show ?thesis by (rule r) +qed + +lemma double_acc: + "\a \ acc r; b \ acc r; \x z. ((\y. (y, x)\r\P y z)\(\u. (u, z)\r\P x u))\P x z\\P a b" +apply(rule_tac r="r" in double_acc_aux) +apply(assumption)+ +apply(blast) +done + +lemma abs_RED[rule_format]: "(\s\RED \. t[x::=s]\RED \)\Lam [x].t\RED (\\\)" +apply(simp) +apply(clarify) +apply(subgoal_tac "t\termi Beta")(*1*) +apply(erule rev_mp) +apply(subgoal_tac "u \ RED \")(*A*) +apply(erule rev_mp) +apply(rule_tac a="t" and b="u" in double_acc) +apply(assumption) +apply(subgoal_tac "CR1 \")(*A*) +apply(simp add: CR1_def SN_def) +(*A*) +apply(force simp add: RED_props) +apply(simp) +apply(clarify) +apply(subgoal_tac "CR3 \")(*B*) +apply(simp add: CR3_def) +apply(rotate_tac 6) +apply(drule_tac x="App(Lam[x].xa ) z" in spec) +apply(drule mp) +apply(rule conjI) +apply(force simp add: NEUT_def) +apply(simp add: CR3_RED_def) +apply(clarify) +apply(ind_cases "App(Lam[x].xa) z \\<^isub>\ t'") +apply(auto simp add: lam.inject lam.distinct) +apply(drule beta_abs) +apply(auto) +apply(drule_tac x="t''" in spec) +apply(simp) +apply(drule mp) +apply(clarify) +apply(drule_tac x="s" in bspec) +apply(assumption) +apply(subgoal_tac "xa [ x ::= s ] \\<^isub>\ t'' [ x ::= s ]")(*B*) +apply(subgoal_tac "CR2 \")(*C*) +apply(simp (no_asm_use) add: CR2_def) +apply(blast) +(*C*) +apply(force simp add: RED_props) +(*B*) +apply(force intro!: beta_subst) +apply(assumption) +apply(rotate_tac 3) +apply(drule_tac x="s2" in spec) +apply(subgoal_tac "s2\RED \")(*D*) +apply(simp) +(*D*) +apply(subgoal_tac "CR2 \")(*E*) +apply(simp (no_asm_use) add: CR2_def) +apply(blast) +(*E*) +apply(force simp add: RED_props) +apply(simp add: alpha) +apply(erule disjE) +apply(force) +apply(auto) +apply(simp add: subst_rename) +apply(drule_tac x="z" in bspec) +apply(assumption) +(*B*) +apply(force simp add: RED_props) +(*1*) +apply(drule_tac x="Var x" in bspec) +apply(subgoal_tac "CR3 \")(*2*) +apply(drule CR3_CR4) +apply(simp add: CR4_def) +apply(drule_tac x="Var x" in spec) +apply(drule mp) +apply(rule conjI) +apply(force simp add: NEUT_def) +apply(simp add: NORMAL_def) +apply(clarify) +apply(ind_cases "Var x \\<^isub>\ t'") +apply(auto simp add: lam.inject lam.distinct) +apply(force simp add: RED_props) +apply(simp add: id_subs) +apply(subgoal_tac "CR1 \")(*3*) +apply(simp add: CR1_def SN_def) +(*3*) +apply(force simp add: RED_props) +done + +lemma all_RED: + "((\a \. (a,\)\set(\)\(a\set(dom_sss \)\\\RED \))\\\t:\) \ (t[<\>]\RED \)" +apply(nominal_induct t rule: lam_induct) +(* Variables *) +apply(force dest: t1_elim) +(* Applications *) +apply(auto dest!: t2_elim) +apply(drule_tac x="a" in spec) +apply(drule_tac x="a" in spec) +apply(drule_tac x="\\aa" in spec) +apply(drule_tac x="\" in spec) +apply(drule_tac x="b" in spec) +apply(drule_tac x="b" in spec) +apply(force) +(* Abstractions *) +apply(drule t3_elim) +apply(simp add: fresh_prod) +apply(auto) +apply(drule_tac x="((ab,\)#a)" in spec) +apply(drule_tac x="\'" in spec) +apply(drule_tac x="b" in spec) +apply(simp) +(* HERE *) + + +done +