# HG changeset patch # User bulwahn # Date 1288283794 -7200 # Node ID 783c23f6afbfcc98f7d7de00c6f4ce146408b2b9 # Parent 3102b27ca03aed102d8cbfd39d1f7fa5a803457d# Parent 997d6fb439a9e5a9ae82f6ace3317fa04c367c9a merged diff -r 3102b27ca03a -r 783c23f6afbf doc-src/IsarImplementation/Thy/ML.thy --- a/doc-src/IsarImplementation/Thy/ML.thy Thu Oct 28 17:28:45 2010 +0200 +++ b/doc-src/IsarImplementation/Thy/ML.thy Thu Oct 28 18:36:34 2010 +0200 @@ -750,7 +750,7 @@ This can be avoided by \emph{canonical argument order}, which observes certain standard patterns and minimizes adhoc permutations - in their application. In Isabelle/ML, large portions text can be + in their application. In Isabelle/ML, large portions of text can be written without ever using @{text "swap: \ \ \ \ \ \ \"}, or the combinator @{text "C: (\ \ \ \ \) \ (\ \ \ \ \)"} that is not even defined in our library. @@ -787,7 +787,7 @@ to the right: @{text "insert a"} is a function @{text "\ \ \"} to insert a value @{text "a"}. These can be composed naturally as @{text "insert c \ insert b \ insert a"}. The slightly awkward - inversion if the composition order is due to conventional + inversion of the composition order is due to conventional mathematical notation, which can be easily amended as explained below. *} @@ -1138,9 +1138,9 @@ language definition. It was excluded from the SML97 version to avoid its malign impact on ML program semantics, but without providing a viable alternative. Isabelle/ML recovers physical - interruptibility (which an indispensable tool to implement managed - evaluation of command transactions), but requires user code to be - strictly transparent wrt.\ interrupts. + interruptibility (which is an indispensable tool to implement + managed evaluation of command transactions), but requires user code + to be strictly transparent wrt.\ interrupts. \begin{warn} Isabelle/ML user code needs to terminate promptly on interruption, diff -r 3102b27ca03a -r 783c23f6afbf doc-src/IsarImplementation/Thy/document/ML.tex --- a/doc-src/IsarImplementation/Thy/document/ML.tex Thu Oct 28 17:28:45 2010 +0200 +++ b/doc-src/IsarImplementation/Thy/document/ML.tex Thu Oct 28 18:36:34 2010 +0200 @@ -948,7 +948,7 @@ This can be avoided by \emph{canonical argument order}, which observes certain standard patterns and minimizes adhoc permutations - in their application. In Isabelle/ML, large portions text can be + in their application. In Isabelle/ML, large portions of text can be written without ever using \isa{swap{\isacharcolon}\ {\isasymalpha}\ {\isasymtimes}\ {\isasymbeta}\ {\isasymrightarrow}\ {\isasymbeta}\ {\isasymtimes}\ {\isasymalpha}}, or the combinator \isa{C{\isacharcolon}\ {\isacharparenleft}{\isasymalpha}\ {\isasymrightarrow}\ {\isasymbeta}\ {\isasymrightarrow}\ {\isasymgamma}{\isacharparenright}\ {\isasymrightarrow}\ {\isacharparenleft}{\isasymbeta}\ {\isasymrightarrow}\ {\isasymalpha}\ {\isasymrightarrow}\ {\isasymgamma}{\isacharparenright}} that is not even defined in our library. @@ -983,7 +983,7 @@ to the right: \isa{insert\ a} is a function \isa{{\isasymbeta}\ {\isasymrightarrow}\ {\isasymbeta}} to insert a value \isa{a}. These can be composed naturally as \isa{insert\ c\ {\isasymcirc}\ insert\ b\ {\isasymcirc}\ insert\ a}. The slightly awkward - inversion if the composition order is due to conventional + inversion of the composition order is due to conventional mathematical notation, which can be easily amended as explained below.% \end{isamarkuptext}% @@ -1450,9 +1450,9 @@ language definition. It was excluded from the SML97 version to avoid its malign impact on ML program semantics, but without providing a viable alternative. Isabelle/ML recovers physical - interruptibility (which an indispensable tool to implement managed - evaluation of command transactions), but requires user code to be - strictly transparent wrt.\ interrupts. + interruptibility (which is an indispensable tool to implement + managed evaluation of command transactions), but requires user code + to be strictly transparent wrt.\ interrupts. \begin{warn} Isabelle/ML user code needs to terminate promptly on interruption, diff -r 3102b27ca03a -r 783c23f6afbf src/HOL/List.thy --- a/src/HOL/List.thy Thu Oct 28 17:28:45 2010 +0200 +++ b/src/HOL/List.thy Thu Oct 28 18:36:34 2010 +0200 @@ -1576,6 +1576,10 @@ "map f (butlast xs) = butlast (map f xs)" by (induct xs) simp_all +lemma snoc_eq_iff_butlast: + "xs @ [x] = ys \ (ys \ [] & butlast ys = xs & last ys = x)" +by (metis append_butlast_last_id append_is_Nil_conv butlast_snoc last_snoc not_Cons_self) + subsubsection {* @{text take} and @{text drop} *} @@ -2288,6 +2292,10 @@ "xs = ys \ list_all2 (op =) xs ys" by (induct xs ys rule: list_induct2') auto +lemma list_eq_iff_zip_eq: + "xs = ys \ length xs = length ys \ (\(x,y) \ set (zip xs ys). x = y)" +by(auto simp add: set_zip list_all2_eq list_all2_conv_all_nth cong: conj_cong) + subsubsection {* @{text foldl} and @{text foldr} *} @@ -4457,7 +4465,7 @@ by blast -subsection {* Lexicographic combination of measure functions *} +subsubsection {* Lexicographic combination of measure functions *} text {* These are useful for termination proofs *} @@ -4482,7 +4490,133 @@ by auto -subsubsection {* Lifting a Relation on List Elements to the Lists *} +subsubsection {* Lifting Relations to Lists: one element *} + +definition listrel1 :: "('a \ 'a) set \ ('a list \ 'a list) set" where +"listrel1 r = {(xs,ys). + \us z z' vs. xs = us @ z # vs \ (z,z') \ r \ ys = us @ z' # vs}" + +lemma listrel1I: + "\ (x, y) \ r; xs = us @ x # vs; ys = us @ y # vs \ \ + (xs, ys) \ listrel1 r" +unfolding listrel1_def by auto + +lemma listrel1E: + "\ (xs, ys) \ listrel1 r; + !!x y us vs. \ (x, y) \ r; xs = us @ x # vs; ys = us @ y # vs \ \ P + \ \ P" +unfolding listrel1_def by auto + +lemma not_Nil_listrel1 [iff]: "([], xs) \ listrel1 r" +unfolding listrel1_def by blast + +lemma not_listrel1_Nil [iff]: "(xs, []) \ listrel1 r" +unfolding listrel1_def by blast + +lemma Cons_listrel1_Cons [iff]: + "(x # xs, y # ys) \ listrel1 r \ + (x,y) \ r \ xs = ys \ x = y \ (xs, ys) \ listrel1 r" +by (simp add: listrel1_def Cons_eq_append_conv) (blast) + +lemma listrel1I1: "(x,y) \ r \ (x # xs, y # xs) \ listrel1 r" +by (metis Cons_listrel1_Cons) + +lemma listrel1I2: "(xs, ys) \ listrel1 r \ (x # xs, x # ys) \ listrel1 r" +by (metis Cons_listrel1_Cons) + +lemma append_listrel1I: + "(xs, ys) \ listrel1 r \ us = vs \ xs = ys \ (us, vs) \ listrel1 r + \ (xs @ us, ys @ vs) \ listrel1 r" +unfolding listrel1_def +by auto (blast intro: append_eq_appendI)+ + +lemma Cons_listrel1E1[elim!]: + assumes "(x # xs, ys) \ listrel1 r" + and "\y. ys = y # xs \ (x, y) \ r \ R" + and "\zs. ys = x # zs \ (xs, zs) \ listrel1 r \ R" + shows R +using assms by (cases ys) blast+ + +lemma Cons_listrel1E2[elim!]: + assumes "(xs, y # ys) \ listrel1 r" + and "\x. xs = x # ys \ (x, y) \ r \ R" + and "\zs. xs = y # zs \ (zs, ys) \ listrel1 r \ R" + shows R +using assms by (cases xs) blast+ + +lemma snoc_listrel1_snoc_iff: + "(xs @ [x], ys @ [y]) \ listrel1 r + \ (xs, ys) \ listrel1 r \ x = y \ xs = ys \ (x,y) \ r" (is "?L \ ?R") +proof + assume ?L thus ?R + by (fastsimp simp: listrel1_def snoc_eq_iff_butlast butlast_append) +next + assume ?R then show ?L unfolding listrel1_def by force +qed + +lemma listrel1_eq_len: "(xs,ys) \ listrel1 r \ length xs = length ys" +unfolding listrel1_def by auto + +lemma listrel1_mono: + "r \ s \ listrel1 r \ listrel1 s" +unfolding listrel1_def by blast + + +lemma listrel1_converse: "listrel1 (r^-1) = (listrel1 r)^-1" +unfolding listrel1_def by blast + +lemma in_listrel1_converse: + "(x,y) : listrel1 (r^-1) \ (x,y) : (listrel1 r)^-1" +unfolding listrel1_def by blast + +lemma listrel1_iff_update: + "(xs,ys) \ (listrel1 r) + \ (\y n. (xs ! n, y) \ r \ n < length xs \ ys = xs[n:=y])" (is "?L \ ?R") +proof + assume "?L" + then obtain x y u v where "xs = u @ x # v" "ys = u @ y # v" "(x,y) \ r" + unfolding listrel1_def by auto + then have "ys = xs[length u := y]" and "length u < length xs" + and "(xs ! length u, y) \ r" by auto + then show "?R" by auto +next + assume "?R" + then obtain x y n where "(xs!n, y) \ r" "n < size xs" "ys = xs[n:=y]" "x = xs!n" + by auto + then obtain u v where "xs = u @ x # v" and "ys = u @ y # v" and "(x, y) \ r" + by (auto intro: upd_conv_take_nth_drop id_take_nth_drop) + then show "?L" by (auto simp: listrel1_def) +qed + + +text{* Accessible part of @{term listrel1} relations: *} + +lemma Cons_acc_listrel1I [intro!]: + "x \ acc r \ xs \ acc (listrel1 r) \ (x # xs) \ acc (listrel1 r)" +apply (induct arbitrary: xs set: acc) +apply (erule thin_rl) +apply (erule acc_induct) +apply (rule accI) +apply (blast) +done + +lemma lists_accD: "xs \ lists (acc r) \ xs \ acc (listrel1 r)" +apply (induct set: lists) + apply (rule accI) + apply simp +apply (rule accI) +apply (fast dest: acc_downward) +done + +lemma lists_accI: "xs \ acc (listrel1 r) \ xs \ lists (acc r)" +apply (induct set: acc) +apply clarify +apply (rule accI) +apply (fastsimp dest!: in_set_conv_decomp[THEN iffD1] simp: listrel1_def) +done + + +subsubsection {* Lifting Relations to Lists: all elements *} inductive_set listrel :: "('a * 'a)set => ('a list * 'a list)set" @@ -4497,6 +4631,24 @@ inductive_cases listrel_Cons2 [elim!]: "(xs,y#ys) \ listrel r" +lemma listrel_eq_len: "(xs, ys) \ listrel r \ length xs = length ys" +by(induct rule: listrel.induct) auto + +lemma listrel_iff_zip: "(xs,ys) : listrel r \ + length xs = length ys & (\(x,y) \ set(zip xs ys). (x,y) \ r)" (is "?L \ ?R") +proof + assume ?L thus ?R by induct (auto intro: listrel_eq_len) +next + assume ?R thus ?L + apply (clarify) + by (induct rule: list_induct2) (auto intro: listrel.intros) +qed + +lemma listrel_iff_nth: "(xs,ys) : listrel r \ + length xs = length ys & (\n < length xs. (xs!n, ys!n) \ r)" (is "?L \ ?R") +by (auto simp add: all_set_conv_all_nth listrel_iff_zip) + + lemma listrel_mono: "r \ s \ listrel r \ listrel s" apply clarify apply (erule listrel.induct) @@ -4532,6 +4684,16 @@ theorem equiv_listrel: "equiv A r \ equiv (lists A) (listrel r)" by (simp add: equiv_def listrel_refl_on listrel_sym listrel_trans) +lemma listrel_rtrancl_refl[iff]: "(xs,xs) : listrel(r^*)" +using listrel_refl_on[of UNIV, OF refl_rtrancl] +by(auto simp: refl_on_def) + +lemma listrel_rtrancl_trans: + "\ (xs,ys) : listrel(r^*); (ys,zs) : listrel(r^*) \ + \ (xs,zs) : listrel(r^*)" +by (metis listrel_trans trans_def trans_rtrancl) + + lemma listrel_Nil [simp]: "listrel r `` {[]} = {[]}" by (blast intro: listrel.intros) @@ -4539,6 +4701,74 @@ "listrel r `` {x#xs} = set_Cons (r``{x}) (listrel r `` {xs})" by (auto simp add: set_Cons_def intro: listrel.intros) +text {* Relating @{term listrel1}, @{term listrel} and closures: *} + +lemma listrel1_rtrancl_subset_rtrancl_listrel1: + "listrel1 (r^*) \ (listrel1 r)^*" +proof (rule subrelI) + fix xs ys assume 1: "(xs,ys) \ listrel1 (r^*)" + { fix x y us vs + have "(x,y) : r^* \ (us @ x # vs, us @ y # vs) : (listrel1 r)^*" + proof(induct rule: rtrancl.induct) + case rtrancl_refl show ?case by simp + next + case rtrancl_into_rtrancl thus ?case + by (metis listrel1I rtrancl.rtrancl_into_rtrancl) + qed } + thus "(xs,ys) \ (listrel1 r)^*" using 1 by(blast elim: listrel1E) +qed + +lemma rtrancl_listrel1_eq_len: "(x,y) \ (listrel1 r)^* \ length x = length y" +by (induct rule: rtrancl.induct) (auto intro: listrel1_eq_len) + +lemma rtrancl_listrel1_ConsI1: + "(xs,ys) : (listrel1 r)^* \ (x#xs,x#ys) : (listrel1 r)^*" +apply(induct rule: rtrancl.induct) + apply simp +by (metis listrel1I2 rtrancl.rtrancl_into_rtrancl) + +lemma rtrancl_listrel1_ConsI2: + "(x,y) \ r^* \ (xs, ys) \ (listrel1 r)^* + \ (x # xs, y # ys) \ (listrel1 r)^*" + by (blast intro: rtrancl_trans rtrancl_listrel1_ConsI1 + subsetD[OF listrel1_rtrancl_subset_rtrancl_listrel1 listrel1I1]) + +lemma listrel1_subset_listrel: + "r \ r' \ refl r' \ listrel1 r \ listrel(r')" +by(auto elim!: listrel1E simp add: listrel_iff_zip set_zip refl_on_def) + +lemma listrel_reflcl_if_listrel1: + "(xs,ys) : listrel1 r \ (xs,ys) : listrel(r^*)" +by(erule listrel1E)(auto simp add: listrel_iff_zip set_zip) + +lemma listrel_rtrancl_eq_rtrancl_listrel1: "listrel (r^*) = (listrel1 r)^*" +proof + { fix x y assume "(x,y) \ listrel (r^*)" + then have "(x,y) \ (listrel1 r)^*" + by induct (auto intro: rtrancl_listrel1_ConsI2) } + then show "listrel (r^*) \ (listrel1 r)^*" + by (rule subrelI) +next + show "listrel (r^*) \ (listrel1 r)^*" + proof(rule subrelI) + fix xs ys assume "(xs,ys) \ (listrel1 r)^*" + then show "(xs,ys) \ listrel (r^*)" + proof induct + case base show ?case by(auto simp add: listrel_iff_zip set_zip) + next + case (step ys zs) + thus ?case by (metis listrel_reflcl_if_listrel1 listrel_rtrancl_trans) + qed + qed +qed + +lemma rtrancl_listrel1_if_listrel: + "(xs,ys) : listrel r \ (xs,ys) : (listrel1 r)^*" +by(metis listrel_rtrancl_eq_rtrancl_listrel1 subsetD[OF listrel_mono] r_into_rtrancl subsetI) + +lemma listrel_subset_rtrancl_listrel1: "listrel r \ (listrel1 r)^*" +by(fast intro:rtrancl_listrel1_if_listrel) + subsection {* Size function *}