src/HOL/Data_Structures/Sorting.thy
changeset 75501 426afab39a55
parent 73047 ab9e27da0e85
child 77922 d28dcd57d2f3
equal deleted inserted replaced
75496:99b37c391433 75501:426afab39a55
    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