270 fun sorted :: "'a list \<Rightarrow> bool" where |
270 fun sorted :: "'a list \<Rightarrow> bool" where |
271 "sorted [] \<longleftrightarrow> True" | |
271 "sorted [] \<longleftrightarrow> True" | |
272 "sorted [x] \<longleftrightarrow> True" | |
272 "sorted [x] \<longleftrightarrow> True" | |
273 "sorted (x#y#zs) \<longleftrightarrow> x <= y \<and> sorted (y#zs)" |
273 "sorted (x#y#zs) \<longleftrightarrow> x <= y \<and> sorted (y#zs)" |
274 |
274 |
275 primrec insort :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
275 primrec insort_key :: "('b \<Rightarrow> 'a) \<Rightarrow> 'b \<Rightarrow> 'b list \<Rightarrow> 'b list" where |
276 "insort x [] = [x]" | |
276 "insort_key f x [] = [x]" | |
277 "insort x (y#ys) = (if x <= y then (x#y#ys) else y#(insort x ys))" |
277 "insort_key f x (y#ys) = (if f x \<le> f y then (x#y#ys) else y#(insort_key f x ys))" |
278 |
278 |
279 primrec sort :: "'a list \<Rightarrow> 'a list" where |
279 primrec sort_key :: "('b \<Rightarrow> 'a) \<Rightarrow> 'b list \<Rightarrow> 'b list" where |
280 "sort [] = []" | |
280 "sort_key f [] = []" | |
281 "sort (x#xs) = insort x (sort xs)" |
281 "sort_key f (x#xs) = insort_key f x (sort_key f xs)" |
|
282 |
|
283 abbreviation "sort \<equiv> sort_key (\<lambda>x. x)" |
|
284 abbreviation "insort \<equiv> insort_key (\<lambda>x. x)" |
282 |
285 |
283 end |
286 end |
284 |
287 |
285 |
288 |
286 subsubsection {* List comprehension *} |
289 subsubsection {* List comprehension *} |
1763 by (induct xs) (auto dest: set_takeWhileD) |
1787 by (induct xs) (auto dest: set_takeWhileD) |
1764 |
1788 |
1765 lemma distinct_dropWhile[simp]: "distinct xs ==> distinct (dropWhile P xs)" |
1789 lemma distinct_dropWhile[simp]: "distinct xs ==> distinct (dropWhile P xs)" |
1766 by (induct xs) auto |
1790 by (induct xs) auto |
1767 |
1791 |
|
1792 lemma takeWhile_map: "takeWhile P (map f xs) = map f (takeWhile (P \<circ> f) xs)" |
|
1793 by (induct xs) auto |
|
1794 |
|
1795 lemma dropWhile_map: "dropWhile P (map f xs) = map f (dropWhile (P \<circ> f) xs)" |
|
1796 by (induct xs) auto |
|
1797 |
|
1798 lemma takeWhile_eq_take: "takeWhile P xs = take (length (takeWhile P xs)) xs" |
|
1799 by (induct xs) auto |
|
1800 |
|
1801 lemma dropWhile_eq_drop: "dropWhile P xs = drop (length (takeWhile P xs)) xs" |
|
1802 by (induct xs) auto |
|
1803 |
|
1804 lemma hd_dropWhile: |
|
1805 "dropWhile P xs \<noteq> [] \<Longrightarrow> \<not> P (hd (dropWhile P xs))" |
|
1806 using assms by (induct xs) auto |
|
1807 |
|
1808 lemma takeWhile_eq_filter: |
|
1809 assumes "\<And> x. x \<in> set (dropWhile P xs) \<Longrightarrow> \<not> P x" |
|
1810 shows "takeWhile P xs = filter P xs" |
|
1811 proof - |
|
1812 have A: "filter P xs = filter P (takeWhile P xs @ dropWhile P xs)" |
|
1813 by simp |
|
1814 have B: "filter P (dropWhile P xs) = []" |
|
1815 unfolding filter_empty_conv using assms by blast |
|
1816 have "filter P xs = takeWhile P xs" |
|
1817 unfolding A filter_append B |
|
1818 by (auto simp add: filter_id_conv dest: set_takeWhileD) |
|
1819 thus ?thesis .. |
|
1820 qed |
|
1821 |
|
1822 lemma takeWhile_eq_take_P_nth: |
|
1823 "\<lbrakk> \<And> i. \<lbrakk> i < n ; i < length xs \<rbrakk> \<Longrightarrow> P (xs ! i) ; n < length xs \<Longrightarrow> \<not> P (xs ! n) \<rbrakk> \<Longrightarrow> |
|
1824 takeWhile P xs = take n xs" |
|
1825 proof (induct xs arbitrary: n) |
|
1826 case (Cons x xs) |
|
1827 thus ?case |
|
1828 proof (cases n) |
|
1829 case (Suc n') note this[simp] |
|
1830 have "P x" using Cons.prems(1)[of 0] by simp |
|
1831 moreover have "takeWhile P xs = take n' xs" |
|
1832 proof (rule Cons.hyps) |
|
1833 case goal1 thus "P (xs ! i)" using Cons.prems(1)[of "Suc i"] by simp |
|
1834 next case goal2 thus ?case using Cons by auto |
|
1835 qed |
|
1836 ultimately show ?thesis by simp |
|
1837 qed simp |
|
1838 qed simp |
|
1839 |
|
1840 lemma nth_length_takeWhile: |
|
1841 "length (takeWhile P xs) < length xs \<Longrightarrow> \<not> P (xs ! length (takeWhile P xs))" |
|
1842 by (induct xs) auto |
|
1843 |
|
1844 lemma length_takeWhile_less_P_nth: |
|
1845 assumes all: "\<And> i. i < j \<Longrightarrow> P (xs ! i)" and "j \<le> length xs" |
|
1846 shows "j \<le> length (takeWhile P xs)" |
|
1847 proof (rule classical) |
|
1848 assume "\<not> ?thesis" |
|
1849 hence "length (takeWhile P xs) < length xs" using assms by simp |
|
1850 thus ?thesis using all `\<not> ?thesis` nth_length_takeWhile[of P xs] by auto |
|
1851 qed |
1768 |
1852 |
1769 text{* The following two lemmmas could be generalized to an arbitrary |
1853 text{* The following two lemmmas could be generalized to an arbitrary |
1770 property. *} |
1854 property. *} |
1771 |
1855 |
1772 lemma takeWhile_neq_rev: "\<lbrakk>distinct xs; x \<in> set xs\<rbrakk> \<Longrightarrow> |
1856 lemma takeWhile_neq_rev: "\<lbrakk>distinct xs; x \<in> set xs\<rbrakk> \<Longrightarrow> |
1836 |
1920 |
1837 lemma zip_rev: |
1921 lemma zip_rev: |
1838 "length xs = length ys ==> zip (rev xs) (rev ys) = rev (zip xs ys)" |
1922 "length xs = length ys ==> zip (rev xs) (rev ys) = rev (zip xs ys)" |
1839 by (induct rule:list_induct2, simp_all) |
1923 by (induct rule:list_induct2, simp_all) |
1840 |
1924 |
|
1925 lemma zip_map_map: |
|
1926 "zip (map f xs) (map g ys) = map (\<lambda> (x, y). (f x, g y)) (zip xs ys)" |
|
1927 proof (induct xs arbitrary: ys) |
|
1928 case (Cons x xs) note Cons_x_xs = Cons.hyps |
|
1929 show ?case |
|
1930 proof (cases ys) |
|
1931 case (Cons y ys') |
|
1932 show ?thesis unfolding Cons using Cons_x_xs by simp |
|
1933 qed simp |
|
1934 qed simp |
|
1935 |
|
1936 lemma zip_map1: |
|
1937 "zip (map f xs) ys = map (\<lambda>(x, y). (f x, y)) (zip xs ys)" |
|
1938 using zip_map_map[of f xs "\<lambda>x. x" ys] by simp |
|
1939 |
|
1940 lemma zip_map2: |
|
1941 "zip xs (map f ys) = map (\<lambda>(x, y). (x, f y)) (zip xs ys)" |
|
1942 using zip_map_map[of "\<lambda>x. x" xs f ys] by simp |
|
1943 |
1841 lemma map_zip_map: |
1944 lemma map_zip_map: |
1842 "map f (zip (map g xs) ys) = map (%(x,y). f(g x, y)) (zip xs ys)" |
1945 "map f (zip (map g xs) ys) = map (%(x,y). f(g x, y)) (zip xs ys)" |
1843 apply(induct xs arbitrary:ys) apply simp |
1946 unfolding zip_map1 by auto |
1844 apply(case_tac ys) |
|
1845 apply simp_all |
|
1846 done |
|
1847 |
1947 |
1848 lemma map_zip_map2: |
1948 lemma map_zip_map2: |
1849 "map f (zip xs (map g ys)) = map (%(x,y). f(x, g y)) (zip xs ys)" |
1949 "map f (zip xs (map g ys)) = map (%(x,y). f(x, g y)) (zip xs ys)" |
1850 apply(induct xs arbitrary:ys) apply simp |
1950 unfolding zip_map2 by auto |
1851 apply(case_tac ys) |
|
1852 apply simp_all |
|
1853 done |
|
1854 |
1951 |
1855 text{* Courtesy of Andreas Lochbihler: *} |
1952 text{* Courtesy of Andreas Lochbihler: *} |
1856 lemma zip_same_conv_map: "zip xs xs = map (\<lambda>x. (x, x)) xs" |
1953 lemma zip_same_conv_map: "zip xs xs = map (\<lambda>x. (x, x)) xs" |
1857 by(induct xs) auto |
1954 by(induct xs) auto |
1858 |
1955 |
1891 apply simp |
1991 apply simp |
1892 apply (case_tac xs, simp) |
1992 apply (case_tac xs, simp) |
1893 apply (case_tac ys, simp_all) |
1993 apply (case_tac ys, simp_all) |
1894 done |
1994 done |
1895 |
1995 |
|
1996 lemma zip_takeWhile_fst: "zip (takeWhile P xs) ys = takeWhile (P \<circ> fst) (zip xs ys)" |
|
1997 proof (induct xs arbitrary: ys) |
|
1998 case (Cons x xs) thus ?case by (cases ys) auto |
|
1999 qed simp |
|
2000 |
|
2001 lemma zip_takeWhile_snd: "zip xs (takeWhile P ys) = takeWhile (P \<circ> snd) (zip xs ys)" |
|
2002 proof (induct xs arbitrary: ys) |
|
2003 case (Cons x xs) thus ?case by (cases ys) auto |
|
2004 qed simp |
|
2005 |
1896 lemma set_zip_leftD: |
2006 lemma set_zip_leftD: |
1897 "(x,y)\<in> set (zip xs ys) \<Longrightarrow> x \<in> set xs" |
2007 "(x,y)\<in> set (zip xs ys) \<Longrightarrow> x \<in> set xs" |
1898 by (induct xs ys rule:list_induct2') auto |
2008 by (induct xs ys rule:list_induct2') auto |
1899 |
2009 |
1900 lemma set_zip_rightD: |
2010 lemma set_zip_rightD: |
1911 |
2021 |
1912 lemma zip_eq_conv: |
2022 lemma zip_eq_conv: |
1913 "length xs = length ys \<Longrightarrow> zip xs ys = zs \<longleftrightarrow> map fst zs = xs \<and> map snd zs = ys" |
2023 "length xs = length ys \<Longrightarrow> zip xs ys = zs \<longleftrightarrow> map fst zs = xs \<and> map snd zs = ys" |
1914 by (auto simp add: zip_map_fst_snd) |
2024 by (auto simp add: zip_map_fst_snd) |
1915 |
2025 |
|
2026 lemma distinct_zipI1: |
|
2027 "distinct xs \<Longrightarrow> distinct (zip xs ys)" |
|
2028 proof (induct xs arbitrary: ys) |
|
2029 case (Cons x xs) |
|
2030 show ?case |
|
2031 proof (cases ys) |
|
2032 case (Cons y ys') |
|
2033 have "(x, y) \<notin> set (zip xs ys')" |
|
2034 using Cons.prems by (auto simp: set_zip) |
|
2035 thus ?thesis |
|
2036 unfolding Cons zip_Cons_Cons distinct.simps |
|
2037 using Cons.hyps Cons.prems by simp |
|
2038 qed simp |
|
2039 qed simp |
|
2040 |
|
2041 lemma distinct_zipI2: |
|
2042 "distinct xs \<Longrightarrow> distinct (zip xs ys)" |
|
2043 proof (induct xs arbitrary: ys) |
|
2044 case (Cons x xs) |
|
2045 show ?case |
|
2046 proof (cases ys) |
|
2047 case (Cons y ys') |
|
2048 have "(x, y) \<notin> set (zip xs ys')" |
|
2049 using Cons.prems by (auto simp: set_zip) |
|
2050 thus ?thesis |
|
2051 unfolding Cons zip_Cons_Cons distinct.simps |
|
2052 using Cons.hyps Cons.prems by simp |
|
2053 qed simp |
|
2054 qed simp |
1916 |
2055 |
1917 subsubsection {* @{text list_all2} *} |
2056 subsubsection {* @{text list_all2} *} |
1918 |
2057 |
1919 lemma list_all2_lengthD [intro?]: |
2058 lemma list_all2_lengthD [intro?]: |
1920 "list_all2 P xs ys ==> length xs = length ys" |
2059 "list_all2 P xs ys ==> length xs = length ys" |
2256 lemma listsum_foldr: "listsum xs = foldr (op +) xs 0" |
2395 lemma listsum_foldr: "listsum xs = foldr (op +) xs 0" |
2257 by (induct xs) auto |
2396 by (induct xs) auto |
2258 |
2397 |
2259 lemma length_concat: "length (concat xss) = listsum (map length xss)" |
2398 lemma length_concat: "length (concat xss) = listsum (map length xss)" |
2260 by (induct xss) simp_all |
2399 by (induct xss) simp_all |
|
2400 |
|
2401 lemma listsum_map_filter: |
|
2402 fixes f :: "'a \<Rightarrow> 'b \<Colon> comm_monoid_add" |
|
2403 assumes "\<And> x. \<lbrakk> x \<in> set xs ; \<not> P x \<rbrakk> \<Longrightarrow> f x = 0" |
|
2404 shows "listsum (map f (filter P xs)) = listsum (map f xs)" |
|
2405 using assms by (induct xs) auto |
2261 |
2406 |
2262 text{* For efficient code generation --- |
2407 text{* For efficient code generation --- |
2263 @{const listsum} is not tail recursive but @{const foldl} is. *} |
2408 @{const listsum} is not tail recursive but @{const foldl} is. *} |
2264 lemma listsum[code_unfold]: "listsum xs = foldl (op +) 0 xs" |
2409 lemma listsum[code_unfold]: "listsum xs = foldl (op +) 0 xs" |
2265 by(simp add:listsum_foldr foldl_foldr1) |
2410 by(simp add:listsum_foldr foldl_foldr1) |
3081 that instead of multisets to state the correctness property. *} |
3231 that instead of multisets to state the correctness property. *} |
3082 |
3232 |
3083 context linorder |
3233 context linorder |
3084 begin |
3234 begin |
3085 |
3235 |
|
3236 lemma length_insert[simp] : "length (insort_key f x xs) = Suc (length xs)" |
|
3237 by (induct xs, auto) |
|
3238 |
|
3239 lemma length_sort[simp]: "length (sort_key f xs) = length xs" |
|
3240 by (induct xs, auto) |
|
3241 |
3086 lemma sorted_Cons: "sorted (x#xs) = (sorted xs & (ALL y:set xs. x <= y))" |
3242 lemma sorted_Cons: "sorted (x#xs) = (sorted xs & (ALL y:set xs. x <= y))" |
3087 apply(induct xs arbitrary: x) apply simp |
3243 apply(induct xs arbitrary: x) apply simp |
3088 by simp (blast intro: order_trans) |
3244 by simp (blast intro: order_trans) |
3089 |
3245 |
3090 lemma sorted_append: |
3246 lemma sorted_append: |
3091 "sorted (xs@ys) = (sorted xs & sorted ys & (\<forall>x \<in> set xs. \<forall>y \<in> set ys. x\<le>y))" |
3247 "sorted (xs@ys) = (sorted xs & sorted ys & (\<forall>x \<in> set xs. \<forall>y \<in> set ys. x\<le>y))" |
3092 by (induct xs) (auto simp add:sorted_Cons) |
3248 by (induct xs) (auto simp add:sorted_Cons) |
3093 |
3249 |
3094 lemma sorted_nth_mono: |
3250 lemma sorted_nth_mono: |
3095 "sorted xs \<Longrightarrow> i <= j \<Longrightarrow> j < length xs \<Longrightarrow> xs!i <= xs!j" |
3251 "sorted xs \<Longrightarrow> i \<le> j \<Longrightarrow> j < length xs \<Longrightarrow> xs!i \<le> xs!j" |
3096 by (induct xs arbitrary: i j) (auto simp:nth_Cons' sorted_Cons) |
3252 by (induct xs arbitrary: i j) (auto simp:nth_Cons' sorted_Cons) |
3097 |
3253 |
3098 lemma set_insort: "set(insort x xs) = insert x (set xs)" |
3254 lemma sorted_rev_nth_mono: |
3099 by (induct xs) auto |
3255 "sorted (rev xs) \<Longrightarrow> i \<le> j \<Longrightarrow> j < length xs \<Longrightarrow> xs!j \<le> xs!i" |
3100 |
3256 using sorted_nth_mono[ of "rev xs" "length xs - j - 1" "length xs - i - 1"] |
3101 lemma set_sort[simp]: "set(sort xs) = set xs" |
3257 rev_nth[of "length xs - i - 1" "xs"] rev_nth[of "length xs - j - 1" "xs"] |
|
3258 by auto |
|
3259 |
|
3260 lemma sorted_nth_monoI: |
|
3261 "(\<And> i j. \<lbrakk> i \<le> j ; j < length xs \<rbrakk> \<Longrightarrow> xs ! i \<le> xs ! j) \<Longrightarrow> sorted xs" |
|
3262 proof (induct xs) |
|
3263 case (Cons x xs) |
|
3264 have "sorted xs" |
|
3265 proof (rule Cons.hyps) |
|
3266 fix i j assume "i \<le> j" and "j < length xs" |
|
3267 with Cons.prems[of "Suc i" "Suc j"] |
|
3268 show "xs ! i \<le> xs ! j" by auto |
|
3269 qed |
|
3270 moreover |
|
3271 { |
|
3272 fix y assume "y \<in> set xs" |
|
3273 then obtain j where "j < length xs" and "xs ! j = y" |
|
3274 unfolding in_set_conv_nth by blast |
|
3275 with Cons.prems[of 0 "Suc j"] |
|
3276 have "x \<le> y" |
|
3277 by auto |
|
3278 } |
|
3279 ultimately |
|
3280 show ?case |
|
3281 unfolding sorted_Cons by auto |
|
3282 qed simp |
|
3283 |
|
3284 lemma sorted_equals_nth_mono: |
|
3285 "sorted xs = (\<forall>j < length xs. \<forall>i \<le> j. xs ! i \<le> xs ! j)" |
|
3286 by (auto intro: sorted_nth_monoI sorted_nth_mono) |
|
3287 |
|
3288 lemma set_insort: "set(insort_key f x xs) = insert x (set xs)" |
|
3289 by (induct xs) auto |
|
3290 |
|
3291 lemma set_sort[simp]: "set(sort_key f xs) = set xs" |
3102 by (induct xs) (simp_all add:set_insort) |
3292 by (induct xs) (simp_all add:set_insort) |
3103 |
3293 |
3104 lemma distinct_insort: "distinct (insort x xs) = (x \<notin> set xs \<and> distinct xs)" |
3294 lemma distinct_insort: "distinct (insort_key f x xs) = (x \<notin> set xs \<and> distinct xs)" |
3105 by(induct xs)(auto simp:set_insort) |
3295 by(induct xs)(auto simp:set_insort) |
3106 |
3296 |
3107 lemma distinct_sort[simp]: "distinct (sort xs) = distinct xs" |
3297 lemma distinct_sort[simp]: "distinct (sort_key f xs) = distinct xs" |
3108 by(induct xs)(simp_all add:distinct_insort set_sort) |
3298 by(induct xs)(simp_all add:distinct_insort set_sort) |
3109 |
3299 |
|
3300 lemma sorted_insort_key: "sorted (map f (insort_key f x xs)) = sorted (map f xs)" |
|
3301 by(induct xs)(auto simp:sorted_Cons set_insort) |
|
3302 |
3110 lemma sorted_insort: "sorted (insort x xs) = sorted xs" |
3303 lemma sorted_insort: "sorted (insort x xs) = sorted xs" |
3111 apply (induct xs) |
3304 using sorted_insort_key[where f="\<lambda>x. x"] by simp |
3112 apply(auto simp:sorted_Cons set_insort) |
3305 |
3113 done |
3306 theorem sorted_sort_key[simp]: "sorted (map f (sort_key f xs))" |
|
3307 by(induct xs)(auto simp:sorted_insort_key) |
3114 |
3308 |
3115 theorem sorted_sort[simp]: "sorted (sort xs)" |
3309 theorem sorted_sort[simp]: "sorted (sort xs)" |
3116 by (induct xs) (auto simp:sorted_insort) |
3310 by(induct xs)(auto simp:sorted_insort) |
3117 |
3311 |
3118 lemma insort_is_Cons: "\<forall>x\<in>set xs. a \<le> x \<Longrightarrow> insort a xs = a # xs" |
3312 lemma insort_is_Cons: "\<forall>x\<in>set xs. f a \<le> f x \<Longrightarrow> insort_key f a xs = a # xs" |
3119 by (cases xs) auto |
3313 by (cases xs) auto |
3120 |
3314 |
3121 lemma sorted_remove1: "sorted xs \<Longrightarrow> sorted (remove1 a xs)" |
3315 lemma sorted_remove1: "sorted xs \<Longrightarrow> sorted (remove1 a xs)" |
3122 by (induct xs, auto simp add: sorted_Cons) |
3316 by(induct xs)(auto simp add: sorted_Cons) |
|
3317 |
|
3318 lemma insort_key_remove1: "\<lbrakk> a \<in> set xs; sorted (map f xs) ; inj_on f (set xs) \<rbrakk> |
|
3319 \<Longrightarrow> insort_key f a (remove1 a xs) = xs" |
|
3320 proof (induct xs) |
|
3321 case (Cons x xs) |
|
3322 thus ?case |
|
3323 proof (cases "x = a") |
|
3324 case False |
|
3325 hence "f x \<noteq> f a" using Cons.prems by auto |
|
3326 hence "f x < f a" using Cons.prems by (auto simp: sorted_Cons) |
|
3327 thus ?thesis using Cons by (auto simp: sorted_Cons insort_is_Cons) |
|
3328 qed (auto simp: sorted_Cons insort_is_Cons) |
|
3329 qed simp |
3123 |
3330 |
3124 lemma insort_remove1: "\<lbrakk> a \<in> set xs; sorted xs \<rbrakk> \<Longrightarrow> insort a (remove1 a xs) = xs" |
3331 lemma insort_remove1: "\<lbrakk> a \<in> set xs; sorted xs \<rbrakk> \<Longrightarrow> insort a (remove1 a xs) = xs" |
3125 by (induct xs, auto simp add: sorted_Cons insort_is_Cons) |
3332 using insort_key_remove1[where f="\<lambda>x. x"] by simp |
3126 |
3333 |
3127 lemma sorted_remdups[simp]: |
3334 lemma sorted_remdups[simp]: |
3128 "sorted l \<Longrightarrow> sorted (remdups l)" |
3335 "sorted l \<Longrightarrow> sorted (remdups l)" |
3129 by (induct l) (auto simp: sorted_Cons) |
3336 by (induct l) (auto simp: sorted_Cons) |
3130 |
3337 |