
haftmann@26735: (*  Title:      HOL/Library/Sublist_Order.thy
haftmann@26735:     Authors:    Peter Lammich, Uni Muenster <peter.lammich@uni-muenster.de>
nipkow@33431:                 Florian Haftmann, Tobias Nipkow, TU Muenchen
haftmann@26735: *)
haftmann@26735: 
haftmann@26735: header {* Sublist Ordering *}
haftmann@26735: 
haftmann@26735: theory Sublist_Order
Christian@49084: imports Main Sublist
haftmann@26735: begin
haftmann@26735: 
haftmann@26735: text {*
haftmann@26735:   This theory defines sublist ordering on lists.
haftmann@26735:   A list @{text ys} is a sublist of a list @{text xs},
haftmann@26735:   iff one obtains @{text ys} by erasing some elements from @{text xs}.
haftmann@26735: *}
haftmann@26735: 
haftmann@26735: subsection {* Definitions and basic lemmas *}
haftmann@26735: 
nipkow@33431: instantiation list :: (type) ord
haftmann@26735: begin
haftmann@26735: 
Christian@49084: definition
Christian@49084:   "(xs :: 'a list) \<le> ys \<longleftrightarrow> emb (op =) xs ys"
haftmann@26735: 
haftmann@26735: definition
Christian@49084:   "(xs :: 'a list) < ys \<longleftrightarrow> xs \<le> ys \<and> \<not> ys \<le> xs"
haftmann@26735: 
nipkow@33431: instance proof qed
nipkow@33431: 
nipkow@33431: end
nipkow@33431: 
Christian@49084: lemma empty [simp, intro!]: "[] \<le> xs" by (auto simp: less_eq_list_def)
Christian@49084: 
Christian@49084: lemma drop: "xs \<le> ys \<Longrightarrow> xs \<le> (y # ys)"
Christian@49084:   by (unfold less_eq_list_def) blast
Christian@49084: 
Christian@49084: lemma take: "xs \<le> ys \<Longrightarrow> (x#xs) \<le> (x#ys)"
Christian@49084:   by (unfold less_eq_list_def) blast
Christian@49084: 
Christian@49084: lemmas le_list_induct [consumes 1, case_names empty drop take] =
Christian@49084:   emb.induct [of "op =", folded less_eq_list_def]
Christian@49084: 
Christian@49084: lemmas le_list_cases [consumes 1, case_names empty drop take] =
Christian@49084:   emb.cases [of "op =", folded less_eq_list_def]
Christian@49084: 
nipkow@33431: lemma le_list_length: "xs \<le> ys \<Longrightarrow> length xs \<le> length ys"
Christian@49084:   by (induct rule: le_list_induct) auto
nipkow@33431: 
nipkow@33431: lemma le_list_same_length: "xs \<le> ys \<Longrightarrow> length xs = length ys \<Longrightarrow> xs = ys"
Christian@49084:   by (induct rule: le_list_induct) (auto dest: le_list_length)
nipkow@33431: 
nipkow@33431: lemma not_le_list_length[simp]: "length ys < length xs \<Longrightarrow> ~ xs <= ys"
nipkow@33431: by (metis le_list_length linorder_not_less)
nipkow@33431: 
nipkow@33431: lemma le_list_below_empty [simp]: "xs \<le> [] \<longleftrightarrow> xs = []"
nipkow@33431: by (auto dest: le_list_length)
nipkow@33431: 
nipkow@33431: lemma le_list_drop_many: "xs \<le> ys \<Longrightarrow> xs \<le> zs @ ys"
Christian@49084: by (induct zs) (auto simp: less_eq_list_def)
nipkow@33431: 
nipkow@33431: lemma [code]: "[] <= xs \<longleftrightarrow> True"
Christian@49084: by (simp add: less_eq_list_def)
nipkow@33431: 
nipkow@33431: lemma [code]: "(x#xs) <= [] \<longleftrightarrow> False"
nipkow@33431: by simp
nipkow@33431: 
nipkow@33431: lemma le_list_drop_Cons: assumes "x#xs <= ys" shows "xs <= ys"
nipkow@33431: proof-
nipkow@33431:   { fix xs' ys'
nipkow@33431:     assume "xs' <= ys"
nipkow@33431:     hence "ALL x xs. xs' = x#xs \<longrightarrow> xs <= ys"
Christian@49084:     proof (induct rule: le_list_induct)
nipkow@33431:       case empty thus ?case by simp
nipkow@33431:     next
Christian@49084:       note drop' = drop
Christian@49084:       case drop thus ?case by (metis drop')
nipkow@33431:     next
Christian@49084:       note t = take
nipkow@33431:       case take thus ?case by (simp add: drop)
nipkow@33431:     qed }
nipkow@33431:   from this[OF assms] show ?thesis by simp
nipkow@33431: qed
nipkow@33431: 
nipkow@33431: lemma le_list_drop_Cons2:
nipkow@33431: assumes "x#xs <= x#ys" shows "xs <= ys"
nipkow@33431: using assms
Christian@49084: proof (cases rule: le_list_cases)
nipkow@33431:   case drop thus ?thesis by (metis le_list_drop_Cons list.inject)
nipkow@33431: qed simp_all
nipkow@33431: 
nipkow@33431: lemma le_list_drop_Cons_neq: assumes "x # xs <= y # ys"
nipkow@33431: shows "x ~= y \<Longrightarrow> x # xs <= ys"
Christian@49084: using assms by (cases rule: le_list_cases) auto
nipkow@33431: 
nipkow@33431: lemma le_list_Cons2_iff[simp,code]: "(x#xs) <= (y#ys) \<longleftrightarrow>
nipkow@33431:   (if x=y then xs <= ys else (x#xs) <= ys)"
nipkow@33431: by (metis drop take le_list_drop_Cons2 le_list_drop_Cons_neq)
nipkow@33431: 
nipkow@33431: lemma le_list_take_many_iff: "zs @ xs \<le> zs @ ys \<longleftrightarrow> xs \<le> ys"
nipkow@33431: by (induct zs) (auto intro: take)
nipkow@33431: 
nipkow@33431: lemma le_list_Cons_EX:
nipkow@33431:   assumes "x # ys <= zs" shows "EX us vs. zs = us @ x # vs & ys <= vs"
nipkow@33431: proof-
nipkow@33431:   { fix xys zs :: "'a list" assume "xys <= zs"
nipkow@33431:     hence "ALL x ys. xys = x#ys \<longrightarrow> (EX us vs. zs = us @ x # vs & ys <= vs)"
Christian@49084:     proof (induct rule: le_list_induct)
nipkow@33431:       case empty show ?case by simp
nipkow@33431:     next
nipkow@33431:       case take thus ?case by (metis list.inject self_append_conv2)
nipkow@33431:     next
nipkow@33431:       case drop thus ?case by (metis append_eq_Cons_conv)
nipkow@33431:     qed
nipkow@33431:   } with assms show ?thesis by blast
nipkow@33431: qed
nipkow@33431: 
nipkow@33431: instantiation list :: (type) order
nipkow@33431: begin
haftmann@26735: 
haftmann@26735: instance proof
haftmann@26735:   fix xs ys :: "'a list"
haftmann@27682:   show "xs < ys \<longleftrightarrow> xs \<le> ys \<and> \<not> ys \<le> xs" unfolding less_list_def .. 
haftmann@26735: next
haftmann@26735:   fix xs :: "'a list"
Christian@49084:   show "xs \<le> xs" by (induct xs) (auto intro!: drop)
haftmann@26735: next
haftmann@26735:   fix xs ys :: "'a list"
nipkow@33431:   assume "xs <= ys"
nipkow@33431:   hence "ys <= xs \<longrightarrow> xs = ys"
Christian@49084:   proof (induct rule: le_list_induct)
nipkow@33431:     case empty show ?case by simp
nipkow@33431:   next
nipkow@33431:     case take thus ?case by simp
nipkow@33431:   next
nipkow@33431:     case drop thus ?case
nipkow@33431:       by(metis le_list_drop_Cons le_list_length Suc_length_conv Suc_n_not_le_n)
nipkow@33431:   qed
nipkow@33431:   moreover assume "ys <= xs"
haftmann@26735:   ultimately show "xs = ys" by blast
haftmann@26735: next
haftmann@26735:   fix xs ys zs :: "'a list"
nipkow@33431:   assume "xs <= ys"
nipkow@33431:   hence "ys <= zs \<longrightarrow> xs <= zs"
Christian@49084:   proof (induct arbitrary:zs rule: le_list_induct)
nipkow@33431:     case empty show ?case by simp
nipkow@33431:   next
Christian@49084:     note take' = take
Christian@49084:     case (take x y xs ys) show ?case
nipkow@33431:     proof
Christian@49084:       assume "y # ys <= zs"
nipkow@33431:       with take show "x # xs <= zs"
Christian@49084:         by(metis le_list_Cons_EX le_list_drop_many take')
haftmann@26735:     qed
nipkow@33431:   next
nipkow@33431:     case drop thus ?case by (metis le_list_drop_Cons)
nipkow@33431:   qed
nipkow@33431:   moreover assume "ys <= zs"
nipkow@33431:   ultimately show "xs <= zs" by blast
haftmann@26735: qed
haftmann@26735: 
haftmann@26735: end
haftmann@26735: 
nipkow@33431: lemma le_list_append_le_same_iff: "xs @ ys <= ys \<longleftrightarrow> xs=[]"
nipkow@33431: by (auto dest: le_list_length)
haftmann@26735: 
nipkow@33431: lemma le_list_append_mono: "\<lbrakk> xs <= xs'; ys <= ys' \<rbrakk> \<Longrightarrow> xs@ys <= xs'@ys'"
Christian@49084: apply (induct rule: le_list_induct)
nipkow@33431:   apply (metis eq_Nil_appendI le_list_drop_many)
nipkow@33431:  apply (metis Cons_eq_append_conv le_list_drop_Cons order_eq_refl order_trans)
nipkow@33431: apply simp
nipkow@33431: done
haftmann@26735: 
nipkow@33431: lemma less_list_length: "xs < ys \<Longrightarrow> length xs < length ys"
nipkow@33431: by (metis le_list_length le_list_same_length le_neq_implies_less less_list_def)
haftmann@26735: 
nipkow@33431: lemma less_list_empty [simp]: "[] < xs \<longleftrightarrow> xs \<noteq> []"
nipkow@33431: by (metis empty order_less_le)
nipkow@33431: 
nipkow@33431: lemma less_list_below_empty[simp]: "xs < [] \<longleftrightarrow> False"
nipkow@33431: by (metis empty less_list_def)
nipkow@33431: 
nipkow@33431: lemma less_list_drop: "xs < ys \<Longrightarrow> xs < x # ys"
Christian@49084: by (unfold less_le) (auto intro: drop)
haftmann@26735: 
nipkow@33431: lemma less_list_take_iff: "x # xs < x # ys \<longleftrightarrow> xs < ys"
nipkow@33431: by (metis le_list_Cons2_iff less_list_def)
nipkow@33431: 
nipkow@33431: lemma less_list_drop_many: "xs < ys \<Longrightarrow> xs < zs @ ys"
nipkow@33431: by(metis le_list_append_le_same_iff le_list_drop_many order_less_le self_append_conv2)
nipkow@33431: 
nipkow@33431: lemma less_list_take_many_iff: "zs @ xs < zs @ ys \<longleftrightarrow> xs < ys"
nipkow@33431: by (metis le_list_take_many_iff less_list_def)
haftmann@26735: 
haftmann@26735: 
haftmann@26735: subsection {* Appending elements *}
haftmann@26735: 
nipkow@33431: lemma le_list_rev_take_iff[simp]: "xs @ zs \<le> ys @ zs \<longleftrightarrow> xs \<le> ys" (is "?L = ?R")
nipkow@33431: proof
nipkow@33431:   { fix xs' ys' xs ys zs :: "'a list" assume "xs' <= ys'"
nipkow@33431:     hence "xs' = xs @ zs & ys' = ys @ zs \<longrightarrow> xs <= ys"
Christian@49084:     proof (induct arbitrary: xs ys zs rule: le_list_induct)
nipkow@33431:       case empty show ?case by simp
nipkow@33431:     next
Christian@49084:       note drop' = drop
nipkow@33431:       case (drop xs' ys' x)
nipkow@33431:       { assume "ys=[]" hence ?case using drop(1) by auto }
nipkow@33431:       moreover
nipkow@33431:       { fix us assume "ys = x#us"
Christian@49084:         hence ?case using drop(2) by(simp add: drop') }
nipkow@33431:       ultimately show ?case by (auto simp:Cons_eq_append_conv)
nipkow@33431:     next
Christian@49084:       case (take x y xs' ys')
nipkow@33431:       { assume "xs=[]" hence ?case using take(1) by auto }
nipkow@33431:       moreover
Christian@49084:       { fix us vs assume "xs=x#us" "ys=x#vs" hence ?case using take by auto}
nipkow@33431:       moreover
nipkow@33431:       { fix us assume "xs=x#us" "ys=[]" hence ?case using take(2) by bestsimp }
Christian@49084:       ultimately show ?case using `x = y` by (auto simp:Cons_eq_append_conv)
nipkow@33431:     qed }
nipkow@33431:   moreover assume ?L
nipkow@33431:   ultimately show ?R by blast
nipkow@33431: next
nipkow@33431:   assume ?R thus ?L by(metis le_list_append_mono order_refl)
nipkow@33431: qed
nipkow@33431: 
nipkow@33431: lemma less_list_rev_take: "xs @ zs < ys @ zs \<longleftrightarrow> xs < ys"
nipkow@33431: by (unfold less_le) auto
nipkow@33431: 
nipkow@33431: lemma le_list_rev_drop_many: "xs \<le> ys \<Longrightarrow> xs \<le> ys @ zs"
nipkow@33431: by (metis append_Nil2 empty le_list_append_mono)
haftmann@26735: 
haftmann@26735: 
haftmann@26735: subsection {* Relation to standard list operations *}
haftmann@26735: 
nipkow@33431: lemma le_list_map: "xs \<le> ys \<Longrightarrow> map f xs \<le> map f ys"
Christian@49084: by (induct rule: le_list_induct) (auto intro: drop)
nipkow@33431: 
nipkow@33431: lemma le_list_filter_left[simp]: "filter f xs \<le> xs"
Christian@49084: by (induct xs) (auto intro: drop)
nipkow@33431: 
nipkow@33431: lemma le_list_filter: "xs \<le> ys \<Longrightarrow> filter f xs \<le> filter f ys"
Christian@49084: by (induct rule: le_list_induct) (auto intro: drop)
nipkow@33431: 
haftmann@33499: lemma "xs \<le> ys \<longleftrightarrow> (EX N. xs = sublist ys N)" (is "?L = ?R")
nipkow@33431: proof
nipkow@33431:   assume ?L
nipkow@33431:   thus ?R
Christian@49084:   proof (induct rule: le_list_induct)
nipkow@33431:     case empty show ?case by (metis sublist_empty)
nipkow@33431:   next
nipkow@33431:     case (drop xs ys x)
nipkow@33431:     then obtain N where "xs = sublist ys N" by blast
nipkow@33431:     hence "xs = sublist (x#ys) (Suc ` N)"
nipkow@33431:       by (clarsimp simp add:sublist_Cons inj_image_mem_iff)
nipkow@33431:     thus ?case by blast
nipkow@33431:   next
Christian@49084:     case (take x y xs ys)
nipkow@33431:     then obtain N where "xs = sublist ys N" by blast
nipkow@33431:     hence "x#xs = sublist (x#ys) (insert 0 (Suc ` N))"
nipkow@33431:       by (clarsimp simp add:sublist_Cons inj_image_mem_iff)
Christian@49084:     thus ?case unfolding `x = y` by blast
nipkow@33431:   qed
nipkow@33431: next
nipkow@33431:   assume ?R
nipkow@33431:   then obtain N where "xs = sublist ys N" ..
nipkow@33431:   moreover have "sublist ys N <= ys"
nipkow@33431:   proof (induct ys arbitrary:N)
nipkow@33431:     case Nil show ?case by simp
nipkow@33431:   next
nipkow@33431:     case Cons thus ?case by (auto simp add:sublist_Cons drop)
nipkow@33431:   qed
nipkow@33431:   ultimately show ?L by simp
nipkow@33431: qed
haftmann@26735: 
haftmann@26735: end




