# HG changeset patch # User nipkow # Date 1326888298 -3600 # Node ID 9f39ae84b593ed8ebcbd4f2e9938bce649e19a63 # Parent da375b4b71679ceed4813602f7cc8dcd01444043 Added termination proof for widening diff -r da375b4b7167 -r 9f39ae84b593 src/HOL/IMP/Abs_Int2.thy --- a/src/HOL/IMP/Abs_Int2.thy Wed Jan 18 22:09:29 2012 +1100 +++ b/src/HOL/IMP/Abs_Int2.thy Wed Jan 18 13:04:58 2012 +0100 @@ -4,7 +4,6 @@ imports Abs_Int1_ivl begin - subsection "Widening and Narrowing" class WN = SL_top + @@ -16,6 +15,8 @@ assumes narrow2: "y \ x \ x \ y \ x" +subsubsection "Intervals" + instantiation ivl :: WN begin @@ -38,6 +39,9 @@ end + +subsubsection "Abstract State" + instantiation st :: (WN)WN begin @@ -64,6 +68,9 @@ end + +subsubsection "Option" + instantiation option :: (WN)WN begin @@ -94,6 +101,9 @@ end + +subsubsection "Annotated commands" + fun map2_acom :: "('a \ 'a \ 'a) \ 'a acom \ 'a acom \ 'a acom" where "map2_acom f (SKIP {a1}) (SKIP {a2}) = (SKIP {f a1 a2})" | "map2_acom f (x ::= e {a1}) (x' ::= e' {a2}) = (x ::= e {f a1 a2})" | @@ -121,25 +131,52 @@ lemma narrow2_acom: "y \ x \ x \\<^sub>c y \ x" by(induct y x rule: le_acom.induct) (simp_all add: narrow2) +(* +lemma strip_widen_acom: + "strip c' = strip (c::'a::WN acom) \ strip (c \\<^sub>c c') = strip c" +by(induction "widen::'a\'a\'a" c c' rule: map2_acom.induct) simp_all + +lemma annos_widen_acom[simp]: "strip c1 = strip (c2::'a::WN acom) \ + annos(c1 \\<^sub>c c2) = map (%(x,y).x\y) (zip (annos c1) (annos(c2::'a::WN acom)))" +by(induction "widen::'a\'a\'a" c1 c2 rule: map2_acom.induct) + (simp_all add: size_annos_same2) +*) subsubsection "Post-fixed point computation" +definition iter_widen :: "('a acom \ 'a acom) \ 'a acom \ ('a::WN)acom option" +where "iter_widen f = while_option (\c. \ f c \ c) (\c. c \\<^sub>c f c)" + definition prefp :: "(('a::preord) \ 'a) \ 'a \ 'a option" where "prefp f = while_option (\x. \ x \ f x) f" + definition pfp_WN :: "(('a::WN)option acom \ 'a option acom) \ com \ 'a option acom option" -where "pfp_WN f c = (case lpfp\<^isub>c (\c. c \\<^sub>c f c) c of None \ None +where "pfp_WN f c = (case iter_widen f (\\<^sub>c c) of None \ None | Some c' \ prefp (\c. c \\<^sub>c f c) c')" lemma strip_map2_acom: "strip c1 = strip c2 \ strip(map2_acom f c1 c2) = strip c1" by(induct f c1 c2 rule: map2_acom.induct) simp_all -lemma lpfp_step_up_pfp: - "\ \c. strip(f c) = strip c; lpfp\<^isub>c (\c. c \\<^sub>c f c) c = Some c' \ \ f c' \ c'" -by (metis (no_types) assms lpfpc_pfp le_trans widen2_acom) +lemma iter_widen_pfp: "iter_widen f c = Some c' \ f c' \ c'" +by(auto simp add: iter_widen_def dest: while_option_stop) + +lemma strip_while: fixes f :: "'a acom \ 'a acom" +assumes "\c. strip (f c) = strip c" and "while_option P f c = Some c'" +shows "strip c' = strip c" +using while_option_rule[where P = "\c'. strip c' = strip c", OF _ assms(2)] +by (metis assms(1)) + +lemma strip_iter_widen: fixes f :: "'a::WN acom \ 'a acom" +assumes "\c. strip (f c) = strip c" and "iter_widen f c = Some c'" +shows "strip c' = strip c" +proof- + have "\c. strip(c \\<^sub>c f c) = strip c" by (metis assms(1) strip_map2_acom) + from strip_while[OF this] assms(2) show ?thesis by(simp add: iter_widen_def) +qed lemma iter_down_pfp: assumes "mono f" and "f x0 \ x0" and "prefp (\c. c \\<^sub>c f c) x0 = Some x" @@ -163,22 +200,15 @@ show ?thesis by blast qed - lemma pfp_WN_pfp: - "\ \c. strip (f c) = strip c; mono f; pfp_WN f c = Some c' \ \ f c' \ c'" + "\ mono f; pfp_WN f c = Some c' \ \ f c' \ c'" unfolding pfp_WN_def -by (auto dest: iter_down_pfp lpfp_step_up_pfp split: option.splits) - -lemma strip_while: fixes f :: "'a acom \ 'a acom" -assumes "\c. strip (f c) = strip c" and "while_option P f c = Some c'" -shows "strip c' = strip c" -using while_option_rule[where P = "\c'. strip c' = strip c", OF _ assms(2)] -by (metis assms(1)) +by (auto dest: iter_down_pfp iter_widen_pfp split: option.splits) lemma strip_pfp_WN: "\ \c. strip(f c) = strip c; pfp_WN f c = Some c' \ \ strip c' = c" apply(auto simp add: pfp_WN_def prefp_def split: option.splits) -by (metis (no_types) strip_lpfpc strip_map2_acom strip_while) +by (metis (no_types) strip_map2_acom strip_while strip_bot_acom strip_iter_widen) locale Abs_Int2 = Abs_Int1_mono where \=\ for \ :: "'av::{WN,L_top_bot} \ val set" @@ -190,7 +220,7 @@ lemma AI_WN_sound: "AI_WN c = Some c' \ CS c \ \\<^isub>c c'" proof(simp add: CS_def AI_WN_def) assume 1: "pfp_WN (step' \) c = Some c'" - from pfp_WN_pfp[OF allI[OF strip_step'] mono_step'2 1] + from pfp_WN_pfp[OF mono_step'2 1] have 2: "step' \ c' \ c'" . have 3: "strip (\\<^isub>c (step' \ c')) = c" by(simp add: strip_pfp_WN[OF _ 1]) have "lfp (step UNIV) c \ \\<^isub>c (step' \ c')" @@ -238,4 +268,243 @@ value [code] "show_acom_opt (AI_ivl' test5_ivl)" value [code] "show_acom_opt (AI_ivl' test6_ivl)" + +subsubsection "Termination: Intervals" + +(* interesting(?) relic +lemma widen_assoc: + "~ (y::ivl) \ x \ ~ z \ x \ y \ ((x::ivl) \ y) \ z = x \ (y \ z)" +apply(cases x) +apply(cases y) +apply(cases z) +apply(rename_tac x1 x2 y1 y2 z1 z2) +apply(simp add: le_ivl_def) +apply(case_tac x1) +apply(case_tac x2) +apply(simp add:le_option_def widen_ivl_def split: if_splits option.splits) +apply(simp add:le_option_def widen_ivl_def split: if_splits option.splits) +apply(case_tac x2) +apply(simp add:le_option_def widen_ivl_def split: if_splits option.splits) +apply(case_tac y1) +apply(case_tac y2) +apply(simp add:le_option_def widen_ivl_def split: if_splits option.splits) +apply(case_tac z1) +apply(auto simp add:le_option_def widen_ivl_def split: if_splits option.splits ivl.splits)[1] +apply(auto simp add:le_option_def widen_ivl_def split: if_splits option.splits ivl.splits)[1] +apply(case_tac y2) +apply(auto simp add:le_option_def widen_ivl_def split: if_splits option.splits ivl.splits)[1] +apply(case_tac z1) +apply(auto simp add:le_option_def widen_ivl_def split: if_splits ivl.splits option.splits)[1] +apply(case_tac z2) +apply(auto simp add:le_option_def widen_ivl_def split: if_splits option.splits)[1] +apply(auto simp add:le_option_def widen_ivl_def split: if_splits option.splits)[1] +done + +lemma widen_step_trans: + "~ (y::ivl) \ x \ ~ z \ x \ y \ EX u. (x \ y) \ z = x \ u \ ~ u \ x" +by (metis widen_assoc preord_class.le_trans widen1) +*) + +definition m_ivl :: "ivl \ nat" where +"m_ivl ivl = (case ivl of I l h \ + (case l of None \ 0 | Some _ \ 1) + (case h of None \ 0 | Some _ \ 1))" + +lemma m_ivl_height: "m_ivl ivl \ 2" +by(simp add: m_ivl_def split: ivl.split option.split) + +lemma m_ivl_anti_mono: "(y::ivl) \ x \ m_ivl x \ m_ivl y" +by(auto simp: m_ivl_def le_option_def le_ivl_def + split: ivl.split option.split if_splits) + +lemma less_m_ivl_widen: + "~ y \ x \ m_ivl(x \ y) < m_ivl x" +by(auto simp: m_ivl_def widen_ivl_def le_option_def le_ivl_def + split: ivl.splits option.splits if_splits) + +lemma Top_less_ivl: "\ \ x \ m_ivl x = 0" +by(auto simp: m_ivl_def le_option_def le_ivl_def empty_def Top_ivl_def + split: ivl.split option.split if_splits) + + +subsubsection "Termination: Abstract State" + +definition "m_st m st = (\x\set(dom st). m(fun st x))" + +lemma m_st_height: assumes "finite X" and "set (dom S) \ X" +shows "m_st m_ivl S \ 2 * card X" +proof(auto simp: m_st_def) + have "(\x\set(dom S). m_ivl (fun S x)) \ (\x\set(dom S). 2)" (is "?L \ _") + by(rule setsum_mono)(simp add:m_ivl_height) + also have "\ \ (\x\X. 2)" + by(rule setsum_mono3[OF assms]) simp + also have "\ = 2 * card X" by(simp add: setsum_constant) + finally show "?L \ \" . +qed + +lemma m_st_anti_mono: + "S1 \ S2 \ m_st m_ivl S2 \ m_st m_ivl S1" +proof(auto simp: m_st_def le_st_def lookup_def split: if_splits) + let ?X = "set(dom S1)" let ?Y = "set(dom S2)" + let ?f = "fun S1" let ?g = "fun S2" + assume asm: "\x\?Y. (x \ ?X \ ?f x \ ?g x) \ (x \ ?X \ \ \ ?g x)" + hence 1: "\y\?Y\?X. m_ivl(?g y) \ m_ivl(?f y)" by(simp add: m_ivl_anti_mono) + have 0: "\x\?Y-?X. m_ivl(?g x) = 0" using asm by (auto simp: Top_less_ivl) + have "(\y\?Y. m_ivl(?g y)) = (\y\(?Y-?X) \ (?Y\?X). m_ivl(?g y))" + by (metis Un_Diff_Int) + also have "\ = (\y\?Y-?X. m_ivl(?g y)) + (\y\?Y\?X. m_ivl(?g y))" + by(subst setsum_Un_disjoint) auto + also have "(\y\?Y-?X. m_ivl(?g y)) = 0" using 0 by simp + also have "0 + (\y\?Y\?X. m_ivl(?g y)) = (\y\?Y\?X. m_ivl(?g y))" by simp + also have "\ \ (\y\?Y\?X. m_ivl(?f y))" + by(rule setsum_mono)(simp add: 1) + also have "\ \ (\y\?X. m_ivl(?f y))" + by(simp add: setsum_mono3[of "?X" "?Y Int ?X", OF _ Int_lower2]) + finally show "(\y\?Y. m_ivl(?g y)) \ (\x\?X. m_ivl(?f x))" + by (metis add_less_cancel_left) +qed + +lemma less_m_st_widen: +assumes "\ S2 \ S1" shows "m_st m_ivl (S1 \ S2) < m_st m_ivl S1" +proof- + { let ?X = "set(dom S1)" let ?Y = "set(dom S2)" + let ?f = "fun S1" let ?g = "fun S2" + fix x assume "x \ ?X" "\ lookup S2 x \ ?f x" + have "(\x\?X\?Y. m_ivl(?f x \ ?g x)) < (\x\?X. m_ivl(?f x))" (is "?L < ?R") + proof cases + assume "x : ?Y" + have "?L < (\x\?X\?Y. m_ivl(?f x))" + proof(rule setsum_strict_mono1, simp) + show "\x\?X\?Y. m_ivl(?f x \ ?g x) \ m_ivl (?f x)" + by (metis m_ivl_anti_mono widen1) + next + show "\x\?X\?Y. m_ivl(?f x \ ?g x) < m_ivl(?f x)" + using `x:?X` `x:?Y` `\ lookup S2 x \ ?f x` + by (metis IntI less_m_ivl_widen lookup_def) + qed + also have "\ \ ?R" by(simp add: setsum_mono3[OF _ Int_lower1]) + finally show ?thesis . + next + assume "x ~: ?Y" + have "?L \ (\x\?X\?Y. m_ivl(?f x))" + proof(rule setsum_mono, simp) + fix x assume "x:?X \ x:?Y" show "m_ivl(?f x \ ?g x) \ m_ivl (?f x)" + by (metis m_ivl_anti_mono widen1) + qed + also have "\ < m_ivl(?f x) + \" + using less_m_ivl_widen[OF `\ lookup S2 x \ ?f x`] + by (metis Nat.le_refl add_strict_increasing gr0I not_less0) + also have "\ = (\y\insert x (?X\?Y). m_ivl(?f y))" + using `x ~: ?Y` by simp + also have "\ \ (\x\?X. m_ivl(?f x))" + by(rule setsum_mono3)(insert `x:?X`, auto) + finally show ?thesis . + qed + } with assms show ?thesis + by(auto simp: le_st_def widen_st_def m_st_def Int_def) +qed + + +subsubsection "Termination: Option" + +definition "m_o m n opt = (case opt of None \ n+1 | Some x \ m x)" + +lemma m_o_anti_mono: "finite X \ domo S2 \ X \ S1 \ S2 \ + m_o (m_st m_ivl) (2 * card X) S2 \ m_o (m_st m_ivl) (2 * card X) S1" +apply(induction S1 S2 rule: le_option.induct) +apply(auto simp: domo_def m_o_def m_st_anti_mono le_SucI m_st_height + split: option.splits) +done + +lemma less_m_o_widen: "\ finite X; domo S2 \ X; \ S2 \ S1 \ \ + m_o (m_st m_ivl) (2 * card X) (S1 \ S2) < m_o (m_st m_ivl) (2 * card X) S1" +by(auto simp: m_o_def domo_def m_st_height less_Suc_eq_le less_m_st_widen + split: option.split) + + +lemma domo_widen_subset: "domo (S1 \ S2) \ domo S1 \ domo S2" +apply(induction S1 S2 rule: widen_option.induct) +apply (auto simp: domo_def widen_st_def) +done + +subsubsection "Termination: Commands" + +lemma strip_widen_acom: + "strip c' = strip (c::'a::WN acom) \ strip (c \\<^sub>c c') = strip c" +by(induction "widen::'a\'a\'a" c c' rule: map2_acom.induct) simp_all + +lemma annos_widen_acom[simp]: "strip c1 = strip (c2::'a::WN acom) \ + annos(c1 \\<^sub>c c2) = map (%(x,y).x\y) (zip (annos c1) (annos(c2::'a::WN acom)))" +by(induction "widen::'a\'a\'a" c1 c2 rule: map2_acom.induct) + (simp_all add: size_annos_same2) + +lemma Com_widen_acom: "strip c2 = strip c1 \ + c1 : Com X \ c2 : Com X \ (c1 \\<^sub>c c2) : Com X" +apply(auto simp add: Com_def split: option.splits) +apply(rename_tac S S' x) +apply(erule in_set_zipE) +apply(simp add: domo_def) +apply (auto split: option.splits) +apply(case_tac S) +apply(case_tac S') +apply simp +apply fastforce +apply(case_tac S') +apply fastforce +apply (fastforce simp: widen_st_def) +done + +definition "m_c m c = (let as = annos c in \i=0.. {(c, c \\<^sub>c c') |c c'\ivl st option acom. + strip c' = strip c \ c : Com X \ c' : Com X \ \ c' \ c}\ + \ measure(m_c(m_o (m_st m_ivl) (2*card(X))))" +apply(auto simp: m_c_def Let_def Com_def) +apply(subgoal_tac "length(annos c') = length(annos c)") +prefer 2 apply (simp add: size_annos_same2) +apply (auto) +apply(rule setsum_strict_mono1) +apply simp +apply (clarsimp) +apply(erule m_o_anti_mono) +apply(rule subset_trans[OF domo_widen_subset]) +apply fastsimp +apply(rule widen1) +apply(auto simp: le_iff_le_annos listrel_iff_nth) +apply(rule_tac x=n in bexI) +prefer 2 apply simp +apply(erule less_m_o_widen) +apply (simp)+ +done + + +subsubsection "Termination: Post-Fixed Point Iterations" + +lemma iter_widen_termination: +fixes c0 :: "'a::WN acom" +assumes P_f: "\c. P c \ P(f c)" +assumes P_widen: "\c c'. P c \ P c' \ P(c \\<^sub>c c')" +and "wf({(c::'a acom,c \\<^sub>c c')|c c'. P c \ P c' \ ~ c' \ c}^-1)" +and "P c0" and "c0 \ f c0" shows "EX c. iter_widen f c0 = Some c" +proof(simp add: iter_widen_def, rule wf_while_option_Some[where P = "P"]) + show "wf {(cc', c). (P c \ \ f c \ c) \ cc' = c \\<^sub>c f c}" + apply(rule wf_subset[OF assms(3)]) by(blast intro: P_f) +next + show "P c0" by(rule `P c0`) +next + fix c assume "P c" thus "P (c \\<^sub>c f c)" by(simp add: P_f P_widen) +qed + +lemma + "EX c::ivl st option acom. iter_widen (step_ivl \) (\\<^sub>c c0) = Some c" +apply(rule iter_widen_termination[where + P = "%c. strip c = c0 \ c : Com(vars c0)"]) +apply (simp_all add: strip_step' step'_Com Com_widen_acom strip_widen_acom bot_acom domo_Top) +apply(rule wf_subset) +apply(rule wf_measure) +apply(rule subset_trans) +prefer 2 +apply(rule measure_m_c[where X = "vars c0", OF finite_cvars]) +apply blast +done + end