# HG changeset patch # User Christian Urban # Date 1295721961 21600 # Node ID 2abc8cb46a5c437d394440f773b37003db6368ee # Parent da9bed7baf2323e05887835355395dbbc1419cfb better version of Tutorial 1 diff -r da9bed7baf23 -r 2abc8cb46a5c Tutorial/Tutorial1.thy --- a/Tutorial/Tutorial1.thy Fri Jan 21 22:58:03 2011 +0100 +++ b/Tutorial/Tutorial1.thy Sat Jan 22 12:46:01 2011 -0600 @@ -1,4 +1,3 @@ - header {* Nominal Isabelle Tutorial at POPL'11 @@ -61,7 +60,6 @@ \ bullet (permutation application) *} - theory Tutorial1 imports Lambda begin @@ -183,7 +181,7 @@ text {* In this section we want to define inductively the evaluation - relation for lambda terms. + relation and for cbv-reduction relation. Inductive definitions in Isabelle start with the keyword "inductive" and a predicate name. One can optionally provide a type for the predicate. @@ -213,10 +211,8 @@ e_Lam[intro]: "Lam [x].t \ Lam [x].t" | e_App[intro]: "\t1 \ Lam [x].t; t2 \ v'; t[x::=v'] \ v\ \ App t1 t2 \ v" - text {* - Values are also defined using inductive. In our case values - are just lambda-abstractions. + Values and cbv are also defined using inductive. *} inductive @@ -224,7 +220,6 @@ where v_Lam[intro]: "val (Lam [x].t)" - section {* Theorems *} text {* @@ -362,6 +357,7 @@ Two very simple example proofs are as follows. *} +subsection {* EXERCISE 1 *} lemma eval_val: assumes a: "val t" @@ -372,7 +368,11 @@ show "Lam [x]. t \ Lam [x]. t" sorry qed -lemma eavl_to_val: +subsection {* EXERCISE 2 *} + +text {* Fill the gaps in the proof below. *} + +lemma eval_to_val: assumes a: "t \ t'" shows "val t'" using a @@ -381,16 +381,94 @@ show "val (Lam [x].t)" sorry next case (e_App t1 x t t2 v v') + -- {* all assumptions in this case *} have "t1 \ Lam [x].t" by fact have ih1: "val (Lam [x]. t)" by fact have "t2 \ v" by fact have ih2: "val v" by fact have "t [x ::= v] \ v'" by fact have ih3: "val v'" by fact + show "val v'" sorry qed + + +section {* Datatypes: Evaluation Contexts*} + +text {* + Datatypes can be defined in Isabelle as follows: we have to provide the name + of the datatype and a list its type-constructors. Each type-constructor needs + to have the information about the types of its arguments, and optionally + can also contain some information about pretty syntax. For example, we like + to write "\" for holes. +*} - +datatype ctx = + Hole ("\") + | CAppL "ctx" "lam" + | CAppR "lam" "ctx" + +text {* Now Isabelle knows about: *} + +typ ctx +term "\" +term "CAppL" +term "CAppL \ (Var x)" + +subsection {* MINI EXERCISE *} + +text {* + Try and see what happens if you apply a Hole to a Hole? +*} + + +section {* Machines for Evaluation *} + +type_synonym ctxs = "ctx list" + +inductive + machine :: "lam \ ctxs \lam \ ctxs \ bool" ("<_,_> \ <_,_>" [60, 60, 60, 60] 60) +where + m1: " \ t2) # Es>" +| m2: "val v \ t2) # Es> \ ) # Es>" +| m3: "val v \ ) # Es> \ " + +text {* + Since the machine defined above only performs a single reduction, + we need to define the transitive closure of this machine. *} + +inductive + machines :: "lam \ ctxs \ lam \ ctxs \ bool" ("<_,_> \* <_,_>" [60, 60, 60, 60] 60) +where + ms1: " \* " +| ms2: "\ \ ; \* \ \ \* " + +declare machine.intros[intro] machines.intros[intro] + +section {* EXERCISE 3 *} + +text {* + We need to show that the machines-relation is transitive. + Fill in the gaps below. +*} + +lemma ms3[intro]: + assumes a: " \* " + and b: " \* " + shows " \* " +using a b +proof(induct) + case (ms1 e1 Es1) + have c: " \* " by fact + then show " \* " by simp +next + case (ms2 e1 Es1 e2 Es2 e2' Es2') + have ih: " \* \ \* " by fact + have d1: " \* " by fact + have d2: " \ " by fact + show " \* " using d1 d2 ih by blast +qed + text {* Just like gotos in the Basic programming language, labels often reduce the readability of proofs. Therefore one can use in Isar the notation @@ -398,7 +476,22 @@ the next have-statement. This is used in teh second case below. *} - +lemma + assumes a: " \* " + and b: " \* " + shows " \* " +using a b +proof(induct) + case (ms1 e1 Es1) + show " \* " by fact +next + case (ms2 e1 Es1 e2 Es2 e2' Es2') + have ih: " \* \ \* " by fact + have " \* " by fact + then have d3: " \* " using ih by simp + have d2: " \ " by fact + show " \* " using d2 d3 by auto +qed text {* The label ih2 cannot be got rid of in this way, because it is used @@ -418,108 +511,6 @@ "statement". With this we can simplify our proof further to: *} - -text {* - While automatic proof procedures in Isabelle are not able to prove statements - like "P = NP" assuming usual definitions for P and NP, they can automatically - discharge the lemmas we just proved. For this we only have to set up the induction - and auto will take care of the rest. This means we can write: -*} - - - - -section {* Datatypes: Evaluation Contexts *} - -text {* - - Datatypes can be defined in Isabelle as follows: we have to provide the name - of the datatype and list its type-constructors. Each type-constructor needs - to have the information about the types of its arguments, and optionally - can also contain some information about pretty syntax. For example, we like - to write "\" for holes. -*} - -datatype ctx = - Hole ("\") - | CAppL "ctx" "lam" - | CAppR "lam" "ctx" - -text {* Now Isabelle knows about: *} - -typ ctx -term "\" -term "CAppL" -term "CAppL \ (Var x)" - -subsection {* MINI EXERCISE *} - -text {* - Try and see what happens if you apply a Hole to a Hole? -*} - -type_synonym ctxs = "ctx list" - -inductive - machine :: "lam \ ctxs \lam \ ctxs \ bool" ("<_,_> \ <_,_>" [60, 60, 60, 60] 60) -where - m1[intro]: " \ t2) # Es>" -| m2[intro]: "val v \ t2) # Es> \ ) # Es>" -| m3[intro]: "val v \ ) # Es> \ " - - -text {* - Since the machine defined above only performs a single reduction, - we need to define the transitive closure of this machine. *} - -inductive - machines :: "lam \ ctxs \ lam \ ctxs \ bool" ("<_,_> \* <_,_>" [60, 60, 60, 60] 60) -where - ms1[intro]: " \* " -| ms2[intro]: "\ \ ; \* \ \ \* " - -lemma - assumes a: " \* " - and b: " \* " - shows " \* " -using a b -proof(induct) - case (ms1 e1 Es1) - have c: " \* " by fact - then show " \* " by simp -next - case (ms2 e1 Es1 e2 Es2 e2' Es2') - have ih: " \* \ \* " by fact - have d1: " \* " by fact - have d2: " \ " by fact - show " \* " using d1 d2 ih by blast -qed - -text {* - Just like gotos in the Basic programming language, labels can reduce - the readability of proofs. Therefore one can use in Isar the notation - "then have" in order to feed a have-statement to the proof of - the next have-statement. In the proof below this has been used - in order to get rid of the labels c and d1. -*} - -lemma - assumes a: " \* " - and b: " \* " - shows " \* " -using a b -proof(induct) - case (ms1 e1 Es1) - show " \* " by fact -next - case (ms2 e1 Es1 e2 Es2 e2' Es2') - have ih: " \* \ \* " by fact - have " \* " by fact - then have d3: " \* " using ih by simp - have d2: " \ " by fact - show " \* " using d2 d3 by auto -qed - lemma assumes a: " \* " and b: " \* " @@ -539,16 +530,36 @@ qed -lemma ms3[intro]: +text {* + While automatic proof procedures in Isabelle are not able to prove statements + like "P = NP" assuming usual definitions for P and NP, they can automatically + discharge the lemmas we just proved. For this we only have to set up the induction + and auto will take care of the rest. This means we can write: +*} + +lemma + assumes a: "val t" + shows "t \ t" +using a by (induct) (auto) + +lemma + assumes a: "t \ t'" + shows "val t'" +using a by (induct) (auto) + +lemma assumes a: " \* " and b: " \* " shows " \* " using a b by (induct) (auto) -lemma eval_to_val: (* fixme: done above *) - assumes a: "t \ t'" - shows "val t'" -using a by (induct) (auto) + +section {* EXERCISE 4 *} + +text {* + The point of the machine is that it simulates the evaluation + relation. Therefore we like to prove the following: +*} theorem assumes a: "t \ t'" @@ -567,10 +578,47 @@ have ih2: " \* " by fact have a3: "t[x::=v'] \ v" by fact have ih3: " \* " by fact + -- {* your reasoning *} show " \* " sorry qed + +theorem + assumes a: "t \ t'" + shows " \* " +using a +proof (induct arbitrary: Es) + case (e_Lam x t Es) + -- {* no assumptions *} + show " \* " by auto +next + case (e_App t1 x t t2 v' v Es) + -- {* all assumptions in this case *} + have a1: "t1 \ Lam [x].t" by fact + have ih1: "\Es. \* " by fact + have a2: "t2 \ v'" by fact + have ih2: "\Es. \* " by fact + have a3: "t[x::=v'] \ v" by fact + have ih3: "\Es. \* " by fact + -- {* your reasoning *} + have " \* t2 # Es>" by auto + moreover + have " t2 # Es> \* t2 # Es>" using ih1 by auto + moreover + have " t2 # Es> \* # Es>" by auto + moreover + have " # Es> \* # Es>" + using ih2 by auto + moreover + have "val v'" using a2 eval_to_val by auto + then have " # Es> \* " by auto + moreover + have " \* " using ih3 by auto + ultimately show " \* " by blast +qed + + text {* Again the automatic tools in Isabelle can discharge automatically of the routine work in these proofs. We can write: @@ -607,6 +655,7 @@ | "(CAppL E t')\t\ = App (E\t\) t'" | "(CAppR t' E)\t\ = App t' (E\t\)" + text {* After this definition Isabelle will be able to simplify statements like: diff -r da9bed7baf23 -r 2abc8cb46a5c Tutorial/Tutorial4.thy --- a/Tutorial/Tutorial4.thy Fri Jan 21 22:58:03 2011 +0100 +++ b/Tutorial/Tutorial4.thy Sat Jan 22 12:46:01 2011 -0600 @@ -5,18 +5,62 @@ section {* The CBV Reduction Relation (Small-Step Semantics) *} + +inductive + cbv :: "lam \ lam \ bool" ("_ \cbv _" [60, 60] 60) +where + cbv1: "\val v; atom x \ v\ \ App (Lam [x].t) v \cbv t[x ::= v]" +| cbv2: "t \cbv t' \ App t t2 \cbv App t' t2" +| cbv3: "t \cbv t' \ App t2 t \cbv App t2 t'" + +inductive + "cbv_star" :: "lam \ lam \ bool" (" _ \cbv* _" [60, 60] 60) +where + cbvs1: "e \cbv* e" +| cbvs2: "\e1\cbv e2; e2 \cbv* e3\ \ e1 \cbv* e3" + +declare cbv.intros[intro] cbv_star.intros[intro] + +subsection {* EXERCISE 3 *} + +text {* + Show that cbv* is transitive, by filling the gaps in the + proof below. +*} + +lemma + assumes a: "e1 \cbv* e2" "e2 \cbv* e3" + shows "e1 \cbv* e3" +using a +proof (induct) + case (cbvs1 e1) + have asm: "e1 \cbv* e3" by fact + show "e1 \cbv* e3" sorry +next + case (cbvs2 e1 e2 e3') + have "e1 \cbv e2" by fact + have "e2 \cbv* e3'" by fact + have "e3' \cbv* e3 \ e2 \cbv* e3" by fact + have "e3' \cbv* e3" by fact + + show "e1 \cbv* e3" sorry +qed + +lemma cbvs3 [intro]: + assumes a: "e1 \cbv* e2" "e2 \cbv* e3" + shows "e1 \cbv* e3" +using a by (induct) (auto) + + + + + text {* In order to help establishing the property that the CK Machine calculates a nomrmalform that corresponds to the evaluation relation, we introduce the call-by-value small-step semantics. *} -inductive - cbv :: "lam \ lam \ bool" ("_ \cbv _" [60, 60] 60) -where - cbv1: "\val v; atom x \ v\ \ App (Lam [x].t) v \cbv t[x ::= v]" -| cbv2[intro]: "t \cbv t' \ App t t2 \cbv App t' t2" -| cbv3[intro]: "t \cbv t' \ App t2 t \cbv App t2 t'" equivariance val equivariance cbv @@ -44,7 +88,7 @@ lemma better_cbv1 [intro]: assumes a: "val v" - shows "App (Lam [x].t) v \cbv t[x::=v]" + shows "App (Lam [x].t) v \cbv t[x ::= v]" proof - obtain y::"name" where fs: "atom y \ (x, t, v)" by (rule obtain_fresh) have "App (Lam [x].t) v = App (Lam [y].((y \ x) \ t)) v" using fs @@ -58,16 +102,8 @@ The transitive closure of the cbv-reduction relation: *} -inductive - "cbvs" :: "lam \ lam \ bool" (" _ \cbv* _" [60, 60] 60) -where - cbvs1[intro]: "e \cbv* e" -| cbvs2[intro]: "\e1\cbv e2; e2 \cbv* e3\ \ e1 \cbv* e3" -lemma cbvs3 [intro]: - assumes a: "e1 \cbv* e2" "e2 \cbv* e3" - shows "e1 \cbv* e3" -using a by (induct) (auto) + subsection {* EXERCISE 8 *}