diff --git a/src/HOL/Hoare/Hoare_Logic.thy b/src/HOL/Hoare/Hoare_Logic.thy --- a/src/HOL/Hoare/Hoare_Logic.thy +++ b/src/HOL/Hoare/Hoare_Logic.thy @@ -1,220 +1,219 @@ (* Title: HOL/Hoare/Hoare_Logic.thy Author: Leonor Prensa Nieto & Tobias Nipkow Copyright 1998 TUM Author: Walter Guttmann (extension to total-correctness proofs) Sugared semantic embedding of Hoare logic. Strictly speaking a shallow embedding (as implemented by Norbert Galm following Mike Gordon) would suffice. Maybe the datatype com comes in useful later. *) theory Hoare_Logic imports Main begin type_synonym 'a bexp = "'a set" type_synonym 'a assn = "'a set" type_synonym 'a var = "'a \ nat" datatype 'a com = Basic "'a \ 'a" | Seq "'a com" "'a com" ("(_;/ _)" [61,60] 60) | Cond "'a bexp" "'a com" "'a com" ("(1IF _/ THEN _ / ELSE _/ FI)" [0,0,0] 61) | While "'a bexp" "'a assn" "'a var" "'a com" ("(1WHILE _/ INV {_} / VAR {_} //DO _ /OD)" [0,0,0,0] 61) -syntax (xsymbols) +syntax "_whilePC" :: "'a bexp \ 'a assn \ 'a com \ 'a com" ("(1WHILE _/ INV {_} //DO _ /OD)" [0,0,0] 61) - translations - "WHILE b INV {x} DO c OD" => "WHILE b INV {x} VAR {0} DO c OD" + "WHILE b INV {x} DO c OD" \ "WHILE b INV {x} VAR {0} DO c OD" abbreviation annskip ("SKIP") where "SKIP == Basic id" type_synonym 'a sem = "'a => 'a => bool" inductive Sem :: "'a com \ 'a sem" where "Sem (Basic f) s (f s)" | "Sem c1 s s'' \ Sem c2 s'' s' \ Sem (c1;c2) s s'" | "s \ b \ Sem c1 s s' \ Sem (IF b THEN c1 ELSE c2 FI) s s'" | "s \ b \ Sem c2 s s' \ Sem (IF b THEN c1 ELSE c2 FI) s s'" | "s \ b \ Sem (While b x y c) s s" | "s \ b \ Sem c s s'' \ Sem (While b x y c) s'' s' \ Sem (While b x y c) s s'" inductive_cases [elim!]: "Sem (Basic f) s s'" "Sem (c1;c2) s s'" "Sem (IF b THEN c1 ELSE c2 FI) s s'" lemma Sem_deterministic: assumes "Sem c s s1" and "Sem c s s2" shows "s1 = s2" proof - have "Sem c s s1 \ (\s2. Sem c s s2 \ s1 = s2)" by (induct rule: Sem.induct) (subst Sem.simps, blast)+ thus ?thesis using assms by simp qed definition Valid :: "'a bexp \ 'a com \ 'a bexp \ bool" where "Valid p c q \ \s s'. Sem c s s' \ s \ p \ s' \ q" definition ValidTC :: "'a bexp \ 'a com \ 'a bexp \ bool" where "ValidTC p c q \ \s . s \ p \ (\t . Sem c s t \ t \ q)" lemma tc_implies_pc: "ValidTC p c q \ Valid p c q" by (metis Sem_deterministic Valid_def ValidTC_def) lemma tc_extract_function: "ValidTC p c q \ \f . \s . s \ p \ f s \ q" by (metis ValidTC_def) syntax "_assign" :: "idt => 'b => 'a com" ("(2_ :=/ _)" [70, 65] 61) syntax "_hoare_vars" :: "[idts, 'a assn,'a com,'a assn] => bool" ("VARS _// {_} // _ // {_}" [0,0,55,0] 50) -syntax ("" output) +syntax (output) "_hoare" :: "['a assn,'a com,'a assn] => bool" ("{_} // _ // {_}" [0,55,0] 50) ML_file \hoare_syntax.ML\ parse_translation \[(\<^syntax_const>\_hoare_vars\, K Hoare_Syntax.hoare_vars_tr)]\ print_translation \[(\<^const_syntax>\Valid\, K (Hoare_Syntax.spec_tr' \<^syntax_const>\_hoare\))]\ syntax "_hoare_tc_vars" :: "[idts, 'a assn,'a com,'a assn] => bool" ("VARS _// [_] // _ // [_]" [0,0,55,0] 50) -syntax ("" output) +syntax (output) "_hoare_tc" :: "['a assn,'a com,'a assn] => bool" ("[_] // _ // [_]" [0,55,0] 50) parse_translation \[(\<^syntax_const>\_hoare_tc_vars\, K Hoare_Syntax.hoare_tc_vars_tr)]\ print_translation \[(\<^const_syntax>\ValidTC\, K (Hoare_Syntax.spec_tr' \<^syntax_const>\_hoare_tc\))]\ lemma SkipRule: "p \ q \ Valid p (Basic id) q" by (auto simp:Valid_def) lemma BasicRule: "p \ {s. f s \ q} \ Valid p (Basic f) q" by (auto simp:Valid_def) lemma SeqRule: "Valid P c1 Q \ Valid Q c2 R \ Valid P (c1;c2) R" by (auto simp:Valid_def) lemma CondRule: "p \ {s. (s \ b \ s \ w) \ (s \ b \ s \ w')} \ Valid w c1 q \ Valid w' c2 q \ Valid p (Cond b c1 c2) q" by (auto simp:Valid_def) lemma While_aux: assumes "Sem (WHILE b INV {i} VAR {v} DO c OD) s s'" shows "\s s'. Sem c s s' \ s \ I \ s \ b \ s' \ I \ s \ I \ s' \ I \ s' \ b" using assms by (induct "WHILE b INV {i} VAR {v} DO c OD" s s') auto lemma WhileRule: "p \ i \ Valid (i \ b) c i \ i \ (-b) \ q \ Valid p (While b i v c) q" apply (clarsimp simp:Valid_def) apply(drule While_aux) apply assumption apply blast apply blast done lemma SkipRuleTC: assumes "p \ q" shows "ValidTC p (Basic id) q" by (metis assms Sem.intros(1) ValidTC_def id_apply subsetD) lemma BasicRuleTC: assumes "p \ {s. f s \ q}" shows "ValidTC p (Basic f) q" by (metis assms Ball_Collect Sem.intros(1) ValidTC_def) lemma SeqRuleTC: assumes "ValidTC p c1 q" and "ValidTC q c2 r" shows "ValidTC p (c1;c2) r" by (meson assms Sem.intros(2) ValidTC_def) lemma CondRuleTC: assumes "p \ {s. (s \ b \ s \ w) \ (s \ b \ s \ w')}" and "ValidTC w c1 q" and "ValidTC w' c2 q" shows "ValidTC p (Cond b c1 c2) q" proof (unfold ValidTC_def, rule allI) fix s show "s \ p \ (\t . Sem (Cond b c1 c2) s t \ t \ q)" apply (cases "s \ b") apply (metis (mono_tags, lifting) assms(1,2) Ball_Collect Sem.intros(3) ValidTC_def) by (metis (mono_tags, lifting) assms(1,3) Ball_Collect Sem.intros(4) ValidTC_def) qed lemma WhileRuleTC: assumes "p \ i" and "\n::nat . ValidTC (i \ b \ {s . v s = n}) c (i \ {s . v s < n})" and "i \ uminus b \ q" shows "ValidTC p (While b i v c) q" proof - { fix s n have "s \ i \ v s = n \ (\t . Sem (While b i v c) s t \ t \ q)" proof (induction "n" arbitrary: s rule: less_induct) fix n :: nat fix s :: 'a assume 1: "\(m::nat) s::'a . m < n \ s \ i \ v s = m \ (\t . Sem (While b i v c) s t \ t \ q)" show "s \ i \ v s = n \ (\t . Sem (While b i v c) s t \ t \ q)" proof (rule impI, cases "s \ b") assume 2: "s \ b" and "s \ i \ v s = n" hence "s \ i \ b \ {s . v s = n}" using assms(1) by auto hence "\t . Sem c s t \ t \ i \ {s . v s < n}" by (metis assms(2) ValidTC_def) from this obtain t where 3: "Sem c s t \ t \ i \ {s . v s < n}" by auto hence "\u . Sem (While b i v c) t u \ u \ q" using 1 by auto thus "\t . Sem (While b i v c) s t \ t \ q" using 2 3 Sem.intros(6) by force next assume "s \ b" and "s \ i \ v s = n" thus "\t . Sem (While b i v c) s t \ t \ q" using Sem.intros(5) assms(3) by fastforce qed qed } thus ?thesis using assms(1) ValidTC_def by force qed lemma Compl_Collect: "-(Collect b) = {x. \(b x)}" by blast lemmas AbortRule = SkipRule \ \dummy version\ ML_file \hoare_tac.ML\ method_setup vcg = \ Scan.succeed (fn ctxt => SIMPLE_METHOD' (Hoare.hoare_tac ctxt (K all_tac)))\ "verification condition generator" method_setup vcg_simp = \ Scan.succeed (fn ctxt => SIMPLE_METHOD' (Hoare.hoare_tac ctxt (asm_full_simp_tac ctxt)))\ "verification condition generator plus simplification" method_setup vcg_tc = \ Scan.succeed (fn ctxt => SIMPLE_METHOD' (Hoare.hoare_tc_tac ctxt (K all_tac)))\ "verification condition generator" method_setup vcg_tc_simp = \ Scan.succeed (fn ctxt => SIMPLE_METHOD' (Hoare.hoare_tc_tac ctxt (asm_full_simp_tac ctxt)))\ "verification condition generator plus simplification" end diff --git a/src/HOL/Hoare/Hoare_Logic_Abort.thy b/src/HOL/Hoare/Hoare_Logic_Abort.thy --- a/src/HOL/Hoare/Hoare_Logic_Abort.thy +++ b/src/HOL/Hoare/Hoare_Logic_Abort.thy @@ -1,244 +1,243 @@ (* Title: HOL/Hoare/Hoare_Logic_Abort.thy Author: Leonor Prensa Nieto & Tobias Nipkow Copyright 2003 TUM Author: Walter Guttmann (extension to total-correctness proofs) Like Hoare_Logic.thy, but with an Abort statement for modelling run time errors. *) theory Hoare_Logic_Abort imports Main begin type_synonym 'a bexp = "'a set" type_synonym 'a assn = "'a set" type_synonym 'a var = "'a \ nat" datatype 'a com = Basic "'a \ 'a" | Abort | Seq "'a com" "'a com" ("(_;/ _)" [61,60] 60) | Cond "'a bexp" "'a com" "'a com" ("(1IF _/ THEN _ / ELSE _/ FI)" [0,0,0] 61) | While "'a bexp" "'a assn" "'a var" "'a com" ("(1WHILE _/ INV {_} / VAR {_} //DO _ /OD)" [0,0,0,0] 61) -syntax (xsymbols) +syntax "_whilePC" :: "'a bexp \ 'a assn \ 'a com \ 'a com" ("(1WHILE _/ INV {_} //DO _ /OD)" [0,0,0] 61) - translations - "WHILE b INV {x} DO c OD" => "WHILE b INV {x} VAR {0} DO c OD" + "WHILE b INV {x} DO c OD" \ "WHILE b INV {x} VAR {0} DO c OD" abbreviation annskip ("SKIP") where "SKIP == Basic id" type_synonym 'a sem = "'a option => 'a option => bool" inductive Sem :: "'a com \ 'a sem" where "Sem (Basic f) None None" | "Sem (Basic f) (Some s) (Some (f s))" | "Sem Abort s None" | "Sem c1 s s'' \ Sem c2 s'' s' \ Sem (c1;c2) s s'" | "Sem (IF b THEN c1 ELSE c2 FI) None None" | "s \ b \ Sem c1 (Some s) s' \ Sem (IF b THEN c1 ELSE c2 FI) (Some s) s'" | "s \ b \ Sem c2 (Some s) s' \ Sem (IF b THEN c1 ELSE c2 FI) (Some s) s'" | "Sem (While b x y c) None None" | "s \ b \ Sem (While b x y c) (Some s) (Some s)" | "s \ b \ Sem c (Some s) s'' \ Sem (While b x y c) s'' s' \ Sem (While b x y c) (Some s) s'" inductive_cases [elim!]: "Sem (Basic f) s s'" "Sem (c1;c2) s s'" "Sem (IF b THEN c1 ELSE c2 FI) s s'" lemma Sem_deterministic: assumes "Sem c s s1" and "Sem c s s2" shows "s1 = s2" proof - have "Sem c s s1 \ (\s2. Sem c s s2 \ s1 = s2)" by (induct rule: Sem.induct) (subst Sem.simps, blast)+ thus ?thesis using assms by simp qed definition Valid :: "'a bexp \ 'a com \ 'a bexp \ bool" where "Valid p c q \ \s s'. Sem c s s' \ s \ Some ` p \ s' \ Some ` q" definition ValidTC :: "'a bexp \ 'a com \ 'a bexp \ bool" where "ValidTC p c q \ \s . s \ p \ (\t . Sem c (Some s) (Some t) \ t \ q)" lemma tc_implies_pc: "ValidTC p c q \ Valid p c q" by (smt Sem_deterministic ValidTC_def Valid_def image_iff) lemma tc_extract_function: "ValidTC p c q \ \f . \s . s \ p \ f s \ q" by (meson ValidTC_def) syntax "_assign" :: "idt => 'b => 'a com" ("(2_ :=/ _)" [70, 65] 61) syntax "_hoare_abort_vars" :: "[idts, 'a assn,'a com,'a assn] => bool" ("VARS _// {_} // _ // {_}" [0,0,55,0] 50) -syntax ("" output) +syntax (output) "_hoare_abort" :: "['a assn,'a com,'a assn] => bool" ("{_} // _ // {_}" [0,55,0] 50) ML_file \hoare_syntax.ML\ parse_translation \[(\<^syntax_const>\_hoare_abort_vars\, K Hoare_Syntax.hoare_vars_tr)]\ print_translation \[(\<^const_syntax>\Valid\, K (Hoare_Syntax.spec_tr' \<^syntax_const>\_hoare_abort\))]\ syntax "_hoare_abort_tc_vars" :: "[idts, 'a assn,'a com,'a assn] => bool" ("VARS _// [_] // _ // [_]" [0,0,55,0] 50) -syntax ("" output) +syntax (output) "_hoare_abort_tc" :: "['a assn,'a com,'a assn] => bool" ("[_] // _ // [_]" [0,55,0] 50) parse_translation \[(\<^syntax_const>\_hoare_abort_tc_vars\, K Hoare_Syntax.hoare_tc_vars_tr)]\ print_translation \[(\<^const_syntax>\ValidTC\, K (Hoare_Syntax.spec_tr' \<^syntax_const>\_hoare_abort_tc\))]\ text \The proof rules for partial correctness\ lemma SkipRule: "p \ q \ Valid p (Basic id) q" by (auto simp:Valid_def) lemma BasicRule: "p \ {s. f s \ q} \ Valid p (Basic f) q" by (auto simp:Valid_def) lemma SeqRule: "Valid P c1 Q \ Valid Q c2 R \ Valid P (c1;c2) R" by (auto simp:Valid_def) lemma CondRule: "p \ {s. (s \ b \ s \ w) \ (s \ b \ s \ w')} \ Valid w c1 q \ Valid w' c2 q \ Valid p (Cond b c1 c2) q" by (fastforce simp:Valid_def image_def) lemma While_aux: assumes "Sem (WHILE b INV {i} VAR {v} DO c OD) s s'" shows "\s s'. Sem c s s' \ s \ Some ` (I \ b) \ s' \ Some ` I \ s \ Some ` I \ s' \ Some ` (I \ -b)" using assms by (induct "WHILE b INV {i} VAR {v} DO c OD" s s') auto lemma WhileRule: "p \ i \ Valid (i \ b) c i \ i \ (-b) \ q \ Valid p (While b i v c) q" apply (clarsimp simp:Valid_def) apply(drule While_aux) apply assumption apply blast apply blast done lemma AbortRule: "p \ {s. False} \ Valid p Abort q" by(auto simp:Valid_def) text \The proof rules for total correctness\ lemma SkipRuleTC: assumes "p \ q" shows "ValidTC p (Basic id) q" by (metis Sem.intros(2) ValidTC_def assms id_def subsetD) lemma BasicRuleTC: assumes "p \ {s. f s \ q}" shows "ValidTC p (Basic f) q" by (metis Ball_Collect Sem.intros(2) ValidTC_def assms) lemma SeqRuleTC: assumes "ValidTC p c1 q" and "ValidTC q c2 r" shows "ValidTC p (c1;c2) r" by (meson assms Sem.intros(4) ValidTC_def) lemma CondRuleTC: assumes "p \ {s. (s \ b \ s \ w) \ (s \ b \ s \ w')}" and "ValidTC w c1 q" and "ValidTC w' c2 q" shows "ValidTC p (Cond b c1 c2) q" proof (unfold ValidTC_def, rule allI) fix s show "s \ p \ (\t . Sem (Cond b c1 c2) (Some s) (Some t) \ t \ q)" apply (cases "s \ b") apply (metis (mono_tags, lifting) Ball_Collect Sem.intros(6) ValidTC_def assms(1,2)) by (metis (mono_tags, lifting) Ball_Collect Sem.intros(7) ValidTC_def assms(1,3)) qed lemma WhileRuleTC: assumes "p \ i" and "\n::nat . ValidTC (i \ b \ {s . v s = n}) c (i \ {s . v s < n})" and "i \ uminus b \ q" shows "ValidTC p (While b i v c) q" proof - { fix s n have "s \ i \ v s = n \ (\t . Sem (While b i v c) (Some s) (Some t) \ t \ q)" proof (induction "n" arbitrary: s rule: less_induct) fix n :: nat fix s :: 'a assume 1: "\(m::nat) s::'a . m < n \ s \ i \ v s = m \ (\t . Sem (While b i v c) (Some s) (Some t) \ t \ q)" show "s \ i \ v s = n \ (\t . Sem (While b i v c) (Some s) (Some t) \ t \ q)" proof (rule impI, cases "s \ b") assume 2: "s \ b" and "s \ i \ v s = n" hence "s \ i \ b \ {s . v s = n}" using assms(1) by auto hence "\t . Sem c (Some s) (Some t) \ t \ i \ {s . v s < n}" by (metis assms(2) ValidTC_def) from this obtain t where 3: "Sem c (Some s) (Some t) \ t \ i \ {s . v s < n}" by auto hence "\u . Sem (While b i v c) (Some t) (Some u) \ u \ q" using 1 by auto thus "\t . Sem (While b i v c) (Some s) (Some t) \ t \ q" using 2 3 Sem.intros(10) by force next assume "s \ b" and "s \ i \ v s = n" thus "\t . Sem (While b i v c) (Some s) (Some t) \ t \ q" using Sem.intros(9) assms(3) by fastforce qed qed } thus ?thesis using assms(1) ValidTC_def by force qed subsection \Derivation of the proof rules and, most importantly, the VCG tactic\ lemma Compl_Collect: "-(Collect b) = {x. \(b x)}" by blast ML_file \hoare_tac.ML\ method_setup vcg = \ Scan.succeed (fn ctxt => SIMPLE_METHOD' (Hoare.hoare_tac ctxt (K all_tac)))\ "verification condition generator" method_setup vcg_simp = \ Scan.succeed (fn ctxt => SIMPLE_METHOD' (Hoare.hoare_tac ctxt (asm_full_simp_tac ctxt)))\ "verification condition generator plus simplification" method_setup vcg_tc = \ Scan.succeed (fn ctxt => SIMPLE_METHOD' (Hoare.hoare_tc_tac ctxt (K all_tac)))\ "verification condition generator" method_setup vcg_tc_simp = \ Scan.succeed (fn ctxt => SIMPLE_METHOD' (Hoare.hoare_tc_tac ctxt (asm_full_simp_tac ctxt)))\ "verification condition generator plus simplification" \ \Special syntax for guarded statements and guarded array updates:\ syntax "_guarded_com" :: "bool \ 'a com \ 'a com" ("(2_ \/ _)" 71) "_array_update" :: "'a list \ nat \ 'a \ 'a com" ("(2_[_] :=/ _)" [70, 65] 61) translations "P \ c" == "IF P THEN c ELSE CONST Abort FI" "a[i] := v" => "(i < CONST length a) \ (a := CONST list_update a i v)" \ \reverse translation not possible because of duplicate \a\\ text \ Note: there is no special syntax for guarded array access. Thus you must write \j < length a \ a[i] := a!j\. \ end