Theory List_Extra
section ‹ Lists: extra functions and properties ›
theory List_Extra
imports
"HOL-Library.Sublist"
"HOL-Library.Monad_Syntax"
"HOL-Library.Prefix_Order"
"Optics.Lens_Instances"
begin
subsection ‹ Useful Abbreviations ›
abbreviation " xs ≡ foldr (+) xs 0"
subsection ‹ Folds ›
context abel_semigroup
begin
lemma : "foldr (❙*) (xs @ [x]) k = (foldr (❙*) xs k) ❙* x"
by (induct xs, simp_all add: commute left_commute)
end
subsection ‹ List Lookup ›
text ‹
The following variant of the standard ‹nth› function returns ‹⊥› if the index is
out of range.
›
:: "'a list ⇒ nat ⇒ 'a option" ("_⟨_⟩⇩l" [90, 0] 91)
where
"[]⟨i⟩⇩l = None"
| "(x # xs)⟨i⟩⇩l = (case i of 0 ⇒ Some x | Suc j ⇒ xs ⟨j⟩⇩l)"
lemma [simp]: "i < length xs ⟹ (xs @ ys)⟨i⟩⇩l = xs⟨i⟩⇩l"
apply (induct xs arbitrary: i)
apply simp
apply (case_tac i)
apply simp_all
done
lemma [simp]: "length xs ≤ i ⟹ (xs @ ys)⟨i⟩⇩l = ys⟨i - length xs⟩⇩l"
apply (induct xs arbitrary: i)
apply simp
apply (case_tac i)
apply simp_all
done
subsection ‹ Extra List Theorems ›
subsubsection ‹ Map ›
lemma :
"map (nth (x # xs)) [Suc m..<n] = map (nth xs) [m..<n - 1]"
proof -
have "nth xs = nth (x # xs) ∘ Suc"
by auto
hence "map (nth xs) [m..<n - 1] = map (nth (x # xs) ∘ Suc) [m..<n - 1]"
by simp
also have "... = map (nth (x # xs)) (map Suc [m..<n - 1])"
by simp
also have "... = map (nth (x # xs)) [Suc m..<n]"
by (metis Suc_diff_1 le_0_eq length_upt list.simps(8) list.size(3) map_Suc_upt not_less upt_0)
finally show ?thesis ..
qed
subsubsection ‹ Sorted Lists ›
lemma [simp]: "⟦ x ∈ set xs; sorted xs ⟧ ⟹ x ≤ last xs"
by (induct xs, auto)
lemma :
assumes "xs ≤ ys" "sorted ys"
shows "sorted xs"
proof -
obtain zs where "ys = xs @ zs"
using Prefix_Order.prefixE assms(1) by auto
thus ?thesis
using assms(2) sorted_append by blast
qed
lemma : "⟦ sorted xs; mono f ⟧ ⟹ sorted (map f xs)"
by (simp add: monoD sorted_iff_nth_mono)
lemma [intro]: "⟦ sorted (xs); distinct(xs) ⟧ ⟹ (∀ i<length xs - 1. xs!i < xs!(i + 1))"
apply (induct xs)
apply (auto)
apply (metis (no_types, opaque_lifting) Suc_leI Suc_less_eq Suc_pred gr0_conv_Suc not_le not_less_iff_gr_or_eq nth_Cons_Suc nth_mem nth_non_equal_first_eq)
done
text ‹ Is the given list a permutation of the given set? ›
:: "('a::ord) set ⇒ 'a list ⇒ bool" where
"is_sorted_list_of_set A xs = ((∀ i<length(xs) - 1. xs!i < xs!(i + 1)) ∧ set(xs) = A)"
lemma :
assumes "is_sorted_list_of_set A xs"
shows "sorted(xs)" and "distinct(xs)"
using assms proof (induct xs arbitrary: A)
show "sorted []"
by auto
next
show "distinct []"
by auto
next
fix A :: "'a set"
case (Cons x xs) note hyps = this
assume isl: "is_sorted_list_of_set A (x # xs)"
hence srt: "(∀i<length xs - Suc 0. xs ! i < xs ! Suc i)"
using less_diff_conv by (auto simp add: is_sorted_list_of_set_def)
with hyps(1) have srtd: "sorted xs"
by (simp add: is_sorted_list_of_set_def)
with isl show "sorted (x # xs)"
apply (auto simp add: is_sorted_list_of_set_def)
apply (metis (mono_tags, lifting) all_nth_imp_all_set less_le_trans linorder_not_less not_less_iff_gr_or_eq nth_Cons_0 sorted_iff_nth_mono zero_order(3))
done
from srt hyps(2) have "distinct xs"
by (simp add: is_sorted_list_of_set_def)
then have False if "x ∈ set xs"
using distinct_Ex1 [OF _ that] isl unfolding is_sorted_list_of_set_def
by (metis add.commute add_diff_cancel_left' leD length_Cons less_le not_gr_zero nth_Cons' plus_1_eq_Suc sorted_iff_nth_mono srtd)
with isl ‹distinct xs› show "distinct (x # xs)"
by force
qed
lemma :
"is_sorted_list_of_set A xs ⟷ sorted (xs) ∧ distinct (xs) ∧ set(xs) = A"
apply (auto intro: sorted_is_sorted_list_of_set)
apply (auto simp add: is_sorted_list_of_set_def)
apply (metis Nat.add_0_right One_nat_def add_Suc_right sorted_distinct)
done
:: "('a::ord) set ⇒ 'a list" where
"sorted_list_of_set_alt A =
(if (A = {}) then [] else (THE xs. is_sorted_list_of_set A xs))"
lemma :
"finite A ⟹ is_sorted_list_of_set A (sorted_list_of_set A)"
by (simp add: is_sorted_list_of_set_alt_def)
lemma :
"finite A ⟹ sorted_list_of_set(A) = (THE xs. sorted(xs) ∧ distinct(xs) ∧ set xs = A)"
apply (rule sym)
apply (rule the_equality)
apply (auto)
apply (simp add: sorted_distinct_set_unique)
done
lemma [simp]:
"finite A ⟹ sorted_list_of_set_alt(A) = sorted_list_of_set(A)"
apply (rule sym)
apply (auto simp add: sorted_list_of_set_alt_def is_sorted_list_of_set_alt_def sorted_list_of_set_other_def)
done
text ‹ Sorting lists according to a relation ›
:: "'a rel ⇒ 'a set ⇒ 'a list ⇒ bool" where
"is_sorted_list_of_set_by R A xs = ((∀ i<length(xs) - 1. (xs!i, xs!(i + 1)) ∈ R) ∧ set(xs) = A)"
:: "'a rel ⇒ 'a set ⇒ 'a list" where
"sorted_list_of_set_by R A = (THE xs. is_sorted_list_of_set_by R A xs)"
:: "'a rel ⇒ 'a set rel" where
"fin_set_lexord R = {(A, B). finite A ∧ finite B ∧
(∃ xs ys. is_sorted_list_of_set_by R A xs ∧ is_sorted_list_of_set_by R B ys
∧ (xs, ys) ∈ lexord R)}"
lemma :
"⟦ R ⊆ S; is_sorted_list_of_set_by R A xs ⟧ ⟹ is_sorted_list_of_set_by S A xs"
by (auto simp add: is_sorted_list_of_set_by_def)
lemma :
"⟦ (⋀ x y. f x y ⟶ g x y); (xs, ys) ∈ lexord {(x, y). f x y} ⟧ ⟹ (xs, ys) ∈ lexord {(x, y). g x y}"
by (metis case_prodD case_prodI lexord_take_index_conv mem_Collect_eq)
lemma [mono]:
"(⋀ x y. f x y ⟶ g x y) ⟹ (xs, ys) ∈ fin_set_lexord {(x, y). f x y} ⟶ (xs, ys) ∈ fin_set_lexord {(x, y). g x y}"
proof
assume
fin: "(xs, ys) ∈ fin_set_lexord {(x, y). f x y}" and
hyp: "(⋀ x y. f x y ⟶ g x y)"
from fin have "finite xs" "finite ys"
using fin_set_lexord_def by fastforce+
with fin hyp show "(xs, ys) ∈ fin_set_lexord {(x, y). g x y}"
apply (auto simp add: fin_set_lexord_def)
apply (rename_tac xs' ys')
apply (rule_tac x="xs'" in exI)
apply (auto)
apply (metis case_prodD case_prodI is_sorted_list_of_set_by_def mem_Collect_eq)
apply (metis case_prodD case_prodI is_sorted_list_of_set_by_def lexord_mono' mem_Collect_eq)
done
qed
:: "'a set ⇒ 'a list set" where
"distincts A = {xs ∈ lists A. distinct(xs)}"
lemma :
"⟦ x ∈ set xs; x ≠ hd(xs) ⟧ ⟹ x ∈ set(tl(xs))"
by (metis in_set_insert insert_Nil list.collapse list.distinct(2) set_ConsD)
subsubsection ‹ List Update ›
lemma :
fixes xs :: "'a::ring list"
assumes "i < length xs"
shows "list_sum (xs[i := v]) = list_sum xs - xs ! i + v"
using assms proof (induct xs arbitrary: i)
case Nil
then show ?case by (simp)
next
case (Cons a xs)
then show ?case
proof (cases i)
case 0
thus ?thesis
by (simp add: add.commute)
next
case (Suc i')
with Cons show ?thesis
by (auto)
qed
qed
subsubsection ‹ Drop While and Take While ›
lemma :
"⟦ sorted xs; x ∈ set (dropWhile (λ x. x ≤ n) xs) ⟧ ⟹ x > n"
apply (induct xs)
apply (auto)
apply (rename_tac a xs)
apply (case_tac "a ≤ n")
apply (auto)
done
lemma :
"sorted xs ⟹ set (dropWhile (λ x. x ≤ n) xs) = {x∈set xs. x > n}"
apply (induct xs)
apply (simp)
apply (rename_tac x xs)
apply (subgoal_tac "sorted xs")
apply (simp)
apply (safe)
apply (auto)
done
lemma :
"⟦ sorted I; x ∈ set I; x < n ⟧ ⟹ x ∈ set (takeWhile (λx. x < n) I)"
proof (induct I arbitrary: x)
case Nil thus ?case
by (simp)
next
case (Cons a I) thus ?case
by auto
qed
lemma : "⟦ sorted xs; i ≥ length (takeWhile (λ x. x ≤ n) xs); i < length xs ⟧ ⟹ n ≤ xs ! i"
apply (induct xs arbitrary: i, auto)
apply (rename_tac x xs i)
apply (case_tac "x ≤ n")
apply (auto)
apply (metis One_nat_def Suc_eq_plus1 le_less_linear le_less_trans less_imp_le list.size(4) nth_mem set_ConsD)
done
lemma :
"⟦ a ∈ set xs; ¬ P a ⟧ ⟹ length (takeWhile P xs) < length xs"
by (metis in_set_conv_nth length_takeWhile_le nat_neq_iff not_less set_takeWhileD takeWhile_nth)
lemma :
"⟦ sorted xs; distinct xs; (∃ a ∈ set xs. a ≥ n) ⟧ ⟹ xs ! length (takeWhile (λx. x < n) xs) ≥ n"
by (induct xs, auto)
subsubsection ‹ Last and But Last ›
lemma :
assumes "length ys > 0"
shows "butlast (xs @ ys) = xs @ (butlast ys)"
using assms by (metis butlast_append length_greater_0_conv)
lemma :
assumes "length ys = 0"
shows "butlast (xs @ ys) = butlast xs"
using assms by (metis append_Nil2 length_0_conv)
lemma :
shows "butlast [e] = []"
by (metis butlast.simps(2))
lemma :
shows "last [e] = e"
by (metis last.simps)
lemma :
assumes "length t = 0"
shows "last (s @ t) = last s"
by (metis append_Nil2 assms length_0_conv)
lemma :
assumes "length t > 0"
shows "last (s @ t) = last t"
by (metis assms last_append length_greater_0_conv)
subsubsection ‹ Prefixes and Strict Prefixes ›
lemma :
"⟦ length xs = length ys; prefix xs ys ⟧ ⟹ xs = ys"
by (metis not_equal_is_parallel parallel_def)
lemma [elim]:
assumes "prefix (x # xs) ys"
obtains ys' where "ys = x # ys'" "prefix xs ys'"
using assms
by (metis append_Cons prefix_def)
lemma :
"⟦ inj_on f (set xs ∪ set ys); prefix (map f xs) (map f ys) ⟧ ⟹
prefix xs ys"
apply (induct xs arbitrary:ys)
apply (simp_all)
apply (erule prefix_Cons_elim)
apply (auto)
apply (metis image_insert insertI1 insert_Diff_if singletonE)
done
lemma [simp]:
"inj_on f (set xs ∪ set ys) ⟹
prefix (map f xs) (map f ys) ⟷ prefix xs ys"
using map_mono_prefix prefix_map_inj by blast
lemma [elim]:
assumes "strict_prefix (x # xs) ys"
obtains ys' where "ys = x # ys'" "strict_prefix xs ys'"
using assms
by (metis Sublist.strict_prefixE' Sublist.strict_prefixI' append_Cons)
lemma :
"⟦ inj_on f (set xs ∪ set ys); strict_prefix (map f xs) (map f ys) ⟧ ⟹
strict_prefix xs ys"
apply (induct xs arbitrary:ys)
apply auto
apply (simp flip: prefix_bot.bot_less)
apply (erule strict_prefix_Cons_elim)
apply (auto)
apply (metis image_eqI insert_Diff_single insert_iff)
done
lemma [simp]:
"inj_on f (set xs ∪ set ys) ⟹
strict_prefix (map f xs) (map f ys) ⟷ strict_prefix xs ys"
by (simp add: inj_on_map_eq_map strict_prefix_def)
lemma :
"⟦ drop (length xs) ys = zs; prefix xs ys ⟧
⟹ ys = xs @ zs"
by (metis append_eq_conv_conj prefix_def)
lemma [dest]: "x @ y ≤ z ⟹ x ≤ z"
using append_prefixD less_eq_list_def by blast
lemma :
assumes "strict_prefix xs ys" and "xs ≠ []"
shows "ys ≠ []"
using Sublist.strict_prefix_simps(1) assms(1) by blast
lemma :
assumes "strict_prefix xs ys" and "xs ≠ []"
shows "length ys > 0"
using assms prefix_not_empty by auto
lemma :
assumes "strict_prefix (butlast xs) ys"
shows "ys ≠ []"
using assms prefix_not_empty_length_gt_zero by fastforce
lemma prefix_and_concat_prefix_is_concat_prefix:
assumes "prefix s t" "prefix (e @ t) u"
shows "prefix (e @ s) u"
using Sublist.same_prefix_prefix assms(1) assms(2) prefix_order.dual_order.trans by blast
lemma :
"prefix s t ⟷ (∃xs . s @ xs = t)"
using prefix_def by auto
lemma :
"strict_prefix s t ⟷ (∃xs . s @ xs = t ∧ (length xs) > 0)"
using prefix_def strict_prefix_def by auto
lemma :
assumes "length s = length t" and "strict_prefix (butlast s) t"
shows "strict_prefix (butlast s) t ⟷ (butlast s) = (butlast t)"
by (metis append_butlast_last_id append_eq_append_conv assms(1) assms(2) length_0_conv length_butlast strict_prefix_eq_exists)
lemma butlast_eq_if_eq_length_and_prefix:
assumes "length s > 0" "length z > 0"
"length s = length z" "strict_prefix (butlast s) t" "strict_prefix (butlast z) t"
shows "(butlast s) = (butlast z)"
using assms by (auto simp add:strict_prefix_eq_exists)
lemma :
assumes "length s > 0" "strict_prefix (butlast s) t"
shows "¬ (length t < length s)"
using assms prefix_length_less by fastforce
lemma :
assumes "length s > 0" and "strict_prefix (butlast s) t"
shows "(¬ (length s < length t)) = (length s = length t)"
proof -
have "(¬ (length s < length t)) = ((length t < length s) ∨ (length s = length t))"
by (metis not_less_iff_gr_or_eq)
also have "... = (length s = length t)"
using assms
by (simp add:butlast_prefix_imp_length_not_gt)
finally show ?thesis .
qed
text ‹ Greatest common prefix ›
:: "'a list ⇒ 'a list ⇒ 'a list" where
"gcp [] ys = []" |
"gcp (x # xs) (y # ys) = (if (x = y) then x # gcp xs ys else [])" |
"gcp _ _ = []"
lemma [simp]: "gcp xs [] = []"
by (induct xs, auto)
lemma [simp]: "gcp (xs @ ys) (xs @ zs) = xs @ gcp ys zs"
by (induct xs, auto)
lemma : "prefix (gcp xs ys) xs"
apply (induct xs arbitrary: ys, auto)
apply (case_tac ys, auto)
done
lemma : "prefix (gcp xs ys) ys"
apply (induct ys arbitrary: xs, auto)
apply (case_tac xs, auto)
done
prefix_semilattice: semilattice_inf gcp prefix strict_prefix
proof
fix xs ys :: "'a list"
show "prefix (gcp xs ys) xs"
by (induct xs arbitrary: ys, auto, case_tac ys, auto)
show "prefix (gcp xs ys) ys"
by (induct ys arbitrary: xs, auto, case_tac xs, auto)
next
fix xs ys zs :: "'a list"
assume "prefix xs ys" "prefix xs zs"
thus "prefix xs (gcp ys zs)"
by (simp add: prefix_def, auto)
qed
subsubsection ‹ Lexicographic Order ›
lemma :
assumes "(xs⇩1 @ ys⇩1, xs⇩2 @ ys⇩2) ∈ lexord R" "length(xs⇩1) = length(xs⇩2)"
shows "(xs⇩1, xs⇩2) ∈ lexord R ∨ (xs⇩1 = xs⇩2 ∧ (ys⇩1, ys⇩2) ∈ lexord R)"
using assms
proof (induct xs⇩2 arbitrary: xs⇩1)
case (Cons x⇩2 xs⇩2') note hyps = this
from hyps(3) obtain x⇩1 xs⇩1' where xs⇩1: "xs⇩1 = x⇩1 # xs⇩1'" "length(xs⇩1') = length(xs⇩2')"
by (auto, metis Suc_length_conv)
with hyps(2) have xcases: "(x⇩1, x⇩2) ∈ R ∨ (xs⇩1' @ ys⇩1, xs⇩2' @ ys⇩2) ∈ lexord R"
by (auto)
show ?case
proof (cases "(x⇩1, x⇩2) ∈ R")
case True with xs⇩1 show ?thesis
by (auto)
next
case False
with xcases have "(xs⇩1' @ ys⇩1, xs⇩2' @ ys⇩2) ∈ lexord R"
by (auto)
with hyps(1) xs⇩1 have dichot: "(xs⇩1', xs⇩2') ∈ lexord R ∨ (xs⇩1' = xs⇩2' ∧ (ys⇩1, ys⇩2) ∈ lexord R)"
by (auto)
have "x⇩1 = x⇩2"
using False hyps(2) xs⇩1(1) by auto
with dichot xs⇩1 show ?thesis
by (simp)
qed
next
case Nil thus ?case
by auto
qed
lemma :
"strict_prefix xs ys ⟹ (xs, ys) ∈ lexord R"
by (metis Sublist.strict_prefixE' lexord_append_rightI)
lemma :
assumes "trans R" "(xs, ys) ∈ lexord R" "strict_prefix xs' xs"
shows "(xs', ys) ∈ lexord R"
by (metis assms lexord_trans strict_prefix_lexord_rel)
lemma :
assumes "trans R" "(xs, ys) ∈ lexord R" "strict_prefix ys ys'"
shows "(xs, ys') ∈ lexord R"
by (metis assms lexord_trans strict_prefix_lexord_rel)
lemma :
assumes "(xs, ys) ∈ lexord R" "length xs = length ys"
shows "∃ i. (xs!i, ys!i) ∈ R ∧ i < length xs ∧ (∀ j<i. xs!j = ys!j)"
using assms proof (induct xs arbitrary: ys)
case (Cons x xs) note hyps = this
then obtain y ys' where ys: "ys = y # ys'" "length ys' = length xs"
by (metis Suc_length_conv)
show ?case
proof (cases "(x, y) ∈ R")
case True with ys show ?thesis
by (rule_tac x="0" in exI, simp)
next
case False
with ys hyps(2) have xy: "x = y" "(xs, ys') ∈ lexord R"
by auto
with hyps(1,3) ys obtain i where "(xs!i, ys'!i) ∈ R" "i < length xs" "(∀ j<i. xs!j = ys'!j)"
by force
with xy ys show ?thesis
apply (rule_tac x="Suc i" in exI)
apply (auto simp add: less_Suc_eq_0_disj)
done
qed
next
case Nil thus ?case by (auto)
qed
lemma :
assumes "length xs > i" "length ys > i" "(xs!i, ys!i) ∈ R" "∀ j<i. xs!j = ys!j"
shows "(xs, ys) ∈ lexord R"
using assms proof (induct i arbitrary: xs ys)
case 0 thus ?case
by (auto, metis lexord_cons_cons list.exhaust nth_Cons_0)
next
case (Suc i) note hyps = this
then obtain x' y' xs' ys' where "xs = x' # xs'" "ys = y' # ys'"
by (metis Suc_length_conv Suc_lessE)
moreover with hyps(5) have "∀j<i. xs' ! j = ys' ! j"
by (auto)
ultimately show ?case using hyps
by (auto)
qed
subsection ‹ Distributed Concatenation ›
:: "('a ⇒ 'b ⇒ 'c) ⇒ ('a × 'b ⇒ 'c)" where
[simp]: "uncurry f = (λ(x, y). f x y)"
::
"'a list set ⇒ 'a list set ⇒ 'a list set" (infixr "⇧⌢" 100) where
"dist_concat ls1 ls2 = (uncurry (@) ` (ls1 × ls2))"
lemma [simp]:
"{} ⇧⌢ ys = {}"
by (simp add: dist_concat_def)
lemma [simp]:
"xs ⇧⌢ {} = {}"
by (simp add: dist_concat_def)
lemma [simp]:
"insert l ls1 ⇧⌢ ls2 = ((@) l ` ( ls2)) ∪ (ls1 ⇧⌢ ls2)"
by (auto simp add: dist_concat_def)
subsection ‹ List Domain and Range ›
abbreviation :: "'a list ⇒ nat set" ("dom⇩l") where
"seq_dom xs ≡ {0..<length xs}"
abbreviation :: "'a list ⇒ 'a set" ("ran⇩l") where
"seq_ran xs ≡ set xs"
subsection ‹ Extracting List Elements ›
:: "nat set ⇒ 'a list ⇒ 'a list" (infix "↿⇩l" 80) where
"seq_extract A xs = nths xs A"
lemma [simp]: "A ↿⇩l [] = []"
by (simp add: seq_extract_def)
lemma :
"A ↿⇩l (x # xs) = (if 0 ∈ A then [x] else []) @ {j. Suc j ∈ A} ↿⇩l xs"
by (simp add: seq_extract_def nths_Cons)
lemma [simp]: "{} ↿⇩l xs = []"
by (simp add: seq_extract_def)
lemma [simp]: "{0..<length xs} ↿⇩l xs = xs"
unfolding list_eq_iff_nth_eq
by (auto simp add: seq_extract_def length_nths atLeast0LessThan)
lemma :
assumes "i ≤ length xs"
shows "{0..<i} ↿⇩l xs @ {i..<length xs} ↿⇩l xs = xs"
using assms
proof (induct xs arbitrary: i)
case Nil thus ?case by (simp add: seq_extract_def)
next
case (Cons x xs) note hyp = this
have "{j. Suc j < i} = {0..<i - 1}"
by (auto)
moreover have "{j. i ≤ Suc j ∧ j < length xs} = {i - 1..<length xs}"
by (auto)
ultimately show ?case
using hyp by (force simp add: seq_extract_def nths_Cons)
qed
lemma :
"A ↿⇩l (xs @ ys) = (A ↿⇩l xs) @ ({j. j + length xs ∈ A} ↿⇩l ys)"
by (simp add: seq_extract_def nths_append)
lemma : "A ↿⇩l xs = (A ∩ dom⇩l(xs)) ↿⇩l xs"
apply (auto simp add: seq_extract_def nths_def)
apply (metis (no_types, lifting) atLeastLessThan_iff filter_cong in_set_zip nth_mem set_upt)
done
lemma :
"A ∩ dom⇩l(xs) = {} ⟹ A ↿⇩l xs = []"
by (metis seq_extract_def seq_extract_range nths_empty)
lemma [simp]:
"length (A ↿⇩l xs) = card (A ∩ dom⇩l(xs))"
proof -
have "{i. i < length(xs) ∧ i ∈ A} = (A ∩ {0..<length(xs)})"
by (auto)
thus ?thesis
by (simp add: seq_extract_def length_nths)
qed
lemma :
assumes "m < n"
shows "{m..<n} ↿⇩l (x # xs) = (if (m = 0) then x # ({0..<n-1} ↿⇩l xs) else {m-1..<n-1} ↿⇩l xs)"
proof -
have "{j. Suc j < n} = {0..<n - Suc 0}"
by (auto)
moreover have "{j. m ≤ Suc j ∧ Suc j < n} = {m - Suc 0..<n - Suc 0}"
by (auto)
ultimately show ?thesis using assms
by (auto simp add: seq_extract_Cons)
qed
lemma :
assumes "i < length xs"
shows "{i} ↿⇩l xs = [xs ! i]"
using assms
apply (induct xs arbitrary: i)
apply (auto simp add: seq_extract_Cons)
apply (rename_tac xs i)
apply (subgoal_tac "{j. Suc j = i} = {i - 1}")
apply (auto)
done
lemma :
assumes "m < n" "n ≤ length xs"
shows "{m..<n} ↿⇩l xs = map (nth xs) [m..<n]"
using assms proof (induct xs arbitrary: m n)
case Nil thus ?case by simp
next
case (Cons x xs)
have "[m..<n] = m # [m+1..<n]"
using Cons.prems(1) upt_eq_Cons_conv by blast
moreover have "map (nth (x # xs)) [Suc m..<n] = map (nth xs) [m..<n-1]"
by (simp add: map_nth_Cons_atLeastLessThan)
ultimately show ?case
using Cons upt_rec
by (auto simp add: seq_extract_Cons_atLeastLessThan)
qed
lemma :
"xs = ys @ zs ⟷ (∃ i≤length(xs). ys = {0..<i} ↿⇩l xs ∧ zs = {i..<length(xs)} ↿⇩l xs)"
proof
assume xs: "xs = ys @ zs"
moreover have "ys = {0..<length ys} ↿⇩l (ys @ zs)"
by (simp add: seq_extract_append)
moreover have "zs = {length ys..<length ys + length zs} ↿⇩l (ys @ zs)"
proof -
have "{length ys..<length ys + length zs} ∩ {0..<length ys} = {}"
by auto
moreover have s1: "{j. j < length zs} = {0..<length zs}"
by auto
ultimately show ?thesis
by (simp add: seq_extract_append seq_extract_out_of_range)
qed
ultimately show "(∃ i≤length(xs). ys = {0..<i} ↿⇩l xs ∧ zs = {i..<length(xs)} ↿⇩l xs)"
by (rule_tac x="length ys" in exI, auto)
next
assume "∃i≤length xs. ys = {0..<i} ↿⇩l xs ∧ zs = {i..<length xs} ↿⇩l xs"
thus "xs = ys @ zs"
by (auto simp add: seq_extract_split)
qed
subsection ‹ Filtering a list according to a set ›
:: "'a list ⇒ 'a set ⇒ 'a list" (infix "↾⇩l" 80) where
"seq_filter xs A = filter (λ x. x ∈ A) xs"
lemma [simp]:
"x ∈ cs ⟹ (x # xs) ↾⇩l cs = x # (xs ↾⇩l cs)"
by (simp add: seq_filter_def)
lemma [simp]:
"x ∉ cs ⟹ (x # xs) ↾⇩l cs = (xs ↾⇩l cs)"
by (simp add: seq_filter_def)
lemma [simp]: "[] ↾⇩l A = []"
by (simp add: seq_filter_def)
lemma [simp]: "xs ↾⇩l {} = []"
by (simp add: seq_filter_def)
lemma : "(xs @ ys) ↾⇩l A = (xs ↾⇩l A) @ (ys ↾⇩l A)"
by (simp add: seq_filter_def)
lemma [simp]: "xs ↾⇩l UNIV = xs"
by (simp add: seq_filter_def)
lemma [simp]: "(xs ↾⇩l A) ↾⇩l B = xs ↾⇩l (A ∩ B)"
by (simp add: seq_filter_def)
subsection ‹ Minus on lists ›
instantiation list :: (type) minus
begin
text ‹ We define list minus so that if the second list is not a prefix of the first, then an arbitrary
list longer than the combined length is produced. Thus we can always determined from the output
whether the minus is defined or not. ›
"xs - ys = (if (prefix ys xs) then drop (length ys) xs else [])"
..
end
lemma [simp]: "xs - xs = []"
by (simp add: minus_list_def)
lemma [simp]: "(xs @ ys) - xs = ys"
by (simp add: minus_list_def)
lemma [simp]: "xs - [] = xs"
by (simp add: minus_list_def)
lemma : "(s @ t) - (s @ z) = t - z"
by (simp add: minus_list_def)
lemma : "y ≤ x ⟹ length(x - y) = length(x) - length(y)"
by (simp add: less_eq_list_def minus_list_def)
lemma :
"xs ≤ ys ⟹ map f (ys - xs) = map f ys - map f xs"
by (simp add: drop_map less_eq_list_def map_mono_prefix minus_list_def)
lemma [simp]:
"[x] ≤ xs ⟹ (xs - [x]) = tl xs"
by (metis Prefix_Order.prefixE append.left_neutral append_minus list.sel(3) not_Cons_self2 tl_append2)
text ‹ Extra lemmas about @{term prefix} and @{term strict_prefix} ›
lemma :
assumes "prefix xs ys"
shows "xs @ (ys - xs) = ys"
using assms by (metis minus_list_def prefix_drop)
lemma :
assumes "prefix s t"
shows "(t - s) @ z = (t @ z) - s"
using assms by (simp add: Sublist.prefix_length_le minus_list_def)
lemma :
assumes "strict_prefix xs ys"
shows "ys - xs ≠ []"
using assms by (metis append_Nil2 prefix_concat_minus strict_prefix_def)
lemma :
assumes "prefix xs ys" and "xs ≠ ys"
shows "(ys - xs) ≠ []"
using assms by (simp add: strict_prefix_minus_not_empty)
lemma :
assumes "length s < length t" and "strict_prefix (butlast s) t" and "length s > 0"
shows "length (tl (t - (butlast s))) > 0"
using assms
by (metis Nitpick.size_list_simp(2) butlast_snoc hd_Cons_tl length_butlast length_greater_0_conv length_tl less_trans nat_neq_iff strict_prefix_minus_not_empty prefix_order.dual_order.strict_implies_order prefix_concat_minus)
lemma :
assumes "length t = length s" and "strict_prefix (butlast s) t"
shows "t - (butlast s) = [last t]"
using assms
by (metis append_butlast_last_id append_eq_append_conv butlast.simps(1) length_butlast less_numeral_extra(3) list.size(3) prefix_order.dual_order.strict_implies_order prefix_concat_minus prefix_length_less)
lemma :
assumes "length s > 0" "strict_prefix (butlast s) t" "length s < length t"
shows "last (tl (t - (butlast s))) = (last t)"
using assms by (metis last_append last_tl length_tl_list_minus_butlast_gt_zero less_numeral_extra(3) list.size(3) append_minus strict_prefix_eq_exists)
lemma :
assumes "strict_prefix (butlast s) t" and "length s > 0" and "length t > length s"
shows "tl (t - (butlast s)) ≠ []"
using assms length_tl_list_minus_butlast_gt_zero by fastforce
lemma :
assumes "strict_prefix (butlast s) t" and "length s > 0" and "length t = length s"
shows "tl (t - (butlast s)) = []"
using assms by (simp add: list_minus_butlast_eq_butlast_list)
lemma :
assumes "strict_prefix (butlast s) t" and "length s = length t"
shows "tl (t - (butlast s)) = []"
using assms by (metis list.sel(3) list_minus_butlast_eq_butlast_list)
lemma :
assumes "strict_prefix s t"
shows "length(t - s) = length(t) - length(s)"
using assms by (simp add: minus_list_def prefix_order.dual_order.strict_implies_order)
subsection ‹ Laws on @{term take}, @{term drop}, and @{term nths} ›
lemma : "m ≤ n ⟹ take m xs ≤ take n xs"
by (metis Prefix_Order.prefixI append_take_drop_id min_absorb2 take_append take_take)
lemma : "nths xs {0..m} = take (Suc m) xs"
by (metis atLeast0AtMost lessThan_Suc_atMost nths_upt_eq_take)
lemma : "nths xs {0..<m} = take m xs"
by (simp add: atLeast0LessThan)
lemma : "m ≤ n ⟹ nths xs {0..m} ≤ nths xs {0..n}"
by (simp add: nths_atLeastAtMost_0_take take_prefix)
lemma : "⟦ m ≤ n; sorted (nths xs {0..n}) ⟧ ⟹ sorted (nths xs {0..m})"
using nths_atLeastAtMost_prefix sorted_prefix by blast
lemma : "⟦ m ≤ n; sorted (nths xs {0..<n}) ⟧ ⟹ sorted (nths xs {0..<m})"
by (metis atLeast0LessThan nths_upt_eq_take sorted_prefix take_prefix)
lemma :
"k < length xs ⟹ list_augment xs k x = list_update xs k x"
by (metis list_augment_def list_augment_idem list_update_overwrite)
lemma : "k ∉ A ⟹ nths (list_update xs k x) A = nths xs A"
apply (induct xs arbitrary: k x A)
apply (auto)
apply (rename_tac a xs k x A)
apply (case_tac k)
apply (auto simp add: nths_Cons)
done
lemma : "⟦ k < length xs; k ∉ A ⟧ ⟹ nths (list_augment xs k x) A = nths xs A"
by (simp add: list_augment_as_update nths_list_update_out)
end