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 insort :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
18 fun insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
19 "insort x [] = [x]" | |
19 "insort1 x [] = [x]" | |
20 "insort x (y#ys) = |
20 "insort1 x (y#ys) = |
21 (if x \<le> y then x#y#ys else y#(insort x ys))" |
21 (if x \<le> y then x#y#ys else y#(insort1 x ys))" |
22 |
22 |
23 fun isort :: "'a::linorder list \<Rightarrow> 'a list" where |
23 fun insort :: "'a::linorder list \<Rightarrow> 'a list" where |
24 "isort [] = []" | |
24 "insort [] = []" | |
25 "isort (x#xs) = insort x (isort 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_insort: "mset (insort x xs) = {#x#} + mset xs" |
30 lemma mset_insort1: "mset (insort1 x xs) = {#x#} + mset xs" |
31 apply(induction xs) |
31 apply(induction xs) |
32 apply auto |
32 apply auto |
33 done |
33 done |
34 |
34 |
35 lemma mset_isort: "mset (isort xs) = mset xs" |
35 lemma mset_insort: "mset (insort xs) = mset xs" |
36 apply(induction xs) |
36 apply(induction xs) |
37 apply simp |
37 apply simp |
38 apply (simp add: mset_insort) |
38 apply (simp add: mset_insort1) |
39 done |
39 done |
40 |
40 |
41 lemma set_insort: "set (insort x xs) = {x} \<union> set xs" |
41 lemma set_insort1: "set (insort1 x xs) = {x} \<union> set xs" |
42 by(simp add: mset_insort flip: set_mset_mset) |
42 by(simp add: mset_insort1 flip: set_mset_mset) |
43 |
43 |
44 lemma sorted_insort: "sorted (insort a xs) = sorted xs" |
44 lemma sorted_insort1: "sorted (insort1 a xs) = sorted xs" |
45 apply(induction xs) |
45 apply(induction xs) |
46 apply(auto simp add: set_insort) |
46 apply(auto simp add: set_insort1) |
47 done |
47 done |
48 |
48 |
49 lemma sorted_isort: "sorted (isort xs)" |
49 lemma sorted_insort: "sorted (insort xs)" |
50 apply(induction xs) |
50 apply(induction xs) |
51 apply(auto simp: sorted_insort) |
51 apply(auto simp: sorted_insort1) |
52 done |
52 done |
53 |
53 |
54 |
54 |
55 subsubsection "Time Complexity" |
55 subsubsection "Time Complexity" |
56 |
56 |
57 text \<open>We count the number of function calls.\<close> |
57 text \<open>We count the number of function calls.\<close> |
58 |
58 |
59 text\<open> |
59 text\<open> |
60 \<open>insort x [] = [x]\<close> |
60 \<open>insort1 x [] = [x]\<close> |
61 \<open>insort x (y#ys) = |
61 \<open>insort1 x (y#ys) = |
62 (if x \<le> y then x#y#ys else y#(insort x ys))\<close> |
62 (if x \<le> y then x#y#ys else y#(insort1 x ys))\<close> |
63 \<close> |
63 \<close> |
64 fun T_insort :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> nat" where |
64 fun T_insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> nat" where |
65 "T_insort x [] = 1" | |
65 "T_insort1 x [] = 1" | |
66 "T_insort x (y#ys) = |
66 "T_insort1 x (y#ys) = |
67 (if x \<le> y then 0 else T_insort x ys) + 1" |
67 (if x \<le> y then 0 else T_insort1 x ys) + 1" |
68 |
68 |
69 text\<open> |
69 text\<open> |
70 \<open>isort [] = []\<close> |
70 \<open>insort [] = []\<close> |
71 \<open>isort (x#xs) = insort x (isort xs)\<close> |
71 \<open>insort (x#xs) = insort1 x (insort xs)\<close> |
72 \<close> |
72 \<close> |
73 fun T_isort :: "'a::linorder list \<Rightarrow> nat" where |
73 fun T_insort :: "'a::linorder list \<Rightarrow> nat" where |
74 "T_isort [] = 1" | |
74 "T_insort [] = 1" | |
75 "T_isort (x#xs) = T_isort xs + T_insort x (isort xs) + 1" |
75 "T_insort (x#xs) = T_insort xs + T_insort1 x (insort xs) + 1" |
76 |
76 |
77 |
77 |
78 lemma T_insort_length: "T_insort x xs \<le> length xs + 1" |
78 lemma T_insort1_length: "T_insort1 x xs \<le> length xs + 1" |
79 apply(induction xs) |
79 apply(induction xs) |
80 apply auto |
80 apply auto |
81 done |
81 done |
82 |
82 |
83 lemma length_insort: "length (insort x xs) = length xs + 1" |
83 lemma length_insort1: "length (insort1 x xs) = length xs + 1" |
84 apply(induction xs) |
84 apply(induction xs) |
85 apply auto |
85 apply auto |
86 done |
86 done |
87 |
87 |
88 lemma length_isort: "length (isort xs) = length xs" |
88 lemma length_insort: "length (insort xs) = length xs" |
89 apply(induction xs) |
89 apply(induction xs) |
90 apply (auto simp: length_insort) |
90 apply (auto simp: length_insort1) |
91 done |
91 done |
92 |
92 |
93 lemma T_isort_length: "T_isort xs \<le> (length xs + 1) ^ 2" |
93 lemma T_insort_length: "T_insort xs \<le> (length xs + 1) ^ 2" |
94 proof(induction xs) |
94 proof(induction xs) |
95 case Nil show ?case by simp |
95 case Nil show ?case by simp |
96 next |
96 next |
97 case (Cons x xs) |
97 case (Cons x xs) |
98 have "T_isort (x#xs) = T_isort xs + T_insort x (isort xs) + 1" by simp |
98 have "T_insort (x#xs) = T_insort xs + T_insort1 x (insort xs) + 1" by simp |
99 also have "\<dots> \<le> (length xs + 1) ^ 2 + T_insort x (isort xs) + 1" |
99 also have "\<dots> \<le> (length xs + 1) ^ 2 + T_insort1 x (insort xs) + 1" |
100 using Cons.IH by simp |
100 using Cons.IH by simp |
101 also have "\<dots> \<le> (length xs + 1) ^ 2 + length xs + 1 + 1" |
101 also have "\<dots> \<le> (length xs + 1) ^ 2 + length xs + 1 + 1" |
102 using T_insort_length[of x "isort xs"] by (simp add: length_isort) |
102 using T_insort1_length[of x "insort xs"] by (simp add: length_insort) |
103 also have "\<dots> \<le> (length(x#xs) + 1) ^ 2" |
103 also have "\<dots> \<le> (length(x#xs) + 1) ^ 2" |
104 by (simp add: power2_eq_square) |
104 by (simp add: power2_eq_square) |
105 finally show ?case . |
105 finally show ?case . |
106 qed |
106 qed |
107 |
107 |
377 done |
377 done |
378 |
378 |
379 |
379 |
380 subsection "Insertion Sort w.r.t. Keys and Stability" |
380 subsection "Insertion Sort w.r.t. Keys and Stability" |
381 |
381 |
382 text \<open>Note that \<^const>\<open>insort_key\<close> is already defined in theory \<^theory>\<open>HOL.List\<close>. |
382 hide_const List.insort_key |
383 Thus some of the lemmas are already present as well.\<close> |
383 |
384 |
384 fun insort1_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
385 fun isort_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
385 "insort1_key f x [] = [x]" | |
386 "isort_key f [] = []" | |
386 "insort1_key f x (y # ys) = (if f x \<le> f y then x # y # ys else y # insort1_key f x ys)" |
387 "isort_key f (x # xs) = insort_key f x (isort_key f xs)" |
387 |
|
388 fun insort_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
|
389 "insort_key f [] = []" | |
|
390 "insort_key f (x # xs) = insort1_key f x (insort_key f xs)" |
388 |
391 |
389 |
392 |
390 subsubsection "Standard functional correctness" |
393 subsubsection "Standard functional correctness" |
391 |
394 |
392 lemma mset_insort_key: "mset (insort_key f x xs) = {#x#} + mset xs" |
395 lemma mset_insort1_key: "mset (insort1_key f x xs) = {#x#} + mset xs" |
393 by(induction xs) simp_all |
396 by(induction xs) simp_all |
394 |
397 |
395 lemma mset_isort_key: "mset (isort_key f xs) = mset xs" |
398 lemma mset_insort_key: "mset (insort_key f xs) = mset xs" |
396 by(induction xs) (simp_all add: mset_insort_key) |
399 by(induction xs) (simp_all add: mset_insort1_key) |
397 |
400 |
398 lemma set_isort_key: "set (isort_key f xs) = set xs" |
401 (* Inductive proof simpler than derivation from mset lemma: *) |
399 by (rule mset_eq_setD[OF mset_isort_key]) |
402 lemma set_insort1_key: "set (insort1_key f x xs) = {x} \<union> set xs" |
400 |
403 by (induction xs) auto |
401 lemma sorted_insort_key: "sorted (map f (insort_key f a xs)) = sorted (map f xs)" |
404 |
402 by(induction xs)(auto simp: set_insort_key) |
405 lemma sorted_insort1_key: "sorted (map f (insort1_key f a xs)) = sorted (map f xs)" |
403 |
406 by(induction xs)(auto simp: set_insort1_key) |
404 lemma sorted_isort_key: "sorted (map f (isort_key f xs))" |
407 |
405 by(induction xs)(simp_all add: sorted_insort_key) |
408 lemma sorted_insort_key: "sorted (map f (insort_key f xs))" |
|
409 by(induction xs)(simp_all add: sorted_insort1_key) |
406 |
410 |
407 |
411 |
408 subsubsection "Stability" |
412 subsubsection "Stability" |
409 |
413 |
410 lemma insort_is_Cons: "\<forall>x\<in>set xs. f a \<le> f x \<Longrightarrow> insort_key f a xs = a # xs" |
414 lemma insort1_is_Cons: "\<forall>x\<in>set xs. f a \<le> f x \<Longrightarrow> insort1_key f a xs = a # xs" |
411 by (cases xs) auto |
415 by (cases xs) auto |
412 |
416 |
413 lemma filter_insort_key_neg: |
417 lemma filter_insort1_key_neg: |
414 "\<not> P x \<Longrightarrow> filter P (insort_key f x xs) = filter P xs" |
418 "\<not> P x \<Longrightarrow> filter P (insort1_key f x xs) = filter P xs" |
415 by (induction xs) simp_all |
419 by (induction xs) simp_all |
416 |
420 |
417 lemma filter_insort_key_pos: |
421 lemma filter_insort1_key_pos: |
418 "sorted (map f xs) \<Longrightarrow> P x \<Longrightarrow> filter P (insort_key f x xs) = insort_key f x (filter P xs)" |
422 "sorted (map f xs) \<Longrightarrow> P x \<Longrightarrow> filter P (insort1_key f x xs) = insort1_key f x (filter P xs)" |
419 by (induction xs) (auto, subst insort_is_Cons, auto) |
423 by (induction xs) (auto, subst insort1_is_Cons, auto) |
420 |
424 |
421 lemma sort_key_stable: "filter (\<lambda>y. f y = k) (isort_key f xs) = filter (\<lambda>y. f y = k) xs" |
425 lemma sort_key_stable: "filter (\<lambda>y. f y = k) (insort_key f xs) = filter (\<lambda>y. f y = k) xs" |
422 proof (induction xs) |
426 proof (induction xs) |
423 case Nil thus ?case by simp |
427 case Nil thus ?case by simp |
424 next |
428 next |
425 case (Cons a xs) |
429 case (Cons a xs) |
426 thus ?case |
430 thus ?case |
427 proof (cases "f a = k") |
431 proof (cases "f a = k") |
428 case False thus ?thesis by (simp add: Cons.IH filter_insort_key_neg) |
432 case False thus ?thesis by (simp add: Cons.IH filter_insort1_key_neg) |
429 next |
433 next |
430 case True |
434 case True |
431 have "filter (\<lambda>y. f y = k) (isort_key f (a # xs)) |
435 have "filter (\<lambda>y. f y = k) (insort_key f (a # xs)) |
432 = filter (\<lambda>y. f y = k) (insort_key f a (isort_key f xs))" by simp |
436 = filter (\<lambda>y. f y = k) (insort1_key f a (insort_key f xs))" by simp |
433 also have "\<dots> = insort_key f a (filter (\<lambda>y. f y = k) (isort_key f xs))" |
437 also have "\<dots> = insort1_key f a (filter (\<lambda>y. f y = k) (insort_key f xs))" |
434 by (simp add: True filter_insort_key_pos sorted_isort_key) |
438 by (simp add: True filter_insort1_key_pos sorted_insort_key) |
435 also have "\<dots> = insort_key f a (filter (\<lambda>y. f y = k) xs)" by (simp add: Cons.IH) |
439 also have "\<dots> = insort1_key f a (filter (\<lambda>y. f y = k) xs)" by (simp add: Cons.IH) |
436 also have "\<dots> = a # (filter (\<lambda>y. f y = k) xs)" by(simp add: True insort_is_Cons) |
440 also have "\<dots> = a # (filter (\<lambda>y. f y = k) xs)" by(simp add: True insort1_is_Cons) |
437 also have "\<dots> = filter (\<lambda>y. f y = k) (a # xs)" by (simp add: True) |
441 also have "\<dots> = filter (\<lambda>y. f y = k) (a # xs)" by (simp add: True) |
438 finally show ?thesis . |
442 finally show ?thesis . |
439 qed |
443 qed |
440 qed |
444 qed |
441 |
445 |