author | nipkow |
Fri, 10 Nov 2017 22:05:30 +0100 | |
changeset 67040 | c1b87d15774a |
parent 66912 | a99a7cbf0fb5 |
child 67983 | 487685540a51 |
permissions | -rw-r--r-- |
66543 | 1 |
(* Author: Tobias Nipkow *) |
2 |
||
3 |
(* FIXME adjust List.sorted to work like below; [code] is different! *) |
|
4 |
||
5 |
theory Sorting |
|
6 |
imports |
|
7 |
Complex_Main |
|
8 |
"HOL-Library.Multiset" |
|
9 |
begin |
|
10 |
||
11 |
hide_const List.sorted List.insort |
|
12 |
||
13 |
declare Let_def [simp] |
|
14 |
||
15 |
fun sorted :: "'a::linorder list \<Rightarrow> bool" where |
|
16 |
"sorted [] = True" | |
|
17 |
"sorted (x # xs) = ((\<forall>y\<in>set xs. x \<le> y) & sorted xs)" |
|
18 |
||
19 |
lemma sorted_append: |
|
20 |
"sorted (xs@ys) = (sorted xs & sorted ys & (\<forall>x \<in> set xs. \<forall>y \<in> set ys. x\<le>y))" |
|
21 |
by (induct xs) (auto) |
|
22 |
||
23 |
||
24 |
subsection "Insertion Sort" |
|
25 |
||
26 |
fun insort :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
|
27 |
"insort x [] = [x]" | |
|
28 |
"insort x (y#ys) = |
|
29 |
(if x \<le> y then x#y#ys else y#(insort x ys))" |
|
30 |
||
31 |
fun isort :: "'a::linorder list \<Rightarrow> 'a list" where |
|
32 |
"isort [] = []" | |
|
33 |
"isort (x#xs) = insort x (isort xs)" |
|
34 |
||
35 |
subsubsection "Functional Correctness" |
|
36 |
||
37 |
lemma mset_insort: "mset (insort x xs) = add_mset x (mset xs)" |
|
38 |
apply(induction xs) |
|
39 |
apply auto |
|
40 |
done |
|
41 |
||
42 |
lemma mset_isort: "mset (isort xs) = mset xs" |
|
43 |
apply(induction xs) |
|
44 |
apply simp |
|
45 |
apply (simp add: mset_insort) |
|
46 |
done |
|
47 |
||
48 |
lemma "sorted (insort a xs) = sorted xs" |
|
49 |
apply(induction xs) |
|
50 |
apply (auto) |
|
51 |
oops |
|
52 |
||
53 |
lemma set_insort: "set (insort x xs) = insert x (set xs)" |
|
54 |
by (metis mset_insort set_mset_add_mset_insert set_mset_mset) |
|
55 |
||
56 |
lemma set_isort: "set (isort xs) = set xs" |
|
57 |
by (metis mset_isort set_mset_mset) |
|
58 |
||
59 |
lemma sorted_insort: "sorted (insort a xs) = sorted xs" |
|
60 |
apply(induction xs) |
|
61 |
apply(auto simp add: set_insort) |
|
62 |
done |
|
63 |
||
64 |
lemma "sorted (isort xs)" |
|
65 |
apply(induction xs) |
|
66 |
apply(auto simp: sorted_insort) |
|
67 |
done |
|
68 |
||
69 |
subsection "Time Complexity" |
|
70 |
||
71 |
text \<open>We count the number of function calls.\<close> |
|
72 |
||
73 |
text\<open> |
|
74 |
\<open>insort x [] = [x]\<close> |
|
75 |
\<open>insort x (y#ys) = |
|
76 |
(if x \<le> y then x#y#ys else y#(insort x ys))\<close> |
|
77 |
\<close> |
|
78 |
fun t_insort :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> nat" where |
|
79 |
"t_insort x [] = 1" | |
|
80 |
"t_insort x (y#ys) = |
|
81 |
(if x \<le> y then 0 else t_insort x ys) + 1" |
|
82 |
||
83 |
text\<open> |
|
84 |
\<open>isort [] = []\<close> |
|
85 |
\<open>isort (x#xs) = insort x (isort xs)\<close> |
|
86 |
\<close> |
|
87 |
fun t_isort :: "'a::linorder list \<Rightarrow> nat" where |
|
88 |
"t_isort [] = 1" | |
|
89 |
"t_isort (x#xs) = t_isort xs + t_insort x (isort xs) + 1" |
|
90 |
||
91 |
||
92 |
lemma t_insort_length: "t_insort x xs \<le> length xs + 1" |
|
93 |
apply(induction xs) |
|
94 |
apply auto |
|
95 |
done |
|
96 |
||
97 |
lemma length_insort: "length (insort x xs) = length xs + 1" |
|
98 |
apply(induction xs) |
|
99 |
apply auto |
|
100 |
done |
|
101 |
||
102 |
lemma length_isort: "length (isort xs) = length xs" |
|
103 |
apply(induction xs) |
|
104 |
apply (auto simp: length_insort) |
|
105 |
done |
|
106 |
||
107 |
lemma t_isort_length: "t_isort xs \<le> (length xs + 1) ^ 2" |
|
108 |
proof(induction xs) |
|
109 |
case Nil show ?case by simp |
|
110 |
next |
|
111 |
case (Cons x xs) |
|
112 |
have "t_isort (x#xs) = t_isort xs + t_insort x (isort xs) + 1" by simp |
|
113 |
also have "\<dots> \<le> (length xs + 1) ^ 2 + t_insort x (isort xs) + 1" |
|
114 |
using Cons.IH by simp |
|
115 |
also have "\<dots> \<le> (length xs + 1) ^ 2 + length xs + 1 + 1" |
|
116 |
using t_insort_length[of x "isort xs"] by (simp add: length_isort) |
|
117 |
also have "\<dots> \<le> (length(x#xs) + 1) ^ 2" |
|
118 |
by (simp add: power2_eq_square) |
|
119 |
finally show ?case . |
|
120 |
qed |
|
121 |
||
122 |
||
123 |
subsection "Merge Sort" |
|
124 |
||
125 |
fun merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
|
126 |
"merge [] ys = ys" | |
|
127 |
"merge xs [] = xs" | |
|
128 |
"merge (x#xs) (y#ys) = (if x \<le> y then x # merge xs (y#ys) else y # merge (x#xs) ys)" |
|
129 |
||
130 |
fun msort :: "'a::linorder list \<Rightarrow> 'a list" where |
|
131 |
"msort xs = (let n = length xs in |
|
132 |
if n \<le> 1 then xs |
|
133 |
else merge (msort (take (n div 2) xs)) (msort (drop (n div 2) xs)))" |
|
134 |
||
135 |
declare msort.simps [simp del] |
|
136 |
||
137 |
(* We count the number of comparisons between list elements only *) |
|
138 |
||
139 |
fun c_merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> nat" where |
|
140 |
"c_merge [] ys = 0" | |
|
141 |
"c_merge xs [] = 0" | |
|
142 |
"c_merge (x#xs) (y#ys) = 1 + (if x \<le> y then c_merge xs (y#ys) else c_merge (x#xs) ys)" |
|
143 |
||
144 |
lemma c_merge_ub: "c_merge xs ys \<le> length xs + length ys" |
|
145 |
by (induction xs ys rule: c_merge.induct) auto |
|
146 |
||
147 |
fun c_msort :: "'a::linorder list \<Rightarrow> nat" where |
|
148 |
"c_msort xs = |
|
149 |
(let n = length xs; |
|
150 |
ys = take (n div 2) xs; |
|
151 |
zs = drop (n div 2) xs |
|
152 |
in if n \<le> 1 then 0 |
|
153 |
else c_msort ys + c_msort zs + c_merge (msort ys) (msort zs))" |
|
154 |
||
155 |
declare c_msort.simps [simp del] |
|
156 |
||
157 |
lemma length_merge: "length(merge xs ys) = length xs + length ys" |
|
158 |
apply (induction xs ys rule: merge.induct) |
|
159 |
apply auto |
|
160 |
done |
|
161 |
||
162 |
lemma length_msort: "length(msort xs) = length xs" |
|
163 |
proof (induction xs rule: msort.induct) |
|
164 |
case (1 xs) |
|
165 |
thus ?case by (auto simp: msort.simps[of xs] length_merge) |
|
166 |
qed |
|
167 |
text \<open>Why structured proof? |
|
168 |
To have the name "xs" to specialize msort.simps with xs |
|
169 |
to ensure that msort.simps cannot be used recursively. |
|
170 |
Also works without this precaution, but that is just luck.\<close> |
|
171 |
||
172 |
lemma c_msort_le: "length xs = 2^k \<Longrightarrow> c_msort xs \<le> k * 2^k" |
|
173 |
proof(induction k arbitrary: xs) |
|
174 |
case 0 thus ?case by (simp add: c_msort.simps) |
|
175 |
next |
|
176 |
case (Suc k) |
|
177 |
let ?n = "length xs" |
|
178 |
let ?ys = "take (?n div 2) xs" |
|
179 |
let ?zs = "drop (?n div 2) xs" |
|
180 |
show ?case |
|
181 |
proof (cases "?n \<le> 1") |
|
182 |
case True |
|
183 |
thus ?thesis by(simp add: c_msort.simps) |
|
184 |
next |
|
185 |
case False |
|
186 |
have "c_msort(xs) = |
|
187 |
c_msort ?ys + c_msort ?zs + c_merge (msort ?ys) (msort ?zs)" |
|
188 |
by (simp add: c_msort.simps msort.simps) |
|
189 |
also have "\<dots> \<le> c_msort ?ys + c_msort ?zs + length ?ys + length ?zs" |
|
190 |
using c_merge_ub[of "msort ?ys" "msort ?zs"] length_msort[of ?ys] length_msort[of ?zs] |
|
191 |
by arith |
|
192 |
also have "\<dots> \<le> k * 2^k + c_msort ?zs + length ?ys + length ?zs" |
|
193 |
using Suc.IH[of ?ys] Suc.prems by simp |
|
194 |
also have "\<dots> \<le> k * 2^k + k * 2^k + length ?ys + length ?zs" |
|
195 |
using Suc.IH[of ?zs] Suc.prems by simp |
|
196 |
also have "\<dots> = 2 * k * 2^k + 2 * 2 ^ k" |
|
197 |
using Suc.prems by simp |
|
198 |
finally show ?thesis by simp |
|
199 |
qed |
|
200 |
qed |
|
201 |
||
202 |
(* Beware of conversions: *) |
|
203 |
lemma "length xs = 2^k \<Longrightarrow> c_msort xs \<le> length xs * log 2 (length xs)" |
|
204 |
using c_msort_le[of xs k] apply (simp add: log_nat_power algebra_simps) |
|
66912
a99a7cbf0fb5
generalized lemmas cancelling real_of_int/real in (in)equalities with power; completed set of related simp rules; lemmas about floorlog/bitlen
immler
parents:
66543
diff
changeset
|
205 |
by (metis (mono_tags) numeral_power_eq_of_nat_cancel_iff of_nat_le_iff of_nat_mult) |
66543 | 206 |
|
207 |
end |