src/HOL/Data_Structures/Selection.thy
changeset 80093 c0d689c4fd15
parent 75501 426afab39a55
child 80107 247751d25102
equal deleted inserted replaced
80092:1a9f0159de5b 80093:c0d689c4fd15
   632 | "T_partition3 x (y # ys) = T_partition3 x ys + 1"
   632 | "T_partition3 x (y # ys) = T_partition3 x ys + 1"
   633 
   633 
   634 lemma T_partition3_eq: "T_partition3 x xs = length xs + 1"
   634 lemma T_partition3_eq: "T_partition3 x xs = length xs + 1"
   635   by (induction x xs rule: T_partition3.induct) auto
   635   by (induction x xs rule: T_partition3.induct) auto
   636 
   636 
   637 definition T_slow_select :: "nat \<Rightarrow> 'a :: linorder list \<Rightarrow> nat" where
   637 
   638   "T_slow_select k xs = T_insort xs + T_nth (insort xs) k + 1"
   638 time_definition slow_select
       
   639 
       
   640 lemmas T_slow_select_def [simp del] = T_slow_select.simps
       
   641 
   639 
   642 
   640 definition T_slow_median :: "'a :: linorder list \<Rightarrow> nat" where
   643 definition T_slow_median :: "'a :: linorder list \<Rightarrow> nat" where
   641   "T_slow_median xs = T_slow_select ((length xs - 1) div 2) xs + 1"
   644   "T_slow_median xs = T_length xs + T_slow_select ((length xs - 1) div 2) xs"
   642 
   645 
   643 lemma T_slow_select_le: "T_slow_select k xs \<le> length xs ^ 2 + 3 * length xs + 3"
   646 lemma T_slow_select_le: "T_slow_select k xs \<le> length xs ^ 2 + 3 * length xs + 2"
   644 proof -
   647 proof -
   645   have "T_slow_select k xs \<le> (length xs + 1)\<^sup>2 + (length (insort xs) + 1) + 1"
   648   have "T_slow_select k xs \<le> (length xs + 1)\<^sup>2 + (length (insort xs) + 1)"
   646     unfolding T_slow_select_def
   649     unfolding T_slow_select_def
   647     by (intro add_mono T_insort_length) (auto simp: T_nth_eq)
   650     by (intro add_mono T_insort_length) (auto simp: T_nth_eq)
   648   also have "\<dots> = length xs ^ 2 + 3 * length xs + 3"
   651   also have "\<dots> = length xs ^ 2 + 3 * length xs + 2"
   649     by (simp add: insort_correct algebra_simps power2_eq_square)
   652     by (simp add: insort_correct algebra_simps power2_eq_square)
   650   finally show ?thesis .
   653   finally show ?thesis .
   651 qed
   654 qed
   652 
   655 
   653 lemma T_slow_median_le: "T_slow_median xs \<le> length xs ^ 2 + 3 * length xs + 4"
   656 lemma T_slow_median_le: "T_slow_median xs \<le> length xs ^ 2 + 4 * length xs + 3"
   654   unfolding T_slow_median_def using T_slow_select_le[of "(length xs - 1) div 2" xs] by simp
   657   unfolding T_slow_median_def using T_slow_select_le[of "(length xs - 1) div 2" xs]
   655 
   658   by (simp add: algebra_simps T_length_eq)
   656 
   659 
   657 fun T_chop :: "nat \<Rightarrow> 'a list \<Rightarrow> nat" where
   660 
   658   "T_chop 0 _  = 1"
   661 time_fun chop
   659 | "T_chop _ [] = 1"
       
   660 | "T_chop n xs = T_take n xs + T_drop n xs + T_chop n (drop n xs)"
       
   661 
   662 
   662 lemmas [simp del] = T_chop.simps
   663 lemmas [simp del] = T_chop.simps
   663 
   664 
   664 lemma T_chop_Nil [simp]: "T_chop d [] = 1"
   665 lemma T_chop_Nil [simp]: "T_chop d [] = 1"
   665   by (cases d) (auto simp: T_chop.simps)
   666   by (cases d) (auto simp: T_chop.simps)
   666 
   667 
   667 lemma T_chop_0 [simp]: "T_chop 0 xs = 1"
   668 lemma T_chop_0 [simp]: "T_chop 0 xs = 1"
   668   by (auto simp: T_chop.simps)
   669   by (auto simp: T_chop.simps)
   669 
   670 
   670 lemma T_chop_reduce:
   671 lemma T_chop_reduce:
   671   "n > 0 \<Longrightarrow> xs \<noteq> [] \<Longrightarrow> T_chop n xs = T_take n xs + T_drop n xs + T_chop n (drop n xs)"
   672   "n > 0 \<Longrightarrow> xs \<noteq> [] \<Longrightarrow> T_chop n xs = T_take n xs + T_drop n xs + T_chop n (drop n xs) + 1"
   672   by (cases n; cases xs) (auto simp: T_chop.simps)
   673   by (cases n; cases xs) (auto simp: T_chop.simps)
   673 
   674 
   674 lemma T_chop_le: "T_chop d xs \<le> 5 * length xs + 1"
   675 lemma T_chop_le: "T_chop d xs \<le> 5 * length xs + 1"
   675   by (induction d xs rule: T_chop.induct) (auto simp: T_chop_reduce T_take_eq T_drop_eq)
   676   by (induction d xs rule: T_chop.induct) (auto simp: T_chop_reduce T_take_eq T_drop_eq)
       
   677 
   676 
   678 
   677 text \<open>
   679 text \<open>
   678   The option \<open>domintros\<close> here allows us to explicitly reason about where the function does and
   680   The option \<open>domintros\<close> here allows us to explicitly reason about where the function does and
   679   does not terminate. With this, we can skip the termination proof this time because we can
   681   does not terminate. With this, we can skip the termination proof this time because we can
   680   reuse the one for \<^const>\<open>mom_select\<close>.
   682   reuse the one for \<^const>\<open>mom_select\<close>.
   681 \<close>
   683 \<close>
   682 function (domintros) T_mom_select :: "nat \<Rightarrow> 'a :: linorder list \<Rightarrow> nat" where
   684 function (domintros) T_mom_select :: "nat \<Rightarrow> 'a :: linorder list \<Rightarrow> nat" where
   683   "T_mom_select k xs = (
   685   "T_mom_select k xs = T_length xs + (
   684      if length xs \<le> 20 then
   686      if length xs \<le> 20 then
   685        T_slow_select k xs
   687        T_slow_select k xs
   686      else
   688      else
   687        let xss = chop 5 xs;
   689        let xss = chop 5 xs;
   688            ms = map slow_median xss;
   690            ms = map slow_median xss;
   691            (ls, es, gs) = partition3 x xs;
   693            (ls, es, gs) = partition3 x xs;
   692            nl = length ls;
   694            nl = length ls;
   693            ne = length es
   695            ne = length es
   694        in
   696        in
   695          (if k < nl then T_mom_select k ls 
   697          (if k < nl then T_mom_select k ls 
   696           else if k < nl + ne then 0
   698           else T_length es + (if k < nl + ne then 0 else T_mom_select (k - nl - ne) gs)) +
   697           else T_mom_select (k - nl - ne) gs) +
       
   698          T_mom_select idx ms + T_chop 5 xs + T_map T_slow_median xss +
   699          T_mom_select idx ms + T_chop 5 xs + T_map T_slow_median xss +
   699          T_partition3 x xs + T_length ls + T_length es + 1
   700          T_partition3 x xs + T_length ls + 1
   700       )"
   701       )"
   701   by auto
   702   by auto
   702 
   703 
   703 termination T_mom_select
   704 termination T_mom_select
   704 proof (rule allI, safe)
   705 proof (rule allI, safe)
   714 
   715 
   715 
   716 
   716 function T'_mom_select :: "nat \<Rightarrow> nat" where
   717 function T'_mom_select :: "nat \<Rightarrow> nat" where
   717   "T'_mom_select n =
   718   "T'_mom_select n =
   718      (if n \<le> 20 then
   719      (if n \<le> 20 then
   719         463
   720         483
   720       else
   721       else
   721         T'_mom_select (nat \<lceil>0.2*n\<rceil>) + T'_mom_select (nat \<lceil>0.7*n+3\<rceil>) + 17 * n + 50)"
   722         T'_mom_select (nat \<lceil>0.2*n\<rceil>) + T'_mom_select (nat \<lceil>0.7*n+3\<rceil>) + 19 * n + 55)"
   722   by force+
   723   by force+
   723 termination by (relation "measure id"; simp; linarith)
   724 termination by (relation "measure id"; simp; linarith)
   724 
   725 
   725 lemmas [simp del] = T'_mom_select.simps
   726 lemmas [simp del] = T'_mom_select.simps
   726 
   727 
   727 
   728 
   728 lemma T'_mom_select_ge: "T'_mom_select n \<ge> 463"
   729 lemma T'_mom_select_ge: "T'_mom_select n \<ge> 483"
   729   by (induction n rule: T'_mom_select.induct; subst T'_mom_select.simps) auto
   730   by (induction n rule: T'_mom_select.induct; subst T'_mom_select.simps) auto
   730 
   731 
   731 lemma T'_mom_select_mono:
   732 lemma T'_mom_select_mono:
   732   "m \<le> n \<Longrightarrow> T'_mom_select m \<le> T'_mom_select n"
   733   "m \<le> n \<Longrightarrow> T'_mom_select m \<le> T'_mom_select n"
   733 proof (induction n arbitrary: m rule: less_induct)
   734 proof (induction n arbitrary: m rule: less_induct)
   734   case (less n m)
   735   case (less n m)
   735   show ?case
   736   show ?case
   736   proof (cases "m \<le> 20")
   737   proof (cases "m \<le> 20")
   737     case True
   738     case True
   738     hence "T'_mom_select m = 463"
   739     hence "T'_mom_select m = 483"
   739       by (subst T'_mom_select.simps) auto
   740       by (subst T'_mom_select.simps) auto
   740     also have "\<dots> \<le> T'_mom_select n"
   741     also have "\<dots> \<le> T'_mom_select n"
   741       by (rule T'_mom_select_ge)
   742       by (rule T'_mom_select_ge)
   742     finally show ?thesis .
   743     finally show ?thesis .
   743   next
   744   next
   744     case False
   745     case False
   745     hence "T'_mom_select m =
   746     hence "T'_mom_select m =
   746              T'_mom_select (nat \<lceil>0.2*m\<rceil>) + T'_mom_select (nat \<lceil>0.7*m + 3\<rceil>) + 17 * m + 50"
   747              T'_mom_select (nat \<lceil>0.2*m\<rceil>) + T'_mom_select (nat \<lceil>0.7*m + 3\<rceil>) + 19 * m + 55"
   747       by (subst T'_mom_select.simps) auto
   748       by (subst T'_mom_select.simps) auto
   748     also have "\<dots> \<le> T'_mom_select (nat \<lceil>0.2*n\<rceil>) + T'_mom_select (nat \<lceil>0.7*n + 3\<rceil>) + 17 * n + 50"
   749     also have "\<dots> \<le> T'_mom_select (nat \<lceil>0.2*n\<rceil>) + T'_mom_select (nat \<lceil>0.7*n + 3\<rceil>) + 19 * n + 55"
   749       using \<open>m \<le> n\<close> and False by (intro add_mono less.IH; linarith)
   750       using \<open>m \<le> n\<close> and False by (intro add_mono less.IH; linarith)
   750     also have "\<dots> = T'_mom_select n"
   751     also have "\<dots> = T'_mom_select n"
   751       using \<open>m \<le> n\<close> and False by (subst T'_mom_select.simps) auto
   752       using \<open>m \<le> n\<close> and False by (subst T'_mom_select.simps) auto
   752     finally show ?thesis .
   753     finally show ?thesis .
   753   qed
   754   qed
   768   note IH = "1.IH"(1,2,3)[OF _ refl refl refl x_def tw refl refl refl refl]
   769   note IH = "1.IH"(1,2,3)[OF _ refl refl refl x_def tw refl refl refl refl]
   769 
   770 
   770   show ?case
   771   show ?case
   771   proof (cases "length xs \<le> 20")
   772   proof (cases "length xs \<le> 20")
   772     case True \<comment> \<open>base case\<close>
   773     case True \<comment> \<open>base case\<close>
   773     hence "T_mom_select k xs \<le> (length xs)\<^sup>2 + 3 * length xs + 3"
   774     hence "T_mom_select k xs \<le> (length xs)\<^sup>2 + 4 * length xs + 3"
   774       using T_slow_select_le[of k xs] by (subst T_mom_select.simps) auto
   775       using T_slow_select_le[of k xs] by (subst T_mom_select.simps) (auto simp: T_length_eq)
   775     also have "\<dots> \<le> 20\<^sup>2 + 3 * 20 + 3"
   776     also have "\<dots> \<le> 20\<^sup>2 + 4 * 20 + 3"
   776       using True by (intro add_mono power_mono) auto
   777       using True by (intro add_mono power_mono) auto
   777     also have "\<dots> \<le> 463"
   778     also have "\<dots> = 483"
   778       by simp
   779       by simp
   779     also have "\<dots> = T'_mom_select (length xs)"
   780     also have "\<dots> = T'_mom_select (length xs)"
   780       using True by (simp add: T'_mom_select.simps)
   781       using True by (simp add: T'_mom_select.simps)
   781     finally show ?thesis by simp
   782     finally show ?thesis by simp
   782   next
   783   next
   791       by (auto simp: median_def length_chop)
   792       by (auto simp: median_def length_chop)
   792     finally have x_eq: "x = median (map slow_median (chop 5 xs))" .
   793     finally have x_eq: "x = median (map slow_median (chop 5 xs))" .
   793 
   794 
   794     text \<open>The cost of computing the medians of all the subgroups:\<close>
   795     text \<open>The cost of computing the medians of all the subgroups:\<close>
   795     define T_ms where "T_ms = T_map T_slow_median (chop 5 xs)"
   796     define T_ms where "T_ms = T_map T_slow_median (chop 5 xs)"
   796     have "T_ms \<le> 9 * n + 45"
   797     have "T_ms \<le> 10 * n + 49"
   797     proof -
   798     proof -
   798       have "T_ms = (\<Sum>ys\<leftarrow>chop 5 xs. T_slow_median ys) + length (chop 5 xs) + 1"
   799       have "T_ms = (\<Sum>ys\<leftarrow>chop 5 xs. T_slow_median ys) + length (chop 5 xs) + 1"
   799         by (simp add: T_ms_def T_map_eq)
   800         by (simp add: T_ms_def T_map_eq)
   800       also have "(\<Sum>ys\<leftarrow>chop 5 xs. T_slow_median ys) \<le> (\<Sum>ys\<leftarrow>chop 5 xs. 44)"
   801       also have "(\<Sum>ys\<leftarrow>chop 5 xs. T_slow_median ys) \<le> (\<Sum>ys\<leftarrow>chop 5 xs. 48)"
   801       proof (intro sum_list_mono)
   802       proof (intro sum_list_mono)
   802         fix ys assume "ys \<in> set (chop 5 xs)"
   803         fix ys assume "ys \<in> set (chop 5 xs)"
   803         hence "length ys \<le> 5"
   804         hence "length ys \<le> 5"
   804           using length_chop_part_le by blast
   805           using length_chop_part_le by blast
   805         have "T_slow_median ys \<le> (length ys) ^ 2 + 3 * length ys + 4"
   806         have "T_slow_median ys \<le> (length ys) ^ 2 + 4 * length ys + 3"
   806           by (rule T_slow_median_le)
   807           by (rule T_slow_median_le)
   807         also have "\<dots> \<le> 5 ^ 2 + 3 * 5 + 4"
   808         also have "\<dots> \<le> 5 ^ 2 + 4 * 5 + 3"
   808           using \<open>length ys \<le> 5\<close> by (intro add_mono power_mono) auto
   809           using \<open>length ys \<le> 5\<close> by (intro add_mono power_mono) auto
   809         finally show "T_slow_median ys \<le> 44" by simp
   810         finally show "T_slow_median ys \<le> 48" by simp
   810       qed
   811       qed
   811       also have "(\<Sum>ys\<leftarrow>chop 5 xs. 44) + length (chop 5 xs) + 1 =
   812       also have "(\<Sum>ys\<leftarrow>chop 5 xs. 48) + length (chop 5 xs) + 1 =
   812                    45 * nat \<lceil>real n / 5\<rceil> + 1"
   813                    49 * nat \<lceil>real n / 5\<rceil> + 1"
   813         by (simp add: map_replicate_const length_chop)
   814         by (simp add: map_replicate_const length_chop)
   814       also have "\<dots> \<le> 9 * n + 45"
   815       also have "\<dots> \<le> 10 * n + 49"
   815         by linarith
   816         by linarith
   816       finally show "T_ms \<le> 9 * n + 45" by simp
   817       finally show "T_ms \<le> 10 * n + 49" by simp
   817     qed
   818     qed
   818 
   819 
   819     text \<open>The cost of the first recursive call (to compute the median of medians):\<close>
   820     text \<open>The cost of the first recursive call (to compute the median of medians):\<close>
   820     define T_rec1 where
   821     define T_rec1 where
   821       "T_rec1 = T_mom_select (((length xs + 4) div 5 - 1) div 2) (map slow_median (chop 5 xs))"
   822       "T_rec1 = T_mom_select (((length xs + 4) div 5 - 1) div 2) (map slow_median (chop 5 xs))"
   862         by (rule T'_mom_select_mono)
   863         by (rule T'_mom_select_mono)
   863       finally show ?thesis .
   864       finally show ?thesis .
   864     qed
   865     qed
   865 
   866 
   866     text \<open>Now for the final inequality chain:\<close>
   867     text \<open>Now for the final inequality chain:\<close>
   867     have "T_mom_select k xs = T_rec2 + T_rec1 + T_ms + n + nl + ne + T_chop 5 xs + 4" using False
   868     have "T_mom_select k xs \<le> T_rec2 + T_rec1 + T_ms + 2 * n + nl + ne + T_chop 5 xs + 5" using False
   868       by (subst T_mom_select.simps, unfold Let_def tw [symmetric] defs [symmetric])
   869       by (subst T_mom_select.simps, unfold Let_def tw [symmetric] defs [symmetric])
   869          (simp_all add: nl_def ne_def T_rec1_def T_rec2_def T_partition3_eq
   870          (simp_all add: nl_def ne_def T_rec1_def T_rec2_def T_partition3_eq
   870                         T_length_eq T_ms_def)
   871                         T_length_eq T_ms_def)
   871     also have "nl \<le> n" by (simp add: nl_def ls_def)
   872     also have "nl \<le> n" by (simp add: nl_def ls_def)
   872     also have "ne \<le> n" by (simp add: ne_def es_def)
   873     also have "ne \<le> n" by (simp add: ne_def es_def)
   873     also note \<open>T_ms \<le> 9 * n + 45\<close>
   874     also note \<open>T_ms \<le> 10 * n + 49\<close>
   874     also have "T_chop 5 xs \<le> 5 * n + 1"
   875     also have "T_chop 5 xs \<le> 5 * n + 1"
   875       using T_chop_le[of 5 xs] by simp 
   876       using T_chop_le[of 5 xs] by simp 
   876     also note \<open>T_rec1 \<le> T'_mom_select (nat \<lceil>0.2*n\<rceil>)\<close>
   877     also note \<open>T_rec1 \<le> T'_mom_select (nat \<lceil>0.2*n\<rceil>)\<close>
   877     also note \<open>T_rec2 \<le> T'_mom_select (nat \<lceil>0.7*n + 3\<rceil>)\<close>
   878     also note \<open>T_rec2 \<le> T'_mom_select (nat \<lceil>0.7*n + 3\<rceil>)\<close>
   878     finally have "T_mom_select k xs \<le>
   879     finally have "T_mom_select k xs \<le>
   879                     T'_mom_select (nat \<lceil>0.7*n + 3\<rceil>) + T'_mom_select (nat \<lceil>0.2*n\<rceil>) + 17 * n + 50"
   880                     T'_mom_select (nat \<lceil>0.7*n + 3\<rceil>) + T'_mom_select (nat \<lceil>0.2*n\<rceil>) + 19 * n + 55"
   880       by simp
   881       by simp
   881     also have "\<dots> = T'_mom_select n"
   882     also have "\<dots> = T'_mom_select n"
   882       using False by (subst T'_mom_select.simps) auto
   883       using False by (subst T'_mom_select.simps) auto
   883     finally show ?thesis by simp
   884     finally show ?thesis by simp
   884   qed
   885   qed
  1031 qed
  1032 qed
  1032 
  1033 
  1033 lemma T'_mom_select_le': "\<exists>C\<^sub>1 C\<^sub>2. \<forall>n. T'_mom_select n \<le> C\<^sub>1 * n + C\<^sub>2"
  1034 lemma T'_mom_select_le': "\<exists>C\<^sub>1 C\<^sub>2. \<forall>n. T'_mom_select n \<le> C\<^sub>1 * n + C\<^sub>2"
  1034 proof (rule akra_bazzi_light_nat)
  1035 proof (rule akra_bazzi_light_nat)
  1035   show "\<forall>n>20. T'_mom_select n = T'_mom_select (nat \<lceil>0.2 * n + 0\<rceil>) +
  1036   show "\<forall>n>20. T'_mom_select n = T'_mom_select (nat \<lceil>0.2 * n + 0\<rceil>) +
  1036                  T'_mom_select (nat \<lceil>0.7 * n + 3\<rceil>) + 17 * n + 50"
  1037                  T'_mom_select (nat \<lceil>0.7 * n + 3\<rceil>) + 19 * n + 55"
  1037     using T'_mom_select.simps by auto
  1038     using T'_mom_select.simps by auto
  1038 qed auto
  1039 qed auto
  1039 
  1040 
  1040 end
  1041 end