diff --git a/thys/Aggregation_Algebras/Hoare_Logic.thy b/thys/Aggregation_Algebras/Hoare_Logic.thy deleted file mode 100644 --- a/thys/Aggregation_Algebras/Hoare_Logic.thy +++ /dev/null @@ -1,233 +0,0 @@ -(* Title: Hoare Logic for Total Correctness - Author: Walter Guttmann - Maintainer: Walter Guttmann -*) - -(* Title: HOL/Hoare/Hoare_Logic.thy - Author: Leonor Prensa Nieto & Tobias Nipkow - Copyright 1998 TUM - -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. -*) - -section \Hoare Logic for Total Correctness\ - -theory Hoare_Logic -imports Main -begin - -text \ -This theory is based on Isabelle/HOL's \Hoare\/\Hoare_Logic.thy\ written by L. P. Nieto and T. Nipkow. -We have extended it to total-correctness proofs. -We added corresponding modifications to \hoare_syntax.ML\ and \hoare_tac.ML\. -\ - -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) - "_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" - -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) - "_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) - "_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\ -lemmas AbortRuleTC = SkipRuleTC \ \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/thys/Aggregation_Algebras/Hoare_Logic_Examples.thy b/thys/Aggregation_Algebras/Hoare_Logic_Examples.thy deleted file mode 100644 --- a/thys/Aggregation_Algebras/Hoare_Logic_Examples.thy +++ /dev/null @@ -1,80 +0,0 @@ -(* Title: Examples using Hoare Logic for Total Correctness - Author: Walter Guttmann - Maintainer: Walter Guttmann -*) - -section \Examples using Hoare Logic for Total Correctness\ - -theory Hoare_Logic_Examples - -imports Hoare_Logic - -begin - -text \ -This theory demonstrates a few simple partial- and total-correctness proofs. -The first example is taken from HOL/Hoare/Examples.thy written by N. Galm. -We have added the invariant $m \leq a$. -\ - -lemma multiply_by_add: "VARS m s a b - {a=A \ b=B} - m := 0; s := 0; - WHILE m\a - INV {s=m*b \ a=A \ b=B \ m\a} - DO s := s+b; m := m+(1::nat) OD - {s = A*B}" - by vcg_simp - -text \ -Here is the total-correctness proof for the same program. -It needs the additional invariant $m \leq a$. -\ - -lemma multiply_by_add_tc: "VARS m s a b - [a=A \ b=B] - m := 0; s := 0; - WHILE m\a - INV {s=m*b \ a=A \ b=B \ m\a} - VAR {a-m} - DO s := s+b; m := m+(1::nat) OD - [s = A*B]" - apply vcg_tc_simp - by auto - -text \ -Next, we prove partial correctness of a program that computes powers. -\ - -lemma power: "VARS (x::nat) n p i - { 0 \ n } - p := 1; - i := 0; - WHILE i < n - INV { p = x^i \ i \ n } - DO p := p * x; - i := i + 1 - OD - { p = x^n }" - apply vcg_simp - by auto - -text \ -Here is its total-correctness proof. -\ - -lemma power_tc: "VARS (x::nat) n p i - [ 0 \ n ] - p := 1; - i := 0; - WHILE i < n - INV { p = x^i \ i \ n } - VAR { n - i } - DO p := p * x; - i := i + 1 - OD - [ p = x^n ]" - apply vcg_tc - by auto - -end diff --git a/thys/Aggregation_Algebras/Minimum_Spanning_Trees.thy b/thys/Aggregation_Algebras/Minimum_Spanning_Trees.thy deleted file mode 100644 --- a/thys/Aggregation_Algebras/Minimum_Spanning_Trees.thy +++ /dev/null @@ -1,1064 +0,0 @@ -(* Title: Minimum Spanning Tree Algorithms - Author: Walter Guttmann - Maintainer: Walter Guttmann -*) - -section \Minimum Spanning Tree Algorithms\ - -text \ -In this theory we prove the total-correctness of Kruskal's and Prim's minimum spanning tree algorithms. -Specifications and algorithms work in Stone-Kleene relation algebras extended by operations for aggregation and minimisation. -The algorithms are implemented in a simple imperative language and their proof uses Hoare Logic. -The correctness proofs are discussed in \cite{Guttmann2016c,Guttmann2018a,Guttmann2018b}. -\ - -theory Minimum_Spanning_Trees - -imports Hoare_Logic Aggregation_Algebras - -begin - -no_notation - trancl ("(_\<^sup>+)" [1000] 999) - -context m_kleene_algebra -begin - -subsection \Kruskal's Minimum Spanning Tree Algorithm\ - -text \ -The total-correctness proof of Kruskal's minimum spanning tree algorithm uses the following steps \cite{Guttmann2018b}. -We first establish that the algorithm terminates and constructs a spanning tree. -This is a constructive proof of the existence of a spanning tree; any spanning tree algorithm could be used for this. -We then conclude that a minimum spanning tree exists. -This is necessary to establish the invariant for the actual correctness proof, which shows that Kruskal's algorithm produces a minimum spanning tree. -\ - -definition "spanning_forest f g \ forest f \ f \ --g \ components g \ forest_components f \ regular f" -definition "minimum_spanning_forest f g \ spanning_forest f g \ (\u . spanning_forest u g \ sum (f \ g) \ sum (u \ g))" -definition "kruskal_spanning_invariant f g h \ symmetric g \ h = h\<^sup>T \ g \ --h = h \ spanning_forest f (-h \ g)" -definition "kruskal_invariant f g h \ kruskal_spanning_invariant f g h \ (\w . minimum_spanning_forest w g \ f \ w \ w\<^sup>T)" - -text \ -We first show two verification conditions which are used in both correctness proofs. -\ - -lemma kruskal_vc_1: - assumes "symmetric g" - shows "kruskal_spanning_invariant bot g g" -proof (unfold kruskal_spanning_invariant_def, intro conjI) - show "symmetric g" - using assms by simp -next - show "g = g\<^sup>T" - using assms by simp -next - show "g \ --g = g" - using inf.sup_monoid.add_commute selection_closed_id by simp -next - show "spanning_forest bot (-g \ g)" - using star.circ_transitive_equal spanning_forest_def by simp -qed - -lemma kruskal_vc_2: - assumes "kruskal_spanning_invariant f g h" - and "h \ bot" - shows "(minarc h \ -forest_components f \ kruskal_spanning_invariant ((f \ -(top * minarc h * f\<^sup>T\<^sup>\)) \ (f \ top * minarc h * f\<^sup>T\<^sup>\)\<^sup>T \ minarc h) g (h \ -minarc h \ -minarc h\<^sup>T) - \ card { x . regular x \ x \ --h \ x \ -minarc h \ x \ -minarc h\<^sup>T } < card { x . regular x \ x \ --h }) \ - (\ minarc h \ -forest_components f \ kruskal_spanning_invariant f g (h \ -minarc h \ -minarc h\<^sup>T) - \ card { x . regular x \ x \ --h \ x \ -minarc h \ x \ -minarc h\<^sup>T } < card { x . regular x \ x \ --h })" -proof - - let ?e = "minarc h" - let ?f = "(f \ -(top * ?e * f\<^sup>T\<^sup>\)) \ (f \ top * ?e * f\<^sup>T\<^sup>\)\<^sup>T \ ?e" - let ?h = "h \ -?e \ -?e\<^sup>T" - let ?F = "forest_components f" - let ?n1 = "card { x . regular x \ x \ --h }" - let ?n2 = "card { x . regular x \ x \ --h \ x \ -?e \ x \ -?e\<^sup>T }" - have 1: "regular f \ regular ?e" - by (metis assms(1) kruskal_spanning_invariant_def spanning_forest_def minarc_regular) - hence 2: "regular ?f \ regular ?F \ regular (?e\<^sup>T)" - using regular_closed_star regular_conv_closed regular_mult_closed by simp - have 3: "\ ?e \ -?e" - using assms(2) inf.orderE minarc_bot_iff by fastforce - have 4: "?n2 < ?n1" - apply (rule psubset_card_mono) - using finite_regular apply simp - using 1 3 kruskal_spanning_invariant_def minarc_below by auto - show "(?e \ -?F \ kruskal_spanning_invariant ?f g ?h \ ?n2 < ?n1) \ (\ ?e \ -?F \ kruskal_spanning_invariant f g ?h \ ?n2 < ?n1)" - proof (rule conjI) - have 5: "injective ?f" - apply (rule kruskal_injective_inv) - using assms(1) kruskal_spanning_invariant_def spanning_forest_def apply simp - apply (simp add: covector_mult_closed) - apply (simp add: comp_associative comp_isotone star.right_plus_below_circ) - apply (meson mult_left_isotone order_lesseq_imp star_outer_increasing top.extremum) - using assms(1,2) kruskal_spanning_invariant_def kruskal_injective_inv_2 minarc_arc spanning_forest_def apply simp - using assms(2) arc_injective minarc_arc apply blast - using assms(1,2) kruskal_spanning_invariant_def kruskal_injective_inv_3 minarc_arc spanning_forest_def by simp - show "?e \ -?F \ kruskal_spanning_invariant ?f g ?h \ ?n2 < ?n1" - proof - assume 6: "?e \ -?F" - have 7: "equivalence ?F" - using assms(1) kruskal_spanning_invariant_def forest_components_equivalence spanning_forest_def by simp - have "?e\<^sup>T * top * ?e\<^sup>T = ?e\<^sup>T" - using assms(2) by (simp add: arc_top_arc minarc_arc) - hence "?e\<^sup>T * top * ?e\<^sup>T \ -?F" - using 6 7 conv_complement conv_isotone by fastforce - hence 8: "?e * ?F * ?e = bot" - using le_bot triple_schroeder_p by simp - show "kruskal_spanning_invariant ?f g ?h \ ?n2 < ?n1" - proof (unfold kruskal_spanning_invariant_def, intro conjI) - show "symmetric g" - using assms(1) kruskal_spanning_invariant_def by simp - next - show "?h = ?h\<^sup>T" - using assms(1) by (simp add: conv_complement conv_dist_inf inf_commute inf_left_commute kruskal_spanning_invariant_def) - next - show "g \ --?h = ?h" - using 1 2 by (metis (hide_lams) assms(1) kruskal_spanning_invariant_def inf_assoc pp_dist_inf) - next - show "spanning_forest ?f (-?h \ g)" - proof (unfold spanning_forest_def, intro conjI) - show "injective ?f" - using 5 by simp - next - show "acyclic ?f" - apply (rule kruskal_acyclic_inv) - using assms(1) kruskal_spanning_invariant_def spanning_forest_def apply simp - apply (simp add: covector_mult_closed) - using 8 assms(1) kruskal_spanning_invariant_def spanning_forest_def kruskal_acyclic_inv_1 apply simp - using 8 apply (metis comp_associative mult_left_sub_dist_sup_left star.circ_loop_fixpoint sup_commute le_bot) - using 6 by (simp add: p_antitone_iff) - next - show "?f \ --(-?h \ g)" - apply (rule kruskal_subgraph_inv) - using assms(1) kruskal_spanning_invariant_def spanning_forest_def apply simp - using assms(1) apply (metis kruskal_spanning_invariant_def minarc_below order.trans pp_isotone_inf) - using assms(1) kruskal_spanning_invariant_def apply simp - using assms(1) kruskal_spanning_invariant_def by simp - next - show "components (-?h \ g) \ forest_components ?f" - apply (rule kruskal_spanning_inv) - using 5 apply simp - using 1 regular_closed_star regular_conv_closed regular_mult_closed apply simp - using 1 apply simp - using assms(1) kruskal_spanning_invariant_def spanning_forest_def by simp - next - show "regular ?f" - using 2 by simp - qed - next - show "?n2 < ?n1" - using 4 by simp - qed - qed - next - show "\ ?e \ -?F \ kruskal_spanning_invariant f g ?h \ ?n2 < ?n1" - proof - assume "\ ?e \ -?F" - hence 9: "?e \ ?F" - using 2 assms(2) arc_in_partition minarc_arc by fastforce - show "kruskal_spanning_invariant f g ?h \ ?n2 < ?n1" - proof (unfold kruskal_spanning_invariant_def, intro conjI) - show "symmetric g" - using assms(1) kruskal_spanning_invariant_def by simp - next - show "?h = ?h\<^sup>T" - using assms(1) by (simp add: conv_complement conv_dist_inf inf_commute inf_left_commute kruskal_spanning_invariant_def) - next - show "g \ --?h = ?h" - using 1 2 by (metis (hide_lams) assms(1) kruskal_spanning_invariant_def inf_assoc pp_dist_inf) - next - show "spanning_forest f (-?h \ g)" - proof (unfold spanning_forest_def, intro conjI) - show "injective f" - using assms(1) kruskal_spanning_invariant_def spanning_forest_def by simp - next - show "acyclic f" - using assms(1) kruskal_spanning_invariant_def spanning_forest_def by simp - next - have "f \ --(-h \ g)" - using assms(1) kruskal_spanning_invariant_def spanning_forest_def by simp - also have "... \ --(-?h \ g)" - using comp_inf.mult_right_isotone inf.sup_monoid.add_commute inf_left_commute p_antitone_inf pp_isotone by presburger - finally show "f \ --(-?h \ g)" - by simp - next - show "components (-?h \ g) \ ?F" - apply (rule kruskal_spanning_inv_1) - using 9 apply simp - using 1 apply simp - using assms(1) kruskal_spanning_invariant_def spanning_forest_def apply simp - using assms(1) kruskal_spanning_invariant_def forest_components_equivalence spanning_forest_def by simp - next - show "regular f" - using 1 by simp - qed - next - show "?n2 < ?n1" - using 4 by simp - qed - qed - qed -qed - -text \ -The following result shows that Kruskal's algorithm terminates and constructs a spanning tree. -We cannot yet show that this is a minimum spanning tree. -\ - -theorem kruskal_spanning: - "VARS e f h - [ symmetric g ] - f := bot; - h := g; - WHILE h \ bot - INV { kruskal_spanning_invariant f g h } - VAR { card { x . regular x \ x \ --h } } - DO e := minarc h; - IF e \ -forest_components f THEN - f := (f \ -(top * e * f\<^sup>T\<^sup>\)) \ (f \ top * e * f\<^sup>T\<^sup>\)\<^sup>T \ e - ELSE - SKIP - FI; - h := h \ -e \ -e\<^sup>T - OD - [ spanning_forest f g ]" - apply vcg_tc_simp - using kruskal_vc_1 apply simp - using kruskal_vc_2 apply simp - using kruskal_spanning_invariant_def by auto - -text \ -Because we have shown total correctness, we conclude that a spanning tree exists. -\ - -lemma kruskal_exists_spanning: - "symmetric g \ \f . spanning_forest f g" - using tc_extract_function kruskal_spanning by blast - -text \ -This implies that a minimum spanning tree exists, which is used in the subsequent correctness proof. -\ - -lemma kruskal_exists_minimal_spanning: - assumes "symmetric g" - shows "\f . minimum_spanning_forest f g" -proof - - let ?s = "{ f . spanning_forest f g }" - have "\m\?s . \z\?s . sum (m \ g) \ sum (z \ g)" - apply (rule finite_set_minimal) - using finite_regular spanning_forest_def apply simp - using assms kruskal_exists_spanning apply simp - using sum_linear by simp - thus ?thesis - using minimum_spanning_forest_def by simp -qed - -text \ -Kruskal's minimum spanning tree algorithm terminates and is correct. -This is the same algorithm that is used in the previous correctness proof, with the same precondition and variant, but with a different invariant and postcondition. -\ - -theorem kruskal: - "VARS e f h - [ symmetric g ] - f := bot; - h := g; - WHILE h \ bot - INV { kruskal_invariant f g h } - VAR { card { x . regular x \ x \ --h } } - DO e := minarc h; - IF e \ -forest_components f THEN - f := (f \ -(top * e * f\<^sup>T\<^sup>\)) \ (f \ top * e * f\<^sup>T\<^sup>\)\<^sup>T \ e - ELSE - SKIP - FI; - h := h \ -e \ -e\<^sup>T - OD - [ minimum_spanning_forest f g ]" -proof vcg_tc_simp - assume "symmetric g" - thus "kruskal_invariant bot g g" - using kruskal_vc_1 kruskal_exists_minimal_spanning kruskal_invariant_def by simp -next - fix f h - let ?e = "minarc h" - let ?f = "(f \ -(top * ?e * f\<^sup>T\<^sup>\)) \ (f \ top * ?e * f\<^sup>T\<^sup>\)\<^sup>T \ ?e" - let ?h = "h \ -?e \ -?e\<^sup>T" - let ?F = "forest_components f" - let ?n1 = "card { x . regular x \ x \ --h }" - let ?n2 = "card { x . regular x \ x \ --h \ x \ -?e \ x \ -?e\<^sup>T }" - assume 1: "kruskal_invariant f g h \ h \ bot" - from 1 obtain w where 2: "minimum_spanning_forest w g \ f \ w \ w\<^sup>T" - using kruskal_invariant_def by auto - hence 3: "regular f \ regular w \ regular ?e" - using 1 by (metis kruskal_invariant_def kruskal_spanning_invariant_def minimum_spanning_forest_def spanning_forest_def minarc_regular) - show "(?e \ -?F \ kruskal_invariant ?f g ?h \ ?n2 < ?n1) \ (\ ?e \ -?F \ kruskal_invariant f g ?h \ ?n2 < ?n1)" - proof (rule conjI) - show "?e \ -?F \ kruskal_invariant ?f g ?h \ ?n2 < ?n1" - proof - assume 4: "?e \ -?F" - have 5: "equivalence ?F" - using 1 kruskal_invariant_def kruskal_spanning_invariant_def forest_components_equivalence spanning_forest_def by simp - have "?e\<^sup>T * top * ?e\<^sup>T = ?e\<^sup>T" - using 1 by (simp add: arc_top_arc minarc_arc) - hence "?e\<^sup>T * top * ?e\<^sup>T \ -?F" - using 4 5 conv_complement conv_isotone by fastforce - hence 6: "?e * ?F * ?e = bot" - using le_bot triple_schroeder_p by simp - show "kruskal_invariant ?f g ?h \ ?n2 < ?n1" - proof (unfold kruskal_invariant_def, intro conjI) - show "kruskal_spanning_invariant ?f g ?h" - using 1 4 kruskal_vc_2 kruskal_invariant_def by simp - next - show "\w . minimum_spanning_forest w g \ ?f \ w \ w\<^sup>T" - proof - let ?p = "w \ top * ?e * w\<^sup>T\<^sup>\" - let ?v = "(w \ -(top * ?e * w\<^sup>T\<^sup>\)) \ ?p\<^sup>T" - have 7: "regular ?p" - using 3 regular_closed_star regular_conv_closed regular_mult_closed by simp - have 8: "injective ?v" - apply (rule kruskal_exchange_injective_inv_1) - using 2 minimum_spanning_forest_def spanning_forest_def apply simp - apply (simp add: covector_mult_closed) - apply (simp add: comp_associative comp_isotone star.right_plus_below_circ) - using 1 2 kruskal_injective_inv_3 minarc_arc minimum_spanning_forest_def spanning_forest_def by simp - have 9: "components g \ forest_components ?v" - apply (rule kruskal_exchange_spanning_inv_1) - using 8 apply simp - using 7 apply simp - using 2 minimum_spanning_forest_def spanning_forest_def by simp - have 10: "spanning_forest ?v g" - proof (unfold spanning_forest_def, intro conjI) - show "injective ?v" - using 8 by simp - next - show "acyclic ?v" - apply (rule kruskal_exchange_acyclic_inv_1) - using 2 minimum_spanning_forest_def spanning_forest_def apply simp - by (simp add: covector_mult_closed) - next - show "?v \ --g" - apply (rule sup_least) - using 2 inf.coboundedI1 minimum_spanning_forest_def spanning_forest_def apply simp - using 1 2 by (metis kruskal_invariant_def kruskal_spanning_invariant_def conv_complement conv_dist_inf order.trans inf.absorb2 inf.cobounded1 minimum_spanning_forest_def spanning_forest_def) - next - show "components g \ forest_components ?v" - using 9 by simp - next - show "regular ?v" - using 3 regular_closed_star regular_conv_closed regular_mult_closed by simp - qed - have 11: "sum (?v \ g) = sum (w \ g)" - proof - - have "sum (?v \ g) = sum (w \ -(top * ?e * w\<^sup>T\<^sup>\) \ g) + sum (?p\<^sup>T \ g)" - using 2 by (metis conv_complement conv_top epm_8 inf_import_p inf_top_right regular_closed_top vector_top_closed minimum_spanning_forest_def spanning_forest_def sum_disjoint) - also have "... = sum (w \ -(top * ?e * w\<^sup>T\<^sup>\) \ g) + sum (?p \ g)" - using 1 kruskal_invariant_def kruskal_spanning_invariant_def sum_symmetric by simp - also have "... = sum (((w \ -(top * ?e * w\<^sup>T\<^sup>\)) \ ?p) \ g)" - using inf_commute inf_left_commute sum_disjoint by simp - also have "... = sum (w \ g)" - using 3 7 maddux_3_11_pp by simp - finally show ?thesis - by simp - qed - have 12: "?v \ ?v\<^sup>T = w \ w\<^sup>T" - proof - - have "?v \ ?v\<^sup>T = (w \ -?p) \ ?p\<^sup>T \ (w\<^sup>T \ -?p\<^sup>T) \ ?p" - using conv_complement conv_dist_inf conv_dist_sup inf_import_p sup_assoc by simp - also have "... = w \ w\<^sup>T" - using 3 7 conv_complement conv_dist_inf inf_import_p maddux_3_11_pp sup_monoid.add_assoc sup_monoid.add_commute by simp - finally show ?thesis - by simp - qed - have 13: "?v * ?e\<^sup>T = bot" - apply (rule kruskal_reroot_edge) - using 1 apply (simp add: minarc_arc) - using 2 minimum_spanning_forest_def spanning_forest_def by simp - have "?v \ ?e \ ?v \ top * ?e" - using inf.sup_right_isotone top_left_mult_increasing by simp - also have "... \ ?v * (top * ?e)\<^sup>T" - using covector_restrict_comp_conv covector_mult_closed vector_top_closed by simp - finally have 14: "?v \ ?e = bot" - using 13 by (metis conv_dist_comp mult_assoc le_bot mult_left_zero) - let ?d = "?v \ top * ?e\<^sup>T * ?v\<^sup>T\<^sup>\ \ ?F * ?e\<^sup>T * top \ top * ?e * -?F" - let ?w = "(?v \ -?d) \ ?e" - have 15: "regular ?d" - using 3 regular_closed_star regular_conv_closed regular_mult_closed by simp - have 16: "?F \ -?d" - apply (rule kruskal_edge_between_components_1) - using 5 apply simp - using 1 conv_dist_comp minarc_arc mult_assoc by simp - have 17: "f \ f\<^sup>T \ (?v \ -?d \ -?d\<^sup>T) \ (?v\<^sup>T \ -?d \ -?d\<^sup>T)" - apply (rule kruskal_edge_between_components_2) - using 16 apply simp - using 1 kruskal_invariant_def kruskal_spanning_invariant_def spanning_forest_def apply simp - using 2 12 by (metis conv_dist_sup conv_involutive conv_isotone le_supI sup_commute) - show "minimum_spanning_forest ?w g \ ?f \ ?w \ ?w\<^sup>T" - proof (intro conjI) - have 18: "?e\<^sup>T \ ?v\<^sup>\" - apply (rule kruskal_edge_arc_1[where g=g and h=h]) - using minarc_below apply simp - using 1 apply (metis kruskal_invariant_def kruskal_spanning_invariant_def inf_le1) - using 1 kruskal_invariant_def kruskal_spanning_invariant_def apply simp - using 9 apply simp - using 13 by simp - have 19: "arc ?d" - apply (rule kruskal_edge_arc) - using 5 apply simp - using 10 spanning_forest_def apply blast - using 1 apply (simp add: minarc_arc) - using 3 apply (metis conv_complement pp_dist_star regular_mult_closed) - using 2 8 12 apply (simp add: kruskal_forest_components_inf) - using 10 spanning_forest_def apply simp - using 13 apply simp - using 6 apply simp - using 18 by simp - show "minimum_spanning_forest ?w g" - proof (unfold minimum_spanning_forest_def, intro conjI) - have "(?v \ -?d) * ?e\<^sup>T \ ?v * ?e\<^sup>T" - using inf_le1 mult_left_isotone by simp - hence "(?v \ -?d) * ?e\<^sup>T = bot" - using 13 le_bot by simp - hence 20: "?e * (?v \ -?d)\<^sup>T = bot" - using conv_dist_comp conv_involutive conv_bot by force - have 21: "injective ?w" - apply (rule injective_sup) - using 8 apply (simp add: injective_inf_closed) - using 20 apply simp - using 1 arc_injective minarc_arc by blast - show "spanning_forest ?w g" - proof (unfold spanning_forest_def, intro conjI) - show "injective ?w" - using 21 by simp - next - show "acyclic ?w" - apply (rule kruskal_exchange_acyclic_inv_2) - using 10 spanning_forest_def apply blast - using 8 apply simp - using inf.coboundedI1 apply simp - using 19 apply simp - using 1 apply (simp add: minarc_arc) - using inf.cobounded2 inf.coboundedI1 apply simp - using 13 by simp - next - have "?w \ ?v \ ?e" - using inf_le1 sup_left_isotone by simp - also have "... \ --g \ ?e" - using 10 sup_left_isotone spanning_forest_def by blast - also have "... \ --g \ --h" - by (simp add: le_supI2 minarc_below) - also have "... = --g" - using 1 by (metis kruskal_invariant_def kruskal_spanning_invariant_def pp_isotone_inf sup.orderE) - finally show "?w \ --g" - by simp - next - have 22: "?d \ (?v \ -?d)\<^sup>T\<^sup>\ * ?e\<^sup>T * top" - apply (rule kruskal_exchange_spanning_inv_2) - using 8 apply simp - using 13 apply (metis semiring.mult_not_zero star_absorb star_simulation_right_equal) - using 17 apply simp - by (simp add: inf.coboundedI1) - have "components g \ forest_components ?v" - using 10 spanning_forest_def by auto - also have "... \ forest_components ?w" - apply (rule kruskal_exchange_forest_components_inv) - using 21 apply simp - using 15 apply simp - using 1 apply (simp add: arc_top_arc minarc_arc) - apply (simp add: inf.coboundedI1) - using 13 apply simp - using 8 apply simp - apply (simp add: le_infI1) - using 22 by simp - finally show "components g \ forest_components ?w" - by simp - next - show "regular ?w" - using 3 7 regular_conv_closed by simp - qed - next - have 23: "?e \ g \ bot" - using 1 by (metis kruskal_invariant_def kruskal_spanning_invariant_def comp_inf.semiring.mult_zero_right inf.sup_monoid.add_assoc inf.sup_monoid.add_commute minarc_bot_iff minarc_meet_bot) - have "g \ -h \ (g \ -h)\<^sup>\" - using star.circ_increasing by simp - also have "... \ (--(g \ -h))\<^sup>\" - using pp_increasing star_isotone by blast - also have "... \ ?F" - using 1 kruskal_invariant_def kruskal_spanning_invariant_def inf.sup_monoid.add_commute spanning_forest_def by simp - finally have 24: "g \ -h \ ?F" - by simp - have "?d \ --g" - using 10 inf.coboundedI1 spanning_forest_def by blast - hence "?d \ --g \ -?F" - using 16 inf.boundedI p_antitone_iff by simp - also have "... = --(g \ -?F)" - by simp - also have "... \ --h" - using 24 p_shunting_swap pp_isotone by fastforce - finally have 25: "?d \ --h" - by simp - have "?d = bot \ top = bot" - using 19 by (metis mult_left_zero mult_right_zero) - hence "?d \ bot" - using 1 le_bot by auto - hence 26: "?d \ h \ bot" - using 25 by (metis inf.absorb_iff2 inf_commute pseudo_complement) - have "sum (?e \ g) = sum (?e \ --h \ g)" - by (simp add: inf.absorb1 minarc_below) - also have "... = sum (?e \ h)" - using 1 by (metis kruskal_invariant_def kruskal_spanning_invariant_def inf.left_commute inf.sup_monoid.add_commute) - also have "... \ sum (?d \ h)" - using 19 26 minarc_min by simp - also have "... = sum (?d \ (--h \ g))" - using 1 kruskal_invariant_def kruskal_spanning_invariant_def inf_commute by simp - also have "... = sum (?d \ g)" - using 25 by (simp add: inf.absorb2 inf_assoc inf_commute) - finally have 27: "sum (?e \ g) \ sum (?d \ g)" - by simp - have "?v \ ?e \ -?d = bot" - using 14 by simp - hence "sum (?w \ g) = sum (?v \ -?d \ g) + sum (?e \ g)" - using sum_disjoint inf_commute inf_assoc by simp - also have "... \ sum (?v \ -?d \ g) + sum (?d \ g)" - using 23 27 sum_plus_right_isotone by simp - also have "... = sum (((?v \ -?d) \ ?d) \ g)" - using sum_disjoint inf_le2 pseudo_complement by simp - also have "... = sum ((?v \ ?d) \ (-?d \ ?d) \ g)" - by (simp add: sup_inf_distrib2) - also have "... = sum ((?v \ ?d) \ g)" - using 15 by (metis inf_top_right stone) - also have "... = sum (?v \ g)" - by (simp add: inf.sup_monoid.add_assoc) - finally have "sum (?w \ g) \ sum (?v \ g)" - by simp - thus "\u . spanning_forest u g \ sum (?w \ g) \ sum (u \ g)" - using 2 11 minimum_spanning_forest_def by auto - qed - next - have "?f \ f \ f\<^sup>T \ ?e" - using conv_dist_inf inf_le1 sup_left_isotone sup_mono by presburger - also have "... \ (?v \ -?d \ -?d\<^sup>T) \ (?v\<^sup>T \ -?d \ -?d\<^sup>T) \ ?e" - using 17 sup_left_isotone by simp - also have "... \ (?v \ -?d) \ (?v\<^sup>T \ -?d \ -?d\<^sup>T) \ ?e" - using inf.cobounded1 sup_inf_distrib2 by presburger - also have "... = ?w \ (?v\<^sup>T \ -?d \ -?d\<^sup>T)" - by (simp add: sup_assoc sup_commute) - also have "... \ ?w \ (?v\<^sup>T \ -?d\<^sup>T)" - using inf.sup_right_isotone inf_assoc sup_right_isotone by simp - also have "... \ ?w \ ?w\<^sup>T" - using conv_complement conv_dist_inf conv_dist_sup sup_right_isotone by simp - finally show "?f \ ?w \ ?w\<^sup>T" - by simp - qed - qed - next - show "?n2 < ?n1" - using 1 kruskal_vc_2 kruskal_invariant_def by auto - qed - qed - next - show "\ ?e \ -?F \ kruskal_invariant f g ?h \ ?n2 < ?n1" - using 1 kruskal_vc_2 kruskal_invariant_def by auto - qed -next - fix f - assume 28: "kruskal_invariant f g bot" - hence 29: "spanning_forest f g" - using kruskal_invariant_def kruskal_spanning_invariant_def by auto - from 28 obtain w where 30: "minimum_spanning_forest w g \ f \ w \ w\<^sup>T" - using kruskal_invariant_def by auto - hence "w = w \ --g" - by (simp add: inf.absorb1 minimum_spanning_forest_def spanning_forest_def) - also have "... \ w \ components g" - by (metis inf.sup_right_isotone star.circ_increasing) - also have "... \ w \ f\<^sup>T\<^sup>\ * f\<^sup>\" - using 29 spanning_forest_def inf.sup_right_isotone by simp - also have "... \ f \ f\<^sup>T" - apply (rule cancel_separate_6[where z=w and y="w\<^sup>T"]) - using 30 minimum_spanning_forest_def spanning_forest_def apply simp - using 30 apply (metis conv_dist_inf conv_dist_sup conv_involutive inf.cobounded2 inf.orderE) - using 30 apply (simp add: sup_commute) - using 30 minimum_spanning_forest_def spanning_forest_def apply simp - using 30 by (metis acyclic_star_below_complement comp_inf.mult_right_isotone inf_p le_bot minimum_spanning_forest_def spanning_forest_def) - finally have 31: "w \ f \ f\<^sup>T" - by simp - have "sum (f \ g) = sum ((w \ w\<^sup>T) \ (f \ g))" - using 30 by (metis inf_absorb2 inf.assoc) - also have "... = sum (w \ (f \ g)) + sum (w\<^sup>T \ (f \ g))" - using 30 inf.commute acyclic_asymmetric sum_disjoint minimum_spanning_forest_def spanning_forest_def by simp - also have "... = sum (w \ (f \ g)) + sum (w \ (f\<^sup>T \ g\<^sup>T))" - by (metis conv_dist_inf conv_involutive sum_conv) - also have "... = sum (f \ (w \ g)) + sum (f\<^sup>T \ (w \ g))" - using 28 inf.commute inf.assoc kruskal_invariant_def kruskal_spanning_invariant_def by simp - also have "... = sum ((f \ f\<^sup>T) \ (w \ g))" - using 29 acyclic_asymmetric inf.sup_monoid.add_commute sum_disjoint spanning_forest_def by simp - also have "... = sum (w \ g)" - using 31 by (metis inf_absorb2 inf.assoc) - finally show "minimum_spanning_forest f g" - using 29 30 minimum_spanning_forest_def by simp -qed - -subsection \Prim's Minimum Spanning Tree Algorithm\ - -text \ -The total-correctness proof of Prim's minimum spanning tree algorithm has the same overall structure as the proof of Kruskal's algorithm. -The partial-correctness proof is discussed in \cite{Guttmann2016c,Guttmann2018a}. -\ - -abbreviation "component g r \ r\<^sup>T * (--g)\<^sup>\" -definition "spanning_tree t g r \ forest t \ t \ (component g r)\<^sup>T * (component g r) \ --g \ component g r \ r\<^sup>T * t\<^sup>\ \ regular t" -definition "minimum_spanning_tree t g r \ spanning_tree t g r \ (\u . spanning_tree u g r \ sum (t \ g) \ sum (u \ g))" -definition "prim_precondition g r \ g = g\<^sup>T \ injective r \ vector r \ regular r" -definition "prim_spanning_invariant t v g r \ prim_precondition g r \ v\<^sup>T = r\<^sup>T * t\<^sup>\ \ spanning_tree t (v * v\<^sup>T \ g) r" -definition "prim_invariant t v g r \ prim_spanning_invariant t v g r \ (\w . minimum_spanning_tree w g r \ t \ w)" - -lemma span_tree_split: - assumes "vector r" - shows "t \ (component g r)\<^sup>T * (component g r) \ --g \ (t \ (component g r)\<^sup>T \ t \ component g r \ t \ --g)" -proof - - have "(component g r)\<^sup>T * (component g r) = (component g r)\<^sup>T \ component g r" - by (metis assms conv_involutive covector_mult_closed vector_conv_covector vector_covector) - thus ?thesis - by simp -qed - -lemma span_tree_component: - assumes "spanning_tree t g r" - shows "component g r = component t r" - using assms by (simp add: antisym mult_right_isotone star_isotone spanning_tree_def) - -text \ -We first show three verification conditions which are used in both correctness proofs. -\ - -lemma prim_vc_1: - assumes "prim_precondition g r" - shows "prim_spanning_invariant bot r g r" -proof (unfold prim_spanning_invariant_def, intro conjI) - show "prim_precondition g r" - using assms by simp -next - show "r\<^sup>T = r\<^sup>T * bot\<^sup>\" - by (simp add: star_absorb) -next - let ?ss = "r * r\<^sup>T \ g" - show "spanning_tree bot ?ss r" - proof (unfold spanning_tree_def, intro conjI) - show "injective bot" - by simp - next - show "acyclic bot" - by simp - next - show "bot \ (component ?ss r)\<^sup>T * (component ?ss r) \ --?ss" - by simp - next - have "component ?ss r \ component (r * r\<^sup>T) r" - by (simp add: mult_right_isotone star_isotone) - also have "... \ r\<^sup>T * 1\<^sup>\" - using assms by (metis inf.eq_iff p_antitone regular_one_closed star_sub_one prim_precondition_def) - also have "... = r\<^sup>T * bot\<^sup>\" - by (simp add: star.circ_zero star_one) - finally show "component ?ss r \ r\<^sup>T * bot\<^sup>\" - . - next - show "regular bot" - by simp - qed -qed - -lemma prim_vc_2: - assumes "prim_spanning_invariant t v g r" - and "v * -v\<^sup>T \ g \ bot" - shows "prim_spanning_invariant (t \ minarc (v * -v\<^sup>T \ g)) (v \ minarc (v * -v\<^sup>T \ g)\<^sup>T * top) g r \ card { x . regular x \ x \ component g r \ x \ -(v \ minarc (v * -v\<^sup>T \ g)\<^sup>T * top)\<^sup>T } < card { x . regular x \ x \ component g r \ x \ -v\<^sup>T }" -proof - - let ?vcv = "v * -v\<^sup>T \ g" - let ?e = "minarc ?vcv" - let ?t = "t \ ?e" - let ?v = "v \ ?e\<^sup>T * top" - let ?c = "component g r" - let ?g = "--g" - let ?n1 = "card { x . regular x \ x \ ?c \ x \ -v\<^sup>T }" - let ?n2 = "card { x . regular x \ x \ ?c \ x \ -?v\<^sup>T }" - have 1: "regular v \ regular (v * v\<^sup>T) \ regular (?v * ?v\<^sup>T) \ regular (top * ?e)" - using assms(1) by (metis prim_spanning_invariant_def spanning_tree_def prim_precondition_def regular_conv_closed regular_closed_star regular_mult_closed conv_involutive regular_closed_top regular_closed_sup minarc_regular) - hence 2: "t \ v * v\<^sup>T \ ?g" - using assms(1) by (metis prim_spanning_invariant_def spanning_tree_def inf_pp_commute inf.boundedE) - hence 3: "t \ v * v\<^sup>T" - by simp - have 4: "t \ ?g" - using 2 by simp - have 5: "?e \ v * -v\<^sup>T \ ?g" - using 1 by (metis minarc_below pp_dist_inf regular_mult_closed regular_closed_p) - hence 6: "?e \ v * -v\<^sup>T" - by simp - have 7: "vector v" - using assms(1) prim_spanning_invariant_def prim_precondition_def by (simp add: covector_mult_closed vector_conv_covector) - hence 8: "?e \ v" - using 6 by (metis conv_complement inf.boundedE vector_complement_closed vector_covector) - have 9: "?e * t = bot" - using 3 6 7 et(1) by blast - have 10: "?e * t\<^sup>T = bot" - using 3 6 7 et(2) by simp - have 11: "arc ?e" - using assms(2) minarc_arc by simp - have "r\<^sup>T \ r\<^sup>T * t\<^sup>\" - by (metis mult_right_isotone order_refl semiring.mult_not_zero star.circ_separate_mult_1 star_absorb) - hence 12: "r\<^sup>T \ v\<^sup>T" - using assms(1) by (simp add: prim_spanning_invariant_def) - have 13: "vector r \ injective r \ v\<^sup>T = r\<^sup>T * t\<^sup>\" - using assms(1) prim_spanning_invariant_def prim_precondition_def minimum_spanning_tree_def spanning_tree_def reachable_restrict by simp - have "g = g\<^sup>T" - using assms(1) prim_invariant_def prim_spanning_invariant_def prim_precondition_def by simp - hence 14: "?g\<^sup>T = ?g" - using conv_complement by simp - show "prim_spanning_invariant ?t ?v g r \ ?n2 < ?n1" - proof (rule conjI) - show "prim_spanning_invariant ?t ?v g r" - proof (unfold prim_spanning_invariant_def, intro conjI) - show "prim_precondition g r" - using assms(1) prim_spanning_invariant_def by simp - next - show "?v\<^sup>T = r\<^sup>T * ?t\<^sup>\" - using assms(1) 6 7 9 by (simp add: reachable_inv prim_spanning_invariant_def prim_precondition_def spanning_tree_def) - next - let ?G = "?v * ?v\<^sup>T \ g" - show "spanning_tree ?t ?G r" - proof (unfold spanning_tree_def, intro conjI) - show "injective ?t" - using assms(1) 10 11 by (simp add: injective_inv prim_spanning_invariant_def spanning_tree_def) - next - show "acyclic ?t" - using assms(1) 3 6 7 acyclic_inv prim_spanning_invariant_def spanning_tree_def by simp - next - show "?t \ (component ?G r)\<^sup>T * (component ?G r) \ --?G" - using 1 2 5 7 13 prim_subgraph_inv inf_pp_commute mst_subgraph_inv_2 by auto - next - show "component (?v * ?v\<^sup>T \ g) r \ r\<^sup>T * ?t\<^sup>\" - proof - - have 15: "r\<^sup>T * (v * v\<^sup>T \ ?g)\<^sup>\ \ r\<^sup>T * t\<^sup>\" - using assms(1) 1 by (metis prim_spanning_invariant_def spanning_tree_def inf_pp_commute) - have "component (?v * ?v\<^sup>T \ g) r = r\<^sup>T * (?v * ?v\<^sup>T \ ?g)\<^sup>\" - using 1 by simp - also have "... \ r\<^sup>T * ?t\<^sup>\" - using 2 6 7 11 12 13 14 15 by (metis span_inv) - finally show ?thesis - . - qed - next - show "regular ?t" - using assms(1) by (metis prim_spanning_invariant_def spanning_tree_def regular_closed_sup minarc_regular) - qed - qed - next - have 16: "top * ?e \ ?c" - proof - - have "top * ?e = top * ?e\<^sup>T * ?e" - using 11 by (metis arc_top_edge mult_assoc) - also have "... \ v\<^sup>T * ?e" - using 7 8 by (metis conv_dist_comp conv_isotone mult_left_isotone symmetric_top_closed) - also have "... \ v\<^sup>T * ?g" - using 5 mult_right_isotone by auto - also have "... = r\<^sup>T * t\<^sup>\ * ?g" - using 13 by simp - also have "... \ r\<^sup>T * ?g\<^sup>\ * ?g" - using 4 by (simp add: mult_left_isotone mult_right_isotone star_isotone) - also have "... \ ?c" - by (simp add: comp_associative mult_right_isotone star.right_plus_below_circ) - finally show ?thesis - by simp - qed - have 17: "top * ?e \ -v\<^sup>T" - using 6 7 by (simp add: schroeder_4_p vTeT) - have 18: "\ top * ?e \ -(top * ?e)" - by (metis assms(2) inf.orderE minarc_bot_iff conv_complement_sub_inf inf_p inf_top.left_neutral p_bot symmetric_top_closed vector_top_closed) - have 19: "-?v\<^sup>T = -v\<^sup>T \ -(top * ?e)" - by (simp add: conv_dist_comp conv_dist_sup) - hence 20: "\ top * ?e \ -?v\<^sup>T" - using 18 by simp - show "?n2 < ?n1" - apply (rule psubset_card_mono) - using finite_regular apply simp - using 1 16 17 19 20 by auto - qed -qed - -lemma prim_vc_3: - assumes "prim_spanning_invariant t v g r" - and "v * -v\<^sup>T \ g = bot" - shows "spanning_tree t g r" -proof - - let ?g = "--g" - have 1: "regular v \ regular (v * v\<^sup>T)" - using assms(1) by (metis prim_spanning_invariant_def spanning_tree_def prim_precondition_def regular_conv_closed regular_closed_star regular_mult_closed conv_involutive) - have 2: "v * -v\<^sup>T \ ?g = bot" - using assms(2) pp_inf_bot_iff pp_pp_inf_bot_iff by simp - have 3: "v\<^sup>T = r\<^sup>T * t\<^sup>\ \ vector v" - using assms(1) by (simp add: covector_mult_closed prim_invariant_def prim_spanning_invariant_def vector_conv_covector prim_precondition_def) - have 4: "t \ v * v\<^sup>T \ ?g" - using assms(1) 1 by (metis prim_spanning_invariant_def inf_pp_commute spanning_tree_def inf.boundedE) - have "r\<^sup>T * (v * v\<^sup>T \ ?g)\<^sup>\ \ r\<^sup>T * t\<^sup>\" - using assms(1) 1 by (metis prim_spanning_invariant_def inf_pp_commute spanning_tree_def) - hence 5: "component g r = v\<^sup>T" - using 1 2 3 4 by (metis span_post) - have "regular (v * v\<^sup>T)" - using assms(1) by (metis prim_spanning_invariant_def spanning_tree_def prim_precondition_def regular_conv_closed regular_closed_star regular_mult_closed conv_involutive) - hence 6: "t \ v * v\<^sup>T \ ?g" - by (metis assms(1) prim_spanning_invariant_def spanning_tree_def inf_pp_commute inf.boundedE) - show "spanning_tree t g r" - apply (unfold spanning_tree_def, intro conjI) - using assms(1) prim_spanning_invariant_def spanning_tree_def apply simp - using assms(1) prim_spanning_invariant_def spanning_tree_def apply simp - using 5 6 apply simp - using assms(1) 5 prim_spanning_invariant_def apply simp - using assms(1) prim_spanning_invariant_def spanning_tree_def by simp -qed - -text \ -The following result shows that Prim's algorithm terminates and constructs a spanning tree. -We cannot yet show that this is a minimum spanning tree. -\ - -theorem prim_spanning: - "VARS t v e - [ prim_precondition g r ] - t := bot; - v := r; - WHILE v * -v\<^sup>T \ g \ bot - INV { prim_spanning_invariant t v g r } - VAR { card { x . regular x \ x \ component g r \ -v\<^sup>T } } - DO e := minarc (v * -v\<^sup>T \ g); - t := t \ e; - v := v \ e\<^sup>T * top - OD - [ spanning_tree t g r ]" - apply vcg_tc_simp - apply (simp add: prim_vc_1) - using prim_vc_2 apply blast - using prim_vc_3 by auto - -text \ -Because we have shown total correctness, we conclude that a spanning tree exists. -\ - -lemma prim_exists_spanning: - "prim_precondition g r \ \t . spanning_tree t g r" - using tc_extract_function prim_spanning by blast - -text \ -This implies that a minimum spanning tree exists, which is used in the subsequent correctness proof. -\ - -lemma prim_exists_minimal_spanning: - assumes "prim_precondition g r" - shows "\t . minimum_spanning_tree t g r" -proof - - let ?s = "{ t . spanning_tree t g r }" - have "\m\?s . \z\?s . sum (m \ g) \ sum (z \ g)" - apply (rule finite_set_minimal) - using finite_regular spanning_tree_def apply simp - using assms prim_exists_spanning apply simp - using sum_linear by simp - thus ?thesis - using minimum_spanning_tree_def by simp -qed - -text \ -Prim's minimum spanning tree algorithm terminates and is correct. -This is the same algorithm that is used in the previous correctness proof, with the same precondition and variant, but with a different invariant and postcondition. -\ - -theorem prim: - "VARS t v e - [ prim_precondition g r \ (\w . minimum_spanning_tree w g r) ] - t := bot; - v := r; - WHILE v * -v\<^sup>T \ g \ bot - INV { prim_invariant t v g r } - VAR { card { x . regular x \ x \ component g r \ -v\<^sup>T } } - DO e := minarc (v * -v\<^sup>T \ g); - t := t \ e; - v := v \ e\<^sup>T * top - OD - [ minimum_spanning_tree t g r ]" -proof vcg_tc_simp - assume "prim_precondition g r \ (\w . minimum_spanning_tree w g r)" - thus "prim_invariant bot r g r" - using prim_invariant_def prim_vc_1 by simp -next - fix t v - let ?vcv = "v * -v\<^sup>T \ g" - let ?vv = "v * v\<^sup>T \ g" - let ?e = "minarc ?vcv" - let ?t = "t \ ?e" - let ?v = "v \ ?e\<^sup>T * top" - let ?c = "component g r" - let ?g = "--g" - let ?n1 = "card { x . regular x \ x \ ?c \ x \ -v\<^sup>T }" - let ?n2 = "card { x . regular x \ x \ ?c \ x \ -?v\<^sup>T }" - assume 1: "prim_invariant t v g r \ ?vcv \ bot" - hence 2: "regular v \ regular (v * v\<^sup>T)" - by (metis (no_types, hide_lams) prim_invariant_def prim_spanning_invariant_def spanning_tree_def prim_precondition_def regular_conv_closed regular_closed_star regular_mult_closed conv_involutive) - have 3: "t \ v * v\<^sup>T \ ?g" - using 1 2 by (metis (no_types, hide_lams) prim_invariant_def prim_spanning_invariant_def spanning_tree_def inf_pp_commute inf.boundedE) - hence 4: "t \ v * v\<^sup>T" - by simp - have 5: "t \ ?g" - using 3 by simp - have 6: "?e \ v * -v\<^sup>T \ ?g" - using 2 by (metis minarc_below pp_dist_inf regular_mult_closed regular_closed_p) - hence 7: "?e \ v * -v\<^sup>T" - by simp - have 8: "vector v" - using 1 prim_invariant_def prim_spanning_invariant_def prim_precondition_def by (simp add: covector_mult_closed vector_conv_covector) - have 9: "arc ?e" - using 1 minarc_arc by simp - from 1 obtain w where 10: "minimum_spanning_tree w g r \ t \ w" - by (metis prim_invariant_def) - hence 11: "vector r \ injective r \ v\<^sup>T = r\<^sup>T * t\<^sup>\ \ forest w \ t \ w \ w \ ?c\<^sup>T * ?c \ ?g \ r\<^sup>T * (?c\<^sup>T * ?c \ ?g)\<^sup>\ \ r\<^sup>T * w\<^sup>\" - using 1 2 prim_invariant_def prim_spanning_invariant_def prim_precondition_def minimum_spanning_tree_def spanning_tree_def reachable_restrict by simp - hence 12: "w * v \ v" - using predecessors_reachable reachable_restrict by auto - have 13: "g = g\<^sup>T" - using 1 prim_invariant_def prim_spanning_invariant_def prim_precondition_def by simp - hence 14: "?g\<^sup>T = ?g" - using conv_complement by simp - show "prim_invariant ?t ?v g r \ ?n2 < ?n1" - proof (unfold prim_invariant_def, intro conjI) - show "prim_spanning_invariant ?t ?v g r" - using 1 prim_invariant_def prim_vc_2 by blast - next - show "\w . minimum_spanning_tree w g r \ ?t \ w" - proof - let ?f = "w \ v * -v\<^sup>T \ top * ?e * w\<^sup>T\<^sup>\" - let ?p = "w \ -v * -v\<^sup>T \ top * ?e * w\<^sup>T\<^sup>\" - let ?fp = "w \ -v\<^sup>T \ top * ?e * w\<^sup>T\<^sup>\" - let ?w = "(w \ -?fp) \ ?p\<^sup>T \ ?e" - have 15: "regular ?f \ regular ?fp \ regular ?w" - using 2 10 by (metis regular_conv_closed regular_closed_star regular_mult_closed regular_closed_top regular_closed_inf regular_closed_sup minarc_regular minimum_spanning_tree_def spanning_tree_def) - show "minimum_spanning_tree ?w g r \ ?t \ ?w" - proof (intro conjI) - show "minimum_spanning_tree ?w g r" - proof (unfold minimum_spanning_tree_def, intro conjI) - show "spanning_tree ?w g r" - proof (unfold spanning_tree_def, intro conjI) - show "injective ?w" - using 7 8 9 11 exchange_injective by blast - next - show "acyclic ?w" - using 7 8 11 12 exchange_acyclic by blast - next - show "?w \ ?c\<^sup>T * ?c \ --g" - proof - - have 16: "w \ -?fp \ ?c\<^sup>T * ?c \ --g" - using 10 by (simp add: le_infI1 minimum_spanning_tree_def spanning_tree_def) - have "?p\<^sup>T \ w\<^sup>T" - by (simp add: conv_isotone inf.sup_monoid.add_assoc) - also have "... \ (?c\<^sup>T * ?c \ --g)\<^sup>T" - using 11 conv_order by simp - also have "... = ?c\<^sup>T * ?c \ --g" - using 2 14 conv_dist_comp conv_dist_inf by simp - finally have 17: "?p\<^sup>T \ ?c\<^sup>T * ?c \ --g" - . - have "?e \ ?c\<^sup>T * ?c \ ?g" - using 5 6 11 mst_subgraph_inv by auto - thus ?thesis - using 16 17 by simp - qed - next - show "?c \ r\<^sup>T * ?w\<^sup>\" - proof - - have "?c \ r\<^sup>T * w\<^sup>\" - using 10 minimum_spanning_tree_def spanning_tree_def by simp - also have "... \ r\<^sup>T * ?w\<^sup>\" - using 4 7 8 10 11 12 15 by (metis mst_reachable_inv) - finally show ?thesis - . - qed - next - show "regular ?w" - using 15 by simp - qed - next - have 18: "?f \ ?p = ?fp" - using 2 8 epm_1 by fastforce - have "arc (w \ --v * -v\<^sup>T \ top * ?e * w\<^sup>T\<^sup>\)" - using 5 6 8 9 11 12 reachable_restrict arc_edge by auto - hence 19: "arc ?f" - using 2 by simp - hence "?f = bot \ top = bot" - by (metis mult_left_zero mult_right_zero) - hence "?f \ bot" - using 1 le_bot by auto - hence "?f \ v * -v\<^sup>T \ ?g \ bot" - using 2 11 by (simp add: inf.absorb1 le_infI1) - hence "g \ (?f \ v * -v\<^sup>T) \ bot" - using inf_commute pp_inf_bot_iff by simp - hence 20: "?f \ ?vcv \ bot" - by (simp add: inf_assoc inf_commute) - hence 21: "?f \ g = ?f \ ?vcv" - using 2 by (simp add: inf_assoc inf_commute inf_left_commute) - have 22: "?e \ g = minarc ?vcv \ ?vcv" - using 7 by (simp add: inf.absorb2 inf.assoc inf.commute) - hence 23: "sum (?e \ g) \ sum (?f \ g)" - using 15 19 20 21 by (simp add: minarc_min) - have "?e \ bot" - using 20 comp_inf.semiring.mult_not_zero semiring.mult_not_zero by blast - hence 24: "?e \ g \ bot" - using 22 minarc_meet_bot by auto - have "sum (?w \ g) = sum (w \ -?fp \ g) + sum (?p\<^sup>T \ g) + sum (?e \ g)" - using 7 8 10 by (metis sum_disjoint_3 epm_8 epm_9 epm_10 minimum_spanning_tree_def spanning_tree_def) - also have "... = sum (((w \ -?fp) \ ?p\<^sup>T) \ g) + sum (?e \ g)" - using 11 by (metis epm_8 sum_disjoint) - also have "... \ sum (((w \ -?fp) \ ?p\<^sup>T) \ g) + sum (?f \ g)" - using 23 24 by (simp add: sum_plus_right_isotone) - also have "... = sum (w \ -?fp \ g) + sum (?p\<^sup>T \ g) + sum (?f \ g)" - using 11 by (metis epm_8 sum_disjoint) - also have "... = sum (w \ -?fp \ g) + sum (?p \ g) + sum (?f \ g)" - using 13 sum_symmetric by auto - also have "... = sum (((w \ -?fp) \ ?p \ ?f) \ g)" - using 2 8 by (metis sum_disjoint_3 epm_11 epm_12 epm_13) - also have "... = sum (w \ g)" - using 2 8 15 18 epm_2 by force - finally have "sum (?w \ g) \ sum (w \ g)" - . - thus "\u . spanning_tree u g r \ sum (?w \ g) \ sum (u \ g)" - using 10 order_lesseq_imp minimum_spanning_tree_def by auto - qed - next - show "?t \ ?w" - using 4 8 10 mst_extends_new_tree by simp - qed - qed - next - show "?n2 < ?n1" - using 1 prim_invariant_def prim_vc_2 by auto - qed -next - fix t v - let ?g = "--g" - assume 25: "prim_invariant t v g r \ v * -v\<^sup>T \ g = bot" - hence 26: "regular v" - by (metis prim_invariant_def prim_spanning_invariant_def spanning_tree_def prim_precondition_def regular_conv_closed regular_closed_star regular_mult_closed conv_involutive) - from 25 obtain w where 27: "minimum_spanning_tree w g r \ t \ w" - by (metis prim_invariant_def) - have "spanning_tree t g r" - using 25 prim_invariant_def prim_vc_3 by blast - hence "component g r = v\<^sup>T" - by (metis 25 prim_invariant_def span_tree_component prim_spanning_invariant_def spanning_tree_def) - hence 28: "w \ v * v\<^sup>T" - using 26 27 by (simp add: minimum_spanning_tree_def spanning_tree_def inf_pp_commute) - have "vector r \ injective r \ forest w" - using 25 27 by (simp add: prim_invariant_def prim_spanning_invariant_def prim_precondition_def minimum_spanning_tree_def spanning_tree_def) - hence "w = t" - using 25 27 28 prim_invariant_def prim_spanning_invariant_def mst_post by blast - thus "minimum_spanning_tree t g r" - using 27 by simp -qed - -end - -end - diff --git a/thys/Aggregation_Algebras/hoare_syntax.ML b/thys/Aggregation_Algebras/hoare_syntax.ML deleted file mode 100644 --- a/thys/Aggregation_Algebras/hoare_syntax.ML +++ /dev/null @@ -1,170 +0,0 @@ -(* Title: HOL/Hoare/hoare_syntax.ML - Author: Leonor Prensa Nieto & Tobias Nipkow - Author: Walter Guttmann (extension to total-correctness proofs) - -Syntax translations for Hoare logic. -*) - -signature HOARE_SYNTAX = -sig - val hoare_vars_tr: term list -> term - val hoare_tc_vars_tr: term list -> term - val spec_tr': string -> term list -> term -end; - -structure Hoare_Syntax: HOARE_SYNTAX = -struct - -(** parse translation **) - -local - -fun idt_name (Free (x, _)) = SOME x - | idt_name (Const (@{syntax_const "_constrain"}, _) $ t $ _) = idt_name t - | idt_name _ = NONE; - -fun eq_idt tu = - (case apply2 idt_name tu of - (SOME x, SOME y) => x = y - | _ => false); - -fun mk_abstuple [x] body = Syntax_Trans.abs_tr [x, body] - | mk_abstuple (x :: xs) body = - Syntax.const @{const_syntax case_prod} $ Syntax_Trans.abs_tr [x, mk_abstuple xs body]; - -fun mk_fbody x e [y] = if eq_idt (x, y) then e else y - | mk_fbody x e (y :: xs) = - Syntax.const @{const_syntax Pair} $ - (if eq_idt (x, y) then e else y) $ mk_fbody x e xs; - -fun mk_fexp x e xs = mk_abstuple xs (mk_fbody x e xs); - - -(* bexp_tr & assn_tr *) -(*all meta-variables for bexp except for TRUE are translated as if they - were boolean expressions*) - -fun bexp_tr (Const ("TRUE", _)) _ = Syntax.const "TRUE" (* FIXME !? *) - | bexp_tr b xs = Syntax.const @{const_syntax Collect} $ mk_abstuple xs b; - -fun assn_tr r xs = Syntax.const @{const_syntax Collect} $ mk_abstuple xs r; - -fun var_tr v xs = mk_abstuple xs v; - - -(* com_tr *) - -fun com_tr (Const (@{syntax_const "_assign"}, _) $ x $ e) xs = - Syntax.const @{const_syntax Basic} $ mk_fexp x e xs - | com_tr (Const (@{const_syntax Basic},_) $ f) _ = Syntax.const @{const_syntax Basic} $ f - | com_tr (Const (@{const_syntax Seq},_) $ c1 $ c2) xs = - Syntax.const @{const_syntax Seq} $ com_tr c1 xs $ com_tr c2 xs - | com_tr (Const (@{const_syntax Cond},_) $ b $ c1 $ c2) xs = - Syntax.const @{const_syntax Cond} $ bexp_tr b xs $ com_tr c1 xs $ com_tr c2 xs - | com_tr (Const (@{const_syntax While},_) $ b $ I $ V $ c) xs = - Syntax.const @{const_syntax While} $ bexp_tr b xs $ assn_tr I xs $ var_tr V xs $ com_tr c xs - | com_tr t _ = t; - -fun vars_tr (Const (@{syntax_const "_idts"}, _) $ idt $ vars) = idt :: vars_tr vars - | vars_tr t = [t]; - -in - -fun hoare_vars_tr [vars, pre, prg, post] = - let val xs = vars_tr vars - in Syntax.const @{const_syntax Valid} $ - assn_tr pre xs $ com_tr prg xs $ assn_tr post xs - end - | hoare_vars_tr ts = raise TERM ("hoare_vars_tr", ts); - -fun hoare_tc_vars_tr [vars, pre, prg, post] = - let val xs = vars_tr vars - in Syntax.const @{const_syntax ValidTC} $ - assn_tr pre xs $ com_tr prg xs $ assn_tr post xs - end - | hoare_tc_vars_tr ts = raise TERM ("hoare_tc_vars_tr", ts); - -end; - - - -(** print translation **) - -local - -fun dest_abstuple - (Const (@{const_syntax case_prod}, _) $ Abs (v, _, body)) = - subst_bound (Syntax.free v, dest_abstuple body) - | dest_abstuple (Abs (v,_, body)) = subst_bound (Syntax.free v, body) - | dest_abstuple tm = tm; - -fun abs2list (Const (@{const_syntax case_prod}, _) $ Abs (x, T, t)) = Free (x, T) :: abs2list t - | abs2list (Abs (x, T, _)) = [Free (x, T)] - | abs2list _ = []; - -fun mk_ts (Const (@{const_syntax case_prod}, _) $ Abs (_, _, t)) = mk_ts t - | mk_ts (Abs (_, _, t)) = mk_ts t - | mk_ts (Const (@{const_syntax Pair}, _) $ a $ b) = a :: mk_ts b - | mk_ts t = [t]; - -fun mk_vts (Const (@{const_syntax case_prod},_) $ Abs (x, _, t)) = - (Syntax.free x :: abs2list t, mk_ts t) - | mk_vts (Abs (x, _, t)) = ([Syntax.free x], [t]) - | mk_vts _ = raise Match; - -fun find_ch [] _ _ = (false, (Syntax.free "not_ch", Syntax.free "not_ch")) (* FIXME no_ch!? *) - | find_ch ((v, t) :: vts) i xs = - if t = Bound i then find_ch vts (i - 1) xs - else (true, (v, subst_bounds (xs, t))); - -fun is_f (Const (@{const_syntax case_prod}, _) $ Abs _) = true - | is_f (Abs _) = true - | is_f _ = false; - - -(* assn_tr' & bexp_tr'*) - -fun assn_tr' (Const (@{const_syntax Collect}, _) $ T) = dest_abstuple T - | assn_tr' (Const (@{const_syntax inter}, _) $ - (Const (@{const_syntax Collect}, _) $ T1) $ (Const (@{const_syntax Collect}, _) $ T2)) = - Syntax.const @{const_syntax inter} $ dest_abstuple T1 $ dest_abstuple T2 - | assn_tr' t = t; - -fun bexp_tr' (Const (@{const_syntax Collect}, _) $ T) = dest_abstuple T - | bexp_tr' t = t; - -fun var_tr' (Const (@{const_syntax Collect}, _) $ T) = dest_abstuple T - | var_tr' t = t; - - -(* com_tr' *) - -fun mk_assign f = - let - val (vs, ts) = mk_vts f; - val (ch, which) = find_ch (vs ~~ ts) (length vs - 1) (rev vs); - in - if ch - then Syntax.const @{syntax_const "_assign"} $ fst which $ snd which - else Syntax.const @{const_syntax annskip} - end; - -fun com_tr' (Const (@{const_syntax Basic}, _) $ f) = - if is_f f then mk_assign f - else Syntax.const @{const_syntax Basic} $ f - | com_tr' (Const (@{const_syntax Seq},_) $ c1 $ c2) = - Syntax.const @{const_syntax Seq} $ com_tr' c1 $ com_tr' c2 - | com_tr' (Const (@{const_syntax Cond}, _) $ b $ c1 $ c2) = - Syntax.const @{const_syntax Cond} $ bexp_tr' b $ com_tr' c1 $ com_tr' c2 - | com_tr' (Const (@{const_syntax While}, _) $ b $ I $ V $ c) = - Syntax.const @{const_syntax While} $ bexp_tr' b $ assn_tr' I $ var_tr' V $ com_tr' c - | com_tr' t = t; - -in - -fun spec_tr' syn [p, c, q] = Syntax.const syn $ assn_tr' p $ com_tr' c $ assn_tr' q; - -end; - -end; - diff --git a/thys/Aggregation_Algebras/hoare_tac.ML b/thys/Aggregation_Algebras/hoare_tac.ML deleted file mode 100644 --- a/thys/Aggregation_Algebras/hoare_tac.ML +++ /dev/null @@ -1,236 +0,0 @@ -(* Title: HOL/Hoare/hoare_tac.ML - Author: Leonor Prensa Nieto & Tobias Nipkow - Author: Walter Guttmann (extension to total-correctness proofs) - -Derivation of the proof rules and, most importantly, the VCG tactic. -*) - -signature HOARE = -sig - val hoare_rule_tac: Proof.context -> term list * thm -> (int -> tactic) -> bool -> - int -> tactic - val hoare_tac: Proof.context -> (int -> tactic) -> int -> tactic - val hoare_tc_tac: Proof.context -> (int -> tactic) -> int -> tactic -end; - -structure Hoare: HOARE = -struct - -(*** The tactics ***) - -(*****************************************************************************) -(** The function Mset makes the theorem **) -(** "?Mset <= {(x1,...,xn). ?P (x1,...,xn)} ==> ?Mset <= {s. ?P s}", **) -(** where (x1,...,xn) are the variables of the particular program we are **) -(** working on at the moment of the call **) -(*****************************************************************************) - -local - -(** maps (%x1 ... xn. t) to [x1,...,xn] **) -fun abs2list (Const (@{const_name case_prod}, _) $ Abs (x, T, t)) = Free (x, T) :: abs2list t - | abs2list (Abs (x, T, _)) = [Free (x, T)] - | abs2list _ = []; - -(** maps {(x1,...,xn). t} to [x1,...,xn] **) -fun mk_vars (Const (@{const_name Collect},_) $ T) = abs2list T - | mk_vars _ = []; - -(** abstraction of body over a tuple formed from a list of free variables. -Types are also built **) -fun mk_abstupleC [] body = absfree ("x", HOLogic.unitT) body - | mk_abstupleC [v] body = absfree (dest_Free v) body - | mk_abstupleC (v :: w) body = - let - val (x, T) = dest_Free v; - val z = mk_abstupleC w body; - val T2 = - (case z of - Abs (_, T, _) => T - | Const (_, Type (_, [_, Type (_, [T, _])])) $ _ => T); - in - Const (@{const_name case_prod}, - (T --> T2 --> HOLogic.boolT) --> HOLogic.mk_prodT (T, T2) --> HOLogic.boolT) $ - absfree (x, T) z - end; - -(** maps [x1,...,xn] to (x1,...,xn) and types**) -fun mk_bodyC [] = HOLogic.unit - | mk_bodyC [x] = x - | mk_bodyC (x :: xs) = - let - val (_, T) = dest_Free x; - val z = mk_bodyC xs; - val T2 = - (case z of - Free (_, T) => T - | Const (@{const_name Pair}, Type ("fun", [_, Type ("fun", [_, T])])) $ _ $ _ => T); - in Const (@{const_name Pair}, [T, T2] ---> HOLogic.mk_prodT (T, T2)) $ x $ z end; - -(** maps a subgoal of the form: - VARS x1 ... xn {._.} _ {._.} or to [x1,...,xn] -**) -fun get_vars c = - let - val d = Logic.strip_assums_concl c; - val Const _ $ pre $ _ $ _ = HOLogic.dest_Trueprop d; - in mk_vars pre end; - -fun mk_CollectC tm = - let val T as Type ("fun",[t,_]) = fastype_of tm; - in HOLogic.Collect_const t $ tm end; - -fun inclt ty = Const (@{const_name Orderings.less_eq}, [ty,ty] ---> HOLogic.boolT); - -in - -fun Mset ctxt prop = - let - val [(Mset, _), (P, _)] = Variable.variant_frees ctxt [] [("Mset", ()), ("P", ())]; - - val vars = get_vars prop; - val varsT = fastype_of (mk_bodyC vars); - val big_Collect = - mk_CollectC (mk_abstupleC vars (Free (P, varsT --> HOLogic.boolT) $ mk_bodyC vars)); - val small_Collect = - mk_CollectC (Abs ("x", varsT, Free (P, varsT --> HOLogic.boolT) $ Bound 0)); - - val MsetT = fastype_of big_Collect; - fun Mset_incl t = HOLogic.mk_Trueprop (inclt MsetT $ Free (Mset, MsetT) $ t); - val impl = Logic.mk_implies (Mset_incl big_Collect, Mset_incl small_Collect); - val th = Goal.prove ctxt [Mset, P] [] impl (fn _ => blast_tac ctxt 1); - in (vars, th) end; - -end; - - -(*****************************************************************************) -(** Simplifying: **) -(** Some useful lemmata, lists and simplification tactics to control which **) -(** theorems are used to simplify at each moment, so that the original **) -(** input does not suffer any unexpected transformation **) -(*****************************************************************************) - -(**Simp_tacs**) - -fun before_set2pred_simp_tac ctxt = - simp_tac (put_simpset HOL_basic_ss ctxt addsimps [Collect_conj_eq RS sym, @{thm Compl_Collect}]); - -fun split_simp_tac ctxt = - simp_tac (put_simpset HOL_basic_ss ctxt addsimps [@{thm split_conv}]); - -(*****************************************************************************) -(** set_to_pred_tac transforms sets inclusion into predicates implication, **) -(** maintaining the original variable names. **) -(** Ex. "{x. x=0} <= {x. x <= 1}" -set2pred-> "x=0 --> x <= 1" **) -(** Subgoals containing intersections (A Int B) or complement sets (-A) **) -(** are first simplified by "before_set2pred_simp_tac", that returns only **) -(** subgoals of the form "{x. P x} <= {x. Q x}", which are easily **) -(** transformed. **) -(** This transformation may solve very easy subgoals due to a ligth **) -(** simplification done by (split_all_tac) **) -(*****************************************************************************) - -fun set_to_pred_tac ctxt var_names = SUBGOAL (fn (_, i) => - before_set2pred_simp_tac ctxt i THEN_MAYBE - EVERY [ - resolve_tac ctxt [subsetI] i, - resolve_tac ctxt [CollectI] i, - dresolve_tac ctxt [CollectD] i, - TRY (split_all_tac ctxt i) THEN_MAYBE - (rename_tac var_names i THEN - full_simp_tac (put_simpset HOL_basic_ss ctxt addsimps [@{thm split_conv}]) i)]); - -(*******************************************************************************) -(** basic_simp_tac is called to simplify all verification conditions. It does **) -(** a light simplification by applying "mem_Collect_eq", then it calls **) -(** max_simp_tac, which solves subgoals of the form "A <= A", **) -(** and transforms any other into predicates, applying then **) -(** the tactic chosen by the user, which may solve the subgoal completely. **) -(*******************************************************************************) - -fun max_simp_tac ctxt var_names tac = - FIRST' [resolve_tac ctxt [subset_refl], - set_to_pred_tac ctxt var_names THEN_MAYBE' tac]; - -fun basic_simp_tac ctxt var_names tac = - simp_tac - (put_simpset HOL_basic_ss ctxt - addsimps [mem_Collect_eq, @{thm split_conv}] addsimprocs [Record.simproc]) - THEN_MAYBE' max_simp_tac ctxt var_names tac; - - -(** hoare_rule_tac **) - -fun hoare_rule_tac ctxt (vars, Mlem) tac = - let - val var_names = map (fst o dest_Free) vars; - fun wlp_tac i = - resolve_tac ctxt @{thms SeqRule} i THEN rule_tac false (i + 1) - and rule_tac pre_cond i st = st |> (*abstraction over st prevents looping*) - ((wlp_tac i THEN rule_tac pre_cond i) - ORELSE - (FIRST [ - resolve_tac ctxt @{thms SkipRule} i, - resolve_tac ctxt @{thms AbortRule} i, - EVERY [ - resolve_tac ctxt @{thms BasicRule} i, - resolve_tac ctxt [Mlem] i, - split_simp_tac ctxt i], - EVERY [ - resolve_tac ctxt @{thms CondRule} i, - rule_tac false (i + 2), - rule_tac false (i + 1)], - EVERY [ - resolve_tac ctxt @{thms WhileRule} i, - basic_simp_tac ctxt var_names tac (i + 2), - rule_tac true (i + 1)]] - THEN ( - if pre_cond then basic_simp_tac ctxt var_names tac i - else resolve_tac ctxt [subset_refl] i))); - in rule_tac end; - - -(** tac is the tactic the user chooses to solve or simplify **) -(** the final verification conditions **) - -fun hoare_tac ctxt tac = SUBGOAL (fn (goal, i) => - SELECT_GOAL (hoare_rule_tac ctxt (Mset ctxt goal) tac true 1) i); - - -(* total correctness rules *) - -fun hoare_tc_rule_tac ctxt (vars, Mlem) tac = - let - val var_names = map (fst o dest_Free) vars; - fun wlp_tac i = - resolve_tac ctxt @{thms SeqRuleTC} i THEN rule_tac false (i + 1) - and rule_tac pre_cond i st = st |> (*abstraction over st prevents looping*) - ((wlp_tac i THEN rule_tac pre_cond i) - ORELSE - (FIRST [ - resolve_tac ctxt @{thms SkipRuleTC} i, - resolve_tac ctxt @{thms AbortRuleTC} i, - EVERY [ - resolve_tac ctxt @{thms BasicRuleTC} i, - resolve_tac ctxt [Mlem] i, - split_simp_tac ctxt i], - EVERY [ - resolve_tac ctxt @{thms CondRuleTC} i, - rule_tac false (i + 2), - rule_tac false (i + 1)], - EVERY [ - resolve_tac ctxt @{thms WhileRuleTC} i, - basic_simp_tac ctxt var_names tac (i + 2), - rule_tac true (i + 1)]] - THEN ( - if pre_cond then basic_simp_tac ctxt var_names tac i - else resolve_tac ctxt [subset_refl] i))); - in rule_tac end; - - -fun hoare_tc_tac ctxt tac = SUBGOAL (fn (goal, i) => - SELECT_GOAL (hoare_tc_rule_tac ctxt (Mset ctxt goal) tac true 1) i); - -end; -