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 ≤ 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‹We only count the number of comparisons between list elements.›
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 in if n ≤ 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‹Why structured proof? To have 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.›
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‹For the termination proof of ‹merge_all› below.› 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 ≡∑🪙# (image_mset mset (mset xss))"
lemma length_merge_adj: "[ even(length xss); ∀xs ∈ set xss. length xs = m ] ==>∀xs ∈ set (merge_adj xss). length xs = 2*m" by(induction xss rule: merge_adj.induct) (auto simp: length_merge)
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 ] ==> C_merge_all xss ≤ 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 (λ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‹Uniqueness of Sorting›
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
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-04-28)
¤
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 und die Messung sind noch experimentell.