theory Sem04 imports "Lambda" begin text {****************************************************************** Formalising Barendregt's Proof of the Substitution Lemma -------------------------------------------------------- Barendregt's proof needs in the variable case a case distinction. One way to do this in Isar is to use blocks. A block is some sequent or reasoning steps enclosed in curly braces { \ have "statement" } Such a block can contain local assumptions like { assume "A" assume "B" \ have "C" by \ } Where "C" is the last have-statement in this block. The behaviour of such a block to the 'outside' is the implication \A; B\ \ "C" Now if we want to prove a property "smth" using the case-distinctions P\<^isub>1, P\<^isub>2 and P\<^isub>3 then we can use the following reasoning: { assume "P\<^isub>1" \ have "smth" } moreover { assume "P\<^isub>2" \ have "smth" } moreover { assume "P\<^isub>3" \ have "smth" } ultimately have "smth" by blast The blocks establish the implications P\<^isub>1 \ smth P\<^isub>2 \ smth P\<^isub>3 \ smth If we know that P\<^isub>1, P\<^isub>2 and P\<^isub>3 cover all the cases, that is P\<^isub>1 \ P\<^isub>2 \ P\<^isub>3 is true, then we have 'ultimately' established the property "smth" *} text {****************************************************************** Exercise -------- Fill in the cases 1.2 and 1.3 and the equational reasoning in the lambda-case. *} thm forget[no_vars] thm fresh_fact[no_vars] lemma assumes a: "x\y" and b: "x\L" shows "M[x::=N][y::=L] = M[y::=L][x::=N[y::=L]]" using a b proof (nominal_induct M avoiding: x y N L rule: lam.strong_induct) case (Var z) have a1: "x\y" by fact have a2: "x\L" by fact show "Var z[x::=N][y::=L] = Var z[y::=L][x::=N[y::=L]]" (is "?LHS = ?RHS") proof - { (*Case 1.1*) assume c1: "z=x" have "(1)": "?LHS = N[y::=L]" using c1 by simp have "(2)": "?RHS = N[y::=L]" using c1 a1 by simp have "?LHS = ?RHS" using "(1)" "(2)" by simp } moreover { (*Case 1.2*) assume c2: "z=y" "z\x" have "?LHS = ?RHS" sorry } moreover { (*Case 1.3*) assume c3: "z\x" "z\y" have "?LHS = ?RHS" sorry } ultimately show "?LHS = ?RHS" by blast qed next case (Lam z M1) (* case 2: lambdas *) have ih: "\x\y; x\L\ \ M1[x::=N][y::=L] = M1[y::=L][x::=N[y::=L]]" by fact have a1: "x\y" by fact have a2: "x\L" by fact have fs: "z\x" "z\y" "z\N" "z\L" by fact+ then have b: "z\N[y::=L]" by (simp add: fresh_fact) show "(Lam [z].M1)[x::=N][y::=L] = (Lam [z].M1)[y::=L][x::=N[y::=L]]" (is "?LHS=?RHS") proof - have "?LHS = \" sorry also have "\ = ?RHS" sorry finally show "?LHS = ?RHS" by simp qed next case (App M1 M2) (* case 3: applications *) then show "(App M1 M2)[x::=N][y::=L] = (App M1 M2)[y::=L][x::=N[y::=L]]" by simp qed text {* Again the strong induction principle enables Isabelle to find the proof of the substitution lemma automatically. *} lemma substitution_lemma_version: assumes asm: "x\y" "x\L" shows "M[x::=N][y::=L] = M[y::=L][x::=N[y::=L]]" using asm by (nominal_induct M avoiding: x y N L rule: lam.strong_induct) (auto simp add: fresh_fact forget) text {****************************************************************** Proof for the Strong Induction Principle ---------------------------------------- *} lemma lam_strong_induct: fixes c::"'a::fs_name" assumes a1: "\x c. P c (Var x)" and a2: "\t1 t2 c. \\c. P c t1; \c. P c t2\ \ P c (App t1 t2)" and a3: "\x t c. \x\c; \c. P c t\ \ P c Lam [x].t" shows "P c t" proof - have "\(pi::name prm) c. P c (pi\t)" proof (induct t rule: lam.induct) case (Lam x t) have ih: "\(pi::name prm) c. P c (pi\t)" by fact { fix pi::"name prm" and c::"'a::fs_name" obtain y::"name" where fc: "y\(pi\x,pi\t,c)" by (rule exists_fresh, auto simp add: fs_name1) from ih have "\c. P c (([(y,pi\x)]@pi)\t)" by simp then have "\c. P c ([(y,pi\x)]\(pi\t))" by (auto simp only: pt_name2) with a3 have "P c (Lam [y].[(y,pi\x)]\(pi\t))" using fc by (simp) moreover have "Lam [y].[(y,pi\x)]\(pi\t) = Lam [(pi\x)].(pi\t)" using fc by (simp add: lam.inject alpha fresh_atm fresh_prod) ultimately have "P c (Lam [(pi\x)].(pi\t))" by simp } then have "\(pi::name prm) c. P c (Lam [(pi\x)].(pi\t))" by auto then show "\(pi::name prm) c. P c (pi\(Lam [x].t))" by simp qed (auto intro: a1 a2) then have "P c (([]::name prm)\t)" by blast then show "P c t" by simp qed text {* Support ------- *} lemma shows "supp (t\<^isub>1,t\<^isub>2) = supp t\<^isub>1 \ ((supp t\<^isub>2)::atom set)" proof - have "supp (t\<^isub>1,t\<^isub>2) = {a. inf {b. [(a,b)]\(t\<^isub>1,t\<^isub>2) \ (t\<^isub>1,t\<^isub>2)}}" by (simp add: supp_def) also have "\ = {a. inf {b. ([(a,b)]\t\<^isub>1,[(a,b)]\t\<^isub>2) \ (t\<^isub>1,t\<^isub>2)}}" by simp also have "\ = {a. inf {b. [(a,b)]\t\<^isub>1 \ t\<^isub>1 \ [(a,b)]\t\<^isub>2 \ t\<^isub>2}}" by simp also have "\ = {a. inf ({b. [(a,b)]\t\<^isub>1 \ t\<^isub>1} \ {b. [(a,b)]\t\<^isub>2 \ t\<^isub>2})}" by (simp only: Collect_disj_eq) also have "\ = {a. (inf {b. [(a,b)]\t\<^isub>1 \ t\<^isub>1})\(inf {b. [(a,b)]\t\<^isub>2 \ t\<^isub>2})}" by simp also have "\ = {a. inf {b. [(a,b)]\t\<^isub>1 \ t\<^isub>1}}\{a. inf {b. [(a,b)]\t\<^isub>2 \ t\<^isub>2}}" by (simp only: Collect_disj_eq) also have "\ = supp t\<^isub>1 \ supp t\<^isub>2" by (simp add: supp_def) finally show "supp (t\<^isub>1,t\<^isub>2) = supp t\<^isub>1 \ ((supp t\<^isub>2)::atom set)" by simp qed end