wenzelm@10330: (* Title: HOL/Library/List_Prefix.thy wenzelm@10330: ID: $Id$ wenzelm@10330: Author: Tobias Nipkow and Markus Wenzel, TU Muenchen wenzelm@11780: License: GPL (GNU GENERAL PUBLIC LICENSE) wenzelm@10330: *) wenzelm@10330: wenzelm@10330: header {* wenzelm@10330: \title{List prefixes} wenzelm@10330: \author{Tobias Nipkow and Markus Wenzel} wenzelm@10330: *} wenzelm@10330: wenzelm@10330: theory List_Prefix = Main: wenzelm@10330: wenzelm@10330: subsection {* Prefix order on lists *} wenzelm@10330: wenzelm@10330: instance list :: ("term") ord .. wenzelm@10330: wenzelm@10330: defs (overloaded) wenzelm@10389: prefix_def: "xs \ ys == \zs. ys = xs @ zs" wenzelm@10389: strict_prefix_def: "xs < ys == xs \ ys \ xs \ (ys::'a list)" wenzelm@10330: wenzelm@10330: instance list :: ("term") order wenzelm@10389: by intro_classes (auto simp add: prefix_def strict_prefix_def) wenzelm@10330: wenzelm@10389: lemma prefixI [intro?]: "ys = xs @ zs ==> xs \ ys" wenzelm@10389: by (unfold prefix_def) blast wenzelm@10330: wenzelm@10389: lemma prefixE [elim?]: "xs \ ys ==> (!!zs. ys = xs @ zs ==> C) ==> C" wenzelm@10389: by (unfold prefix_def) blast wenzelm@10330: wenzelm@10870: lemma strict_prefixI' [intro?]: "ys = xs @ z # zs ==> xs < ys" wenzelm@10870: by (unfold strict_prefix_def prefix_def) blast wenzelm@10870: wenzelm@10870: lemma strict_prefixE' [elim?]: wenzelm@10870: "xs < ys ==> (!!z zs. ys = xs @ z # zs ==> C) ==> C" wenzelm@10870: proof - wenzelm@10870: assume r: "!!z zs. ys = xs @ z # zs ==> C" wenzelm@10870: assume "xs < ys" wenzelm@10870: then obtain us where "ys = xs @ us" and "xs \ ys" wenzelm@10870: by (unfold strict_prefix_def prefix_def) blast wenzelm@10870: with r show ?thesis by (auto simp add: neq_Nil_conv) wenzelm@10870: qed wenzelm@10870: wenzelm@10389: lemma strict_prefixI [intro?]: "xs \ ys ==> xs \ ys ==> xs < (ys::'a list)" wenzelm@10389: by (unfold strict_prefix_def) blast wenzelm@10330: wenzelm@10389: lemma strict_prefixE [elim?]: wenzelm@10389: "xs < ys ==> (xs \ ys ==> xs \ (ys::'a list) ==> C) ==> C" wenzelm@10389: by (unfold strict_prefix_def) blast wenzelm@10330: wenzelm@10330: wenzelm@10389: subsection {* Basic properties of prefixes *} wenzelm@10330: wenzelm@10330: theorem Nil_prefix [iff]: "[] \ xs" wenzelm@10389: by (simp add: prefix_def) wenzelm@10330: wenzelm@10330: theorem prefix_Nil [simp]: "(xs \ []) = (xs = [])" wenzelm@10389: by (induct xs) (simp_all add: prefix_def) wenzelm@10330: wenzelm@10330: lemma prefix_snoc [simp]: "(xs \ ys @ [y]) = (xs = ys @ [y] \ xs \ ys)" wenzelm@10389: proof wenzelm@10389: assume "xs \ ys @ [y]" wenzelm@10389: then obtain zs where zs: "ys @ [y] = xs @ zs" .. wenzelm@10389: show "xs = ys @ [y] \ xs \ ys" wenzelm@10389: proof (cases zs rule: rev_cases) wenzelm@10389: assume "zs = []" wenzelm@10389: with zs have "xs = ys @ [y]" by simp wenzelm@10389: thus ?thesis .. wenzelm@10389: next wenzelm@10389: fix z zs' assume "zs = zs' @ [z]" wenzelm@10389: with zs have "ys = xs @ zs'" by simp wenzelm@10389: hence "xs \ ys" .. wenzelm@10389: thus ?thesis .. wenzelm@10389: qed wenzelm@10389: next wenzelm@10389: assume "xs = ys @ [y] \ xs \ ys" wenzelm@10389: thus "xs \ ys @ [y]" wenzelm@10389: proof wenzelm@10389: assume "xs = ys @ [y]" wenzelm@10389: thus ?thesis by simp wenzelm@10389: next wenzelm@10389: assume "xs \ ys" wenzelm@10389: then obtain zs where "ys = xs @ zs" .. wenzelm@10389: hence "ys @ [y] = xs @ (zs @ [y])" by simp wenzelm@10389: thus ?thesis .. wenzelm@10389: qed wenzelm@10389: qed wenzelm@10330: wenzelm@10330: lemma Cons_prefix_Cons [simp]: "(x # xs \ y # ys) = (x = y \ xs \ ys)" wenzelm@10389: by (auto simp add: prefix_def) wenzelm@10330: wenzelm@10330: lemma same_prefix_prefix [simp]: "(xs @ ys \ xs @ zs) = (ys \ zs)" wenzelm@10389: by (induct xs) simp_all wenzelm@10330: wenzelm@10389: lemma same_prefix_nil [iff]: "(xs @ ys \ xs) = (ys = [])" wenzelm@10389: proof - wenzelm@10389: have "(xs @ ys \ xs @ []) = (ys \ [])" by (rule same_prefix_prefix) wenzelm@10389: thus ?thesis by simp wenzelm@10389: qed wenzelm@10330: wenzelm@10330: lemma prefix_prefix [simp]: "xs \ ys ==> xs \ ys @ zs" wenzelm@10389: proof - wenzelm@10389: assume "xs \ ys" wenzelm@10389: then obtain us where "ys = xs @ us" .. wenzelm@10389: hence "ys @ zs = xs @ (us @ zs)" by simp wenzelm@10389: thus ?thesis .. wenzelm@10389: qed wenzelm@10330: wenzelm@10330: theorem prefix_Cons: "(xs \ y # ys) = (xs = [] \ (\zs. xs = y # zs \ zs \ ys))" wenzelm@10389: by (cases xs) (auto simp add: prefix_def) wenzelm@10330: wenzelm@10330: theorem prefix_append: wenzelm@10330: "(xs \ ys @ zs) = (xs \ ys \ (\us. xs = ys @ us \ us \ zs))" wenzelm@10330: apply (induct zs rule: rev_induct) wenzelm@10330: apply force wenzelm@10330: apply (simp del: append_assoc add: append_assoc [symmetric]) wenzelm@10330: apply simp wenzelm@10330: apply blast wenzelm@10330: done wenzelm@10330: wenzelm@10330: lemma append_one_prefix: wenzelm@10330: "xs \ ys ==> length xs < length ys ==> xs @ [ys ! length xs] \ ys" wenzelm@10330: apply (unfold prefix_def) wenzelm@10330: apply (auto simp add: nth_append) wenzelm@10389: apply (case_tac zs) wenzelm@10330: apply auto wenzelm@10330: done wenzelm@10330: wenzelm@10330: theorem prefix_length_le: "xs \ ys ==> length xs \ length ys" wenzelm@10389: by (auto simp add: prefix_def) wenzelm@10330: wenzelm@10330: wenzelm@10389: subsection {* Parallel lists *} wenzelm@10389: wenzelm@10389: constdefs wenzelm@10389: parallel :: "'a list => 'a list => bool" (infixl "\" 50) wenzelm@10389: "xs \ ys == \ xs \ ys \ \ ys \ xs" wenzelm@10389: wenzelm@10389: lemma parallelI [intro]: "\ xs \ ys ==> \ ys \ xs ==> xs \ ys" wenzelm@10389: by (unfold parallel_def) blast wenzelm@10330: wenzelm@10389: lemma parallelE [elim]: wenzelm@10389: "xs \ ys ==> (\ xs \ ys ==> \ ys \ xs ==> C) ==> C" wenzelm@10389: by (unfold parallel_def) blast wenzelm@10330: wenzelm@10389: theorem prefix_cases: wenzelm@10389: "(xs \ ys ==> C) ==> wenzelm@10512: (ys < xs ==> C) ==> wenzelm@10389: (xs \ ys ==> C) ==> C" wenzelm@10512: by (unfold parallel_def strict_prefix_def) blast wenzelm@10330: wenzelm@10389: theorem parallel_decomp: wenzelm@10389: "xs \ ys ==> \as b bs c cs. b \ c \ xs = as @ b # bs \ ys = as @ c # cs" wenzelm@10408: (is "PROP ?P xs" concl is "?E xs") wenzelm@10408: proof (induct xs rule: rev_induct) wenzelm@10408: assume "[] \ ys" hence False by auto wenzelm@10408: thus "?E []" .. wenzelm@10408: next wenzelm@10408: fix x xs wenzelm@10408: assume hyp: "PROP ?P xs" wenzelm@10408: assume asm: "xs @ [x] \ ys" wenzelm@10408: show "?E (xs @ [x])" wenzelm@10408: proof (rule prefix_cases) wenzelm@10408: assume le: "xs \ ys" wenzelm@10408: then obtain ys' where ys: "ys = xs @ ys'" .. wenzelm@10408: show ?thesis wenzelm@10408: proof (cases ys') wenzelm@10408: assume "ys' = []" with ys have "xs = ys" by simp wenzelm@10408: with asm have "[x] \ []" by auto wenzelm@10408: hence False by blast wenzelm@10389: thus ?thesis .. wenzelm@10389: next wenzelm@10408: fix c cs assume ys': "ys' = c # cs" wenzelm@10408: with asm ys have "xs @ [x] \ xs @ c # cs" by (simp only:) wenzelm@10408: hence "x \ c" by auto wenzelm@10408: moreover have "xs @ [x] = xs @ x # []" by simp wenzelm@10408: moreover from ys ys' have "ys = xs @ c # cs" by (simp only:) wenzelm@10408: ultimately show ?thesis by blast wenzelm@10389: qed wenzelm@10408: next wenzelm@10512: assume "ys < xs" hence "ys \ xs @ [x]" by (simp add: strict_prefix_def) wenzelm@10408: with asm have False by blast wenzelm@10408: thus ?thesis .. wenzelm@10408: next wenzelm@10408: assume "xs \ ys" wenzelm@10408: with hyp obtain as b bs c cs where neq: "(b::'a) \ c" wenzelm@10408: and xs: "xs = as @ b # bs" and ys: "ys = as @ c # cs" wenzelm@10408: by blast wenzelm@10408: from xs have "xs @ [x] = as @ b # (bs @ [x])" by simp wenzelm@10408: with neq ys show ?thesis by blast wenzelm@10389: qed wenzelm@10389: qed wenzelm@10330: wenzelm@10330: end