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 |