lemma T_insort_length: "T_insort xs \ (length xs + 1) ^ 2" proof(induction xs) case Nil show ?caseby simp next case (Cons x xs) have"T_insort (x#xs) = T_insort xs + T_insort1 x (insort xs) + 1"by simp alsohave"\ \ (length xs + 1) ^ 2 + T_insort1 x (insort xs) + 1" using Cons.IH by simp alsohave"\ \ (length xs + 1) ^ 2 + length xs + 1 + 1" using T_insort1_length[of x "insort xs"] by (simp add: length_insort) alsohave"\ \ (length(x#xs) + 1) ^ 2" by (simp add: power2_eq_square) finallyshow ?case . qed
subsection "Merge Sort"
fun merge :: "'a::linorder list \ 'a list \ 'a list" where "merge [] ys = ys" | "merge xs [] = xs" | "merge (x#xs) (y#ys) = (if x \ y then x # merge xs (y#ys) else y # merge (x#xs) ys)"
fun msort :: "'a::linorder list \ 'a list" where "msort xs = (let n = length xs in if n \<le> 1 then xs
else merge (msort (take (n div 2) xs)) (msort (drop (n div 2) xs)))"
lemma sorted_msort: "sorted (msort xs)" proof(induction xs rule: msort.induct) case (1 xs) let ?n = "length xs" show ?case proof cases assume"?n \ 1" thus ?thesis by(simp add: msort.simps[of xs] sorted01) next assume"\ ?n \ 1" thus ?thesis using"1.IH" by(simp add: sorted_merge msort.simps[of xs]) qed qed
subsubsection "Time Complexity"
text\<open>We only count the number of comparisons between list elements.\<close>
fun C_merge :: "'a::linorder list \ 'a list \ nat" where "C_merge [] ys = 0" | "C_merge xs [] = 0" | "C_merge (x#xs) (y#ys) = 1 + (if x \ y then C_merge xs (y#ys) else C_merge (x#xs) ys)"
lemma C_merge_ub: "C_merge xs ys \ length xs + length ys" by (induction xs ys rule: C_merge.induct) auto
fun C_msort :: "'a::linorder list \ nat" where "C_msort xs =
(let n = length xs;
ys = take (n div 2) xs;
zs = drop (n div 2) xs inif n \<le> 1 then 0
else C_msort ys + C_msort zs + C_merge (msort ys) (msort zs))"
declare C_msort.simps [simp del]
lemma length_merge: "length(merge xs ys) = length xs + length ys" by (induction xs ys rule: merge.induct) auto
lemma length_msort: "length(msort xs) = length xs" proof (induction xs rule: msort.induct) case (1 xs) show ?case by (auto simp: msort.simps [of xs] 1 length_merge) qed text\<open>Why structured proof? Tohave the name "xs"to specialize msort.simps with xs to ensure that msort.simps cannot be used recursively. Also works without this precaution, but that is just luck.\<close>
lemma C_msort_le: "length xs = 2^k \ C_msort xs \ k * 2^k" proof(induction k arbitrary: xs) case 0 thus ?caseby (simp add: C_msort.simps) next case (Suc k) let ?n = "length xs" let ?ys = "take (?n div 2) xs" let ?zs = "drop (?n div 2) xs" show ?case proof (cases "?n \ 1") case True thus ?thesis by(simp add: C_msort.simps) next case False have"C_msort(xs) =
C_msort ?ys + C_msort ?zs + C_merge (msort ?ys) (msort ?zs)" by (simp add: C_msort.simps msort.simps) alsohave"\ \ C_msort ?ys + C_msort ?zs + length ?ys + length ?zs" using C_merge_ub[of "msort ?ys""msort ?zs"] length_msort[of ?ys] length_msort[of ?zs] by arith alsohave"\ \ k * 2^k + C_msort ?zs + length ?ys + length ?zs" using Suc.IH[of ?ys] Suc.prems by simp alsohave"\ \ k * 2^k + k * 2^k + length ?ys + length ?zs" using Suc.IH[of ?zs] Suc.prems by simp alsohave"\ = 2 * k * 2^k + 2 * 2 ^ k" using Suc.prems by simp finallyshow ?thesis by simp qed qed
fun merge_adj :: "('a::linorder) list list \ 'a list list" where "merge_adj [] = []" | "merge_adj [xs] = [xs]" | "merge_adj (xs # ys # zss) = merge xs ys # merge_adj zss"
text\<open>For the termination proof of \<open>merge_all\<close> below.\<close> lemma length_merge_adjacent[simp]: "length (merge_adj xs) = (length xs + 1) div 2" by (induction xs rule: merge_adj.induct) auto
fun merge_all :: "('a::linorder) list list \ 'a list" where "merge_all [] = []" | "merge_all [xs] = xs" | "merge_all xss = merge_all (merge_adj xss)"
definition msort_bu :: "('a::linorder) list \ 'a list" where "msort_bu xs = merge_all (map (\x. [x]) xs)"
subsubsection "Functional Correctness"
abbreviation mset_mset :: "'a list list \ 'a multiset" where "mset_mset xss \ \\<^sub># (image_mset mset (mset xss))"
lemma C_merge_adj: "\xs \ set xss. length xs = m \ C_merge_adj xss \ m * length xss" proof(induction xss rule: C_merge_adj.induct) case 1 thus ?caseby simp next case 2 thus ?caseby simp next case (3 x y) thus ?caseusing C_merge_ub[of x y] by (simp add: algebra_simps) qed
lemma C_merge_all: "\ \xs \ set xss. length xs = m; length xss = 2^k \ \<Longrightarrow> C_merge_all xss \<le> m * k * 2^k" proof (induction xss arbitrary: k m rule: C_merge_all.induct) case 1 thus ?caseby simp next case 2 thus ?caseby simp next case (3 xs ys xss) let ?xss = "xs # ys # xss" let ?xss2 = "merge_adj ?xss" obtain k' where k': "k = Suc k'"using"3.prems"(2) by (metis length_Cons nat.inject nat_power_eq_Suc_0_iff nat.exhaust) have"even (length ?xss)"using"3.prems"(2) k' by auto from length_merge_adj[OF this "3.prems"(1)] have *: "\x \ set(merge_adj ?xss). length x = 2*m" . have **: "length ?xss2 = 2 ^ k'"using"3.prems"(2) k' by auto have"C_merge_all ?xss = C_merge_adj ?xss + C_merge_all ?xss2"by simp alsohave"\ \ m * 2^k + C_merge_all ?xss2" using"3.prems"(2) C_merge_adj[OF "3.prems"(1)] by (auto simp: algebra_simps) alsohave"\ \ m * 2^k + (2*m) * k' * 2^k'" using"3.IH"[OF * **] by simp alsohave"\ = m * k * 2^k" using k' by (simp add: algebra_simps) finallyshow ?case . qed
corollary C_msort_bu: "length xs = 2 ^ k \ C_msort_bu xs \ k * 2 ^ k" using C_merge_all[of "map (\x. [x]) xs" 1] by (simp add: C_msort_bu_def)
subsection "Quicksort"
fun quicksort :: "('a::linorder) list \ 'a list" where "quicksort [] = []" | "quicksort (x#xs) = quicksort (filter (\y. y < x) xs) @ [x] @ quicksort (filter (\y. x \ y) xs)"
subsection "Insertion Sort w.r.t. Keys and Stability"
hide_const List.insort_key
fun insort1_key :: "('a \ 'k::linorder) \ 'a \ 'a list \ 'a list" where "insort1_key f x [] = [x]" | "insort1_key f x (y # ys) = (if f x \ f y then x # y # ys else y # insort1_key f x ys)"
fun insort_key :: "('a \ 'k::linorder) \ 'a list \ 'a list" where "insort_key f [] = []" | "insort_key f (x # xs) = insort1_key f x (insort_key f xs)"
subsubsection "Standard functional correctness"
lemma mset_insort1_key: "mset (insort1_key f x xs) = {#x#} + mset xs" by(induction xs) simp_all
(* Inductive proof simpler than derivation from mset lemma: *) lemma set_insort1_key: "set (insort1_key f x xs) = {x} \ set xs" by (induction xs) auto
lemma sorted_insort1_key: "sorted (map f (insort1_key f a xs)) = sorted (map f xs)" by(induction xs)(auto simp: set_insort1_key)
lemma sorted_insort_key: "sorted (map f (insort_key f xs))" by(induction xs)(simp_all add: sorted_insort1_key)
subsubsection "Stability"
lemma insort1_is_Cons: "\x\set xs. f a \ f x \ insort1_key f a xs = a # xs" by (cases xs) auto
lemma filter_insort1_key_neg: "\ P x \ filter P (insort1_key f x xs) = filter P xs" by (induction xs) simp_all
lemma filter_insort1_key_pos: "sorted (map f xs) \ P x \ filter P (insort1_key f x xs) = insort1_key f x (filter P xs)" by (induction xs) (auto, subst insort1_is_Cons, auto)
lemma sort_key_stable: "filter (\y. f y = k) (insort_key f xs) = filter (\y. f y = k) xs" proof (induction xs) case Nil thus ?caseby simp next case (Cons a xs) thus ?case proof (cases "f a = k") case False thus ?thesis by (simp add: Cons.IH filter_insort1_key_neg) next case True have"filter (\y. f y = k) (insort_key f (a # xs))
= filter (\<lambda>y. f y = k) (insort1_key f a (insort_key f xs))" by simp alsohave"\ = insort1_key f a (filter (\y. f y = k) (insort_key f xs))" by (simp add: True filter_insort1_key_pos sorted_insort_key) alsohave"\ = insort1_key f a (filter (\y. f y = k) xs)" by (simp add: Cons.IH) alsohave"\ = a # (filter (\y. f y = k) xs)" by(simp add: True insort1_is_Cons) alsohave"\ = filter (\y. f y = k) (a # xs)" by (simp add: True) finallyshow ?thesis . qed qed
subsection \<open>Uniqueness of Sorting\<close>
lemma sorting_unique: assumes"mset ys = mset xs""sorted xs""sorted ys" shows"xs = ys" using assms proof (induction xs arbitrary: ys) case (Cons x xs ys') obtain y ys where ys': "ys' = y # ys" using Cons.prems by (cases ys') auto have"x = y" using Cons.prems unfolding ys' proof (induction x y arbitrary: xs ys rule: linorder_wlog) case (le x y xs ys) have"x \# mset (x # xs)" by simp alsohave"mset (x # xs) = mset (y # ys)" using le by simp finallyshow"x = y" using le by auto qed (simp_all add: eq_commute) thus ?case using Cons.prems Cons.IH[of ys] by (auto simp: ys') qed auto
end
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.