header {* Hand-in on 17 June at noon. Please rename the file and send your solution to me as Hw16_\your name\ *} theory Hw16 imports Nominal begin atom_decl name text {* Task 1 (moderate) Add to the language a equality test on numbers. Change the definitions and proofs so that they go through. The big-step semantics of this equality test is given by: t1 \ (NUM n) t2 \ (NUM n) ------------------------------ EQI t1 t2 \ TRUE t1 \ (NUM n1) t2 \ (NUM n2) n1 \ n2 --------------------------------------- EQI t1 t2 \ FALSE *} nominal_datatype lam = VAR "name" | APP "lam" "lam" | LAM "\name\lam" ("LAM [_]._") | NUM "nat" | DIFF "lam" "lam" ("_ -- _") | PLUS "lam" "lam" ("_ ++ _") | TRUE | FALSE | IF "lam" "lam" "lam" | FIX "\name\lam" ("FIX [_]._") | ZET "lam" consts subst :: "lam \ name \ lam \ lam" ("_[_::=_]" [100,100,100] 100) nominal_primrec "(VAR x)[y::=s] = (if x=y then s else (VAR x))" "(APP t\<^isub>1 t\<^isub>2)[y::=s] = APP (t\<^isub>1[y::=s]) (t\<^isub>2[y::=s])" "x\(y,s) \ (LAM [x].t)[y::=s] = LAM [x].(t[y::=s])" "(NUM n)[y::=s] = NUM n" "(t\<^isub>1 -- t\<^isub>2)[y::=s] = (t\<^isub>1[y::=s]) -- (t\<^isub>2[y::=s])" "(t\<^isub>1 ++ t\<^isub>2)[y::=s] = (t\<^isub>1[y::=s]) ++ (t\<^isub>2[y::=s])" "x\(y,s) \ (FIX [x].t)[y::=s] = FIX [x].(t[y::=s])" "TRUE[y::=s] = TRUE" "FALSE[y::=s] = FALSE" "(IF t1 t2 t3)[y::=s] = IF (t1[y::=s]) (t2[y::=s]) (t3[y::=s])" "(ZET t)[y::=s] = ZET (t[y::=s])" apply(finite_guess)+ apply(rule TrueI)+ apply(simp add: abs_fresh)+ apply(fresh_guess)+ done datatype ctx = Hole ("\") | CAPPL "ctx" "lam" | CAPPR "lam" "ctx" | CDIFFL "ctx" "lam" | CDIFFR "lam" "ctx" | CPLUSL "ctx" "lam" | CPLUSR "lam" "ctx" | CIF "ctx" "lam" "lam" | CZE "ctx" fun filling :: "ctx \ lam \ lam" ("_\_\") where "\\t\ = t" | "(CAPPL E t')\t\ = APP (E\t\) t'" | "(CAPPR t' E)\t\ = APP t' (E\t\)" | "(CDIFFL E t')\t\ = (E\t\) -- t'" | "(CDIFFR t' E)\t\ = t' -- (E\t\)" | "(CPLUSL E t')\t\ = (E\t\) ++ t'" | "(CPLUSR t' E)\t\ = t' ++ (E\t\)" | "(CIF E t1 t2)\t\ = IF (E\t\) t1 t2" | "(CZE E)\t\ = ZET (E\t\)" inductive val :: "lam\bool" where v_LAM[intro]: "val (LAM [x].e)" | v_NUM[intro]: "val (NUM n)" | v_FALSE[intro]: "val FALSE" | v_TRUE[intro]: "val TRUE" inductive machine :: "lam\ctx list\lam\ctx list\bool" ("<_,_> \ <_,_>") where m1[intro]: " \ e2)#Es>" | m2[intro]: "val v \ e2)#Es> \ )#Es>" | m3[intro]: "val v \ )#Es> \ " | m4[intro]: " \ e2)#Es>" | m5[intro]: " e2)#Es> \ )#Es>" | m6[intro]: ")#Es> \ " | m4'[intro]:" \ e2)#Es>" | m5'[intro]:" e2)#Es> \ )#Es>" | m6'[intro]:")#Es> \ " | m7[intro]: " \ e2 e3)#Es>" | m8[intro]: " e1 e2)#Es> \ " | m9[intro]: " e1 e2)#Es> \ " | mA[intro]: " \ " | mB[intro]: " \ )#Es>" | mC[intro]: ")#Es> \ " | mD[intro]: "0 < n \ )#Es> \ " inductive "machine_star" :: "lam\ctx list\lam\ctx list\bool" ("<_,_> \* <_,_>") where ms1[intro]: " \* " | ms2[intro]: "\ \ ; \* \ \ \* " lemma ms3[intro,trans]: assumes a: " \* " " \* " shows " \* " using a by (induct) (auto) lemma ms4[intro]: assumes a: " \ " shows " \* " using a by (rule ms2) (rule ms1) inductive eval :: "lam\lam\bool" ("_ \ _") where eval_NUM[intro]: "NUM n \ NUM n" | eval_DIFF[intro]: "\t1 \ (NUM n1); t2 \ (NUM n2)\ \ t1 -- t2 \ NUM (n1 - n2)" | eval_PLUS[intro]: "\t1 \ (NUM n1); t2 \ (NUM n2)\ \ t1 ++ t2 \ NUM (n1 + n2)" | eval_LAM[intro]: "LAM [x].t \ LAM [x].t" | eval_APP[intro]: "\t1\ LAM [x].t; t2\ t2'; t[x::=t2']\ t'\ \ APP t1 t2 \ t'" | eval_FIX[intro]: "t[x::= FIX [x].t] \ t' \ FIX [x].t \ t'" | eval_IF1[intro]: "\t1 \ TRUE; t2 \ t'\ \ IF t1 t2 t3 \ t'" | eval_IF2[intro]: "\t1 \ FALSE; t3 \ t'\ \ IF t1 t2 t3 \ t'" | eval_TRUE[intro]: "TRUE \ TRUE" | eval_FALSE[intro]:"FALSE \ FALSE" | eval_ZE1[intro]: "t \ NUM 0 \ ZET t \ TRUE" | eval_ZE2[intro]: "\t \ NUM n; 0 < n\ \ ZET t \ FALSE" lemma eval_APP_elim: assumes a: "APP t1 t2 \ t'" shows "\x t t2'. t1\ LAM [x].t \ t2\ t2' \ t[x::=t2']\ t'" using a by (cases) (auto simp add: lam.inject) lemma eval_IF_elim: assumes a: "IF t1 t2 t3 \ t'" shows "(t1 \ TRUE \ t2 \ t') \ (t1 \ FALSE \ t3 \ t')" using a by (cases) (auto simp add: lam.inject) lemma eval_ZET_elim: assumes a: "ZET t \ t'" shows "(t \ NUM 0 \ t' = TRUE) \ (\n. t \ NUM n \ 0 < n \ t' = FALSE)" using a by (cases) (auto simp add: lam.inject) lemma eval_PLUS_elim: assumes a: "t1 ++ t2 \ t'" shows "\n1 n2. t1\ (NUM n1) \ t2\ (NUM n2) \ t' = NUM (n1 + n2)" using a by (cases) (auto simp add: lam.inject) lemma eval_DIFF_elim: assumes a: "t1 -- t2 \ t'" shows "\n1 n2. t1\ (NUM n1) \ t2\ (NUM n2) \ t' = NUM (n1 - n2)" using a by (cases) (auto simp add: lam.inject) lemma eval_NUM_elim: assumes a: "(NUM n) \ t" shows "t = NUM n" using a by (cases) (auto simp add: lam.inject) lemma eval_TRUE_elim: assumes a: "TRUE \ t" shows "t = TRUE" using a by (cases) (auto) lemma eval_FALSE_elim: assumes a: "FALSE \ t" shows "t = FALSE" using a by (cases) (auto) lemma eval_to: assumes a: "t \ t'" shows "val t'" using a by (induct) (auto) lemma eval_val: assumes a: "val t" shows "t \ t" using a by (induct) (auto) theorem eval_implies_machine: assumes a: "t \ t'" shows " \* " using a apply(induct arbitrary: Es) apply(metis eval_to m1 ms1 m2 ms2 m3 ms3 ms4 m4 m5 m6 m4' m5' m6' m7 m8 m9 mA mB mC mD v_LAM)+ done fun ctx_compose :: "ctx \ ctx \ ctx" ("_ \ _") where "\ \ E' = E'" | "(CAPPL E t') \ E' = CAPPL (E \ E') t'" | "(CAPPR t' E) \ E' = CAPPR t' (E \ E')" | "(CDIFFL E t') \ E' = CDIFFL (E \ E') t'" | "(CDIFFR t' E) \ E' = CDIFFR t' (E \ E')" | "(CPLUSL E t') \ E' = CPLUSL (E \ E') t'" | "(CPLUSR t' E) \ E' = CPLUSR t' (E \ E')" | "(CIF E t1 t2) \ E' = CIF (E \ E') t1 t2" | "(CZE E) \ E' = CZE (E \ E')" lemma ctx_compose: shows "(E1 \ E2)\t\ = E1\E2\t\\" by (induct E1 rule: ctx.induct) (auto) fun ctx_composes :: "ctx list \ ctx" ("_\") where "[]\ = \" | "(E#Es)\ = (Es\) \ E" inductive cbv :: "lam\lam\bool" ("_ \cbv _") where cbv1[intro]: "val 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'" | cbv4[intro]: "t \cbv t' \ t -- t2 \cbv t' -- t2" | cbv5[intro]: "t \cbv t' \ t2 -- t \cbv t2 -- t'" | cbv6[intro]: "(NUM n1) -- (NUM n2) \cbv NUM (n1 - n2)" | cbv4'[intro]: "t \cbv t' \ t ++ t2 \cbv t' ++ t2" | cbv5'[intro]: "t \cbv t' \ t2 ++ t \cbv t2 ++ t'" | cbv6'[intro]:"(NUM n1) ++ (NUM n2) \cbv NUM (n1 + n2)" | cbv7[intro]: "t \cbv t' \ IF t t1 t2 \cbv IF t' t1 t2" | cbv8[intro]: "IF TRUE t1 t2 \cbv t1" | cbv9[intro]: "IF FALSE t1 t2 \cbv t2" | cbvA[intro]: "FIX [x].t \cbv t[x::=FIX [x].t]" | cbvB[intro]: "t \cbv t' \ ZET t \cbv ZET t'" | cbvC[intro]: "ZET (NUM 0) \cbv TRUE" | cbvD[intro]: "0 < n \ ZET (NUM n) \cbv FALSE" inductive "cbv_star" :: "lam\lam\bool" (" _ \cbv* _") where cbvs1[intro]: "e \cbv* e" | cbvs2[intro]: "e \cbv e' \ e \cbv* e'" | cbvs3[intro,trans]: "\e1\cbv* e2; e2 \cbv* e3\ \ e1 \cbv* e3" lemma cbv_in_ctx: assumes a: "t \cbv t'" shows "E\t\ \cbv E\t'\" using a by (induct E) (auto) lemma machine_implies_cbv_star: assumes a: " \ " shows "(Es\)\e\ \cbv* (Es'\)\e'\" using a by (induct) (auto simp add: ctx_compose intro: cbv_in_ctx) lemma cbv_eval: assumes a: "t1 \cbv t2" "t2 \ t3" shows "t1 \ t3" using a apply(induct arbitrary: t3) apply(auto dest!: eval_APP_elim eval_ZET_elim eval_DIFF_elim eval_NUM_elim eval_IF_elim eval_PLUS_elim eval_FALSE_elim eval_TRUE_elim intro: eval_val) done lemma cbv_star_eval: assumes a: "t1 \cbv* t2" "t2 \ t3" shows "t1 \ t3" using a by (induct) (auto simp add: cbv_eval) lemma machine_implies_eval: assumes a: " \ " and b: "(Es'\)\t2\ \ t3" shows "(Es\)\t1\ \ t3" proof - from a have "(Es\)\t1\ \cbv* (Es'\)\t2\" by (rule machine_implies_cbv_star) moreover have "(Es'\)\t2\ \ t3" by fact ultimately show "(Es\)\t1\ \ t3" by (rule cbv_star_eval) qed lemma machine_star_implies_eval: assumes a: " \* " "val t2" shows "(Es\)\t1\ \ t2" using a by (induct t1 Es t2 Es'\"[]::ctx list") (auto simp add: eval_val machine_implies_eval) theorem assumes a: " \* " "val t2" shows "t1 \ t2" using a by (auto dest: machine_star_implies_eval) lemma forget: assumes asm: "y\t" shows "t[y::=s] = t" using asm by (nominal_induct t avoiding: y s rule: lam.strong_induct) (auto simp add: abs_fresh fresh_atm) lemma forget2: shows "(LAM [y].t)[y::=s] = (LAM [y].t)" by (rule forget) (simp add: abs_fresh) text {* Task 2: (moderate) Have a look at the program below calculating the sum of the first n numbers. Write a program that calculates the nth Fibonacci number. *} consts x::"name" f::"name" abbreviation Sum :: "lam" where "Sum \ FIX [f].LAM [x].(IF (ZET (VAR x)) (NUM 0) ((VAR x) ++ (APP (VAR f) ((VAR x) -- NUM 1))))" text {* Task 3: (easy) For theorem eval_implies_machine (stated above) give on *paper* the cases for applications, lambda-abstractions and if's. State clearly which property you are proving and what the induction hypotheses are. *} end