author | nipkow |
Tue, 17 Jun 2025 14:11:40 +0200 | |
changeset 82733 | 8b537e1af2ec |
parent 82393 | 88064da0ae76 |
permissions | -rw-r--r-- |
69194 | 1 |
(* Title: HOL/Library/Sorting_Algorithms.thy |
2 |
Author: Florian Haftmann, TU Muenchen |
|
3 |
*) |
|
4 |
||
5 |
theory Sorting_Algorithms |
|
6 |
imports Main Multiset Comparator |
|
7 |
begin |
|
8 |
||
9 |
section \<open>Stably sorted lists\<close> |
|
10 |
||
82388 | 11 |
abbreviation (input) stable_segment :: \<open>'a comparator \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a list\<close> |
12 |
where \<open>stable_segment cmp x \<equiv> filter (\<lambda>y. compare cmp x y = Equiv)\<close> |
|
69194 | 13 |
|
82388 | 14 |
fun sorted :: \<open>'a comparator \<Rightarrow> 'a list \<Rightarrow> bool\<close> |
15 |
where sorted_Nil: \<open>sorted cmp [] \<longleftrightarrow> True\<close> |
|
16 |
| sorted_single: \<open>sorted cmp [x] \<longleftrightarrow> True\<close> |
|
17 |
| sorted_rec: \<open>sorted cmp (y # x # xs) \<longleftrightarrow> compare cmp y x \<noteq> Greater \<and> sorted cmp (x # xs)\<close> |
|
69194 | 18 |
|
19 |
lemma sorted_ConsI: |
|
82388 | 20 |
\<open>sorted cmp (x # xs)\<close> if \<open>sorted cmp xs\<close> |
21 |
and \<open>\<And>y ys. xs = y # ys \<Longrightarrow> compare cmp x y \<noteq> Greater\<close> |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
22 |
using that by (cases xs) simp_all |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
23 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
24 |
lemma sorted_Cons_imp_sorted: |
82388 | 25 |
\<open>sorted cmp xs\<close> if \<open>sorted cmp (x # xs)\<close> |
69194 | 26 |
using that by (cases xs) simp_all |
27 |
||
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
28 |
lemma sorted_Cons_imp_not_less: |
82388 | 29 |
\<open>compare cmp y x \<noteq> Greater\<close> if \<open>sorted cmp (y # xs)\<close> |
30 |
and \<open>x \<in> set xs\<close> |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
31 |
using that by (induction xs arbitrary: y) (auto dest: compare.trans_not_greater) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
32 |
|
69194 | 33 |
lemma sorted_induct [consumes 1, case_names Nil Cons, induct pred: sorted]: |
82388 | 34 |
\<open>P xs\<close> if \<open>sorted cmp xs\<close> and \<open>P []\<close> |
35 |
and *: \<open>\<And>x xs. sorted cmp xs \<Longrightarrow> P xs |
|
36 |
\<Longrightarrow> (\<And>y. y \<in> set xs \<Longrightarrow> compare cmp x y \<noteq> Greater) \<Longrightarrow> P (x # xs)\<close> |
|
69194 | 37 |
using \<open>sorted cmp xs\<close> proof (induction xs) |
38 |
case Nil |
|
39 |
show ?case |
|
40 |
by (rule \<open>P []\<close>) |
|
41 |
next |
|
42 |
case (Cons x xs) |
|
82388 | 43 |
from \<open>sorted cmp (x # xs)\<close> have \<open>sorted cmp xs\<close> |
69194 | 44 |
by (cases xs) simp_all |
82388 | 45 |
moreover have \<open>P xs\<close> using \<open>sorted cmp xs\<close> |
69194 | 46 |
by (rule Cons.IH) |
82388 | 47 |
moreover have \<open>compare cmp x y \<noteq> Greater\<close> if \<open>y \<in> set xs\<close> for y |
69194 | 48 |
using that \<open>sorted cmp (x # xs)\<close> proof (induction xs) |
49 |
case Nil |
|
50 |
then show ?case |
|
51 |
by simp |
|
52 |
next |
|
53 |
case (Cons z zs) |
|
54 |
then show ?case |
|
55 |
proof (cases zs) |
|
56 |
case Nil |
|
57 |
with Cons.prems show ?thesis |
|
58 |
by simp |
|
59 |
next |
|
60 |
case (Cons w ws) |
|
82388 | 61 |
with Cons.prems have \<open>compare cmp z w \<noteq> Greater\<close> \<open>compare cmp x z \<noteq> Greater\<close> |
69194 | 62 |
by auto |
82388 | 63 |
then have \<open>compare cmp x w \<noteq> Greater\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
64 |
by (auto dest: compare.trans_not_greater) |
69194 | 65 |
with Cons show ?thesis |
66 |
using Cons.prems Cons.IH by auto |
|
67 |
qed |
|
68 |
qed |
|
69 |
ultimately show ?case |
|
70 |
by (rule *) |
|
71 |
qed |
|
72 |
||
73 |
lemma sorted_induct_remove1 [consumes 1, case_names Nil minimum]: |
|
82388 | 74 |
\<open>P xs\<close> if \<open>sorted cmp xs\<close> and \<open>P []\<close> |
75 |
and *: \<open>\<And>x xs. sorted cmp xs \<Longrightarrow> P (remove1 x xs) |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
76 |
\<Longrightarrow> x \<in> set xs \<Longrightarrow> hd (stable_segment cmp x xs) = x \<Longrightarrow> (\<And>y. y \<in> set xs \<Longrightarrow> compare cmp x y \<noteq> Greater) |
82388 | 77 |
\<Longrightarrow> P xs\<close> |
69194 | 78 |
using \<open>sorted cmp xs\<close> proof (induction xs) |
79 |
case Nil |
|
80 |
show ?case |
|
81 |
by (rule \<open>P []\<close>) |
|
82 |
next |
|
83 |
case (Cons x xs) |
|
82388 | 84 |
then have \<open>sorted cmp (x # xs)\<close> |
69194 | 85 |
by (simp add: sorted_ConsI) |
86 |
moreover note Cons.IH |
|
82388 | 87 |
moreover have \<open>\<And>y. compare cmp x y = Greater \<Longrightarrow> y \<in> set xs \<Longrightarrow> False\<close> |
69194 | 88 |
using Cons.hyps by simp |
89 |
ultimately show ?case |
|
82388 | 90 |
by (auto intro!: * [of \<open>x # xs\<close> x]) blast |
69194 | 91 |
qed |
92 |
||
93 |
lemma sorted_remove1: |
|
82388 | 94 |
\<open>sorted cmp (remove1 x xs)\<close> if \<open>sorted cmp xs\<close> |
95 |
proof (cases \<open>x \<in> set xs\<close>) |
|
69194 | 96 |
case False |
97 |
with that show ?thesis |
|
98 |
by (simp add: remove1_idem) |
|
99 |
next |
|
100 |
case True |
|
101 |
with that show ?thesis proof (induction xs) |
|
102 |
case Nil |
|
103 |
then show ?case |
|
104 |
by simp |
|
105 |
next |
|
106 |
case (Cons y ys) |
|
82388 | 107 |
show ?case proof (cases \<open>x = y\<close>) |
69194 | 108 |
case True |
109 |
with Cons.hyps show ?thesis |
|
110 |
by simp |
|
111 |
next |
|
112 |
case False |
|
82388 | 113 |
then have \<open>sorted cmp (remove1 x ys)\<close> |
69194 | 114 |
using Cons.IH Cons.prems by auto |
82388 | 115 |
then have \<open>sorted cmp (y # remove1 x ys)\<close> |
69194 | 116 |
proof (rule sorted_ConsI) |
117 |
fix z zs |
|
82388 | 118 |
assume \<open>remove1 x ys = z # zs\<close> |
119 |
with \<open>x \<noteq> y\<close> have \<open>z \<in> set ys\<close> |
|
69194 | 120 |
using notin_set_remove1 [of z ys x] by auto |
82388 | 121 |
then show \<open>compare cmp y z \<noteq> Greater\<close> |
69194 | 122 |
by (rule Cons.hyps(2)) |
123 |
qed |
|
124 |
with False show ?thesis |
|
125 |
by simp |
|
126 |
qed |
|
127 |
qed |
|
128 |
qed |
|
129 |
||
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
130 |
lemma sorted_stable_segment: |
82388 | 131 |
\<open>sorted cmp (stable_segment cmp x xs)\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
132 |
proof (induction xs) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
133 |
case Nil |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
134 |
show ?case |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
135 |
by simp |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
136 |
next |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
137 |
case (Cons y ys) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
138 |
then show ?case |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
139 |
by (auto intro!: sorted_ConsI simp add: filter_eq_Cons_iff compare.sym) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
140 |
(auto dest: compare.trans_equiv simp add: compare.sym compare.greater_iff_sym_less) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
141 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
142 |
qed |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
143 |
|
82388 | 144 |
primrec insort :: \<open>'a comparator \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a list\<close> |
145 |
where \<open>insort cmp y [] = [y]\<close> |
|
146 |
| \<open>insort cmp y (x # xs) = (if compare cmp y x \<noteq> Greater |
|
69194 | 147 |
then y # x # xs |
82388 | 148 |
else x # insort cmp y xs)\<close> |
69194 | 149 |
|
150 |
lemma mset_insort [simp]: |
|
82388 | 151 |
\<open>mset (insort cmp x xs) = add_mset x (mset xs)\<close> |
69194 | 152 |
by (induction xs) simp_all |
153 |
||
154 |
lemma length_insort [simp]: |
|
82388 | 155 |
\<open>length (insort cmp x xs) = Suc (length xs)\<close> |
69194 | 156 |
by (induction xs) simp_all |
157 |
||
158 |
lemma sorted_insort: |
|
82388 | 159 |
\<open>sorted cmp (insort cmp x xs)\<close> if \<open>sorted cmp xs\<close> |
69194 | 160 |
using that proof (induction xs) |
161 |
case Nil |
|
162 |
then show ?case |
|
163 |
by simp |
|
164 |
next |
|
165 |
case (Cons y ys) |
|
166 |
then show ?case by (cases ys) |
|
167 |
(auto, simp_all add: compare.greater_iff_sym_less) |
|
168 |
qed |
|
169 |
||
170 |
lemma stable_insort_equiv: |
|
82388 | 171 |
\<open>stable_segment cmp y (insort cmp x xs) = x # stable_segment cmp y xs\<close> |
172 |
if \<open>compare cmp y x = Equiv\<close> |
|
69194 | 173 |
proof (induction xs) |
174 |
case Nil |
|
175 |
from that show ?case |
|
176 |
by simp |
|
177 |
next |
|
178 |
case (Cons z xs) |
|
82388 | 179 |
moreover from that have \<open>compare cmp y z = Equiv \<Longrightarrow> compare cmp z x = Equiv\<close> |
69194 | 180 |
by (auto intro: compare.trans_equiv simp add: compare.sym) |
181 |
ultimately show ?case |
|
182 |
using that by (auto simp add: compare.greater_iff_sym_less) |
|
183 |
qed |
|
184 |
||
185 |
lemma stable_insort_not_equiv: |
|
82388 | 186 |
\<open>stable_segment cmp y (insort cmp x xs) = stable_segment cmp y xs\<close> |
187 |
if \<open>compare cmp y x \<noteq> Equiv\<close> |
|
69194 | 188 |
using that by (induction xs) simp_all |
189 |
||
190 |
lemma remove1_insort_same_eq [simp]: |
|
82388 | 191 |
\<open>remove1 x (insort cmp x xs) = xs\<close> |
69194 | 192 |
by (induction xs) simp_all |
193 |
||
194 |
lemma insort_eq_ConsI: |
|
82388 | 195 |
\<open>insort cmp x xs = x # xs\<close> |
196 |
if \<open>sorted cmp xs\<close> \<open>\<And>y. y \<in> set xs \<Longrightarrow> compare cmp x y \<noteq> Greater\<close> |
|
69194 | 197 |
using that by (induction xs) (simp_all add: compare.greater_iff_sym_less) |
198 |
||
199 |
lemma remove1_insort_not_same_eq [simp]: |
|
82388 | 200 |
\<open>remove1 y (insort cmp x xs) = insort cmp x (remove1 y xs)\<close> |
201 |
if \<open>sorted cmp xs\<close> \<open>x \<noteq> y\<close> |
|
69194 | 202 |
using that proof (induction xs) |
203 |
case Nil |
|
204 |
then show ?case |
|
205 |
by simp |
|
206 |
next |
|
207 |
case (Cons z zs) |
|
208 |
show ?case |
|
82388 | 209 |
proof (cases \<open>compare cmp x z = Greater\<close>) |
69194 | 210 |
case True |
211 |
with Cons show ?thesis |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
212 |
by simp |
69194 | 213 |
next |
214 |
case False |
|
82388 | 215 |
then have \<open>compare cmp x y \<noteq> Greater\<close> if \<open>y \<in> set zs\<close> for y |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
216 |
using that Cons.hyps |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
217 |
by (auto dest: compare.trans_not_greater) |
69194 | 218 |
with Cons show ?thesis |
219 |
by (simp add: insort_eq_ConsI) |
|
220 |
qed |
|
221 |
qed |
|
222 |
||
223 |
lemma insort_remove1_same_eq: |
|
82388 | 224 |
\<open>insort cmp x (remove1 x xs) = xs\<close> |
225 |
if \<open>sorted cmp xs\<close> and \<open>x \<in> set xs\<close> and \<open>hd (stable_segment cmp x xs) = x\<close> |
|
69194 | 226 |
using that proof (induction xs) |
227 |
case Nil |
|
228 |
then show ?case |
|
229 |
by simp |
|
230 |
next |
|
231 |
case (Cons y ys) |
|
82388 | 232 |
then have \<open>compare cmp x y \<noteq> Less\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
233 |
by (auto simp add: compare.greater_iff_sym_less) |
82388 | 234 |
then consider \<open>compare cmp x y = Greater\<close> | \<open>compare cmp x y = Equiv\<close> |
235 |
by (cases \<open>compare cmp x y\<close>) auto |
|
69194 | 236 |
then show ?case proof cases |
237 |
case 1 |
|
238 |
with Cons.prems Cons.IH show ?thesis |
|
239 |
by auto |
|
240 |
next |
|
241 |
case 2 |
|
82388 | 242 |
with Cons.prems have \<open>x = y\<close> |
69194 | 243 |
by simp |
244 |
with Cons.hyps show ?thesis |
|
245 |
by (simp add: insort_eq_ConsI) |
|
246 |
qed |
|
247 |
qed |
|
248 |
||
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
249 |
lemma sorted_append_iff: |
82388 | 250 |
\<open>sorted cmp (xs @ ys) \<longleftrightarrow> sorted cmp xs \<and> sorted cmp ys |
251 |
\<and> (\<forall>x \<in> set xs. \<forall>y \<in> set ys. compare cmp x y \<noteq> Greater)\<close> (is \<open>?P \<longleftrightarrow> ?R \<and> ?S \<and> ?Q\<close>) |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
252 |
proof |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
253 |
assume ?P |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
254 |
have ?R |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
255 |
using \<open>?P\<close> by (induction xs) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
256 |
(auto simp add: sorted_Cons_imp_not_less, |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
257 |
auto simp add: sorted_Cons_imp_sorted intro: sorted_ConsI) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
258 |
moreover have ?S |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
259 |
using \<open>?P\<close> by (induction xs) (auto dest: sorted_Cons_imp_sorted) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
260 |
moreover have ?Q |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
261 |
using \<open>?P\<close> by (induction xs) (auto simp add: sorted_Cons_imp_not_less, |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
262 |
simp add: sorted_Cons_imp_sorted) |
82388 | 263 |
ultimately show \<open>?R \<and> ?S \<and> ?Q\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
264 |
by simp |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
265 |
next |
82388 | 266 |
assume \<open>?R \<and> ?S \<and> ?Q\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
267 |
then have ?R ?S ?Q |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
268 |
by simp_all |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
269 |
then show ?P |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
270 |
by (induction xs) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
271 |
(auto simp add: append_eq_Cons_conv intro!: sorted_ConsI) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
272 |
qed |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
273 |
|
82388 | 274 |
definition sort :: \<open>'a comparator \<Rightarrow> 'a list \<Rightarrow> 'a list\<close> |
275 |
where \<open>sort cmp xs = foldr (insort cmp) xs []\<close> |
|
69194 | 276 |
|
277 |
lemma sort_simps [simp]: |
|
82388 | 278 |
\<open>sort cmp [] = []\<close> |
279 |
\<open>sort cmp (x # xs) = insort cmp x (sort cmp xs)\<close> |
|
69194 | 280 |
by (simp_all add: sort_def) |
281 |
||
282 |
lemma mset_sort [simp]: |
|
82388 | 283 |
\<open>mset (sort cmp xs) = mset xs\<close> |
69194 | 284 |
by (induction xs) simp_all |
285 |
||
286 |
lemma length_sort [simp]: |
|
82388 | 287 |
\<open>length (sort cmp xs) = length xs\<close> |
69194 | 288 |
by (induction xs) simp_all |
289 |
||
290 |
lemma sorted_sort [simp]: |
|
82388 | 291 |
\<open>sorted cmp (sort cmp xs)\<close> |
69194 | 292 |
by (induction xs) (simp_all add: sorted_insort) |
293 |
||
294 |
lemma stable_sort: |
|
82388 | 295 |
\<open>stable_segment cmp x (sort cmp xs) = stable_segment cmp x xs\<close> |
69194 | 296 |
by (induction xs) (simp_all add: stable_insort_equiv stable_insort_not_equiv) |
297 |
||
298 |
lemma sort_remove1_eq [simp]: |
|
82388 | 299 |
\<open>sort cmp (remove1 x xs) = remove1 x (sort cmp xs)\<close> |
69194 | 300 |
by (induction xs) simp_all |
301 |
||
302 |
lemma set_insort [simp]: |
|
82388 | 303 |
\<open>set (insort cmp x xs) = insert x (set xs)\<close> |
69194 | 304 |
by (induction xs) auto |
305 |
||
306 |
lemma set_sort [simp]: |
|
82388 | 307 |
\<open>set (sort cmp xs) = set xs\<close> |
69194 | 308 |
by (induction xs) auto |
309 |
||
310 |
lemma sort_eqI: |
|
82388 | 311 |
\<open>sort cmp ys = xs\<close> |
312 |
if permutation: \<open>mset ys = mset xs\<close> |
|
313 |
and sorted: \<open>sorted cmp xs\<close> |
|
314 |
and stable: \<open>\<And>y. y \<in> set ys \<Longrightarrow> |
|
315 |
stable_segment cmp y ys = stable_segment cmp y xs\<close> |
|
69194 | 316 |
proof - |
82388 | 317 |
have stable': \<open>stable_segment cmp y ys = |
318 |
stable_segment cmp y xs\<close> for y |
|
319 |
proof (cases \<open>\<exists>x\<in>set ys. compare cmp y x = Equiv\<close>) |
|
69194 | 320 |
case True |
82388 | 321 |
then obtain z where \<open>z \<in> set ys\<close> and \<open>compare cmp y z = Equiv\<close> |
69194 | 322 |
by auto |
82388 | 323 |
then have \<open>compare cmp y x = Equiv \<longleftrightarrow> compare cmp z x = Equiv\<close> for x |
69194 | 324 |
by (meson compare.sym compare.trans_equiv) |
82388 | 325 |
moreover have \<open>stable_segment cmp z ys = |
326 |
stable_segment cmp z xs\<close> |
|
69194 | 327 |
using \<open>z \<in> set ys\<close> by (rule stable) |
328 |
ultimately show ?thesis |
|
329 |
by simp |
|
330 |
next |
|
331 |
case False |
|
82388 | 332 |
moreover from permutation have \<open>set ys = set xs\<close> |
69194 | 333 |
by (rule mset_eq_setD) |
334 |
ultimately show ?thesis |
|
335 |
by simp |
|
336 |
qed |
|
337 |
show ?thesis |
|
338 |
using sorted permutation stable' proof (induction xs arbitrary: ys rule: sorted_induct_remove1) |
|
339 |
case Nil |
|
340 |
then show ?case |
|
341 |
by simp |
|
342 |
next |
|
343 |
case (minimum x xs) |
|
82388 | 344 |
from \<open>mset ys = mset xs\<close> have ys: \<open>set ys = set xs\<close> |
69194 | 345 |
by (rule mset_eq_setD) |
82388 | 346 |
then have \<open>compare cmp x y \<noteq> Greater\<close> if \<open>y \<in> set ys\<close> for y |
69194 | 347 |
using that minimum.hyps by simp |
82388 | 348 |
from minimum.prems have stable: \<open>stable_segment cmp x ys = stable_segment cmp x xs\<close> |
69194 | 349 |
by simp |
82388 | 350 |
have \<open>sort cmp (remove1 x ys) = remove1 x xs\<close> |
69194 | 351 |
by (rule minimum.IH) (simp_all add: minimum.prems filter_remove1) |
82388 | 352 |
then have \<open>remove1 x (sort cmp ys) = remove1 x xs\<close> |
69194 | 353 |
by simp |
82388 | 354 |
then have \<open>insort cmp x (remove1 x (sort cmp ys)) = |
355 |
insort cmp x (remove1 x xs)\<close> |
|
69194 | 356 |
by simp |
82388 | 357 |
also from minimum.hyps ys stable have \<open>insort cmp x (remove1 x (sort cmp ys)) = sort cmp ys\<close> |
69194 | 358 |
by (simp add: stable_sort insort_remove1_same_eq) |
82388 | 359 |
also from minimum.hyps have \<open>insort cmp x (remove1 x xs) = xs\<close> |
69194 | 360 |
by (simp add: insort_remove1_same_eq) |
361 |
finally show ?case . |
|
362 |
qed |
|
363 |
qed |
|
364 |
||
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
365 |
lemma filter_insort: |
82388 | 366 |
\<open>filter P (insort cmp x xs) = insort cmp x (filter P xs)\<close> |
367 |
if \<open>sorted cmp xs\<close> and \<open>P x\<close> |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
368 |
using that by (induction xs) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
369 |
(auto simp add: compare.trans_not_greater insort_eq_ConsI) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
370 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
371 |
lemma filter_insort_triv: |
82388 | 372 |
\<open>filter P (insort cmp x xs) = filter P xs\<close> |
373 |
if \<open>\<not> P x\<close> |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
374 |
using that by (induction xs) simp_all |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
375 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
376 |
lemma filter_sort: |
82388 | 377 |
\<open>filter P (sort cmp xs) = sort cmp (filter P xs)\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
378 |
by (induction xs) (auto simp add: filter_insort filter_insort_triv) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
379 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
380 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
381 |
section \<open>Alternative sorting algorithms\<close> |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
382 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
383 |
subsection \<open>Quicksort\<close> |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
384 |
|
82388 | 385 |
definition quicksort :: \<open>'a comparator \<Rightarrow> 'a list \<Rightarrow> 'a list\<close> |
386 |
where quicksort_is_sort [simp]: \<open>quicksort = sort\<close> |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
387 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
388 |
lemma sort_by_quicksort: |
82388 | 389 |
\<open>sort = quicksort\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
390 |
by simp |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
391 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
392 |
lemma sort_by_quicksort_rec: |
82388 | 393 |
\<open>sort cmp xs = sort cmp [x\<leftarrow>xs. compare cmp x (xs ! (length xs div 2)) = Less] |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
394 |
@ stable_segment cmp (xs ! (length xs div 2)) xs |
82388 | 395 |
@ sort cmp [x\<leftarrow>xs. compare cmp x (xs ! (length xs div 2)) = Greater]\<close> (is \<open>_ = ?rhs\<close>) |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
396 |
proof (rule sort_eqI) |
82388 | 397 |
show \<open>mset xs = mset ?rhs\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
398 |
by (rule multiset_eqI) (auto simp add: compare.sym intro: comp.exhaust) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
399 |
next |
82388 | 400 |
show \<open>sorted cmp ?rhs\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
401 |
by (auto simp add: sorted_append_iff sorted_stable_segment compare.equiv_subst_right dest: compare.trans_greater) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
402 |
next |
82388 | 403 |
let ?pivot = \<open>xs ! (length xs div 2)\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
404 |
fix l |
82388 | 405 |
have \<open>compare cmp x ?pivot = comp \<and> compare cmp l x = Equiv |
406 |
\<longleftrightarrow> compare cmp l ?pivot = comp \<and> compare cmp l x = Equiv\<close> for x comp |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
407 |
proof - |
82388 | 408 |
have \<open>compare cmp x ?pivot = comp \<longleftrightarrow> compare cmp l ?pivot = comp\<close> |
409 |
if \<open>compare cmp l x = Equiv\<close> |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
410 |
using that by (simp add: compare.equiv_subst_left compare.sym) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
411 |
then show ?thesis by blast |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
412 |
qed |
82388 | 413 |
then show \<open>stable_segment cmp l xs = stable_segment cmp l ?rhs\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
414 |
by (simp add: stable_sort compare.sym [of _ ?pivot]) |
82388 | 415 |
(cases \<open>compare cmp l ?pivot\<close>, simp_all) |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
416 |
qed |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
417 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
418 |
context |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
419 |
begin |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
420 |
|
82388 | 421 |
qualified definition partition :: \<open>'a comparator \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a list \<times> 'a list \<times> 'a list\<close> |
422 |
where \<open>partition cmp pivot xs = |
|
423 |
([x \<leftarrow> xs. compare cmp x pivot = Less], stable_segment cmp pivot xs, [x \<leftarrow> xs. compare cmp x pivot = Greater])\<close> |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
424 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
425 |
qualified lemma partition_code [code]: |
82388 | 426 |
\<open>partition cmp pivot [] = ([], [], [])\<close> |
427 |
\<open>partition cmp pivot (x # xs) = |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
428 |
(let (lts, eqs, gts) = partition cmp pivot xs |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
429 |
in case compare cmp x pivot of |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
430 |
Less \<Rightarrow> (x # lts, eqs, gts) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
431 |
| Equiv \<Rightarrow> (lts, x # eqs, gts) |
82388 | 432 |
| Greater \<Rightarrow> (lts, eqs, x # gts))\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
433 |
using comp.exhaust by (auto simp add: partition_def Let_def compare.sym [of _ pivot]) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
434 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
435 |
lemma quicksort_code [code]: |
82388 | 436 |
\<open>quicksort cmp xs = |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
437 |
(case xs of |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
438 |
[] \<Rightarrow> [] |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
439 |
| [x] \<Rightarrow> xs |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
440 |
| [x, y] \<Rightarrow> (if compare cmp x y \<noteq> Greater then xs else [y, x]) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
441 |
| _ \<Rightarrow> |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
442 |
let (lts, eqs, gts) = partition cmp (xs ! (length xs div 2)) xs |
82388 | 443 |
in quicksort cmp lts @ eqs @ quicksort cmp gts)\<close> |
444 |
proof (cases \<open>length xs \<ge> 3\<close>) |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
445 |
case False |
82388 | 446 |
then have \<open>length xs \<in> {0, 1, 2}\<close> |
69250 | 447 |
by (auto simp add: not_le le_less less_antisym) |
82388 | 448 |
then consider \<open>xs = []\<close> | x where \<open>xs = [x]\<close> | x y where \<open>xs = [x, y]\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
449 |
by (auto simp add: length_Suc_conv numeral_2_eq_2) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
450 |
then show ?thesis |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
451 |
by cases simp_all |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
452 |
next |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
453 |
case True |
82388 | 454 |
then obtain x y z zs where \<open>xs = x # y # z # zs\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
455 |
by (metis le_0_eq length_0_conv length_Cons list.exhaust not_less_eq_eq numeral_3_eq_3) |
82388 | 456 |
moreover have \<open>quicksort cmp xs = |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
457 |
(let (lts, eqs, gts) = partition cmp (xs ! (length xs div 2)) xs |
82388 | 458 |
in quicksort cmp lts @ eqs @ quicksort cmp gts)\<close> |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
459 |
using sort_by_quicksort_rec [of cmp xs] by (simp add: partition_def) |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
460 |
ultimately show ?thesis |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
461 |
by simp |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
462 |
qed |
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
463 |
|
69194 | 464 |
end |
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
465 |
|
69250 | 466 |
|
467 |
subsection \<open>Mergesort\<close> |
|
468 |
||
82388 | 469 |
definition mergesort :: \<open>'a comparator \<Rightarrow> 'a list \<Rightarrow> 'a list\<close> |
470 |
where mergesort_is_sort [simp]: \<open>mergesort = sort\<close> |
|
69250 | 471 |
|
472 |
lemma sort_by_mergesort: |
|
82388 | 473 |
\<open>sort = mergesort\<close> |
69250 | 474 |
by simp |
475 |
||
476 |
context |
|
82388 | 477 |
fixes cmp :: \<open>'a comparator\<close> |
69250 | 478 |
begin |
479 |
||
82388 | 480 |
qualified function merge :: \<open>'a list \<Rightarrow> 'a list \<Rightarrow> 'a list\<close> |
481 |
where \<open>merge [] ys = ys\<close> |
|
482 |
| \<open>merge xs [] = xs\<close> |
|
483 |
| \<open>merge (x # xs) (y # ys) = (if compare cmp x y = Greater |
|
484 |
then y # merge (x # xs) ys else x # merge xs (y # ys))\<close> |
|
69250 | 485 |
by pat_completeness auto |
486 |
||
487 |
qualified termination by lexicographic_order |
|
488 |
||
489 |
lemma mset_merge: |
|
82388 | 490 |
\<open>mset (merge xs ys) = mset xs + mset ys\<close> |
69250 | 491 |
by (induction xs ys rule: merge.induct) simp_all |
492 |
||
493 |
lemma merge_eq_Cons_imp: |
|
82388 | 494 |
\<open>xs \<noteq> [] \<and> z = hd xs \<or> ys \<noteq> [] \<and> z = hd ys\<close> |
495 |
if \<open>merge xs ys = z # zs\<close> |
|
69250 | 496 |
using that by (induction xs ys rule: merge.induct) (auto split: if_splits) |
497 |
||
498 |
lemma filter_merge: |
|
82388 | 499 |
\<open>filter P (merge xs ys) = merge (filter P xs) (filter P ys)\<close> |
500 |
if \<open>sorted cmp xs\<close> and \<open>sorted cmp ys\<close> |
|
69250 | 501 |
using that proof (induction xs ys rule: merge.induct) |
502 |
case (1 ys) |
|
503 |
then show ?case |
|
504 |
by simp |
|
505 |
next |
|
506 |
case (2 xs) |
|
507 |
then show ?case |
|
508 |
by simp |
|
509 |
next |
|
510 |
case (3 x xs y ys) |
|
511 |
show ?case |
|
82388 | 512 |
proof (cases \<open>compare cmp x y = Greater\<close>) |
69250 | 513 |
case True |
82388 | 514 |
with 3 have hyp: \<open>filter P (merge (x # xs) ys) = |
515 |
merge (filter P (x # xs)) (filter P ys)\<close> |
|
69250 | 516 |
by (simp add: sorted_Cons_imp_sorted) |
517 |
show ?thesis |
|
82388 | 518 |
proof (cases \<open>\<not> P x \<and> P y\<close>) |
69250 | 519 |
case False |
520 |
with \<open>compare cmp x y = Greater\<close> show ?thesis |
|
521 |
by (auto simp add: hyp) |
|
522 |
next |
|
523 |
case True |
|
524 |
from \<open>compare cmp x y = Greater\<close> "3.prems" |
|
82388 | 525 |
have *: \<open>compare cmp z y = Greater\<close> if \<open>z \<in> set (filter P xs)\<close> for z |
69250 | 526 |
using that by (auto dest: compare.trans_not_greater sorted_Cons_imp_not_less) |
527 |
from \<open>compare cmp x y = Greater\<close> show ?thesis |
|
82388 | 528 |
by (cases \<open>filter P xs\<close>) (simp_all add: hyp *) |
69250 | 529 |
qed |
530 |
next |
|
531 |
case False |
|
82388 | 532 |
with 3 have hyp: \<open>filter P (merge xs (y # ys)) = |
533 |
merge (filter P xs) (filter P (y # ys))\<close> |
|
69250 | 534 |
by (simp add: sorted_Cons_imp_sorted) |
535 |
show ?thesis |
|
82388 | 536 |
proof (cases \<open>P x \<and> \<not> P y\<close>) |
69250 | 537 |
case False |
538 |
with \<open>compare cmp x y \<noteq> Greater\<close> show ?thesis |
|
539 |
by (auto simp add: hyp) |
|
540 |
next |
|
541 |
case True |
|
542 |
from \<open>compare cmp x y \<noteq> Greater\<close> "3.prems" |
|
82388 | 543 |
have *: \<open>compare cmp x z \<noteq> Greater\<close> if \<open>z \<in> set (filter P ys)\<close> for z |
69250 | 544 |
using that by (auto dest: compare.trans_not_greater sorted_Cons_imp_not_less) |
545 |
from \<open>compare cmp x y \<noteq> Greater\<close> show ?thesis |
|
82388 | 546 |
by (cases \<open>filter P ys\<close>) (simp_all add: hyp *) |
69250 | 547 |
qed |
548 |
qed |
|
549 |
qed |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
550 |
|
69250 | 551 |
lemma sorted_merge: |
82388 | 552 |
\<open>sorted cmp (merge xs ys)\<close> if \<open>sorted cmp xs\<close> and \<open>sorted cmp ys\<close> |
69250 | 553 |
using that proof (induction xs ys rule: merge.induct) |
554 |
case (1 ys) |
|
555 |
then show ?case |
|
556 |
by simp |
|
557 |
next |
|
558 |
case (2 xs) |
|
559 |
then show ?case |
|
560 |
by simp |
|
561 |
next |
|
562 |
case (3 x xs y ys) |
|
563 |
show ?case |
|
82388 | 564 |
proof (cases \<open>compare cmp x y = Greater\<close>) |
69250 | 565 |
case True |
82388 | 566 |
with 3 have \<open>sorted cmp (merge (x # xs) ys)\<close> |
69250 | 567 |
by (simp add: sorted_Cons_imp_sorted) |
82388 | 568 |
then have \<open>sorted cmp (y # merge (x # xs) ys)\<close> |
69250 | 569 |
proof (rule sorted_ConsI) |
570 |
fix z zs |
|
82388 | 571 |
assume \<open>merge (x # xs) ys = z # zs\<close> |
572 |
with 3(4) True show \<open>compare cmp y z \<noteq> Greater\<close> |
|
69250 | 573 |
by (clarsimp simp add: sorted_Cons_imp_sorted dest!: merge_eq_Cons_imp) |
574 |
(auto simp add: compare.asym_greater sorted_Cons_imp_not_less) |
|
575 |
qed |
|
576 |
with True show ?thesis |
|
577 |
by simp |
|
578 |
next |
|
579 |
case False |
|
82388 | 580 |
with 3 have \<open>sorted cmp (merge xs (y # ys))\<close> |
69250 | 581 |
by (simp add: sorted_Cons_imp_sorted) |
82388 | 582 |
then have \<open>sorted cmp (x # merge xs (y # ys))\<close> |
69250 | 583 |
proof (rule sorted_ConsI) |
584 |
fix z zs |
|
82388 | 585 |
assume \<open>merge xs (y # ys) = z # zs\<close> |
586 |
with 3(3) False show \<open>compare cmp x z \<noteq> Greater\<close> |
|
69250 | 587 |
by (clarsimp simp add: sorted_Cons_imp_sorted dest!: merge_eq_Cons_imp) |
588 |
(auto simp add: compare.asym_greater sorted_Cons_imp_not_less) |
|
589 |
qed |
|
590 |
with False show ?thesis |
|
591 |
by simp |
|
592 |
qed |
|
593 |
qed |
|
594 |
||
595 |
lemma merge_eq_appendI: |
|
82388 | 596 |
\<open>merge xs ys = xs @ ys\<close> |
597 |
if \<open>\<And>x y. x \<in> set xs \<Longrightarrow> y \<in> set ys \<Longrightarrow> compare cmp x y \<noteq> Greater\<close> |
|
69250 | 598 |
using that by (induction xs ys rule: merge.induct) simp_all |
599 |
||
600 |
lemma merge_stable_segments: |
|
82388 | 601 |
\<open>merge (stable_segment cmp l xs) (stable_segment cmp l ys) = |
602 |
stable_segment cmp l xs @ stable_segment cmp l ys\<close> |
|
69250 | 603 |
by (rule merge_eq_appendI) (auto dest: compare.trans_equiv_greater) |
604 |
||
605 |
lemma sort_by_mergesort_rec: |
|
82388 | 606 |
\<open>sort cmp xs = |
69250 | 607 |
merge (sort cmp (take (length xs div 2) xs)) |
82388 | 608 |
(sort cmp (drop (length xs div 2) xs))\<close> (is \<open>_ = ?rhs\<close>) |
69250 | 609 |
proof (rule sort_eqI) |
82388 | 610 |
have \<open>mset (take (length xs div 2) xs) + mset (drop (length xs div 2) xs) = |
611 |
mset (take (length xs div 2) xs @ drop (length xs div 2) xs)\<close> |
|
69250 | 612 |
by (simp only: mset_append) |
82388 | 613 |
then show \<open>mset xs = mset ?rhs\<close> |
69250 | 614 |
by (simp add: mset_merge) |
615 |
next |
|
82388 | 616 |
show \<open>sorted cmp ?rhs\<close> |
69250 | 617 |
by (simp add: sorted_merge) |
618 |
next |
|
619 |
fix l |
|
82388 | 620 |
have \<open>stable_segment cmp l (take (length xs div 2) xs) @ stable_segment cmp l (drop (length xs div 2) xs) |
621 |
= stable_segment cmp l xs\<close> |
|
69250 | 622 |
by (simp only: filter_append [symmetric] append_take_drop_id) |
82388 | 623 |
have \<open>merge (stable_segment cmp l (take (length xs div 2) xs)) |
69250 | 624 |
(stable_segment cmp l (drop (length xs div 2) xs)) = |
82388 | 625 |
stable_segment cmp l (take (length xs div 2) xs) @ stable_segment cmp l (drop (length xs div 2) xs)\<close> |
69250 | 626 |
by (rule merge_eq_appendI) (auto simp add: compare.trans_equiv_greater) |
82388 | 627 |
also have \<open>\<dots> = stable_segment cmp l xs\<close> |
69250 | 628 |
by (simp only: filter_append [symmetric] append_take_drop_id) |
82388 | 629 |
finally show \<open>stable_segment cmp l xs = stable_segment cmp l ?rhs\<close> |
69250 | 630 |
by (simp add: stable_sort filter_merge) |
631 |
qed |
|
632 |
||
633 |
lemma mergesort_code [code]: |
|
82388 | 634 |
\<open>mergesort cmp xs = |
69250 | 635 |
(case xs of |
636 |
[] \<Rightarrow> [] |
|
637 |
| [x] \<Rightarrow> xs |
|
638 |
| [x, y] \<Rightarrow> (if compare cmp x y \<noteq> Greater then xs else [y, x]) |
|
639 |
| _ \<Rightarrow> |
|
640 |
let |
|
641 |
half = length xs div 2; |
|
642 |
ys = take half xs; |
|
643 |
zs = drop half xs |
|
82388 | 644 |
in merge (mergesort cmp ys) (mergesort cmp zs))\<close> |
645 |
proof (cases \<open>length xs \<ge> 3\<close>) |
|
69250 | 646 |
case False |
82388 | 647 |
then have \<open>length xs \<in> {0, 1, 2}\<close> |
69250 | 648 |
by (auto simp add: not_le le_less less_antisym) |
82388 | 649 |
then consider \<open>xs = []\<close> | x where \<open>xs = [x]\<close> | x y where \<open>xs = [x, y]\<close> |
69250 | 650 |
by (auto simp add: length_Suc_conv numeral_2_eq_2) |
651 |
then show ?thesis |
|
652 |
by cases simp_all |
|
653 |
next |
|
654 |
case True |
|
82388 | 655 |
then obtain x y z zs where \<open>xs = x # y # z # zs\<close> |
69250 | 656 |
by (metis le_0_eq length_0_conv length_Cons list.exhaust not_less_eq_eq numeral_3_eq_3) |
82388 | 657 |
moreover have \<open>mergesort cmp xs = |
69250 | 658 |
(let |
659 |
half = length xs div 2; |
|
660 |
ys = take half xs; |
|
661 |
zs = drop half xs |
|
82388 | 662 |
in merge (mergesort cmp ys) (mergesort cmp zs))\<close> |
69250 | 663 |
using sort_by_mergesort_rec [of xs] by (simp add: Let_def) |
664 |
ultimately show ?thesis |
|
665 |
by simp |
|
666 |
qed |
|
69246
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
667 |
|
c1fe9dcc274a
concrecte sorting algorithms beyond insertion sort
haftmann
parents:
69194
diff
changeset
|
668 |
end |
69250 | 669 |
|
82393 | 670 |
|
671 |
subsection \<open>Lexicographic products\<close> |
|
672 |
||
673 |
lemma sorted_prod_lex_imp_sorted_fst: |
|
674 |
\<open>sorted (key fst cmp1) ps\<close> if \<open>sorted (prod_lex cmp1 cmp2) ps\<close> |
|
675 |
using that proof (induction rule: sorted_induct) |
|
676 |
case Nil |
|
677 |
then show ?case |
|
678 |
by simp |
|
679 |
next |
|
680 |
case (Cons p ps) |
|
681 |
have \<open>compare (key fst cmp1) p q \<noteq> Greater\<close> if \<open>ps = q # qs\<close> for q qs |
|
682 |
using that Cons.hyps(2) [of q] by (simp add: compare_prod_lex_apply split: comp.splits) |
|
683 |
with Cons.IH show ?case |
|
684 |
by (rule sorted_ConsI) simp |
|
685 |
qed |
|
686 |
||
687 |
lemma sorted_prod_lex_imp_sorted_snd: |
|
688 |
\<open>sorted (key snd cmp2) ps\<close> if \<open>sorted (prod_lex cmp1 cmp2) ps\<close> \<open>\<And>a' b'. (a', b') \<in> set ps \<Longrightarrow> compare cmp1 a a' = Equiv\<close> |
|
689 |
using that proof (induction rule: sorted_induct) |
|
690 |
case Nil |
|
691 |
then show ?case |
|
692 |
by simp |
|
693 |
next |
|
694 |
case (Cons p ps) |
|
695 |
then show ?case |
|
696 |
apply (cases p) |
|
697 |
apply (rule sorted_ConsI) |
|
698 |
apply (simp_all add: compare_prod_lex_apply) |
|
699 |
apply (auto cong del: comp.case_cong_weak) |
|
700 |
apply (metis comp.simps(8) compare.equiv_subst_left) |
|
701 |
done |
|
702 |
qed |
|
703 |
||
704 |
lemma sort_comp_fst_snd_eq_sort_prod_lex: |
|
705 |
\<open>sort (key fst cmp1) \<circ> sort (key snd cmp2) = sort (prod_lex cmp1 cmp2)\<close> (is \<open>sort ?cmp1 \<circ> sort ?cmp2 = sort ?cmp\<close>) |
|
706 |
proof |
|
707 |
fix ps :: \<open>('a \<times> 'b) list\<close> |
|
708 |
have \<open>sort ?cmp1 (sort ?cmp2 ps) = sort ?cmp ps\<close> |
|
709 |
proof (rule sort_eqI) |
|
710 |
show \<open>mset (sort ?cmp2 ps) = mset (sort ?cmp ps)\<close> |
|
711 |
by simp |
|
712 |
show \<open>sorted ?cmp1 (sort ?cmp ps)\<close> |
|
713 |
by (rule sorted_prod_lex_imp_sorted_fst [of _ cmp2]) simp |
|
714 |
next |
|
715 |
fix p :: \<open>'a \<times> 'b\<close> |
|
716 |
define a b where ab: \<open>a = fst p\<close> \<open>b = snd p\<close> |
|
717 |
moreover assume \<open>p \<in> set (sort ?cmp2 ps)\<close> |
|
718 |
ultimately have \<open>(a, b) \<in> set (sort ?cmp2 ps)\<close> |
|
719 |
by simp |
|
720 |
let ?qs = \<open>filter (\<lambda>(a', _). compare cmp1 a a' = Equiv) ps\<close> |
|
721 |
have \<open>sort ?cmp2 ?qs = sort ?cmp ?qs\<close> |
|
722 |
proof (rule sort_eqI) |
|
723 |
show \<open>mset ?qs = mset (sort ?cmp ?qs)\<close> |
|
724 |
by simp |
|
725 |
show \<open>sorted ?cmp2 (sort ?cmp ?qs)\<close> |
|
726 |
by (rule sorted_prod_lex_imp_sorted_snd) auto |
|
727 |
next |
|
728 |
fix q :: \<open>'a \<times> 'b\<close> |
|
729 |
define c d where \<open>c = fst q\<close> \<open>d = snd q\<close> |
|
730 |
moreover assume \<open>q \<in> set ?qs\<close> |
|
731 |
ultimately have \<open>(c, d) \<in> set ?qs\<close> |
|
732 |
by simp |
|
733 |
from sorted_stable_segment [of ?cmp \<open>(a, d)\<close> ps] |
|
734 |
have \<open>sorted ?cmp (filter (\<lambda>(c, b). compare (prod_lex cmp1 cmp2) (a, d) (c, b) = Equiv) ps)\<close> |
|
735 |
by (simp only: case_prod_unfold prod.collapse) |
|
736 |
also have \<open>(\<lambda>(c, b). compare (prod_lex cmp1 cmp2) (a, d) (c, b) = Equiv) = |
|
737 |
(\<lambda>(c, b). compare cmp1 a c = Equiv \<and> compare cmp2 d b = Equiv)\<close> |
|
738 |
by (simp add: fun_eq_iff compare_prod_lex_apply split: comp.split) |
|
739 |
finally have *: \<open>sorted ?cmp (filter (\<lambda>(c, b). compare cmp1 a c = Equiv \<and> compare cmp2 d b = Equiv) ps)\<close> . |
|
740 |
let ?rs = \<open>filter (\<lambda>(_, d'). compare cmp2 d d' = Equiv) ?qs\<close> |
|
741 |
have \<open>sort ?cmp ?rs = ?rs\<close> |
|
742 |
by (rule sort_eqI) (use * in \<open>simp_all add: case_prod_unfold\<close>) |
|
743 |
then show \<open>filter (\<lambda>r. compare ?cmp2 q r = Equiv) ?qs = |
|
744 |
filter (\<lambda>r. compare ?cmp2 q r = Equiv) (sort ?cmp ?qs)\<close> |
|
745 |
by (simp add: filter_sort case_prod_unfold flip: \<open>d = snd q\<close>) |
|
746 |
qed |
|
747 |
then show \<open>filter (\<lambda>q. compare ?cmp1 p q = Equiv) (sort ?cmp2 ps) = |
|
748 |
filter (\<lambda>q. compare ?cmp1 p q = Equiv) (sort ?cmp ps)\<close> |
|
749 |
by (simp add: filter_sort case_prod_unfold flip: ab) |
|
750 |
qed |
|
751 |
then show \<open>(sort (key fst cmp1) \<circ> sort (key snd cmp2)) ps = sort (prod_lex cmp1 cmp2) ps\<close> |
|
752 |
by simp |
|
753 |
qed |
|
754 |
||
69250 | 755 |
end |