# HG changeset patch # User haftmann # Date 1449829917 -3600 # Node ID c43f87119d80578a5e1c1c2ee6eb1f770649fb8e # Parent 4f5ab843cf5b573ebbf78ccdb8ad39c1a48a46f3 modernized diff -r 4f5ab843cf5b -r c43f87119d80 src/HOL/Library/Discrete.thy --- a/src/HOL/Library/Discrete.thy Thu Dec 10 21:39:33 2015 +0100 +++ b/src/HOL/Library/Discrete.thy Fri Dec 11 11:31:57 2015 +0100 @@ -14,6 +14,28 @@ qualified fun log :: "nat \ nat" where [simp del]: "log n = (if n < 2 then 0 else Suc (log (n div 2)))" +lemma log_induct [consumes 1, case_names one double]: + fixes n :: nat + assumes "n > 0" + assumes one: "P 1" + assumes double: "\n. n \ 2 \ P (n div 2) \ P n" + shows "P n" +using `n > 0` proof (induct n rule: log.induct) + fix n + assume "\ n < 2 \ + 0 < n div 2 \ P (n div 2)" + then have *: "n \ 2 \ P (n div 2)" by simp + assume "n > 0" + show "P n" + proof (cases "n = 1") + case True with one show ?thesis by simp + next + case False with `n > 0` have "n \ 2" by auto + moreover with * have "P (n div 2)" . + ultimately show ?thesis by (rule double) + qed +qed + lemma log_zero [simp]: "log 0 = 0" by (simp add: log.simps) @@ -51,22 +73,41 @@ case (1 m) then have mn2: "m div 2 \ n div 2" by arith show "log m \ log n" - proof (cases "m < 2") - case True + proof (cases "m \ 2") + case False then have "m = 0 \ m = 1" by arith then show ?thesis by (auto simp del: One_nat_def) next - case False - with mn2 have "m \ 2" and "n \ 2" by auto arith - from False have m2_0: "m div 2 \ 0" by arith + case True then have "\ m < 2" by simp + with mn2 have "n \ 2" by arith + from True have m2_0: "m div 2 \ 0" by arith with mn2 have n2_0: "n div 2 \ 0" by arith - from False "1.hyps" mn2 have "log (m div 2) \ log (n div 2)" by blast + from `\ m < 2` "1.hyps" mn2 have "log (m div 2) \ log (n div 2)" by blast with m2_0 n2_0 have "log (2 * (m div 2)) \ log (2 * (n div 2))" by simp with m2_0 n2_0 \m \ 2\ \n \ 2\ show ?thesis by (simp only: log_rec [of m] log_rec [of n]) simp qed qed qed +lemma log_exp2_le: + assumes "n > 0" + shows "2 ^ log n \ n" +using assms proof (induct n rule: log_induct) + show "2 ^ log 1 \ (1 :: nat)" by simp +next + fix n :: nat + assume "n \ 2" + with log_mono have "log n \ Suc 0" + by (simp add: log.simps) + assume "2 ^ log (n div 2) \ n div 2" + with `n \ 2` have "2 ^ (log n - Suc 0) \ n div 2" by simp + then have "2 ^ (log n - Suc 0) * 2 ^ 1 \ n div 2 * 2" by simp + with `log n \ Suc 0` have "2 ^ log n \ n div 2 * 2" + unfolding power_add [symmetric] by simp + also have "n div 2 * 2 \ n" by (cases "even n") simp_all + finally show "2 ^ log n \ n" . +qed + subsection \Discrete square root\ diff -r 4f5ab843cf5b -r c43f87119d80 src/HOL/Library/Function_Growth.thy --- a/src/HOL/Library/Function_Growth.thy Thu Dec 10 21:39:33 2015 +0100 +++ b/src/HOL/Library/Function_Growth.thy Fri Dec 11 11:31:57 2015 +0100 @@ -7,6 +7,40 @@ imports Main Preorder Discrete begin +(* FIXME move *) + +context linorder +begin + +lemma mono_invE: + fixes f :: "'a \ 'b::order" + assumes "mono f" + assumes "f x < f y" + obtains "x < y" +proof + show "x < y" + proof (rule ccontr) + assume "\ x < y" + then have "y \ x" by simp + with \mono f\ obtain "f y \ f x" by (rule monoE) + with \f x < f y\ show False by simp + qed +qed + +end + +lemma (in semidom_divide) power_diff: + fixes a :: 'a + assumes "a \ 0" + assumes "m \ n" + shows "a ^ (m - n) = (a ^ m) div (a ^ n)" +proof - + def q == "m - n" + moreover with assms have "m = q + n" by (simp add: q_def) + ultimately show ?thesis using `a \ 0` by (simp add: power_add) +qed + + subsection \Motivation\ text \ @@ -80,7 +114,7 @@ restricted to @{typ nat}, see note above on \(\)\. \ -lemma equiv_funI [intro?]: +lemma equiv_funI: assumes "\c\<^sub>1>0. \c\<^sub>2>0. \n. \m>n. f m \ c\<^sub>1 * g m \ g m \ c\<^sub>2 * f m" shows "f \ g" unfolding equiv_fun_def by (rule assms) @@ -91,7 +125,7 @@ shows "\ f \ g" using assms unfolding equiv_fun_def linorder_not_le [symmetric] by blast -lemma equiv_funE [elim?]: +lemma equiv_funE: assumes "f \ g" obtains n c\<^sub>1 c\<^sub>2 where "c\<^sub>1 > 0" and "c\<^sub>2 > 0" and "\m. m > n \ f m \ c\<^sub>1 * g m \ g m \ c\<^sub>2 * f m" @@ -160,7 +194,7 @@ is that the situation is dual to the definition of \O\: the definition works since \c\ may become arbitrary small. Since this is not possible within @{term \}, we push the coefficient to the left hand side instead such - that it become arbitrary big instead. + that it may become arbitrary big instead. \ lemma less_fun_strongI: @@ -192,7 +226,7 @@ text \This yields all lemmas relating \\\, \\\ and \\\.\ interpretation fun_order: preorder_equiv less_eq_fun less_fun - rewrites "preorder_equiv.equiv less_eq_fun = equiv_fun" + rewrites "fun_order.equiv = equiv_fun" proof - interpret preorder: preorder_equiv less_eq_fun less_fun proof @@ -236,7 +270,7 @@ assume "f \ g" then obtain n c\<^sub>1 c\<^sub>2 where "c\<^sub>1 > 0" and "c\<^sub>2 > 0" and *: "\m. m > n \ f m \ c\<^sub>1 * g m \ g m \ c\<^sub>2 * f m" - by rule blast + by (rule equiv_funE) blast have "\m>n. f m \ c\<^sub>1 * g m" proof (rule allI, rule impI) fix m @@ -271,11 +305,13 @@ qed with \c\<^sub>1 > 0\ \c\<^sub>2 > 0\ have "\c\<^sub>1>0. \c\<^sub>2>0. \n. \m>n. f m \ c\<^sub>1 * g m \ g m \ c\<^sub>2 * f m" by blast - then show "f \ g" .. + then show "f \ g" by (rule equiv_funI) qed qed qed +declare fun_order.antisym [intro?] + subsection \Simple examples\ @@ -288,15 +324,79 @@ text \@{prop "(\n. f n + k) \ f"}\ -text \@{prop "(\n. Suc k * f n) \ f"}\ +lemma equiv_fun_mono_const: + assumes "mono f" and "\n. f n > 0" + shows "(\n. f n + k) \ f" +proof (cases "k = 0") + case True then show ?thesis by simp +next + case False + show ?thesis + proof + show "(\n. f n + k) \ f" + proof + from `\n. f n > 0` obtain n where "f n > 0" .. + have "\m>n. f m + k \ Suc k * f m" + proof (rule allI, rule impI) + fix m + assume "n < m" + with `mono f` have "f n \ f m" + using less_imp_le_nat monoE by blast + with `0 < f n` have "0 < f m" by auto + then obtain l where "f m = Suc l" by (cases "f m") simp_all + then show "f m + k \ Suc k * f m" by simp + qed + then show "\c>0. \n. \m>n. f m + k \ c * f m" by blast + qed + show "f \ (\n. f n + k)" + proof + have "f m \ 1 * (f m + k)" for m by simp + then show "\c>0. \n. \m>n. f m \ c * (f m + k)" by blast + qed + qed +qed -lemma "f \ (\n. f n + g n)" +lemma + assumes "strict_mono f" + shows "(\n. f n + k) \ f" +proof (rule equiv_fun_mono_const) + from assms show "mono f" by (rule strict_mono_mono) + show "\n. 0 < f n" + proof (rule ccontr) + assume "\ (\n. 0 < f n)" + then have "\n. f n = 0" by simp + then have "f 0 = f 1" by simp + moreover from `strict_mono f` have "f 0 < f 1" + by (simp add: strict_mono_def) + ultimately show False by simp + qed +qed + +lemma + "(\n. Suc k * f n) \ f" +proof + show "(\n. Suc k * f n) \ f" + proof + have "Suc k * f m \ Suc k * f m" for m by simp + then show "\c>0. \n. \m>n. Suc k * f m \ c * f m" by blast + qed + show "f \ (\n. Suc k * f n)" + proof + have "f m \ 1 * (Suc k * f m)" for m by simp + then show "\c>0. \n. \m>n. f m \ c * (Suc k * f m)" by blast + qed +qed + +lemma + "f \ (\n. f n + g n)" by rule auto -lemma "(\_. 0) \ (\n. Suc k)" +lemma + "(\_. 0) \ (\n. Suc k)" by (rule less_fun_strongI) auto -lemma "(\_. k) \ Discrete.log" +lemma + "(\_. k) \ Discrete.log" proof (rule less_fun_strongI) fix c :: nat have "\m>2 ^ (Suc (c * k)). c * k < Discrete.log m" @@ -311,10 +411,14 @@ qed then show "\n. \m>n. c * k < Discrete.log m" .. qed - + +(*lemma + "Discrete.log \ Discrete.sqrt" +proof (rule less_fun_strongI)*) text \@{prop "Discrete.log \ Discrete.sqrt"}\ -lemma "Discrete.sqrt \ id" +lemma + "Discrete.sqrt \ id" proof (rule less_fun_strongI) fix c :: nat assume "0 < c" @@ -334,13 +438,17 @@ then show "\n. \m>n. c * Discrete.sqrt m < id m" .. qed -lemma "id \ (\n. n\<^sup>2)" +lemma + "id \ (\n. n\<^sup>2)" by (rule less_fun_strongI) (auto simp add: power2_eq_square) -lemma "(\n. n ^ k) \ (\n. n ^ Suc k)" +lemma + "(\n. n ^ k) \ (\n. n ^ Suc k)" by (rule less_fun_strongI) auto +(*lemma + "(\n. n ^ k) \ (\n. 2 ^ n)" +proof (rule less_fun_strongI)*) text \@{prop "(\n. n ^ k) \ (\n. 2 ^ n)"}\ end -