src/HOL/List.thy
changeset 68249 949d93804740
parent 68215 a477f78a9365
child 68325 57e4bd1e2e18
equal deleted inserted replaced
68248:ef1e0cb80fde 68249:949d93804740
    76 
    76 
    77 primrec filter:: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    77 primrec filter:: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    78 "filter P [] = []" |
    78 "filter P [] = []" |
    79 "filter P (x # xs) = (if P x then x # filter P xs else filter P xs)"
    79 "filter P (x # xs) = (if P x then x # filter P xs else filter P xs)"
    80 
    80 
    81 text \<open>Special syntax for filter:\<close>
    81 text \<open>Special input syntax for filter:\<close>
    82 syntax (ASCII)
    82 syntax (ASCII)
    83   "_filter" :: "[pttrn, 'a list, bool] => 'a list"  ("(1[_<-_./ _])")
    83   "_filter" :: "[pttrn, 'a list, bool] => 'a list"  ("(1[_<-_./ _])")
    84 syntax
    84 syntax
    85   "_filter" :: "[pttrn, 'a list, bool] => 'a list"  ("(1[_\<leftarrow>_ ./ _])")
    85   "_filter" :: "[pttrn, 'a list, bool] => 'a list"  ("(1[_\<leftarrow>_ ./ _])")
    86 translations
    86 translations
    87   "[x<-xs . P]" \<rightleftharpoons> "CONST filter (\<lambda>x. P) xs"
    87   "[x<-xs . P]" \<rightharpoonup> "CONST filter (\<lambda>x. P) xs"
    88 
    88 
    89 primrec fold :: "('a \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> 'a list \<Rightarrow> 'b \<Rightarrow> 'b" where
    89 primrec fold :: "('a \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> 'a list \<Rightarrow> 'b \<Rightarrow> 'b" where
    90 fold_Nil:  "fold f [] = id" |
    90 fold_Nil:  "fold f [] = id" |
    91 fold_Cons: "fold f (x # xs) = fold f xs \<circ> f x"
    91 fold_Cons: "fold f (x # xs) = fold f xs \<circ> f x"
    92 
    92 
  1596   (\<exists>us vs. ys = us @ x # vs \<and> (\<forall>u\<in>set us. \<not> P u) \<and> P x \<and> xs = filter P vs)"
  1596   (\<exists>us vs. ys = us @ x # vs \<and> (\<forall>u\<in>set us. \<not> P u) \<and> P x \<and> xs = filter P vs)"
  1597 by(auto dest:Cons_eq_filterD)
  1597 by(auto dest:Cons_eq_filterD)
  1598 
  1598 
  1599 lemma inj_on_filter_key_eq:
  1599 lemma inj_on_filter_key_eq:
  1600   assumes "inj_on f (insert y (set xs))"
  1600   assumes "inj_on f (insert y (set xs))"
  1601   shows "[x\<leftarrow>xs . f y = f x] = filter (HOL.eq y) xs"
  1601   shows "filter (\<lambda>x. f y = f x) xs = filter (HOL.eq y) xs"
  1602   using assms by (induct xs) auto
  1602   using assms by (induct xs) auto
  1603 
  1603 
  1604 lemma filter_cong[fundef_cong]:
  1604 lemma filter_cong[fundef_cong]:
  1605   "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> P x = Q x) \<Longrightarrow> filter P xs = filter Q ys"
  1605   "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> P x = Q x) \<Longrightarrow> filter P xs = filter Q ys"
  1606 apply simp
  1606 apply simp
  4428  apply simp
  4428  apply simp
  4429 apply simp
  4429 apply simp
  4430 done
  4430 done
  4431 
  4431 
  4432 lemma nths_shift_lemma:
  4432 lemma nths_shift_lemma:
  4433   "map fst [p<-zip xs [i..<i + length xs] . snd p \<in> A] =
  4433   "map fst (filter (\<lambda>p. snd p \<in> A) (zip xs [i..<i + length xs])) =
  4434    map fst [p<-zip xs [0..<length xs] . snd p + i \<in> A]"
  4434    map fst (filter (\<lambda>p. snd p + i \<in> A) (zip xs [0..<length xs]))"
  4435 by (induct xs rule: rev_induct) (simp_all add: add.commute)
  4435 by (induct xs rule: rev_induct) (simp_all add: add.commute)
  4436 
  4436 
  4437 lemma nths_append:
  4437 lemma nths_append:
  4438   "nths (l @ l') A = nths l A @ nths l' {j. j + length l \<in> A}"
  4438   "nths (l @ l') A = nths l A @ nths l' {j. j + length l \<in> A}"
  4439 apply (unfold nths_def)
  4439 apply (unfold nths_def)
  4718   (x # [h. (h#t) \<leftarrow> xss]) # transpose (xs # [t. (h#t) \<leftarrow> xss])"
  4718   (x # [h. (h#t) \<leftarrow> xss]) # transpose (xs # [t. (h#t) \<leftarrow> xss])"
  4719 by pat_completeness auto
  4719 by pat_completeness auto
  4720 
  4720 
  4721 lemma transpose_aux_filter_head:
  4721 lemma transpose_aux_filter_head:
  4722   "concat (map (case_list [] (\<lambda>h t. [h])) xss) =
  4722   "concat (map (case_list [] (\<lambda>h t. [h])) xss) =
  4723   map (\<lambda>xs. hd xs) [ys\<leftarrow>xss . ys \<noteq> []]"
  4723   map (\<lambda>xs. hd xs) (filter (\<lambda>ys. ys \<noteq> []) xss)"
  4724   by (induct xss) (auto split: list.split)
  4724   by (induct xss) (auto split: list.split)
  4725 
  4725 
  4726 lemma transpose_aux_filter_tail:
  4726 lemma transpose_aux_filter_tail:
  4727   "concat (map (case_list [] (\<lambda>h t. [t])) xss) =
  4727   "concat (map (case_list [] (\<lambda>h t. [t])) xss) =
  4728   map (\<lambda>xs. tl xs) [ys\<leftarrow>xss . ys \<noteq> []]"
  4728   map (\<lambda>xs. tl xs) (filter (\<lambda>ys. ys \<noteq> []) xss)"
  4729   by (induct xss) (auto split: list.split)
  4729   by (induct xss) (auto split: list.split)
  4730 
  4730 
  4731 lemma transpose_aux_max:
  4731 lemma transpose_aux_max:
  4732   "max (Suc (length xs)) (foldr (\<lambda>xs. max (length xs)) xss 0) =
  4732   "max (Suc (length xs)) (foldr (\<lambda>xs. max (length xs)) xss 0) =
  4733   Suc (max (length xs) (foldr (\<lambda>x. max (length x - Suc 0)) [ys\<leftarrow>xss . ys\<noteq>[]] 0))"
  4733   Suc (max (length xs) (foldr (\<lambda>x. max (length x - Suc 0)) (filter (\<lambda>ys. ys \<noteq> []) xss) 0))"
  4734   (is "max _ ?foldB = Suc (max _ ?foldA)")
  4734   (is "max _ ?foldB = Suc (max _ ?foldA)")
  4735 proof (cases "[ys\<leftarrow>xss . ys\<noteq>[]] = []")
  4735 proof (cases "(filter (\<lambda>ys. ys \<noteq> []) xss) = []")
  4736   case True
  4736   case True
  4737   hence "foldr (\<lambda>xs. max (length xs)) xss 0 = 0"
  4737   hence "foldr (\<lambda>xs. max (length xs)) xss 0 = 0"
  4738   proof (induct xss)
  4738   proof (induct xss)
  4739     case (Cons x xs)
  4739     case (Cons x xs)
  4740     then have "x = []" by (cases x) auto
  4740     then have "x = []" by (cases x) auto
  4742   qed simp
  4742   qed simp
  4743   thus ?thesis using True by simp
  4743   thus ?thesis using True by simp
  4744 next
  4744 next
  4745   case False
  4745   case False
  4746 
  4746 
  4747   have foldA: "?foldA = foldr (\<lambda>x. max (length x)) [ys\<leftarrow>xss . ys \<noteq> []] 0 - 1"
  4747   have foldA: "?foldA = foldr (\<lambda>x. max (length x)) (filter (\<lambda>ys. ys \<noteq> []) xss) 0 - 1"
  4748     by (induct xss) auto
  4748     by (induct xss) auto
  4749   have foldB: "?foldB = foldr (\<lambda>x. max (length x)) [ys\<leftarrow>xss . ys \<noteq> []] 0"
  4749   have foldB: "?foldB = foldr (\<lambda>x. max (length x)) (filter (\<lambda>ys. ys \<noteq> []) xss) 0"
  4750     by (induct xss) auto
  4750     by (induct xss) auto
  4751 
  4751 
  4752   have "0 < ?foldB"
  4752   have "0 < ?foldB"
  4753   proof -
  4753   proof -
  4754     from False
  4754     from False
  4755     obtain z zs where zs: "[ys\<leftarrow>xss . ys \<noteq> []] = z#zs" by (auto simp: neq_Nil_conv)
  4755     obtain z zs where zs: "(filter (\<lambda>ys. ys \<noteq> []) xss) = z#zs" by (auto simp: neq_Nil_conv)
  4756     hence "z \<in> set ([ys\<leftarrow>xss . ys \<noteq> []])" by auto
  4756     hence "z \<in> set (filter (\<lambda>ys. ys \<noteq> []) xss)" by auto
  4757     hence "z \<noteq> []" by auto
  4757     hence "z \<noteq> []" by auto
  4758     thus ?thesis
  4758     thus ?thesis
  4759       unfolding foldB zs
  4759       unfolding foldB zs
  4760       by (auto simp: max_def intro: less_le_trans)
  4760       by (auto simp: max_def intro: less_le_trans)
  4761   qed
  4761   qed
  4779                 max_Suc_Suc[symmetric] simp del: max_Suc_Suc)
  4779                 max_Suc_Suc[symmetric] simp del: max_Suc_Suc)
  4780 
  4780 
  4781 lemma nth_transpose:
  4781 lemma nth_transpose:
  4782   fixes xs :: "'a list list"
  4782   fixes xs :: "'a list list"
  4783   assumes "i < length (transpose xs)"
  4783   assumes "i < length (transpose xs)"
  4784   shows "transpose xs ! i = map (\<lambda>xs. xs ! i) [ys \<leftarrow> xs. i < length ys]"
  4784   shows "transpose xs ! i = map (\<lambda>xs. xs ! i) (filter (\<lambda>ys. i < length ys) xs)"
  4785 using assms proof (induct arbitrary: i rule: transpose.induct)
  4785 using assms proof (induct arbitrary: i rule: transpose.induct)
  4786   case (3 x xs xss)
  4786   case (3 x xs xss)
  4787   define XS where "XS = (x # xs) # xss"
  4787   define XS where "XS = (x # xs) # xss"
  4788   hence [simp]: "XS \<noteq> []" by auto
  4788   hence [simp]: "XS \<noteq> []" by auto
  4789   thus ?case
  4789   thus ?case
  5152     by (cases xs) (auto simp add: sorted_append max_def)
  5152     by (cases xs) (auto simp add: sorted_append max_def)
  5153 qed simp
  5153 qed simp
  5154 
  5154 
  5155 lemma filter_equals_takeWhile_sorted_rev:
  5155 lemma filter_equals_takeWhile_sorted_rev:
  5156   assumes sorted: "sorted (rev (map f xs))"
  5156   assumes sorted: "sorted (rev (map f xs))"
  5157   shows "[x \<leftarrow> xs. t < f x] = takeWhile (\<lambda> x. t < f x) xs"
  5157   shows "filter (\<lambda>x. t < f x) xs = takeWhile (\<lambda> x. t < f x) xs"
  5158     (is "filter ?P xs = ?tW")
  5158     (is "filter ?P xs = ?tW")
  5159 proof (rule takeWhile_eq_filter[symmetric])
  5159 proof (rule takeWhile_eq_filter[symmetric])
  5160   let "?dW" = "dropWhile ?P xs"
  5160   let "?dW" = "dropWhile ?P xs"
  5161   fix x assume "x \<in> set ?dW"
  5161   fix x assume "x \<in> set ?dW"
  5162   then obtain i where i: "i < length ?dW" and nth_i: "x = ?dW ! i"
  5162   then obtain i where i: "i < length ?dW" and nth_i: "x = ?dW ! i"
  5176     using hd_conv_nth[of "?dW"] by simp
  5176     using hd_conv_nth[of "?dW"] by simp
  5177   finally show "\<not> t < f x" by simp
  5177   finally show "\<not> t < f x" by simp
  5178 qed
  5178 qed
  5179 
  5179 
  5180 lemma sorted_map_same:
  5180 lemma sorted_map_same:
  5181   "sorted (map f [x\<leftarrow>xs. f x = g xs])"
  5181   "sorted (map f (filter (\<lambda>x. f x = g xs) xs))"
  5182 proof (induct xs arbitrary: g)
  5182 proof (induct xs arbitrary: g)
  5183   case Nil then show ?case by simp
  5183   case Nil then show ?case by simp
  5184 next
  5184 next
  5185   case (Cons x xs)
  5185   case (Cons x xs)
  5186   then have "sorted (map f [y\<leftarrow>xs . f y = (\<lambda>xs. f x) xs])" .
  5186   then have "sorted (map f (filter (\<lambda>y. f y = (\<lambda>xs. f x) xs) xs))" .
  5187   moreover from Cons have "sorted (map f [y\<leftarrow>xs . f y = (g \<circ> Cons x) xs])" .
  5187   moreover from Cons have "sorted (map f (filter (\<lambda>y. f y = (g \<circ> Cons x) xs) xs))" .
  5188   ultimately show ?case by simp_all
  5188   ultimately show ?case by simp_all
  5189 qed
  5189 qed
  5190 
  5190 
  5191 lemma sorted_same:
  5191 lemma sorted_same:
  5192   "sorted [x\<leftarrow>xs. x = g xs]"
  5192   "sorted (filter (\<lambda>x. x = g xs) xs)"
  5193 using sorted_map_same [of "\<lambda>x. x"] by simp
  5193 using sorted_map_same [of "\<lambda>x. x"] by simp
  5194 
  5194 
  5195 end
  5195 end
  5196 
  5196 
  5197 lemma sorted_upt[simp]: "sorted [m..<n]"
  5197 lemma sorted_upt[simp]: "sorted [m..<n]"
  5409 lemma sorted_enumerate [simp]: "sorted (map fst (enumerate n xs))"
  5409 lemma sorted_enumerate [simp]: "sorted (map fst (enumerate n xs))"
  5410 by (simp add: enumerate_eq_zip)
  5410 by (simp add: enumerate_eq_zip)
  5411 
  5411 
  5412 text \<open>Stability of @{const sort_key}:\<close>
  5412 text \<open>Stability of @{const sort_key}:\<close>
  5413 
  5413 
  5414 lemma sort_key_stable: "[y <- sort_key f xs. f y = k] = [y <- xs. f y = k]"
  5414 lemma sort_key_stable: "filter (\<lambda>y. f y = k) (sort_key f xs) = filter (\<lambda>y. f y = k) xs"
  5415 proof (induction xs)
  5415 proof (induction xs)
  5416   case Nil thus ?case by simp
  5416   case Nil thus ?case by simp
  5417 next
  5417 next
  5418   case (Cons a xs)
  5418   case (Cons a xs)
  5419   thus ?case
  5419   thus ?case
  5420   proof (cases "f a = k")
  5420   proof (cases "f a = k")
  5421     case False thus ?thesis
  5421     case False thus ?thesis
  5422       using Cons.IH by (metis (mono_tags) filter.simps(2) filter_sort)
  5422       using Cons.IH by (metis (mono_tags) filter.simps(2) filter_sort)
  5423   next
  5423   next
  5424     case True
  5424     case True
  5425     hence ler: "[y <- (a # xs). f y = k] = a # [y <- xs. f y = f a]" by simp
  5425     hence ler: "filter (\<lambda>y. f y = k) (a # xs) = a # filter (\<lambda>y. f y = f a) xs" by simp
  5426     have "\<forall>y \<in> set (sort_key f [y <- xs. f y = f a]). f y = f a" by simp
  5426     have "\<forall>y \<in> set (sort_key f (filter (\<lambda>y. f y = f a) xs)). f y = f a" by simp
  5427     hence "insort_key f a (sort_key f [y <- xs. f y = f a])
  5427     hence "insort_key f a (sort_key f (filter (\<lambda>y. f y = f a) xs))
  5428             = a # (sort_key f [y <- xs. f y = f a])"
  5428             = a # (sort_key f (filter (\<lambda>y. f y = f a) xs))"
  5429       by (simp add: insort_is_Cons)
  5429       by (simp add: insort_is_Cons)
  5430     hence lel: "[y <- sort_key f (a # xs). f y = k] = a # [y <- sort_key f xs. f y = f a]"
  5430     hence lel: "filter (\<lambda>y. f y = k) (sort_key f (a # xs)) = a # filter (\<lambda>y. f y = f a) (sort_key f xs)"
  5431       by (metis True filter_sort ler sort_key_simps(2))
  5431       by (metis True filter_sort ler sort_key_simps(2))
  5432     from lel ler show ?thesis using Cons.IH True by (auto)
  5432     from lel ler show ?thesis using Cons.IH True by (auto)
  5433   qed
  5433   qed
  5434 qed
  5434 qed
  5435 
  5435 
  5445 lemma sorted_transpose[simp]: "sorted (rev (map length (transpose xs)))"
  5445 lemma sorted_transpose[simp]: "sorted (rev (map length (transpose xs)))"
  5446 by (auto simp: sorted_iff_nth_mono rev_nth nth_transpose
  5446 by (auto simp: sorted_iff_nth_mono rev_nth nth_transpose
  5447     length_filter_conv_card intro: card_mono)
  5447     length_filter_conv_card intro: card_mono)
  5448 
  5448 
  5449 lemma transpose_max_length:
  5449 lemma transpose_max_length:
  5450   "foldr (\<lambda>xs. max (length xs)) (transpose xs) 0 = length [x \<leftarrow> xs. x \<noteq> []]"
  5450   "foldr (\<lambda>xs. max (length xs)) (transpose xs) 0 = length (filter (\<lambda>x. x \<noteq> []) xs)"
  5451   (is "?L = ?R")
  5451   (is "?L = ?R")
  5452 proof (cases "transpose xs = []")
  5452 proof (cases "transpose xs = []")
  5453   case False
  5453   case False
  5454   have "?L = foldr max (map length (transpose xs)) 0"
  5454   have "?L = foldr max (map length (transpose xs)) 0"
  5455     by (simp add: foldr_map comp_def)
  5455     by (simp add: foldr_map comp_def)
  5457     using False sorted_transpose by (simp add: foldr_max_sorted)
  5457     using False sorted_transpose by (simp add: foldr_max_sorted)
  5458   finally show ?thesis
  5458   finally show ?thesis
  5459     using False by (simp add: nth_transpose)
  5459     using False by (simp add: nth_transpose)
  5460 next
  5460 next
  5461   case True
  5461   case True
  5462   hence "[x \<leftarrow> xs. x \<noteq> []] = []"
  5462   hence "filter (\<lambda>x. x \<noteq> []) xs = []"
  5463     by (auto intro!: filter_False simp: transpose_empty)
  5463     by (auto intro!: filter_False simp: transpose_empty)
  5464   thus ?thesis by (simp add: transpose_empty True)
  5464   thus ?thesis by (simp add: transpose_empty True)
  5465 qed
  5465 qed
  5466 
  5466 
  5467 lemma length_transpose_sorted:
  5467 lemma length_transpose_sorted:
  5478 
  5478 
  5479 lemma nth_nth_transpose_sorted[simp]:
  5479 lemma nth_nth_transpose_sorted[simp]:
  5480   fixes xs :: "'a list list"
  5480   fixes xs :: "'a list list"
  5481   assumes sorted: "sorted (rev (map length xs))"
  5481   assumes sorted: "sorted (rev (map length xs))"
  5482   and i: "i < length (transpose xs)"
  5482   and i: "i < length (transpose xs)"
  5483   and j: "j < length [ys \<leftarrow> xs. i < length ys]"
  5483   and j: "j < length (filter (\<lambda>ys. i < length ys) xs)"
  5484   shows "transpose xs ! i ! j = xs ! j  ! i"
  5484   shows "transpose xs ! i ! j = xs ! j  ! i"
  5485 using j filter_equals_takeWhile_sorted_rev[OF sorted, of i]
  5485 using j filter_equals_takeWhile_sorted_rev[OF sorted, of i]
  5486     nth_transpose[OF i] nth_map[OF j]
  5486     nth_transpose[OF i] nth_map[OF j]
  5487 by (simp add: takeWhile_nth)
  5487 by (simp add: takeWhile_nth)
  5488 
  5488 
  5540     hence "k \<le> i" by auto
  5540     hence "k \<le> i" by auto
  5541     with sorted_rev_nth_mono[OF sorted this] \<open>i < length xs\<close>
  5541     with sorted_rev_nth_mono[OF sorted this] \<open>i < length xs\<close>
  5542     have "length (xs ! i) \<le> length (xs ! k)" by simp
  5542     have "length (xs ! i) \<le> length (xs ! k)" by simp
  5543     thus "Suc j \<le> length (xs ! k)" using j_less by simp
  5543     thus "Suc j \<le> length (xs ! k)" using j_less by simp
  5544   qed
  5544   qed
  5545   have i_less_filter: "i < length [ys\<leftarrow>xs . j < length ys]"
  5545   have i_less_filter: "i < length (filter (\<lambda>ys. j < length ys) xs) "
  5546     unfolding filter_equals_takeWhile_sorted_rev[OF sorted, of j]
  5546     unfolding filter_equals_takeWhile_sorted_rev[OF sorted, of j]
  5547     using i_less_tW by (simp_all add: Suc_le_eq)
  5547     using i_less_tW by (simp_all add: Suc_le_eq)
  5548   from j show "?R ! j = xs ! i ! j"
  5548   from j show "?R ! j = xs ! i ! j"
  5549     unfolding filter_equals_takeWhile_sorted_rev[OF sorted_transpose, of i]
  5549     unfolding filter_equals_takeWhile_sorted_rev[OF sorted_transpose, of i]
  5550     by (simp add: takeWhile_nth nth_nth_transpose_sorted[OF sorted * i_less_filter])
  5550     by (simp add: takeWhile_nth nth_nth_transpose_sorted[OF sorted * i_less_filter])
  5579     by (auto simp: rev_nth rect sorted_iff_nth_mono)
  5579     by (auto simp: rev_nth rect sorted_iff_nth_mono)
  5580   from foldr_max_sorted[OF this] assms
  5580   from foldr_max_sorted[OF this] assms
  5581   show len: "length ?trans = length ?map"
  5581   show len: "length ?trans = length ?map"
  5582     by (simp_all add: length_transpose foldr_map comp_def)
  5582     by (simp_all add: length_transpose foldr_map comp_def)
  5583   moreover
  5583   moreover
  5584   { fix i assume "i < n" hence "[ys\<leftarrow>xs . i < length ys] = xs"
  5584   { fix i assume "i < n" hence "filter (\<lambda>ys. i < length ys) xs = xs"
  5585       using rect by (auto simp: in_set_conv_nth intro!: filter_True) }
  5585       using rect by (auto simp: in_set_conv_nth intro!: filter_True) }
  5586   ultimately show "\<forall>i < length ?trans. ?trans ! i = ?map ! i"
  5586   ultimately show "\<forall>i < length ?trans. ?trans ! i = ?map ! i"
  5587     by (auto simp: nth_transpose intro: nth_equalityI)
  5587     by (auto simp: nth_transpose intro: nth_equalityI)
  5588 qed
  5588 qed
  5589 
  5589