# HG changeset patch # User nipkow # Date 1288281265 -7200 # Node ID 997d6fb439a9e5a9ae82f6ace3317fa04c367c9a # Parent e00a2edd1dc6183d3ae1d5edd24955c57c4027bb# Parent be5c622e1de2152dbe4844aa48cf1bb793c92b84 merged diff -r e00a2edd1dc6 -r 997d6fb439a9 src/HOL/List.thy --- a/src/HOL/List.thy Thu Oct 28 17:25:46 2010 +0200 +++ b/src/HOL/List.thy Thu Oct 28 17:54:25 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 *}