1 (* Author: Tobias Nipkow *) |
1 (* Author: Tobias Nipkow *) |
2 |
2 |
3 section "Sorting" |
3 section "Sorting" |
4 |
4 |
5 theory Sorting |
5 theory Sorting |
6 imports |
6 imports |
7 Complex_Main |
7 Complex_Main |
8 "HOL-Library.Multiset" |
8 "HOL-Library.Multiset" |
9 begin |
9 begin |
10 |
10 |
11 hide_const List.insort |
11 hide_const List.insort |
12 |
12 |
13 declare Let_def [simp] |
13 declare Let_def [simp] |
14 |
14 |
15 |
15 |
16 subsection "Insertion Sort" |
16 subsection "Insertion Sort" |
17 |
17 |
18 fun insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
18 fun insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
19 "insort1 x [] = [x]" | |
19 "insort1 x [] = [x]" | |
20 "insort1 x (y#ys) = |
20 "insort1 x (y#ys) = |
21 (if x \<le> y then x#y#ys else y#(insort1 x ys))" |
21 (if x \<le> y then x#y#ys else y#(insort1 x ys))" |
22 |
22 |
23 fun insort :: "'a::linorder list \<Rightarrow> 'a list" where |
23 fun insort :: "'a::linorder list \<Rightarrow> 'a list" where |
24 "insort [] = []" | |
24 "insort [] = []" | |
25 "insort (x#xs) = insort1 x (insort xs)" |
25 "insort (x#xs) = insort1 x (insort xs)" |
26 |
26 |
27 |
27 |
28 subsubsection "Functional Correctness" |
28 subsubsection "Functional Correctness" |
29 |
29 |
30 lemma mset_insort1: "mset (insort1 x xs) = {#x#} + mset xs" |
30 lemma mset_insort1: "mset (insort1 x xs) = {#x#} + mset xs" |
31 apply(induction xs) |
31 by (induction xs) auto |
32 apply auto |
|
33 done |
|
34 |
32 |
35 lemma mset_insort: "mset (insort xs) = mset xs" |
33 lemma mset_insort: "mset (insort xs) = mset xs" |
36 apply(induction xs) |
34 by (induction xs) (auto simp: mset_insort1) |
37 apply simp |
|
38 apply (simp add: mset_insort1) |
|
39 done |
|
40 |
35 |
41 lemma set_insort1: "set (insort1 x xs) = {x} \<union> set xs" |
36 lemma set_insort1: "set (insort1 x xs) = {x} \<union> set xs" |
42 by(simp add: mset_insort1 flip: set_mset_mset) |
37 by(simp add: mset_insort1 flip: set_mset_mset) |
43 |
38 |
44 lemma sorted_insort1: "sorted (insort1 a xs) = sorted xs" |
39 lemma sorted_insort1: "sorted (insort1 a xs) = sorted xs" |
45 apply(induction xs) |
40 by (induction xs) (auto simp: set_insort1) |
46 apply(auto simp add: set_insort1) |
|
47 done |
|
48 |
41 |
49 lemma sorted_insort: "sorted (insort xs)" |
42 lemma sorted_insort: "sorted (insort xs)" |
50 apply(induction xs) |
43 by (induction xs) (auto simp: sorted_insort1) |
51 apply(auto simp: sorted_insort1) |
|
52 done |
|
53 |
44 |
54 |
45 |
55 subsubsection "Time Complexity" |
46 subsubsection "Time Complexity" |
56 |
47 |
57 text \<open>We count the number of function calls.\<close> |
48 text \<open>We count the number of function calls.\<close> |
60 \<open>insort1 x [] = [x]\<close> |
51 \<open>insort1 x [] = [x]\<close> |
61 \<open>insort1 x (y#ys) = |
52 \<open>insort1 x (y#ys) = |
62 (if x \<le> y then x#y#ys else y#(insort1 x ys))\<close> |
53 (if x \<le> y then x#y#ys else y#(insort1 x ys))\<close> |
63 \<close> |
54 \<close> |
64 fun T_insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> nat" where |
55 fun T_insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> nat" where |
65 "T_insort1 x [] = 1" | |
56 "T_insort1 x [] = 1" | |
66 "T_insort1 x (y#ys) = |
57 "T_insort1 x (y#ys) = |
67 (if x \<le> y then 0 else T_insort1 x ys) + 1" |
58 (if x \<le> y then 0 else T_insort1 x ys) + 1" |
68 |
59 |
69 text\<open> |
60 text\<open> |
70 \<open>insort [] = []\<close> |
61 \<open>insort [] = []\<close> |
71 \<open>insort (x#xs) = insort1 x (insort xs)\<close> |
62 \<open>insort (x#xs) = insort1 x (insort xs)\<close> |
72 \<close> |
63 \<close> |
73 fun T_insort :: "'a::linorder list \<Rightarrow> nat" where |
64 fun T_insort :: "'a::linorder list \<Rightarrow> nat" where |
74 "T_insort [] = 1" | |
65 "T_insort [] = 1" | |
75 "T_insort (x#xs) = T_insort xs + T_insort1 x (insort xs) + 1" |
66 "T_insort (x#xs) = T_insort xs + T_insort1 x (insort xs) + 1" |
76 |
67 |
77 |
68 |
78 lemma T_insort1_length: "T_insort1 x xs \<le> length xs + 1" |
69 lemma T_insort1_length: "T_insort1 x xs \<le> length xs + 1" |
79 apply(induction xs) |
70 by (induction xs) auto |
80 apply auto |
|
81 done |
|
82 |
71 |
83 lemma length_insort1: "length (insort1 x xs) = length xs + 1" |
72 lemma length_insort1: "length (insort1 x xs) = length xs + 1" |
84 apply(induction xs) |
73 by (induction xs) auto |
85 apply auto |
|
86 done |
|
87 |
74 |
88 lemma length_insort: "length (insort xs) = length xs" |
75 lemma length_insort: "length (insort xs) = length xs" |
89 apply(induction xs) |
76 by (metis Sorting.mset_insort size_mset) |
90 apply (auto simp: length_insort1) |
|
91 done |
|
92 |
77 |
93 lemma T_insort_length: "T_insort xs \<le> (length xs + 1) ^ 2" |
78 lemma T_insort_length: "T_insort xs \<le> (length xs + 1) ^ 2" |
94 proof(induction xs) |
79 proof(induction xs) |
95 case Nil show ?case by simp |
80 case Nil show ?case by simp |
96 next |
81 next |
107 |
92 |
108 |
93 |
109 subsection "Merge Sort" |
94 subsection "Merge Sort" |
110 |
95 |
111 fun merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
96 fun merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
112 "merge [] ys = ys" | |
97 "merge [] ys = ys" | |
113 "merge xs [] = xs" | |
98 "merge xs [] = xs" | |
114 "merge (x#xs) (y#ys) = (if x \<le> y then x # merge xs (y#ys) else y # merge (x#xs) ys)" |
99 "merge (x#xs) (y#ys) = (if x \<le> y then x # merge xs (y#ys) else y # merge (x#xs) ys)" |
115 |
100 |
116 fun msort :: "'a::linorder list \<Rightarrow> 'a list" where |
101 fun msort :: "'a::linorder list \<Rightarrow> 'a list" where |
117 "msort xs = (let n = length xs in |
102 "msort xs = (let n = length xs in |
118 if n \<le> 1 then xs |
103 if n \<le> 1 then xs |
119 else merge (msort (take (n div 2) xs)) (msort (drop (n div 2) xs)))" |
104 else merge (msort (take (n div 2) xs)) (msort (drop (n div 2) xs)))" |
120 |
105 |
121 declare msort.simps [simp del] |
106 declare msort.simps [simp del] |
122 |
107 |
123 |
108 |
124 subsubsection "Functional Correctness" |
109 subsubsection "Functional Correctness" |
125 |
110 |
126 lemma mset_merge: "mset(merge xs ys) = mset xs + mset ys" |
111 lemma mset_merge: "mset(merge xs ys) = mset xs + mset ys" |
127 by(induction xs ys rule: merge.induct) auto |
112 by(induction xs ys rule: merge.induct) auto |
128 |
113 |
129 lemma mset_msort: "mset (msort xs) = mset xs" |
114 lemma mset_msort: "mset (msort xs) = mset xs" |
130 proof(induction xs rule: msort.induct) |
115 proof(induction xs rule: msort.induct) |
131 case (1 xs) |
116 case (1 xs) |
132 let ?n = "length xs" |
117 let ?n = "length xs" |
178 subsubsection "Time Complexity" |
163 subsubsection "Time Complexity" |
179 |
164 |
180 text \<open>We only count the number of comparisons between list elements.\<close> |
165 text \<open>We only count the number of comparisons between list elements.\<close> |
181 |
166 |
182 fun C_merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> nat" where |
167 fun C_merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> nat" where |
183 "C_merge [] ys = 0" | |
168 "C_merge [] ys = 0" | |
184 "C_merge xs [] = 0" | |
169 "C_merge xs [] = 0" | |
185 "C_merge (x#xs) (y#ys) = 1 + (if x \<le> y then C_merge xs (y#ys) else C_merge (x#xs) ys)" |
170 "C_merge (x#xs) (y#ys) = 1 + (if x \<le> y then C_merge xs (y#ys) else C_merge (x#xs) ys)" |
186 |
171 |
187 lemma C_merge_ub: "C_merge xs ys \<le> length xs + length ys" |
172 lemma C_merge_ub: "C_merge xs ys \<le> length xs + length ys" |
188 by (induction xs ys rule: C_merge.induct) auto |
173 by (induction xs ys rule: C_merge.induct) auto |
189 |
174 |
190 fun C_msort :: "'a::linorder list \<Rightarrow> nat" where |
175 fun C_msort :: "'a::linorder list \<Rightarrow> nat" where |
191 "C_msort xs = |
176 "C_msort xs = |
192 (let n = length xs; |
177 (let n = length xs; |
193 ys = take (n div 2) xs; |
178 ys = take (n div 2) xs; |
194 zs = drop (n div 2) xs |
179 zs = drop (n div 2) xs |
195 in if n \<le> 1 then 0 |
180 in if n \<le> 1 then 0 |
196 else C_msort ys + C_msort zs + C_merge (msort ys) (msort zs))" |
181 else C_msort ys + C_msort zs + C_merge (msort ys) (msort zs))" |
197 |
182 |
198 declare C_msort.simps [simp del] |
183 declare C_msort.simps [simp del] |
199 |
184 |
200 lemma length_merge: "length(merge xs ys) = length xs + length ys" |
185 lemma length_merge: "length(merge xs ys) = length xs + length ys" |
201 apply (induction xs ys rule: merge.induct) |
186 by (induction xs ys rule: merge.induct) auto |
202 apply auto |
|
203 done |
|
204 |
187 |
205 lemma length_msort: "length(msort xs) = length xs" |
188 lemma length_msort: "length(msort xs) = length xs" |
206 proof (induction xs rule: msort.induct) |
189 proof (induction xs rule: msort.induct) |
207 case (1 xs) |
190 case (1 xs) |
208 show ?case |
191 show ?case |
243 qed |
226 qed |
244 qed |
227 qed |
245 |
228 |
246 (* Beware of implicit conversions: *) |
229 (* Beware of implicit conversions: *) |
247 lemma C_msort_log: "length xs = 2^k \<Longrightarrow> C_msort xs \<le> length xs * log 2 (length xs)" |
230 lemma C_msort_log: "length xs = 2^k \<Longrightarrow> C_msort xs \<le> length xs * log 2 (length xs)" |
248 using C_msort_le[of xs k] apply (simp add: log_nat_power algebra_simps) |
231 using C_msort_le[of xs k] |
249 by (metis (mono_tags) numeral_power_eq_of_nat_cancel_iff of_nat_le_iff of_nat_mult) |
232 by (metis log2_of_power_eq mult.commute of_nat_mono of_nat_mult) |
250 |
233 |
251 |
234 |
252 subsection "Bottom-Up Merge Sort" |
235 subsection "Bottom-Up Merge Sort" |
253 |
236 |
254 fun merge_adj :: "('a::linorder) list list \<Rightarrow> 'a list list" where |
237 fun merge_adj :: "('a::linorder) list list \<Rightarrow> 'a list list" where |
255 "merge_adj [] = []" | |
238 "merge_adj [] = []" | |
256 "merge_adj [xs] = [xs]" | |
239 "merge_adj [xs] = [xs]" | |
257 "merge_adj (xs # ys # zss) = merge xs ys # merge_adj zss" |
240 "merge_adj (xs # ys # zss) = merge xs ys # merge_adj zss" |
258 |
241 |
259 text \<open>For the termination proof of \<open>merge_all\<close> below.\<close> |
242 text \<open>For the termination proof of \<open>merge_all\<close> below.\<close> |
260 lemma length_merge_adjacent[simp]: "length (merge_adj xs) = (length xs + 1) div 2" |
243 lemma length_merge_adjacent[simp]: "length (merge_adj xs) = (length xs + 1) div 2" |
261 by (induction xs rule: merge_adj.induct) auto |
244 by (induction xs rule: merge_adj.induct) auto |
262 |
245 |
263 fun merge_all :: "('a::linorder) list list \<Rightarrow> 'a list" where |
246 fun merge_all :: "('a::linorder) list list \<Rightarrow> 'a list" where |
264 "merge_all [] = []" | |
247 "merge_all [] = []" | |
265 "merge_all [xs] = xs" | |
248 "merge_all [xs] = xs" | |
266 "merge_all xss = merge_all (merge_adj xss)" |
249 "merge_all xss = merge_all (merge_adj xss)" |
267 |
250 |
268 definition msort_bu :: "('a::linorder) list \<Rightarrow> 'a list" where |
251 definition msort_bu :: "('a::linorder) list \<Rightarrow> 'a list" where |
269 "msort_bu xs = merge_all (map (\<lambda>x. [x]) xs)" |
252 "msort_bu xs = merge_all (map (\<lambda>x. [x]) xs)" |
270 |
253 |
271 |
254 |
272 subsubsection "Functional Correctness" |
255 subsubsection "Functional Correctness" |
273 |
256 |
274 abbreviation mset_mset :: "'a list list \<Rightarrow> 'a multiset" where |
257 abbreviation mset_mset :: "'a list list \<Rightarrow> 'a multiset" where |
275 "mset_mset xss \<equiv> \<Sum>\<^sub># (image_mset mset (mset xss))" |
258 "mset_mset xss \<equiv> \<Sum>\<^sub># (image_mset mset (mset xss))" |
276 |
259 |
277 lemma mset_merge_adj: |
260 lemma mset_merge_adj: |
278 "mset_mset (merge_adj xss) = mset_mset xss" |
261 "mset_mset (merge_adj xss) = mset_mset xss" |
279 by(induction xss rule: merge_adj.induct) (auto simp: mset_merge) |
262 by(induction xss rule: merge_adj.induct) (auto simp: mset_merge) |
280 |
263 |
281 lemma mset_merge_all: |
264 lemma mset_merge_all: |
282 "mset (merge_all xss) = mset_mset xss" |
265 "mset (merge_all xss) = mset_mset xss" |
283 by(induction xss rule: merge_all.induct) (auto simp: mset_merge mset_merge_adj) |
266 by(induction xss rule: merge_all.induct) (auto simp: mset_merge mset_merge_adj) |
284 |
267 |
285 lemma mset_msort_bu: "mset (msort_bu xs) = mset xs" |
268 lemma mset_msort_bu: "mset (msort_bu xs) = mset xs" |
286 by(simp add: msort_bu_def mset_merge_all multiset.map_comp comp_def) |
269 by(simp add: msort_bu_def mset_merge_all multiset.map_comp comp_def) |
287 |
270 |
288 lemma sorted_merge_adj: |
271 lemma sorted_merge_adj: |
289 "\<forall>xs \<in> set xss. sorted xs \<Longrightarrow> \<forall>xs \<in> set (merge_adj xss). sorted xs" |
272 "\<forall>xs \<in> set xss. sorted xs \<Longrightarrow> \<forall>xs \<in> set (merge_adj xss). sorted xs" |
290 by(induction xss rule: merge_adj.induct) (auto simp: sorted_merge) |
273 by(induction xss rule: merge_adj.induct) (auto simp: sorted_merge) |
291 |
274 |
292 lemma sorted_merge_all: |
275 lemma sorted_merge_all: |
293 "\<forall>xs \<in> set xss. sorted xs \<Longrightarrow> sorted (merge_all xss)" |
276 "\<forall>xs \<in> set xss. sorted xs \<Longrightarrow> sorted (merge_all xss)" |
294 apply(induction xss rule: merge_all.induct) |
277 by (induction xss rule: merge_all.induct) (auto simp add: sorted_merge_adj) |
295 using [[simp_depth_limit=3]] by (auto simp add: sorted_merge_adj) |
|
296 |
278 |
297 lemma sorted_msort_bu: "sorted (msort_bu xs)" |
279 lemma sorted_msort_bu: "sorted (msort_bu xs)" |
298 by(simp add: msort_bu_def sorted_merge_all) |
280 by(simp add: msort_bu_def sorted_merge_all) |
299 |
281 |
300 |
282 |
301 subsubsection "Time Complexity" |
283 subsubsection "Time Complexity" |
302 |
284 |
303 fun C_merge_adj :: "('a::linorder) list list \<Rightarrow> nat" where |
285 fun C_merge_adj :: "('a::linorder) list list \<Rightarrow> nat" where |
304 "C_merge_adj [] = 0" | |
286 "C_merge_adj [] = 0" | |
305 "C_merge_adj [xs] = 0" | |
287 "C_merge_adj [xs] = 0" | |
306 "C_merge_adj (xs # ys # zss) = C_merge xs ys + C_merge_adj zss" |
288 "C_merge_adj (xs # ys # zss) = C_merge xs ys + C_merge_adj zss" |
307 |
289 |
308 fun C_merge_all :: "('a::linorder) list list \<Rightarrow> nat" where |
290 fun C_merge_all :: "('a::linorder) list list \<Rightarrow> nat" where |
309 "C_merge_all [] = 0" | |
291 "C_merge_all [] = 0" | |
310 "C_merge_all [xs] = 0" | |
292 "C_merge_all [xs] = 0" | |
311 "C_merge_all xss = C_merge_adj xss + C_merge_all (merge_adj xss)" |
293 "C_merge_all xss = C_merge_adj xss + C_merge_all (merge_adj xss)" |
312 |
294 |
313 definition C_msort_bu :: "('a::linorder) list \<Rightarrow> nat" where |
295 definition C_msort_bu :: "('a::linorder) list \<Rightarrow> nat" where |
314 "C_msort_bu xs = C_merge_all (map (\<lambda>x. [x]) xs)" |
296 "C_msort_bu xs = C_merge_all (map (\<lambda>x. [x]) xs)" |
315 |
297 |
316 lemma length_merge_adj: |
298 lemma length_merge_adj: |
317 "\<lbrakk> even(length xss); \<forall>xs \<in> set xss. length xs = m \<rbrakk> |
299 "\<lbrakk> even(length xss); \<forall>xs \<in> set xss. length xs = m \<rbrakk> |
318 \<Longrightarrow> \<forall>xs \<in> set (merge_adj xss). length xs = 2*m" |
300 \<Longrightarrow> \<forall>xs \<in> set (merge_adj xss). length xs = 2*m" |
319 by(induction xss rule: merge_adj.induct) (auto simp: length_merge) |
301 by(induction xss rule: merge_adj.induct) (auto simp: length_merge) |
320 |
302 |
321 lemma C_merge_adj: "\<forall>xs \<in> set xss. length xs = m \<Longrightarrow> C_merge_adj xss \<le> m * length xss" |
303 lemma C_merge_adj: "\<forall>xs \<in> set xss. length xs = m \<Longrightarrow> C_merge_adj xss \<le> m * length xss" |
322 proof(induction xss rule: C_merge_adj.induct) |
304 proof(induction xss rule: C_merge_adj.induct) |
323 case 1 thus ?case by simp |
305 case 1 thus ?case by simp |
324 next |
306 next |
352 using k' by (simp add: algebra_simps) |
334 using k' by (simp add: algebra_simps) |
353 finally show ?case . |
335 finally show ?case . |
354 qed |
336 qed |
355 |
337 |
356 corollary C_msort_bu: "length xs = 2 ^ k \<Longrightarrow> C_msort_bu xs \<le> k * 2 ^ k" |
338 corollary C_msort_bu: "length xs = 2 ^ k \<Longrightarrow> C_msort_bu xs \<le> k * 2 ^ k" |
357 using C_merge_all[of "map (\<lambda>x. [x]) xs" 1] by (simp add: C_msort_bu_def) |
339 using C_merge_all[of "map (\<lambda>x. [x]) xs" 1] by (simp add: C_msort_bu_def) |
358 |
340 |
359 |
341 |
360 subsection "Quicksort" |
342 subsection "Quicksort" |
361 |
343 |
362 fun quicksort :: "('a::linorder) list \<Rightarrow> 'a list" where |
344 fun quicksort :: "('a::linorder) list \<Rightarrow> 'a list" where |
363 "quicksort [] = []" | |
345 "quicksort [] = []" | |
364 "quicksort (x#xs) = quicksort (filter (\<lambda>y. y < x) xs) @ [x] @ quicksort (filter (\<lambda>y. x \<le> y) xs)" |
346 "quicksort (x#xs) = quicksort (filter (\<lambda>y. y < x) xs) @ [x] @ quicksort (filter (\<lambda>y. x \<le> y) xs)" |
365 |
347 |
366 lemma mset_quicksort: "mset (quicksort xs) = mset xs" |
348 lemma mset_quicksort: "mset (quicksort xs) = mset xs" |
367 apply (induction xs rule: quicksort.induct) |
349 by (induction xs rule: quicksort.induct) (auto simp: not_le) |
368 apply (auto simp: not_le) |
|
369 done |
|
370 |
350 |
371 lemma set_quicksort: "set (quicksort xs) = set xs" |
351 lemma set_quicksort: "set (quicksort xs) = set xs" |
372 by(rule mset_eq_setD[OF mset_quicksort]) |
352 by(rule mset_eq_setD[OF mset_quicksort]) |
373 |
353 |
374 lemma sorted_quicksort: "sorted (quicksort xs)" |
354 lemma sorted_quicksort: "sorted (quicksort xs)" |
375 apply (induction xs rule: quicksort.induct) |
355 proof (induction xs rule: quicksort.induct) |
376 apply (auto simp add: sorted_append set_quicksort) |
356 qed (auto simp: sorted_append set_quicksort) |
377 done |
|
378 |
357 |
379 |
358 |
380 subsection "Insertion Sort w.r.t. Keys and Stability" |
359 subsection "Insertion Sort w.r.t. Keys and Stability" |
381 |
360 |
382 hide_const List.insort_key |
361 hide_const List.insort_key |
383 |
362 |
384 fun insort1_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
363 fun insort1_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
385 "insort1_key f x [] = [x]" | |
364 "insort1_key f x [] = [x]" | |
386 "insort1_key f x (y # ys) = (if f x \<le> f y then x # y # ys else y # insort1_key f x ys)" |
365 "insort1_key f x (y # ys) = (if f x \<le> f y then x # y # ys else y # insort1_key f x ys)" |
387 |
366 |
388 fun insort_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
367 fun insort_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
389 "insort_key f [] = []" | |
368 "insort_key f [] = []" | |
390 "insort_key f (x # xs) = insort1_key f x (insort_key f xs)" |
369 "insort_key f (x # xs) = insort1_key f x (insort_key f xs)" |
391 |
370 |
392 |
371 |
393 subsubsection "Standard functional correctness" |
372 subsubsection "Standard functional correctness" |
394 |
373 |
395 lemma mset_insort1_key: "mset (insort1_key f x xs) = {#x#} + mset xs" |
374 lemma mset_insort1_key: "mset (insort1_key f x xs) = {#x#} + mset xs" |
396 by(induction xs) simp_all |
375 by(induction xs) simp_all |
397 |
376 |
398 lemma mset_insort_key: "mset (insort_key f xs) = mset xs" |
377 lemma mset_insort_key: "mset (insort_key f xs) = mset xs" |
399 by(induction xs) (simp_all add: mset_insort1_key) |
378 by(induction xs) (simp_all add: mset_insort1_key) |
400 |
379 |
401 (* Inductive proof simpler than derivation from mset lemma: *) |
380 (* Inductive proof simpler than derivation from mset lemma: *) |
402 lemma set_insort1_key: "set (insort1_key f x xs) = {x} \<union> set xs" |
381 lemma set_insort1_key: "set (insort1_key f x xs) = {x} \<union> set xs" |
403 by (induction xs) auto |
382 by (induction xs) auto |
404 |
383 |
405 lemma sorted_insort1_key: "sorted (map f (insort1_key f a xs)) = sorted (map f xs)" |
384 lemma sorted_insort1_key: "sorted (map f (insort1_key f a xs)) = sorted (map f xs)" |
406 by(induction xs)(auto simp: set_insort1_key) |
385 by(induction xs)(auto simp: set_insort1_key) |
407 |
386 |
408 lemma sorted_insort_key: "sorted (map f (insort_key f xs))" |
387 lemma sorted_insort_key: "sorted (map f (insort_key f xs))" |
409 by(induction xs)(simp_all add: sorted_insort1_key) |
388 by(induction xs)(simp_all add: sorted_insort1_key) |
410 |
389 |
411 |
390 |
412 subsubsection "Stability" |
391 subsubsection "Stability" |
413 |
392 |
414 lemma insort1_is_Cons: "\<forall>x\<in>set xs. f a \<le> f x \<Longrightarrow> insort1_key f a xs = a # xs" |
393 lemma insort1_is_Cons: "\<forall>x\<in>set xs. f a \<le> f x \<Longrightarrow> insort1_key f a xs = a # xs" |
415 by (cases xs) auto |
394 by (cases xs) auto |
416 |
395 |
417 lemma filter_insort1_key_neg: |
396 lemma filter_insort1_key_neg: |
418 "\<not> P x \<Longrightarrow> filter P (insort1_key f x xs) = filter P xs" |
397 "\<not> P x \<Longrightarrow> filter P (insort1_key f x xs) = filter P xs" |
419 by (induction xs) simp_all |
398 by (induction xs) simp_all |
420 |
399 |
421 lemma filter_insort1_key_pos: |
400 lemma filter_insort1_key_pos: |
422 "sorted (map f xs) \<Longrightarrow> P x \<Longrightarrow> filter P (insort1_key f x xs) = insort1_key f x (filter P xs)" |
401 "sorted (map f xs) \<Longrightarrow> P x \<Longrightarrow> filter P (insort1_key f x xs) = insort1_key f x (filter P xs)" |
423 by (induction xs) (auto, subst insort1_is_Cons, auto) |
402 by (induction xs) (auto, subst insort1_is_Cons, auto) |
424 |
403 |
425 lemma sort_key_stable: "filter (\<lambda>y. f y = k) (insort_key f xs) = filter (\<lambda>y. f y = k) xs" |
404 lemma sort_key_stable: "filter (\<lambda>y. f y = k) (insort_key f xs) = filter (\<lambda>y. f y = k) xs" |
426 proof (induction xs) |
405 proof (induction xs) |
427 case Nil thus ?case by simp |
406 case Nil thus ?case by simp |
428 next |
407 next |