src/HOL/Data_Structures/Sorting.thy
changeset 78653 7ed1759fe1bd
parent 77922 d28dcd57d2f3
child 80247 a424accf705d
equal deleted inserted replaced
78523:d96dd69903fb 78653:7ed1759fe1bd
     1 (* Author: Tobias Nipkow *)
     1 (* Author: Tobias Nipkow *)
     2 
     2 
     3 section "Sorting"
     3 section "Sorting"
     4 
     4 
     5 theory Sorting
     5 theory Sorting
     6 imports
     6   imports
     7   Complex_Main
     7     Complex_Main
     8   "HOL-Library.Multiset"
     8     "HOL-Library.Multiset"
     9 begin
     9 begin
    10 
    10 
    11 hide_const List.insort
    11 hide_const List.insort
    12 
    12 
    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 insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    18 fun insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    19 "insort1 x [] = [x]" |
    19   "insort1 x [] = [x]" |
    20 "insort1 x (y#ys) =
    20   "insort1 x (y#ys) =
    21   (if x \<le> y then x#y#ys else y#(insort1 x ys))"
    21   (if x \<le> y then x#y#ys else y#(insort1 x ys))"
    22 
    22 
    23 fun insort :: "'a::linorder list \<Rightarrow> 'a list" where
    23 fun insort :: "'a::linorder list \<Rightarrow> 'a list" where
    24 "insort [] = []" |
    24   "insort [] = []" |
    25 "insort (x#xs) = insort1 x (insort 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_insort1: "mset (insort1 x xs) = {#x#} + mset xs"
    30 lemma mset_insort1: "mset (insort1 x xs) = {#x#} + mset xs"
    31 apply(induction xs)
    31   by (induction xs) auto
    32 apply auto
       
    33 done
       
    34 
    32 
    35 lemma mset_insort: "mset (insort xs) = mset xs"
    33 lemma mset_insort: "mset (insort xs) = mset xs"
    36 apply(induction xs)
    34   by (induction xs) (auto simp: mset_insort1)
    37 apply simp
       
    38 apply (simp add: mset_insort1)
       
    39 done
       
    40 
    35 
    41 lemma set_insort1: "set (insort1 x xs) = {x} \<union> set xs"
    36 lemma set_insort1: "set (insort1 x xs) = {x} \<union> set xs"
    42 by(simp add: mset_insort1 flip: set_mset_mset)
    37   by(simp add: mset_insort1 flip: set_mset_mset)
    43 
    38 
    44 lemma sorted_insort1: "sorted (insort1 a xs) = sorted xs"
    39 lemma sorted_insort1: "sorted (insort1 a xs) = sorted xs"
    45 apply(induction xs)
    40   by (induction xs) (auto simp: set_insort1)
    46 apply(auto simp add: set_insort1)
       
    47 done
       
    48 
    41 
    49 lemma sorted_insort: "sorted (insort xs)"
    42 lemma sorted_insort: "sorted (insort xs)"
    50 apply(induction xs)
    43   by (induction xs) (auto simp: sorted_insort1)
    51 apply(auto simp: sorted_insort1)
       
    52 done
       
    53 
    44 
    54 
    45 
    55 subsubsection "Time Complexity"
    46 subsubsection "Time Complexity"
    56 
    47 
    57 text \<open>We count the number of function calls.\<close>
    48 text \<open>We count the number of function calls.\<close>
    60 \<open>insort1 x [] = [x]\<close>
    51 \<open>insort1 x [] = [x]\<close>
    61 \<open>insort1 x (y#ys) =
    52 \<open>insort1 x (y#ys) =
    62   (if x \<le> y then x#y#ys else y#(insort1 x ys))\<close>
    53   (if x \<le> y then x#y#ys else y#(insort1 x ys))\<close>
    63 \<close>
    54 \<close>
    64 fun T_insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> nat" where
    55 fun T_insort1 :: "'a::linorder \<Rightarrow> 'a list \<Rightarrow> nat" where
    65 "T_insort1 x [] = 1" |
    56   "T_insort1 x [] = 1" |
    66 "T_insort1 x (y#ys) =
    57   "T_insort1 x (y#ys) =
    67   (if x \<le> y then 0 else T_insort1 x ys) + 1"
    58   (if x \<le> y then 0 else T_insort1 x ys) + 1"
    68 
    59 
    69 text\<open>
    60 text\<open>
    70 \<open>insort [] = []\<close>
    61 \<open>insort [] = []\<close>
    71 \<open>insort (x#xs) = insort1 x (insort xs)\<close>
    62 \<open>insort (x#xs) = insort1 x (insort xs)\<close>
    72 \<close>
    63 \<close>
    73 fun T_insort :: "'a::linorder list \<Rightarrow> nat" where
    64 fun T_insort :: "'a::linorder list \<Rightarrow> nat" where
    74 "T_insort [] = 1" |
    65   "T_insort [] = 1" |
    75 "T_insort (x#xs) = T_insort xs + T_insort1 x (insort xs) + 1"
    66   "T_insort (x#xs) = T_insort xs + T_insort1 x (insort xs) + 1"
    76 
    67 
    77 
    68 
    78 lemma T_insort1_length: "T_insort1 x xs \<le> length xs + 1"
    69 lemma T_insort1_length: "T_insort1 x xs \<le> length xs + 1"
    79 apply(induction xs)
    70   by (induction xs) auto
    80 apply auto
       
    81 done
       
    82 
    71 
    83 lemma length_insort1: "length (insort1 x xs) = length xs + 1"
    72 lemma length_insort1: "length (insort1 x xs) = length xs + 1"
    84 apply(induction xs)
    73   by (induction xs) auto
    85 apply auto
       
    86 done
       
    87 
    74 
    88 lemma length_insort: "length (insort xs) = length xs"
    75 lemma length_insort: "length (insort xs) = length xs"
    89 apply(induction xs)
    76   by (metis Sorting.mset_insort size_mset)
    90 apply (auto simp: length_insort1)
       
    91 done
       
    92 
    77 
    93 lemma T_insort_length: "T_insort xs \<le> (length xs + 1) ^ 2"
    78 lemma T_insort_length: "T_insort xs \<le> (length xs + 1) ^ 2"
    94 proof(induction xs)
    79 proof(induction xs)
    95   case Nil show ?case by simp
    80   case Nil show ?case by simp
    96 next
    81 next
   107 
    92 
   108 
    93 
   109 subsection "Merge Sort"
    94 subsection "Merge Sort"
   110 
    95 
   111 fun merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    96 fun merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> 'a list" where
   112 "merge [] ys = ys" |
    97   "merge [] ys = ys" |
   113 "merge xs [] = xs" |
    98   "merge xs [] = xs" |
   114 "merge (x#xs) (y#ys) = (if x \<le> y then x # merge xs (y#ys) else y # merge (x#xs) ys)"
    99   "merge (x#xs) (y#ys) = (if x \<le> y then x # merge xs (y#ys) else y # merge (x#xs) ys)"
   115 
   100 
   116 fun msort :: "'a::linorder list \<Rightarrow> 'a list" where
   101 fun msort :: "'a::linorder list \<Rightarrow> 'a list" where
   117 "msort xs = (let n = length xs in
   102   "msort xs = (let n = length xs in
   118   if n \<le> 1 then xs
   103   if n \<le> 1 then xs
   119   else merge (msort (take (n div 2) xs)) (msort (drop (n div 2) xs)))"
   104   else merge (msort (take (n div 2) xs)) (msort (drop (n div 2) xs)))"
   120 
   105 
   121 declare msort.simps [simp del]
   106 declare msort.simps [simp del]
   122 
   107 
   123 
   108 
   124 subsubsection "Functional Correctness"
   109 subsubsection "Functional Correctness"
   125 
   110 
   126 lemma mset_merge: "mset(merge xs ys) = mset xs + mset ys"
   111 lemma mset_merge: "mset(merge xs ys) = mset xs + mset ys"
   127 by(induction xs ys rule: merge.induct) auto
   112   by(induction xs ys rule: merge.induct) auto
   128 
   113 
   129 lemma mset_msort: "mset (msort xs) = mset xs"
   114 lemma mset_msort: "mset (msort xs) = mset xs"
   130 proof(induction xs rule: msort.induct)
   115 proof(induction xs rule: msort.induct)
   131   case (1 xs)
   116   case (1 xs)
   132   let ?n = "length xs"
   117   let ?n = "length xs"
   149 qed
   134 qed
   150 
   135 
   151 text \<open>Via the previous lemma or directly:\<close>
   136 text \<open>Via the previous lemma or directly:\<close>
   152 
   137 
   153 lemma set_merge: "set(merge xs ys) = set xs \<union> set ys"
   138 lemma set_merge: "set(merge xs ys) = set xs \<union> set ys"
   154 by (metis mset_merge set_mset_mset set_mset_union)
   139   by (metis mset_merge set_mset_mset set_mset_union)
   155 
   140 
   156 lemma "set(merge xs ys) = set xs \<union> set ys"
   141 lemma "set(merge xs ys) = set xs \<union> set ys"
   157 by(induction xs ys rule: merge.induct) (auto)
   142   by(induction xs ys rule: merge.induct) (auto)
   158 
   143 
   159 lemma sorted_merge: "sorted (merge xs ys) \<longleftrightarrow> (sorted xs \<and> sorted ys)"
   144 lemma sorted_merge: "sorted (merge xs ys) \<longleftrightarrow> (sorted xs \<and> sorted ys)"
   160 by(induction xs ys rule: merge.induct) (auto simp: set_merge)
   145   by(induction xs ys rule: merge.induct) (auto simp: set_merge)
   161 
   146 
   162 lemma sorted_msort: "sorted (msort xs)"
   147 lemma sorted_msort: "sorted (msort xs)"
   163 proof(induction xs rule: msort.induct)
   148 proof(induction xs rule: msort.induct)
   164   case (1 xs)
   149   case (1 xs)
   165   let ?n = "length xs"
   150   let ?n = "length xs"
   178 subsubsection "Time Complexity"
   163 subsubsection "Time Complexity"
   179 
   164 
   180 text \<open>We only count the number of comparisons between list elements.\<close>
   165 text \<open>We only count the number of comparisons between list elements.\<close>
   181 
   166 
   182 fun C_merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> nat" where
   167 fun C_merge :: "'a::linorder list \<Rightarrow> 'a list \<Rightarrow> nat" where
   183 "C_merge [] ys = 0" |
   168   "C_merge [] ys = 0" |
   184 "C_merge xs [] = 0" |
   169   "C_merge xs [] = 0" |
   185 "C_merge (x#xs) (y#ys) = 1 + (if x \<le> y then C_merge xs (y#ys) else C_merge (x#xs) ys)"
   170   "C_merge (x#xs) (y#ys) = 1 + (if x \<le> y then C_merge xs (y#ys) else C_merge (x#xs) ys)"
   186 
   171 
   187 lemma C_merge_ub: "C_merge xs ys \<le> length xs + length ys"
   172 lemma C_merge_ub: "C_merge xs ys \<le> length xs + length ys"
   188 by (induction xs ys rule: C_merge.induct) auto
   173   by (induction xs ys rule: C_merge.induct) auto
   189 
   174 
   190 fun C_msort :: "'a::linorder list \<Rightarrow> nat" where
   175 fun C_msort :: "'a::linorder list \<Rightarrow> nat" where
   191 "C_msort xs =
   176   "C_msort xs =
   192   (let n = length xs;
   177   (let n = length xs;
   193        ys = take (n div 2) xs;
   178        ys = take (n div 2) xs;
   194        zs = drop (n div 2) xs
   179        zs = drop (n div 2) xs
   195    in if n \<le> 1 then 0
   180    in if n \<le> 1 then 0
   196       else C_msort ys + C_msort zs + C_merge (msort ys) (msort zs))"
   181       else C_msort ys + C_msort zs + C_merge (msort ys) (msort zs))"
   197 
   182 
   198 declare C_msort.simps [simp del]
   183 declare C_msort.simps [simp del]
   199 
   184 
   200 lemma length_merge: "length(merge xs ys) = length xs + length ys"
   185 lemma length_merge: "length(merge xs ys) = length xs + length ys"
   201 apply (induction xs ys rule: merge.induct)
   186   by (induction xs ys rule: merge.induct) auto
   202 apply auto
       
   203 done
       
   204 
   187 
   205 lemma length_msort: "length(msort xs) = length xs"
   188 lemma length_msort: "length(msort xs) = length xs"
   206 proof (induction xs rule: msort.induct)
   189 proof (induction xs rule: msort.induct)
   207   case (1 xs)
   190   case (1 xs)
   208   show ?case
   191   show ?case
   243   qed
   226   qed
   244 qed
   227 qed
   245 
   228 
   246 (* Beware of implicit conversions: *)
   229 (* Beware of implicit conversions: *)
   247 lemma C_msort_log: "length xs = 2^k \<Longrightarrow> C_msort xs \<le> length xs * log 2 (length xs)"
   230 lemma C_msort_log: "length xs = 2^k \<Longrightarrow> C_msort xs \<le> length xs * log 2 (length xs)"
   248 using C_msort_le[of xs k] apply (simp add: log_nat_power algebra_simps)
   231   using C_msort_le[of xs k]
   249 by (metis (mono_tags) numeral_power_eq_of_nat_cancel_iff of_nat_le_iff of_nat_mult)
   232   by (metis log2_of_power_eq mult.commute of_nat_mono of_nat_mult) 
   250 
   233 
   251 
   234 
   252 subsection "Bottom-Up Merge Sort"
   235 subsection "Bottom-Up Merge Sort"
   253 
   236 
   254 fun merge_adj :: "('a::linorder) list list \<Rightarrow> 'a list list" where
   237 fun merge_adj :: "('a::linorder) list list \<Rightarrow> 'a list list" where
   255 "merge_adj [] = []" |
   238   "merge_adj [] = []" |
   256 "merge_adj [xs] = [xs]" |
   239   "merge_adj [xs] = [xs]" |
   257 "merge_adj (xs # ys # zss) = merge xs ys # merge_adj zss"
   240   "merge_adj (xs # ys # zss) = merge xs ys # merge_adj zss"
   258 
   241 
   259 text \<open>For the termination proof of \<open>merge_all\<close> below.\<close>
   242 text \<open>For the termination proof of \<open>merge_all\<close> below.\<close>
   260 lemma length_merge_adjacent[simp]: "length (merge_adj xs) = (length xs + 1) div 2"
   243 lemma length_merge_adjacent[simp]: "length (merge_adj xs) = (length xs + 1) div 2"
   261 by (induction xs rule: merge_adj.induct) auto
   244   by (induction xs rule: merge_adj.induct) auto
   262 
   245 
   263 fun merge_all :: "('a::linorder) list list \<Rightarrow> 'a list" where
   246 fun merge_all :: "('a::linorder) list list \<Rightarrow> 'a list" where
   264 "merge_all [] = []" |
   247   "merge_all [] = []" |
   265 "merge_all [xs] = xs" |
   248   "merge_all [xs] = xs" |
   266 "merge_all xss = merge_all (merge_adj xss)"
   249   "merge_all xss = merge_all (merge_adj xss)"
   267 
   250 
   268 definition msort_bu :: "('a::linorder) list \<Rightarrow> 'a list" where
   251 definition msort_bu :: "('a::linorder) list \<Rightarrow> 'a list" where
   269 "msort_bu xs = merge_all (map (\<lambda>x. [x]) xs)"
   252   "msort_bu xs = merge_all (map (\<lambda>x. [x]) xs)"
   270 
   253 
   271 
   254 
   272 subsubsection "Functional Correctness"
   255 subsubsection "Functional Correctness"
   273 
   256 
   274 abbreviation mset_mset :: "'a list list \<Rightarrow> 'a multiset" where
   257 abbreviation mset_mset :: "'a list list \<Rightarrow> 'a multiset" where
   275 "mset_mset xss \<equiv> \<Sum>\<^sub># (image_mset mset (mset xss))"
   258   "mset_mset xss \<equiv> \<Sum>\<^sub># (image_mset mset (mset xss))"
   276 
   259 
   277 lemma mset_merge_adj:
   260 lemma mset_merge_adj:
   278   "mset_mset (merge_adj xss) = mset_mset xss"
   261   "mset_mset (merge_adj xss) = mset_mset xss"
   279 by(induction xss rule: merge_adj.induct) (auto simp: mset_merge)
   262   by(induction xss rule: merge_adj.induct) (auto simp: mset_merge)
   280 
   263 
   281 lemma mset_merge_all:
   264 lemma mset_merge_all:
   282   "mset (merge_all xss) = mset_mset xss"
   265   "mset (merge_all xss) = mset_mset xss"
   283 by(induction xss rule: merge_all.induct) (auto simp: mset_merge mset_merge_adj)
   266   by(induction xss rule: merge_all.induct) (auto simp: mset_merge mset_merge_adj)
   284 
   267 
   285 lemma mset_msort_bu: "mset (msort_bu xs) = mset xs"
   268 lemma mset_msort_bu: "mset (msort_bu xs) = mset xs"
   286 by(simp add: msort_bu_def mset_merge_all multiset.map_comp comp_def)
   269   by(simp add: msort_bu_def mset_merge_all multiset.map_comp comp_def)
   287 
   270 
   288 lemma sorted_merge_adj:
   271 lemma sorted_merge_adj:
   289   "\<forall>xs \<in> set xss. sorted xs \<Longrightarrow> \<forall>xs \<in> set (merge_adj xss). sorted xs"
   272   "\<forall>xs \<in> set xss. sorted xs \<Longrightarrow> \<forall>xs \<in> set (merge_adj xss). sorted xs"
   290 by(induction xss rule: merge_adj.induct) (auto simp: sorted_merge)
   273   by(induction xss rule: merge_adj.induct) (auto simp: sorted_merge)
   291 
   274 
   292 lemma sorted_merge_all:
   275 lemma sorted_merge_all:
   293   "\<forall>xs \<in> set xss. sorted xs \<Longrightarrow> sorted (merge_all xss)"
   276   "\<forall>xs \<in> set xss. sorted xs \<Longrightarrow> sorted (merge_all xss)"
   294 apply(induction xss rule: merge_all.induct)
   277   by (induction xss rule: merge_all.induct) (auto simp add: sorted_merge_adj)
   295 using [[simp_depth_limit=3]] by (auto simp add: sorted_merge_adj)
       
   296 
   278 
   297 lemma sorted_msort_bu: "sorted (msort_bu xs)"
   279 lemma sorted_msort_bu: "sorted (msort_bu xs)"
   298 by(simp add: msort_bu_def sorted_merge_all)
   280   by(simp add: msort_bu_def sorted_merge_all)
   299 
   281 
   300 
   282 
   301 subsubsection "Time Complexity"
   283 subsubsection "Time Complexity"
   302 
   284 
   303 fun C_merge_adj :: "('a::linorder) list list \<Rightarrow> nat" where
   285 fun C_merge_adj :: "('a::linorder) list list \<Rightarrow> nat" where
   304 "C_merge_adj [] = 0" |
   286   "C_merge_adj [] = 0" |
   305 "C_merge_adj [xs] = 0" |
   287   "C_merge_adj [xs] = 0" |
   306 "C_merge_adj (xs # ys # zss) = C_merge xs ys + C_merge_adj zss"
   288   "C_merge_adj (xs # ys # zss) = C_merge xs ys + C_merge_adj zss"
   307 
   289 
   308 fun C_merge_all :: "('a::linorder) list list \<Rightarrow> nat" where
   290 fun C_merge_all :: "('a::linorder) list list \<Rightarrow> nat" where
   309 "C_merge_all [] = 0" |
   291   "C_merge_all [] = 0" |
   310 "C_merge_all [xs] = 0" |
   292   "C_merge_all [xs] = 0" |
   311 "C_merge_all xss = C_merge_adj xss + C_merge_all (merge_adj xss)"
   293   "C_merge_all xss = C_merge_adj xss + C_merge_all (merge_adj xss)"
   312 
   294 
   313 definition C_msort_bu :: "('a::linorder) list \<Rightarrow> nat" where
   295 definition C_msort_bu :: "('a::linorder) list \<Rightarrow> nat" where
   314 "C_msort_bu xs = C_merge_all (map (\<lambda>x. [x]) xs)"
   296   "C_msort_bu xs = C_merge_all (map (\<lambda>x. [x]) xs)"
   315 
   297 
   316 lemma length_merge_adj:
   298 lemma length_merge_adj:
   317   "\<lbrakk> even(length xss); \<forall>xs \<in> set xss. length xs = m \<rbrakk>
   299   "\<lbrakk> even(length xss); \<forall>xs \<in> set xss. length xs = m \<rbrakk>
   318   \<Longrightarrow> \<forall>xs \<in> set (merge_adj xss). length xs = 2*m"
   300   \<Longrightarrow> \<forall>xs \<in> set (merge_adj xss). length xs = 2*m"
   319 by(induction xss rule: merge_adj.induct) (auto simp: length_merge)
   301   by(induction xss rule: merge_adj.induct) (auto simp: length_merge)
   320 
   302 
   321 lemma C_merge_adj: "\<forall>xs \<in> set xss. length xs = m \<Longrightarrow> C_merge_adj xss \<le> m * length xss"
   303 lemma C_merge_adj: "\<forall>xs \<in> set xss. length xs = m \<Longrightarrow> C_merge_adj xss \<le> m * length xss"
   322 proof(induction xss rule: C_merge_adj.induct)
   304 proof(induction xss rule: C_merge_adj.induct)
   323   case 1 thus ?case by simp
   305   case 1 thus ?case by simp
   324 next
   306 next
   352     using k' by (simp add: algebra_simps)
   334     using k' by (simp add: algebra_simps)
   353   finally show ?case .
   335   finally show ?case .
   354 qed
   336 qed
   355 
   337 
   356 corollary C_msort_bu: "length xs = 2 ^ k \<Longrightarrow> C_msort_bu xs \<le> k * 2 ^ k"
   338 corollary C_msort_bu: "length xs = 2 ^ k \<Longrightarrow> C_msort_bu xs \<le> k * 2 ^ k"
   357 using C_merge_all[of "map (\<lambda>x. [x]) xs" 1] by (simp add: C_msort_bu_def)
   339   using C_merge_all[of "map (\<lambda>x. [x]) xs" 1] by (simp add: C_msort_bu_def)
   358 
   340 
   359 
   341 
   360 subsection "Quicksort"
   342 subsection "Quicksort"
   361 
   343 
   362 fun quicksort :: "('a::linorder) list \<Rightarrow> 'a list" where
   344 fun quicksort :: "('a::linorder) list \<Rightarrow> 'a list" where
   363 "quicksort []     = []" |
   345   "quicksort []     = []" |
   364 "quicksort (x#xs) = quicksort (filter (\<lambda>y. y < x) xs) @ [x] @ quicksort (filter (\<lambda>y. x \<le> y) xs)"
   346   "quicksort (x#xs) = quicksort (filter (\<lambda>y. y < x) xs) @ [x] @ quicksort (filter (\<lambda>y. x \<le> y) xs)"
   365 
   347 
   366 lemma mset_quicksort: "mset (quicksort xs) = mset xs"
   348 lemma mset_quicksort: "mset (quicksort xs) = mset xs"
   367 apply (induction xs rule: quicksort.induct)
   349   by (induction xs rule: quicksort.induct) (auto simp: not_le)
   368 apply (auto simp: not_le)
       
   369 done
       
   370 
   350 
   371 lemma set_quicksort: "set (quicksort xs) = set xs"
   351 lemma set_quicksort: "set (quicksort xs) = set xs"
   372 by(rule mset_eq_setD[OF mset_quicksort])
   352   by(rule mset_eq_setD[OF mset_quicksort])
   373 
   353 
   374 lemma sorted_quicksort: "sorted (quicksort xs)"
   354 lemma sorted_quicksort: "sorted (quicksort xs)"
   375 apply (induction xs rule: quicksort.induct)
   355 proof (induction xs rule: quicksort.induct)
   376 apply (auto simp add: sorted_append set_quicksort)
   356 qed (auto simp: sorted_append set_quicksort)
   377 done
       
   378 
   357 
   379 
   358 
   380 subsection "Insertion Sort w.r.t. Keys and Stability"
   359 subsection "Insertion Sort w.r.t. Keys and Stability"
   381 
   360 
   382 hide_const List.insort_key
   361 hide_const List.insort_key
   383 
   362 
   384 fun insort1_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
   363 fun insort1_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
   385 "insort1_key f x [] = [x]" |
   364   "insort1_key f x [] = [x]" |
   386 "insort1_key f x (y # ys) = (if f x \<le> f y then x # y # ys else y # insort1_key f x ys)"
   365   "insort1_key f x (y # ys) = (if f x \<le> f y then x # y # ys else y # insort1_key f x ys)"
   387 
   366 
   388 fun insort_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a list \<Rightarrow> 'a list" where
   367 fun insort_key :: "('a \<Rightarrow> 'k::linorder) \<Rightarrow> 'a list \<Rightarrow> 'a list" where
   389 "insort_key f [] = []" |
   368   "insort_key f [] = []" |
   390 "insort_key f (x # xs) = insort1_key f x (insort_key f xs)"
   369   "insort_key f (x # xs) = insort1_key f x (insort_key f xs)"
   391 
   370 
   392 
   371 
   393 subsubsection "Standard functional correctness"
   372 subsubsection "Standard functional correctness"
   394 
   373 
   395 lemma mset_insort1_key: "mset (insort1_key f x xs) = {#x#} + mset xs"
   374 lemma mset_insort1_key: "mset (insort1_key f x xs) = {#x#} + mset xs"
   396 by(induction xs) simp_all
   375   by(induction xs) simp_all
   397 
   376 
   398 lemma mset_insort_key: "mset (insort_key f xs) = mset xs"
   377 lemma mset_insort_key: "mset (insort_key f xs) = mset xs"
   399 by(induction xs) (simp_all add: mset_insort1_key)
   378   by(induction xs) (simp_all add: mset_insort1_key)
   400 
   379 
   401 (* Inductive proof simpler than derivation from mset lemma: *)
   380 (* Inductive proof simpler than derivation from mset lemma: *)
   402 lemma set_insort1_key: "set (insort1_key f x xs) = {x} \<union> set xs"
   381 lemma set_insort1_key: "set (insort1_key f x xs) = {x} \<union> set xs"
   403 by (induction xs) auto
   382   by (induction xs) auto
   404 
   383 
   405 lemma sorted_insort1_key: "sorted (map f (insort1_key f a xs)) = sorted (map f xs)"
   384 lemma sorted_insort1_key: "sorted (map f (insort1_key f a xs)) = sorted (map f xs)"
   406 by(induction xs)(auto simp: set_insort1_key)
   385   by(induction xs)(auto simp: set_insort1_key)
   407 
   386 
   408 lemma sorted_insort_key: "sorted (map f (insort_key f xs))"
   387 lemma sorted_insort_key: "sorted (map f (insort_key f xs))"
   409 by(induction xs)(simp_all add: sorted_insort1_key)
   388   by(induction xs)(simp_all add: sorted_insort1_key)
   410 
   389 
   411 
   390 
   412 subsubsection "Stability"
   391 subsubsection "Stability"
   413 
   392 
   414 lemma insort1_is_Cons: "\<forall>x\<in>set xs. f a \<le> f x \<Longrightarrow> insort1_key f a xs = a # xs"
   393 lemma insort1_is_Cons: "\<forall>x\<in>set xs. f a \<le> f x \<Longrightarrow> insort1_key f a xs = a # xs"
   415 by (cases xs) auto
   394   by (cases xs) auto
   416 
   395 
   417 lemma filter_insort1_key_neg:
   396 lemma filter_insort1_key_neg:
   418   "\<not> P x \<Longrightarrow> filter P (insort1_key f x xs) = filter P xs"
   397   "\<not> P x \<Longrightarrow> filter P (insort1_key f x xs) = filter P xs"
   419 by (induction xs) simp_all
   398   by (induction xs) simp_all
   420 
   399 
   421 lemma filter_insort1_key_pos:
   400 lemma filter_insort1_key_pos:
   422   "sorted (map f xs) \<Longrightarrow> P x \<Longrightarrow> filter P (insort1_key f x xs) = insort1_key f x (filter P xs)"
   401   "sorted (map f xs) \<Longrightarrow> P x \<Longrightarrow> filter P (insort1_key f x xs) = insort1_key f x (filter P xs)"
   423 by (induction xs) (auto, subst insort1_is_Cons, auto)
   402   by (induction xs) (auto, subst insort1_is_Cons, auto)
   424 
   403 
   425 lemma sort_key_stable: "filter (\<lambda>y. f y = k) (insort_key f xs) = filter (\<lambda>y. f y = k) xs"
   404 lemma sort_key_stable: "filter (\<lambda>y. f y = k) (insort_key f xs) = filter (\<lambda>y. f y = k) xs"
   426 proof (induction xs)
   405 proof (induction xs)
   427   case Nil thus ?case by simp
   406   case Nil thus ?case by simp
   428 next
   407 next