# HG changeset patch # User kleing # Date 1312814875 -7200 # Node ID cebb7abb54b18bcac5705320cbd11e5d70b80a74 # Parent d7c7ec248ef044fd037af64808a1fcdcc44c1c1e import constant folding theory into IMP diff -r d7c7ec248ef0 -r cebb7abb54b1 src/HOL/IMP/Big_Step.thy --- a/src/HOL/IMP/Big_Step.thy Sat Aug 06 15:48:08 2011 +0200 +++ b/src/HOL/IMP/Big_Step.thy Mon Aug 08 16:47:55 2011 +0200 @@ -113,6 +113,10 @@ qed qed +(* Using rule inversion to prove simplification rules: *) +lemma assign_simp: + "(x ::= a,s) \ s' \ (s' = s(x := aval a s))" + by auto subsection "Command Equivalence" diff -r d7c7ec248ef0 -r cebb7abb54b1 src/HOL/IMP/Comp_Rev.thy --- a/src/HOL/IMP/Comp_Rev.thy Sat Aug 06 15:48:08 2011 +0200 +++ b/src/HOL/IMP/Comp_Rev.thy Mon Aug 08 16:47:55 2011 +0200 @@ -479,9 +479,7 @@ "ccomp c = [] \ (c,s) \ s" by (induct c) auto -lemma assign [simp]: - "(x ::= a,s) \ s' \ (s' = s(x := aval a s))" - by auto +declare assign_simp [simp] lemma ccomp_exec_n: "ccomp c \ (0,s,stk) \^n (isize(ccomp c),t,stk') diff -r d7c7ec248ef0 -r cebb7abb54b1 src/HOL/IMP/Fold.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/IMP/Fold.thy Mon Aug 08 16:47:55 2011 +0200 @@ -0,0 +1,413 @@ +header "Constant Folding" + +theory Fold imports Sem_Equiv begin + +section "Simple folding of arithmetic expressions" + +types + tab = "name \ val option" + +(* maybe better as the composition of substitution and the existing simp_const(0) *) +fun simp_const :: "aexp \ tab \ aexp" where +"simp_const (N n) _ = N n" | +"simp_const (V x) t = (case t x of None \ V x | Some k \ N k)" | +"simp_const (Plus e1 e2) t = (case (simp_const e1 t, simp_const e2 t) of + (N n1, N n2) \ N(n1+n2) | (e1',e2') \ Plus e1' e2')" + +definition "approx t s \ (ALL x k. t x = Some k \ s x = k)" + +theorem aval_simp_const[simp]: +assumes "approx t s" +shows "aval (simp_const a t) s = aval a s" + using assms + by (induct a) (auto simp: approx_def split: aexp.split option.split) + +theorem aval_simp_const_N: +assumes "approx t s" +shows "simp_const a t = N n \ aval a s = n" + using assms + by (induct a arbitrary: n) + (auto simp: approx_def split: aexp.splits option.splits) + +definition + "merge t1 t2 = (\m. if t1 m = t2 m then t1 m else None)" + +primrec lnames :: "com \ name set" where +"lnames SKIP = {}" | +"lnames (x ::= a) = {x}" | +"lnames (c1; c2) = lnames c1 \ lnames c2" | +"lnames (IF b THEN c1 ELSE c2) = lnames c1 \ lnames c2" | +"lnames (WHILE b DO c) = lnames c" + +primrec "defs" :: "com \ tab \ tab" where +"defs SKIP t = t" | +"defs (x ::= a) t = + (case simp_const a t of N k \ t(x \ k) | _ \ t(x:=None))" | +"defs (c1;c2) t = (defs c2 o defs c1) t" | +"defs (IF b THEN c1 ELSE c2) t = merge (defs c1 t) (defs c2 t)" | +"defs (WHILE b DO c) t = t |` (-lnames c)" + +primrec fold where +"fold SKIP _ = SKIP" | +"fold (x ::= a) t = (x ::= (simp_const a t))" | +"fold (c1;c2) t = (fold c1 t; fold c2 (defs c1 t))" | +"fold (IF b THEN c1 ELSE c2) t = IF b THEN fold c1 t ELSE fold c2 t" | +"fold (WHILE b DO c) t = WHILE b DO fold c (t |` (-lnames c))" + +lemma approx_merge: + "approx t1 s \ approx t2 s \ approx (merge t1 t2) s" + by (fastsimp simp: merge_def approx_def) + +lemma approx_map_le: + "approx t2 s \ t1 \\<^sub>m t2 \ approx t1 s" + by (clarsimp simp: approx_def map_le_def dom_def) + +lemma restrict_map_le [intro!, simp]: "t |` S \\<^sub>m t" + by (clarsimp simp: restrict_map_def map_le_def) + +lemma merge_restrict: + assumes "t1 |` S = t |` S" + assumes "t2 |` S = t |` S" + shows "merge t1 t2 |` S = t |` S" +proof - + from assms + have "\x. (t1 |` S) x = (t |` S) x" + and "\x. (t2 |` S) x = (t |` S) x" by auto + thus ?thesis + by (auto simp: merge_def restrict_map_def + split: if_splits intro: ext) +qed + + +lemma defs_restrict: + "defs c t |` (- lnames c) = t |` (- lnames c)" +proof (induct c arbitrary: t) + case (Semi c1 c2) + hence "defs c1 t |` (- lnames c1) = t |` (- lnames c1)" + by simp + hence "defs c1 t |` (- lnames c1) |` (-lnames c2) = + t |` (- lnames c1) |` (-lnames c2)" by simp + moreover + from Semi + have "defs c2 (defs c1 t) |` (- lnames c2) = + defs c1 t |` (- lnames c2)" + by simp + hence "defs c2 (defs c1 t) |` (- lnames c2) |` (- lnames c1) = + defs c1 t |` (- lnames c2) |` (- lnames c1)" + by simp + ultimately + show ?case by (clarsimp simp: Int_commute) +next + case (If b c1 c2) + hence "defs c1 t |` (- lnames c1) = t |` (- lnames c1)" by simp + hence "defs c1 t |` (- lnames c1) |` (-lnames c2) = + t |` (- lnames c1) |` (-lnames c2)" by simp + moreover + from If + have "defs c2 t |` (- lnames c2) = t |` (- lnames c2)" by simp + hence "defs c2 t |` (- lnames c2) |` (-lnames c1) = + t |` (- lnames c2) |` (-lnames c1)" by simp + ultimately + show ?case by (auto simp: Int_commute intro: merge_restrict) +qed (auto split: aexp.split) + + +lemma big_step_pres_approx: + "(c,s) \ s' \ approx t s \ approx (defs c t) s'" +proof (induct arbitrary: t rule: big_step_induct) + case Skip thus ?case by simp +next + case Assign + thus ?case + by (clarsimp simp: aval_simp_const_N approx_def split: aexp.split) +next + case (Semi c1 s1 s2 c2 s3) + have "approx (defs c1 t) s2" by (rule Semi(2) [OF Semi.prems]) + hence "approx (defs c2 (defs c1 t)) s3" by (rule Semi(4)) + thus ?case by simp +next + case (IfTrue b s c1 s') + hence "approx (defs c1 t) s'" by simp + thus ?case by (simp add: approx_merge) +next + case (IfFalse b s c2 s') + hence "approx (defs c2 t) s'" by simp + thus ?case by (simp add: approx_merge) +next + case WhileFalse + thus ?case by (simp add: approx_def restrict_map_def) +next + case (WhileTrue b s1 c s2 s3) + hence "approx (defs c t) s2" by simp + with WhileTrue + have "approx (defs c t |` (-lnames c)) s3" by simp + thus ?case by (simp add: defs_restrict) +qed + +corollary approx_defs_inv [simp]: + "\ {approx t} c {approx (defs c t)}" + by (simp add: hoare_valid_def big_step_pres_approx) + + +lemma big_step_pres_approx_restrict: + "(c,s) \ s' \ approx (t |` (-lnames c)) s \ approx (t |` (-lnames c)) s'" +proof (induct arbitrary: t rule: big_step_induct) + case Assign + thus ?case by (clarsimp simp: approx_def) +next + case (Semi c1 s1 s2 c2 s3) + hence "approx (t |` (-lnames c2) |` (-lnames c1)) s1" + by (simp add: Int_commute) + hence "approx (t |` (-lnames c2) |` (-lnames c1)) s2" + by (rule Semi) + hence "approx (t |` (-lnames c1) |` (-lnames c2)) s2" + by (simp add: Int_commute) + hence "approx (t |` (-lnames c1) |` (-lnames c2)) s3" + by (rule Semi) + thus ?case by simp +next + case (IfTrue b s c1 s' c2) + hence "approx (t |` (-lnames c2) |` (-lnames c1)) s" + by (simp add: Int_commute) + hence "approx (t |` (-lnames c2) |` (-lnames c1)) s'" + by (rule IfTrue) + thus ?case by (simp add: Int_commute) +next + case (IfFalse b s c2 s' c1) + hence "approx (t |` (-lnames c1) |` (-lnames c2)) s" + by simp + hence "approx (t |` (-lnames c1) |` (-lnames c2)) s'" + by (rule IfFalse) + thus ?case by simp +qed auto + + +lemma approx_restrict_inv: + "\ {approx (t |` (-lnames c))} c {approx (t |` (-lnames c))}" + by (simp add: hoare_valid_def big_step_pres_approx_restrict) + +declare assign_simp [simp] + +lemma approx_eq: + "approx t \ c \ fold c t" +proof (induct c arbitrary: t) + case SKIP show ?case by simp +next + case Assign + show ?case by (simp add: equiv_up_to_def) +next + case Semi + thus ?case by (auto intro!: equiv_up_to_semi) +next + case If + thus ?case by (auto intro!: equiv_up_to_if_weak) +next + case (While b c) + hence "approx (t |` (- lnames c)) \ + WHILE b DO c \ WHILE b DO fold c (t |` (- lnames c))" + by (auto intro: equiv_up_to_while_weak approx_restrict_inv) + thus ?case + by (auto intro: equiv_up_to_weaken approx_map_le) +qed + + +lemma approx_empty [simp]: + "approx empty = (\_. True)" + by (auto intro!: ext simp: approx_def) + +lemma equiv_sym: + "c \ c' \ c' \ c" + by (auto simp add: equiv_def) + +theorem constant_folding_equiv: + "fold c empty \ c" + using approx_eq [of empty c] + by (simp add: equiv_up_to_True equiv_sym) + + + +section {* More ambitious folding including boolean expressions *} + + +fun bsimp_const :: "bexp \ tab \ bexp" where +"bsimp_const (Less a1 a2) t = less (simp_const a1 t) (simp_const a2 t)" | +"bsimp_const (And b1 b2) t = and (bsimp_const b1 t) (bsimp_const b2 t)" | +"bsimp_const (Not b) t = not(bsimp_const b t)" | +"bsimp_const (B bv) _ = B bv" + +theorem bvalsimp_const [simp]: + assumes "approx t s" + shows "bval (bsimp_const b t) s = bval b s" + using assms by (induct b) auto + +lemma not_B [simp]: "not (B v) = B (\v)" + by (cases v) auto + +lemma not_B_eq [simp]: "(not b = B v) = (b = B (\v))" + by (cases b) auto + +lemma and_B_eq: + "(and a b = B v) = (a = B False \ \v \ + b = B False \ \v \ + (\v1 v2. a = B v1 \ b = B v2 \ v = v1 \ v2))" + by (rule and.induct) auto + +lemma less_B_eq [simp]: + "(less a b = B v) = (\n1 n2. a = N n1 \ b = N n2 \ v = (n1 < n2))" + by (rule less.induct) auto + +theorem bvalsimp_const_B: +assumes "approx t s" +shows "bsimp_const b t = B v \ bval b s = v" + using assms + by (induct b arbitrary: v) + (auto simp: approx_def and_B_eq aval_simp_const_N + split: bexp.splits bool.splits) + + +primrec "bdefs" :: "com \ tab \ tab" where +"bdefs SKIP t = t" | +"bdefs (x ::= a) t = + (case simp_const a t of N k \ t(x \ k) | _ \ t(x:=None))" | +"bdefs (c1;c2) t = (bdefs c2 o bdefs c1) t" | +"bdefs (IF b THEN c1 ELSE c2) t = (case bsimp_const b t of + B True \ bdefs c1 t + | B False \ bdefs c2 t + | _ \ merge (bdefs c1 t) (bdefs c2 t))" | +"bdefs (WHILE b DO c) t = t |` (-lnames c)" + + +primrec bfold where +"bfold SKIP _ = SKIP" | +"bfold (x ::= a) t = (x ::= (simp_const a t))" | +"bfold (c1;c2) t = (bfold c1 t; bfold c2 (bdefs c1 t))" | +"bfold (IF b THEN c1 ELSE c2) t = (case bsimp_const b t of + B True \ bfold c1 t + | B False \ bfold c2 t + | _ \ IF bsimp_const b t THEN bfold c1 t ELSE bfold c2 t)" | +"bfold (WHILE b DO c) t = (case bsimp_const b t of + B False \ SKIP + | _ \ WHILE bsimp_const b (t |` (-lnames c)) DO bfold c (t |` (-lnames c)))" + + +lemma bdefs_restrict: + "bdefs c t |` (- lnames c) = t |` (- lnames c)" +proof (induct c arbitrary: t) + case (Semi c1 c2) + hence "bdefs c1 t |` (- lnames c1) = t |` (- lnames c1)" + by simp + hence "bdefs c1 t |` (- lnames c1) |` (-lnames c2) = + t |` (- lnames c1) |` (-lnames c2)" by simp + moreover + from Semi + have "bdefs c2 (bdefs c1 t) |` (- lnames c2) = + bdefs c1 t |` (- lnames c2)" + by simp + hence "bdefs c2 (bdefs c1 t) |` (- lnames c2) |` (- lnames c1) = + bdefs c1 t |` (- lnames c2) |` (- lnames c1)" + by simp + ultimately + show ?case by (clarsimp simp: Int_commute) +next + case (If b c1 c2) + hence "bdefs c1 t |` (- lnames c1) = t |` (- lnames c1)" by simp + hence "bdefs c1 t |` (- lnames c1) |` (-lnames c2) = + t |` (- lnames c1) |` (-lnames c2)" by simp + moreover + from If + have "bdefs c2 t |` (- lnames c2) = t |` (- lnames c2)" by simp + hence "bdefs c2 t |` (- lnames c2) |` (-lnames c1) = + t |` (- lnames c2) |` (-lnames c1)" by simp + ultimately + show ?case + by (auto simp: Int_commute intro: merge_restrict + split: bexp.splits bool.splits) +qed (auto split: aexp.split bexp.split bool.split) + + +lemma big_step_pres_approx_b: + "(c,s) \ s' \ approx t s \ approx (bdefs c t) s'" +proof (induct arbitrary: t rule: big_step_induct) + case Skip thus ?case by simp +next + case Assign + thus ?case + by (clarsimp simp: aval_simp_const_N approx_def split: aexp.split) +next + case (Semi c1 s1 s2 c2 s3) + have "approx (bdefs c1 t) s2" by (rule Semi(2) [OF Semi.prems]) + hence "approx (bdefs c2 (bdefs c1 t)) s3" by (rule Semi(4)) + thus ?case by simp +next + case (IfTrue b s c1 s') + hence "approx (bdefs c1 t) s'" by simp + thus ?case using `bval b s` `approx t s` + by (clarsimp simp: approx_merge bvalsimp_const_B + split: bexp.splits bool.splits) +next + case (IfFalse b s c2 s') + hence "approx (bdefs c2 t) s'" by simp + thus ?case using `\bval b s` `approx t s` + by (clarsimp simp: approx_merge bvalsimp_const_B + split: bexp.splits bool.splits) +next + case WhileFalse + thus ?case + by (clarsimp simp: bvalsimp_const_B approx_def restrict_map_def + split: bexp.splits bool.splits) +next + case (WhileTrue b s1 c s2 s3) + hence "approx (bdefs c t) s2" by simp + with WhileTrue + have "approx (bdefs c t |` (- lnames c)) s3" + by simp + thus ?case + by (simp add: bdefs_restrict) +qed + +corollary approx_bdefs_inv [simp]: + "\ {approx t} c {approx (bdefs c t)}" + by (simp add: hoare_valid_def big_step_pres_approx_b) + +lemma bfold_equiv: + "approx t \ c \ bfold c t" +proof (induct c arbitrary: t) + case SKIP show ?case by simp +next + case Assign + thus ?case by (simp add: equiv_up_to_def) +next + case Semi + thus ?case by (auto intro!: equiv_up_to_semi) +next + case (If b c1 c2) + hence "approx t \ IF b THEN c1 ELSE c2 \ + IF Fold.bsimp_const b t THEN bfold c1 t ELSE bfold c2 t" + by (auto intro: equiv_up_to_if_weak simp: bequiv_up_to_def) + thus ?case using If + by (fastsimp simp: bvalsimp_const_B split: bexp.splits bool.splits + intro: equiv_up_to_trans) + next + case (While b c) + hence "approx (t |` (- lnames c)) \ + WHILE b DO c \ + WHILE bsimp_const b (t |` (- lnames c)) + DO bfold c (t |` (- lnames c))" (is "_ \ ?W \ ?W'") + by (auto intro: equiv_up_to_while_weak approx_restrict_inv + simp: bequiv_up_to_def) + hence "approx t \ ?W \ ?W'" + by (auto intro: equiv_up_to_weaken approx_map_le) + thus ?case + by (auto split: bexp.splits bool.splits + intro: equiv_up_to_while_False + simp: bvalsimp_const_B) +qed + + +theorem constant_bfolding_equiv: + "bfold c empty \ c" + using bfold_equiv [of empty c] + by (simp add: equiv_up_to_True equiv_sym) + + +end diff -r d7c7ec248ef0 -r cebb7abb54b1 src/HOL/IMP/ROOT.ML --- a/src/HOL/IMP/ROOT.ML Sat Aug 06 15:48:08 2011 +0200 +++ b/src/HOL/IMP/ROOT.ML Mon Aug 08 16:47:55 2011 +0200 @@ -17,5 +17,6 @@ "Procs_Stat_Vars_Dyn", "Procs_Stat_Vars_Stat", "C_like", - "OO" + "OO", + "Fold" ]; diff -r d7c7ec248ef0 -r cebb7abb54b1 src/HOL/IMP/Sem_Equiv.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/IMP/Sem_Equiv.thy Mon Aug 08 16:47:55 2011 +0200 @@ -0,0 +1,165 @@ +header "Semantic Equivalence up to a Condition" + +theory Sem_Equiv +imports Hoare_Sound_Complete +begin + +definition + equiv_up_to :: "assn \ com \ com \ bool" ("_ \ _ \ _" [60,0,10] 60) +where + "P \ c \ c' \ \s s'. P s \ (c,s) \ s' \ (c',s) \ s'" + +definition + bequiv_up_to :: "assn \ bexp \ bexp \ bool" ("_ \ _ <\> _" [60,0,10] 60) +where + "P \ b <\> b' \ \s. P s \ bval b s = bval b' s" + +lemma equiv_up_to_True: + "((\_. True) \ c \ c') = (c \ c')" + by (simp add: equiv_def equiv_up_to_def) + +lemma equiv_up_to_weaken: + "P \ c \ c' \ (\s. P' s \ P s) \ P' \ c \ c'" + by (simp add: equiv_up_to_def) + +lemma equiv_up_toI: + "(\s s'. P s \ (c, s) \ s' = (c', s) \ s') \ P \ c \ c'" + by (unfold equiv_up_to_def) blast + +lemma equiv_up_toD1: + "P \ c \ c' \ P s \ (c, s) \ s' \ (c', s) \ s'" + by (unfold equiv_up_to_def) blast + +lemma equiv_up_toD2: + "P \ c \ c' \ P s \ (c', s) \ s' \ (c, s) \ s'" + by (unfold equiv_up_to_def) blast + + +lemma equiv_up_to_refl [simp, intro!]: + "P \ c \ c" + by (auto simp: equiv_up_to_def) + +lemma equiv_up_to_sym: + "(P \ c \ c') = (P \ c' \ c)" + by (auto simp: equiv_up_to_def) + +lemma equiv_up_to_trans [trans]: + "P \ c \ c' \ P \ c' \ c'' \ P \ c \ c''" + by (auto simp: equiv_up_to_def) + + +lemma bequiv_up_to_refl [simp, intro!]: + "P \ b <\> b" + by (auto simp: bequiv_up_to_def) + +lemma bequiv_up_to_sym: + "(P \ b <\> b') = (P \ b' <\> b)" + by (auto simp: bequiv_up_to_def) + +lemma bequiv_up_to_trans [trans]: + "P \ b <\> b' \ P \ b' <\> b'' \ P \ b <\> b''" + by (auto simp: bequiv_up_to_def) + + +lemma equiv_up_to_hoare: + "P' \ c \ c' \ (\s. P s \ P' s) \ (\ {P} c {Q}) = (\ {P} c' {Q})" + unfolding hoare_valid_def equiv_up_to_def by blast + +lemma equiv_up_to_hoare_eq: + "P \ c \ c' \ (\ {P} c {Q}) = (\ {P} c' {Q})" + by (rule equiv_up_to_hoare) + + +lemma equiv_up_to_semi: + "P \ c \ c' \ Q \ d \ d' \ \ {P} c {Q} \ + P \ (c; d) \ (c'; d')" + by (clarsimp simp: equiv_up_to_def hoare_valid_def) blast + +lemma equiv_up_to_while_lemma: + shows "(d,s) \ s' \ + P \ b <\> b' \ + (\s. P s \ bval b s) \ c \ c' \ + \ {\s. P s \ bval b s} c {P} \ + P s \ + d = WHILE b DO c \ + (WHILE b' DO c', s) \ s'" +proof (induct rule: big_step_induct) + case (WhileTrue b s1 c s2 s3) + note IH = WhileTrue.hyps(5) [OF WhileTrue.prems(1-3) _ WhileTrue.prems(5)] + + from WhileTrue.prems + have "P \ b <\> b'" by simp + with `bval b s1` `P s1` + have "bval b' s1" by (simp add: bequiv_up_to_def) + moreover + from WhileTrue.prems + have "(\s. P s \ bval b s) \ c \ c'" by simp + with `bval b s1` `P s1` `(c, s1) \ s2` + have "(c', s1) \ s2" by (simp add: equiv_up_to_def) + moreover + from WhileTrue.prems + have "\ {\s. P s \ bval b s} c {P}" by simp + with `P s1` `bval b s1` `(c, s1) \ s2` + have "P s2" by (simp add: hoare_valid_def) + hence "(WHILE b' DO c', s2) \ s3" by (rule IH) + ultimately + show ?case by blast +next + case WhileFalse + thus ?case by (auto simp: bequiv_up_to_def) +qed (fastsimp simp: equiv_up_to_def bequiv_up_to_def hoare_valid_def)+ + +lemma bequiv_context_subst: + "P \ b <\> b' \ (P s \ bval b s) = (P s \ bval b' s)" + by (auto simp: bequiv_up_to_def) + +lemma equiv_up_to_while: + "P \ b <\> b' \ (\s. P s \ bval b s) \ c \ c' \ + \ {\s. P s \ bval b s} c {P} \ + P \ WHILE b DO c \ WHILE b' DO c'" + apply (safe intro!: equiv_up_toI) + apply (auto intro: equiv_up_to_while_lemma)[1] + apply (simp add: equiv_up_to_hoare_eq bequiv_context_subst) + apply (drule equiv_up_to_sym [THEN iffD1]) + apply (drule bequiv_up_to_sym [THEN iffD1]) + apply (auto intro: equiv_up_to_while_lemma)[1] + done + +lemma equiv_up_to_while_weak: + "P \ b <\> b' \ P \ c \ c' \ \ {P} c {P} \ + P \ WHILE b DO c \ WHILE b' DO c'" + by (fastsimp elim!: equiv_up_to_while equiv_up_to_weaken + simp: hoare_valid_def) + +lemma equiv_up_to_if: + "P \ b <\> b' \ P \ bval b \ c \ c' \ (\s. P s \ \bval b s) \ d \ d' \ + P \ IF b THEN c ELSE d \ IF b' THEN c' ELSE d'" + by (auto simp: bequiv_up_to_def equiv_up_to_def) + +lemma equiv_up_to_if_weak: + "P \ b <\> b' \ P \ c \ c' \ P \ d \ d' \ + P \ IF b THEN c ELSE d \ IF b' THEN c' ELSE d'" + by (fastsimp elim!: equiv_up_to_if equiv_up_to_weaken) + +lemma equiv_up_to_if_True [intro!]: + "(\s. P s \ bval b s) \ P \ IF b THEN c1 ELSE c2 \ c1" + by (auto simp: equiv_up_to_def) + +lemma equiv_up_to_if_False [intro!]: + "(\s. P s \ \ bval b s) \ P \ IF b THEN c1 ELSE c2 \ c2" + by (auto simp: equiv_up_to_def) + +lemma equiv_up_to_while_False [intro!]: + "(\s. P s \ \ bval b s) \ P \ WHILE b DO c \ SKIP" + by (auto simp: equiv_up_to_def) + +lemma while_never: "(c, s) \ u \ c \ WHILE (B True) DO c'" + by (induct rule: big_step_induct) auto + +lemma equiv_up_to_while_True [intro!,simp]: + "P \ WHILE B True DO c \ WHILE B True DO SKIP" + unfolding equiv_up_to_def + by (blast dest: while_never) + + +end \ No newline at end of file