# HG changeset patch # User wenzelm # Date 1361822148 -3600 # Node ID 546a9a1c315d84f4a248104342efe335dc928700 # Parent aba03f0c62548f499397ddc684420f2871dea8c3# Parent 05522141d2440850990be7f583071be3a25a6e2a merged; diff -r 05522141d244 -r 546a9a1c315d src/Doc/Codegen/Inductive_Predicate.thy --- a/src/Doc/Codegen/Inductive_Predicate.thy Mon Feb 25 17:47:32 2013 +0100 +++ b/src/Doc/Codegen/Inductive_Predicate.thy Mon Feb 25 20:55:48 2013 +0100 @@ -265,7 +265,7 @@ text {* Further examples for compiling inductive predicates can be found in - the @{text "HOL/ex/Predicate_Compile_ex.thy"} theory file. There are + the @{text "HOL/Predicate_Compile_Examples.thy"} theory file. There are also some examples in the Archive of Formal Proofs, notably in the @{text "POPLmark-deBruijn"} and the @{text "FeatherweightJava"} sessions. diff -r 05522141d244 -r 546a9a1c315d src/HOL/Big_Operators.thy --- a/src/HOL/Big_Operators.thy Mon Feb 25 17:47:32 2013 +0100 +++ b/src/HOL/Big_Operators.thy Mon Feb 25 20:55:48 2013 +0100 @@ -1808,4 +1808,20 @@ end +lemma (in linorder) mono_Max_commute: + assumes "mono f" + assumes "finite A" and "A \ {}" + shows "f (Max A) = Max (f ` A)" +proof (rule linorder_class.Max_eqI [symmetric]) + from `finite A` show "finite (f ` A)" by simp + from assms show "f (Max A) \ f ` A" by simp + fix x + assume "x \ f ` A" + then obtain y where "y \ A" and "x = f y" .. + with assms have "y \ Max A" by auto + with `mono f` have "f y \ f (Max A)" by (rule monoE) + with `x = f y` show "x \ f (Max A)" by simp +qed (* FIXME augment also dual rule mono_Min_commute *) + end + diff -r 05522141d244 -r 546a9a1c315d src/HOL/IMP/Abs_Int2_ivl.thy --- a/src/HOL/IMP/Abs_Int2_ivl.thy Mon Feb 25 17:47:32 2013 +0100 +++ b/src/HOL/IMP/Abs_Int2_ivl.thy Mon Feb 25 20:55:48 2013 +0100 @@ -37,7 +37,7 @@ "in_ivl k (Ivl Minf Pinf) \ True" -instantiation lb :: order +instantiation lb :: linorder begin definition less_eq_lb where @@ -55,11 +55,13 @@ case goal3 thus ?case by(auto simp: less_eq_lb_def split:lub_splits) next case goal4 thus ?case by(auto simp: less_eq_lb_def split:lub_splits) +next + case goal5 thus ?case by(auto simp: less_eq_lb_def split:lub_splits) qed end -instantiation ub :: order +instantiation ub :: linorder begin definition less_eq_ub where @@ -77,12 +79,19 @@ case goal3 thus ?case by(auto simp: less_eq_ub_def split:lub_splits) next case goal4 thus ?case by(auto simp: less_eq_ub_def split:lub_splits) +next + case goal5 thus ?case by(auto simp: less_eq_ub_def split:lub_splits) qed end lemmas le_lub_defs = less_eq_lb_def less_eq_ub_def +lemma le_lub_simps[simp]: + "Minf \ l" "Lb i \ Lb j = (i \ j)" "~ Lb i \ Minf" + "h \ Pinf" "Ub i \ Ub j = (i \ j)" "~ Pinf \ Ub j" +by(auto simp: le_lub_defs split: lub_splits) + definition empty where "empty = {1\0}" fun is_empty where @@ -200,15 +209,6 @@ "uminus_lb(Lb( x)) = Ub(-x)" | "uminus_lb Minf = Pinf" -instantiation ivl :: minus -begin - -definition "i1 - i2 = (if is_empty i1 | is_empty i2 then empty else - case (i1,i2) of (Ivl l1 h1, Ivl l2 h2) \ Ivl (l1 + uminus_ub h2) (h1 + uminus_lb l2))" - -instance .. -end - instantiation ivl :: uminus begin @@ -218,12 +218,22 @@ instance .. end -lemma minus_ivl_nice_def: "(i1::ivl) - i2 = i1 + -i2" +instantiation ivl :: minus +begin + +definition minus_ivl :: "ivl \ ivl \ ivl" where +"(i1::ivl) - i2 = i1 + -i2" + +instance .. +end + +lemma minus_ivl_cases: "i1 - i2 = (if is_empty i1 | is_empty i2 then empty else + case (i1,i2) of (Ivl l1 h1, Ivl l2 h2) \ Ivl (l1 + uminus_ub h2) (h1 + uminus_lb l2))" by(auto simp: plus_ivl_def minus_ivl_def split: ivl.split lub_splits) lemma gamma_minus_ivl: "n1 : \_ivl i1 \ n2 : \_ivl i2 \ n1-n2 : \_ivl(i1 - i2)" -by(auto simp add: minus_ivl_def \_ivl_def split: ivl.splits lub_splits) +by(auto simp add: minus_ivl_def plus_ivl_def \_ivl_def split: ivl.splits lub_splits) definition "filter_plus_ivl i i1 i2 = ((*if is_empty i then empty else*) i1 \ (i - i2), i2 \ (i - i1))" @@ -261,7 +271,7 @@ lemma mono_minus_ivl: fixes i1 :: ivl shows "i1 \ i1' \ i2 \ i2' \ i1 - i2 \ i1' - i2'" -apply(auto simp add: minus_ivl_def empty_def le_ivl_def le_lub_defs split: ivl.splits) +apply(auto simp add: minus_ivl_cases empty_def le_ivl_def le_lub_defs split: ivl.splits) apply(simp split: lub_splits) apply(simp split: lub_splits) apply(simp split: lub_splits) diff -r 05522141d244 -r 546a9a1c315d src/HOL/Library/Discrete.thy --- a/src/HOL/Library/Discrete.thy Mon Feb 25 17:47:32 2013 +0100 +++ b/src/HOL/Library/Discrete.thy Mon Feb 25 20:55:48 2013 +0100 @@ -6,11 +6,6 @@ imports Main begin -lemma power2_nat_le_eq_le: - fixes m n :: nat - shows "m ^ 2 \ n ^ 2 \ m \ n" - by (auto intro: power2_le_imp_le power_mono) - subsection {* Discrete logarithm *} fun log :: "nat \ nat" where @@ -81,10 +76,32 @@ definition sqrt :: "nat \ nat" where - "sqrt n = Max {m. m ^ 2 \ n}" + "sqrt n = Max {m. m\ \ n}" + +lemma sqrt_aux: + fixes n :: nat + shows "finite {m. m\ \ n}" and "{m. m\ \ n} \ {}" +proof - + { fix m + assume "m\ \ n" + then have "m \ n" + by (cases m) (simp_all add: power2_eq_square) + } note ** = this + then have "{m. m\ \ n} \ {m. m \ n}" by auto + then show "finite {m. m\ \ n}" by (rule finite_subset) rule + have "0\ \ n" by simp + then show *: "{m. m\ \ n} \ {}" by blast +qed + +lemma [code]: + "sqrt n = Max (Set.filter (\m. m\ \ n) {0..n})" +proof - + from power2_nat_le_imp_le [of _ n] have "{m. m \ n \ m\ \ n} = {m. m\ \ n}" by auto + then show ?thesis by (simp add: sqrt_def Set.filter_def) +qed lemma sqrt_inverse_power2 [simp]: - "sqrt (n ^ 2) = n" + "sqrt (n\) = n" proof - have "{m. m \ n} \ {}" by auto then have "Max {m. m \ n} \ n" by auto @@ -92,32 +109,74 @@ by (auto simp add: sqrt_def power2_nat_le_eq_le intro: antisym) qed -lemma [code]: - "sqrt n = Max (Set.filter (\m. m ^ 2 \ n) {0..n})" +lemma mono_sqrt: "mono sqrt" +proof + fix m n :: nat + have *: "0 * 0 \ m" by simp + assume "m \ n" + then show "sqrt m \ sqrt n" + by (auto intro!: Max_mono `0 * 0 \ m` finite_less_ub simp add: power2_eq_square sqrt_def) +qed + +lemma sqrt_greater_zero_iff [simp]: + "sqrt n > 0 \ n > 0" proof - - { fix m - assume "m\ \ n" - then have "m \ n" - by (cases m) (simp_all add: power2_eq_square) - } - then have "{m. m \ n \ m\ \ n} = {m. m\ \ n}" by auto - then show ?thesis by (simp add: sqrt_def Set.filter_def) + have *: "0 < Max {m. m\ \ n} \ (\a\{m. m\ \ n}. 0 < a)" + by (rule Max_gr_iff) (fact sqrt_aux)+ + show ?thesis + proof + assume "0 < sqrt n" + then have "0 < Max {m. m\ \ n}" by (simp add: sqrt_def) + with * show "0 < n" by (auto dest: power2_nat_le_imp_le) + next + assume "0 < n" + then have "1\ \ n \ 0 < (1::nat)" by simp + then have "\q. q\ \ n \ 0 < q" .. + with * have "0 < Max {m. m\ \ n}" by blast + then show "0 < sqrt n" by (simp add: sqrt_def) + qed +qed + +lemma sqrt_power2_le [simp]: (* FIXME tune proof *) + "(sqrt n)\ \ n" +proof (cases "n > 0") + case False then show ?thesis by (simp add: sqrt_def) +next + case True then have "sqrt n > 0" by simp + then have "mono (times (Max {m. m\ \ n}))" by (auto intro: mono_times_nat simp add: sqrt_def) + then have *: "Max {m. m\ \ n} * Max {m. m\ \ n} = Max (times (Max {m. m\ \ n}) ` {m. m\ \ n})" + using sqrt_aux [of n] by (rule mono_Max_commute) + have "Max (op * (Max {m. m * m \ n}) ` {m. m * m \ n}) \ n" + apply (subst Max_le_iff) + apply (metis (mono_tags) finite_imageI finite_less_ub le_square) + apply simp + apply (metis le0 mult_0_right) + apply auto + proof - + fix q + assume "q * q \ n" + show "Max {m. m * m \ n} * q \ n" + proof (cases "q > 0") + case False then show ?thesis by simp + next + case True then have "mono (times q)" by (rule mono_times_nat) + then have "q * Max {m. m * m \ n} = Max (times q ` {m. m * m \ n})" + using sqrt_aux [of n] by (auto simp add: power2_eq_square intro: mono_Max_commute) + then have "Max {m. m * m \ n} * q = Max (times q ` {m. m * m \ n})" by (simp add: mult_ac) + then show ?thesis apply simp + apply (subst Max_le_iff) + apply auto + apply (metis (mono_tags) finite_imageI finite_less_ub le_square) + apply (metis `q * q \ n`) + using `q * q \ n` by (metis le_cases mult_le_mono1 mult_le_mono2 order_trans) + qed + qed + with * show ?thesis by (simp add: sqrt_def power2_eq_square) qed lemma sqrt_le: "sqrt n \ n" -proof - - have "0\ \ n" by simp - then have *: "{m. m\ \ n} \ {}" by blast - { fix m - assume "m\ \ n" - then have "m \ n" - by (cases m) (simp_all add: power2_eq_square) - } note ** = this - then have "{m. m\ \ n} \ {m. m \ n}" by auto - then have "finite {m. m\ \ n}" by (rule finite_subset) rule - with * show ?thesis by (auto simp add: sqrt_def intro: **) -qed + using sqrt_aux [of n] by (auto simp add: sqrt_def intro: power2_nat_le_imp_le) hide_const (open) log sqrt diff -r 05522141d244 -r 546a9a1c315d src/HOL/Library/Function_Growth.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Library/Function_Growth.thy Mon Feb 25 20:55:48 2013 +0100 @@ -0,0 +1,346 @@ + +(* Author: Florian Haftmann, TU Muenchen *) + +header {* Comparing growth of functions on natural numbers by a preorder relation *} + +theory Function_Growth +imports Main "~~/src/HOL/Library/Preorder" "~~/src/HOL/Library/Discrete" +begin + +subsection {* Motivation *} + +text {* + When comparing growth of functions in computer science, it is common to adhere + on Landau Symbols (``O-Notation''). However these come at the cost of notational + oddities, particularly writing @{text "f = O(g)"} for @{text "f \ O(g)"} etc. + + Here we suggest a diffent way, following Hardy (G.~H.~Hardy and J.~E.~Littlewood, + Some problems of Diophantine approximation, Acta Mathematica 37 (1914), p.~225). + We establish a quasi order relation @{text "\"} on functions such that + @{text "f \ g \ f \ O(g)"}. From a didactic point of view, this does not only + avoid the notational oddities mentioned above but also emphasizes the key insight + of a growth hierachy of functions: + @{text "(\n. 0) \ (\n. k) \ Discrete.log \ Discrete.sqrt \ id \ \"}. +*} + +subsection {* Model *} + +text {* + Our growth functions are of type @{text "\ \ \"}. This is different + to the usual conventions for Landau symbols for which @{text "\ \ \"} + would be appropriate, but we argue that @{text "\ \ \"} is more + appropriate for analysis, whereas our setting is discrete. + + Note that we also restrict the additional coefficients to @{text \}, something + we discuss at the particular definitions. +*} + +subsection {* The @{text "\"} relation *} + +definition less_eq_fun :: "(nat \ nat) \ (nat \ nat) \ bool" (infix "\" 50) +where + "f \ g \ (\c>0. \n. \m>n. f m \ c * g m)" + +text {* + This yields @{text "f \ g \ f \ O(g)"}. Note that @{text c} is restricted to + @{text \}. This does not pose any problems since if @{text "f \ O(g)"} holds for + a @{text "c \ \"}, it also holds for @{text "\c\ \ \"} by transitivity. +*} + +lemma less_eq_funI [intro?]: + assumes "\c>0. \n. \m>n. f m \ c * g m" + shows "f \ g" + unfolding less_eq_fun_def by (rule assms) + +lemma not_less_eq_funI: + assumes "\c n. c > 0 \ \m>n. c * g m < f m" + shows "\ f \ g" + using assms unfolding less_eq_fun_def linorder_not_le [symmetric] by blast + +lemma less_eq_funE [elim?]: + assumes "f \ g" + obtains n c where "c > 0" and "\m. m > n \ f m \ c * g m" + using assms unfolding less_eq_fun_def by blast + +lemma not_less_eq_funE: + assumes "\ f \ g" and "c > 0" + obtains m where "m > n" and "c * g m < f m" + using assms unfolding less_eq_fun_def linorder_not_le [symmetric] by blast + + +subsection {* The @{text "\"} relation, the equivalence relation induced by @{text "\"} *} + +definition equiv_fun :: "(nat \ nat) \ (nat \ nat) \ bool" (infix "\" 50) +where + "f \ g \ + (\c\<^isub>1>0. \c\<^isub>2>0. \n. \m>n. f m \ c\<^isub>1 * g m \ g m \ c\<^isub>2 * f m)" + +text {* + This yields @{text "f \ g \ f \ \(g)"}. Concerning @{text "c\<^isub>1"} and @{text "c\<^isub>2"} + restricted to @{typ nat}, see note above on @{text "(\)"}. +*} + +lemma equiv_funI [intro?]: + assumes "\c\<^isub>1>0. \c\<^isub>2>0. \n. \m>n. f m \ c\<^isub>1 * g m \ g m \ c\<^isub>2 * f m" + shows "f \ g" + unfolding equiv_fun_def by (rule assms) + +lemma not_equiv_funI: + assumes "\c\<^isub>1 c\<^isub>2 n. c\<^isub>1 > 0 \ c\<^isub>2 > 0 \ + \m>n. c\<^isub>1 * f m < g m \ c\<^isub>2 * g m < f m" + shows "\ f \ g" + using assms unfolding equiv_fun_def linorder_not_le [symmetric] by blast + +lemma equiv_funE [elim?]: + assumes "f \ g" + obtains n c\<^isub>1 c\<^isub>2 where "c\<^isub>1 > 0" and "c\<^isub>2 > 0" + and "\m. m > n \ f m \ c\<^isub>1 * g m \ g m \ c\<^isub>2 * f m" + using assms unfolding equiv_fun_def by blast + +lemma not_equiv_funE: + fixes n c\<^isub>1 c\<^isub>2 + assumes "\ f \ g" and "c\<^isub>1 > 0" and "c\<^isub>2 > 0" + obtains m where "m > n" + and "c\<^isub>1 * f m < g m \ c\<^isub>2 * g m < f m" + using assms unfolding equiv_fun_def linorder_not_le [symmetric] by blast + + +subsection {* The @{text "\"} relation, the strict part of @{text "\"} *} + +definition less_fun :: "(nat \ nat) \ (nat \ nat) \ bool" (infix "\" 50) +where + "f \ g \ f \ g \ \ g \ f" + +lemma less_funI: + assumes "\c>0. \n. \m>n. f m \ c * g m" + and "\c n. c > 0 \ \m>n. c * f m < g m" + shows "f \ g" + using assms unfolding less_fun_def less_eq_fun_def linorder_not_less [symmetric] by blast + +lemma not_less_funI: + assumes "\c n. c > 0 \ \m>n. c * g m < f m" + and "\c>0. \n. \m>n. g m \ c * f m" + shows "\ f \ g" + using assms unfolding less_fun_def less_eq_fun_def linorder_not_less [symmetric] by blast + +lemma less_funE [elim?]: + assumes "f \ g" + obtains n c where "c > 0" and "\m. m > n \ f m \ c * g m" + and "\c n. c > 0 \ \m>n. c * f m < g m" +proof - + from assms have "f \ g" and "\ g \ f" by (simp_all add: less_fun_def) + from `f \ g` obtain n c where *:"c > 0" "\m. m > n \ f m \ c * g m" + by (rule less_eq_funE) blast + { fix c n :: nat + assume "c > 0" + with `\ g \ f` obtain m where "m > n" "c * f m < g m" + by (rule not_less_eq_funE) blast + then have **: "\m>n. c * f m < g m" by blast + } note ** = this + from * ** show thesis by (rule that) +qed + +lemma not_less_funE: + assumes "\ f \ g" and "c > 0" + obtains m where "m > n" and "c * g m < f m" + | d q where "\m. d > 0 \ m > q \ g q \ d * f q" + using assms unfolding less_fun_def linorder_not_less [symmetric] by blast + +text {* + I did not found a proof for @{text "f \ g \ f \ o(g)"}. Maybe this only + holds if @{text f} and/or @{text g} are of a certain class of functions. + However @{text "f \ o(g) \ f \ g"} is provable, and this yields a + handy introduction rule. + + Note that D. Knuth ignores @{text o} altogether. So what \dots + + Something still has to be said about the coefficient @{text c} in + the definition of @{text "(\)"}. In the typical definition of @{text o}, + it occurs on the \emph{right} hand side of the @{text "(>)"}. The reason + is that the situation is dual to the definition of @{text O}: the definition + works since @{text 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. +*} + +lemma less_fun_strongI: + assumes "\c. c > 0 \ \n. \m>n. c * f m < g m" + shows "f \ g" +proof (rule less_funI) + have "1 > (0::nat)" by simp + from assms `1 > 0` have "\n. \m>n. 1 * f m < g m" . + then obtain n where *: "\m. m > n \ 1 * f m < g m" by blast + have "\m>n. f m \ 1 * g m" + proof (rule allI, rule impI) + fix m + assume "m > n" + with * have "1 * f m < g m" by simp + then show "f m \ 1 * g m" by simp + qed + with `1 > 0` show "\c>0. \n. \m>n. f m \ c * g m" by blast + fix c n :: nat + assume "c > 0" + with assms obtain q where "\m. m > q \ c * f m < g m" by blast + then have "c * f (Suc (q + n)) < g (Suc (q + n))" by simp + moreover have "Suc (q + n) > n" by simp + ultimately show "\m>n. c * f m < g m" by blast +qed + + +subsection {* @{text "\"} is a preorder *} + +text {* This yields all lemmas relating @{text "\"}, @{text "\"} and @{text "\"}. *} + +interpretation fun_order: preorder_equiv less_eq_fun less_fun + where "preorder_equiv.equiv less_eq_fun = equiv_fun" +proof - + interpret preorder: preorder_equiv less_eq_fun less_fun + proof + fix f g h + show "f \ f" + proof + have "\n. \m>n. f m \ 1 * f m" by auto + then show "\c>0. \n. \m>n. f m \ c * f m" by blast + qed + show "f \ g \ f \ g \ \ g \ f" + by (fact less_fun_def) + assume "f \ g" and "g \ h" + show "f \ h" + proof + from `f \ g` obtain n\<^isub>1 c\<^isub>1 + where "c\<^isub>1 > 0" and P\<^isub>1: "\m. m > n\<^isub>1 \ f m \ c\<^isub>1 * g m" + by rule blast + from `g \ h` obtain n\<^isub>2 c\<^isub>2 + where "c\<^isub>2 > 0" and P\<^isub>2: "\m. m > n\<^isub>2 \ g m \ c\<^isub>2 * h m" + by rule blast + have "\m>max n\<^isub>1 n\<^isub>2. f m \ (c\<^isub>1 * c\<^isub>2) * h m" + proof (rule allI, rule impI) + fix m + assume Q: "m > max n\<^isub>1 n\<^isub>2" + from P\<^isub>1 Q have *: "f m \ c\<^isub>1 * g m" by simp + from P\<^isub>2 Q have "g m \ c\<^isub>2 * h m" by simp + with `c\<^isub>1 > 0` have "c\<^isub>1 * g m \ (c\<^isub>1 * c\<^isub>2) * h m" by simp + with * show "f m \ (c\<^isub>1 * c\<^isub>2) * h m" by (rule order_trans) + qed + then have "\n. \m>n. f m \ (c\<^isub>1 * c\<^isub>2) * h m" by rule + moreover from `c\<^isub>1 > 0` `c\<^isub>2 > 0` have "c\<^isub>1 * c\<^isub>2 > 0" by (rule mult_pos_pos) + ultimately show "\c>0. \n. \m>n. f m \ c * h m" by blast + qed + qed + from preorder.preorder_equiv_axioms show "class.preorder_equiv less_eq_fun less_fun" . + show "preorder_equiv.equiv less_eq_fun = equiv_fun" + proof (rule ext, rule ext, unfold preorder.equiv_def) + fix f g + show "f \ g \ g \ f \ f \ g" + proof + assume "f \ g" + then obtain n c\<^isub>1 c\<^isub>2 where "c\<^isub>1 > 0" and "c\<^isub>2 > 0" + and *: "\m. m > n \ f m \ c\<^isub>1 * g m \ g m \ c\<^isub>2 * f m" + by rule blast + have "\m>n. f m \ c\<^isub>1 * g m" + proof (rule allI, rule impI) + fix m + assume "m > n" + with * show "f m \ c\<^isub>1 * g m" by simp + qed + with `c\<^isub>1 > 0` have "\c>0. \n. \m>n. f m \ c * g m" by blast + then have "f \ g" .. + have "\m>n. g m \ c\<^isub>2 * f m" + proof (rule allI, rule impI) + fix m + assume "m > n" + with * show "g m \ c\<^isub>2 * f m" by simp + qed + with `c\<^isub>2 > 0` have "\c>0. \n. \m>n. g m \ c * f m" by blast + then have "g \ f" .. + from `f \ g` and `g \ f` show "f \ g \ g \ f" .. + next + assume "f \ g \ g \ f" + then have "f \ g" and "g \ f" by auto + from `f \ g` obtain n\<^isub>1 c\<^isub>1 where "c\<^isub>1 > 0" + and P\<^isub>1: "\m. m > n\<^isub>1 \ f m \ c\<^isub>1 * g m" by rule blast + from `g \ f` obtain n\<^isub>2 c\<^isub>2 where "c\<^isub>2 > 0" + and P\<^isub>2: "\m. m > n\<^isub>2 \ g m \ c\<^isub>2 * f m" by rule blast + have "\m>max n\<^isub>1 n\<^isub>2. f m \ c\<^isub>1 * g m \ g m \ c\<^isub>2 * f m" + proof (rule allI, rule impI) + fix m + assume Q: "m > max n\<^isub>1 n\<^isub>2" + from P\<^isub>1 Q have "f m \ c\<^isub>1 * g m" by simp + moreover from P\<^isub>2 Q have "g m \ c\<^isub>2 * f m" by simp + ultimately show "f m \ c\<^isub>1 * g m \ g m \ c\<^isub>2 * f m" .. + qed + with `c\<^isub>1 > 0` `c\<^isub>2 > 0` have "\c\<^isub>1>0. \c\<^isub>2>0. \n. + \m>n. f m \ c\<^isub>1 * g m \ g m \ c\<^isub>2 * f m" by blast + then show "f \ g" .. + qed + qed +qed + + +subsection {* Simple examples *} + +text {* + Most of these are left as constructive exercises for the reader. Note that additional + preconditions to the functions may be necessary. The list here is by no means to be + intended as complete contruction set for typical functions, here surely something + has to be added yet. +*} + +text {* @{prop "(\n. f n + k) \ f"} *} + +text {* @{prop "(\n. Suc k * f n) \ f"} *} + +lemma "f \ (\n. f n + g n)" + by rule auto + +lemma "(\_. 0) \ (\n. Suc k)" + by (rule less_fun_strongI) auto + +lemma "(\_. k) \ Discrete.log" +proof (rule less_fun_strongI) + fix c :: nat + have "\m>2 ^ (Suc (c * k)). c * k < Discrete.log m" + proof (rule allI, rule impI) + fix m :: nat + assume "2 ^ Suc (c * k) < m" + then have "2 ^ Suc (c * k) \ m" by simp + with log_mono have "Discrete.log (2 ^ (Suc (c * k))) \ Discrete.log m" + by (blast dest: monoD) + moreover have "c * k < Discrete.log (2 ^ (Suc (c * k)))" by simp + ultimately show "c * k < Discrete.log m" by auto + qed + then show "\n. \m>n. c * k < Discrete.log m" .. +qed + +text {* @{prop "Discrete.log \ Discrete.sqrt"} *} + +lemma "Discrete.sqrt \ id" +proof (rule less_fun_strongI) + fix c :: nat + assume "0 < c" + have "\m>(Suc c)\. c * Discrete.sqrt m < id m" + proof (rule allI, rule impI) + fix m + assume "(Suc c)\ < m" + then have "(Suc c)\ \ m" by simp + with mono_sqrt have "Discrete.sqrt ((Suc c)\) \ Discrete.sqrt m" by (rule monoE) + then have "Suc c \ Discrete.sqrt m" by simp + then have "c < Discrete.sqrt m" by simp + moreover from `(Suc c)\ < m` have "Discrete.sqrt m > 0" by simp + ultimately have "c * Discrete.sqrt m < Discrete.sqrt m * Discrete.sqrt m" by simp + also have "\ \ m" by (simp add: power2_eq_square [symmetric]) + finally show "c * Discrete.sqrt m < id m" by simp + qed + then show "\n. \m>n. c * Discrete.sqrt m < id m" .. +qed + +lemma "id \ (\n. n\)" + by (rule less_fun_strongI) (auto simp add: power2_eq_square) + +lemma "(\n. n ^ k) \ (\n. n ^ Suc k)" + by (rule less_fun_strongI) auto + +text {* @{prop "(\n. n ^ k) \ (\n. 2 ^ n)"} *} + +end + diff -r 05522141d244 -r 546a9a1c315d src/HOL/Library/Library.thy --- a/src/HOL/Library/Library.thy Mon Feb 25 17:47:32 2013 +0100 +++ b/src/HOL/Library/Library.thy Mon Feb 25 20:55:48 2013 +0100 @@ -15,7 +15,6 @@ Countable_Set Debug Diagonal_Subsequence - Discrete Dlist Eval_Witness Extended_Nat @@ -26,6 +25,7 @@ FrechetDeriv FuncSet Function_Division + Function_Growth Fundamental_Theorem_Algebra Indicator_Function Infinite_Set diff -r 05522141d244 -r 546a9a1c315d src/HOL/Nat.thy --- a/src/HOL/Nat.thy Mon Feb 25 17:47:32 2013 +0100 +++ b/src/HOL/Nat.thy Mon Feb 25 20:55:48 2013 +0100 @@ -1201,6 +1201,16 @@ apply (auto) done +lemma mono_times_nat: + fixes n :: nat + assumes "n > 0" + shows "mono (times n)" +proof + fix m q :: nat + assume "m \ q" + with assms show "n * m \ n * q" by simp +qed + text {* the lattice order on @{typ nat} *} instantiation nat :: distrib_lattice diff -r 05522141d244 -r 546a9a1c315d src/HOL/Orderings.thy --- a/src/HOL/Orderings.thy Mon Feb 25 17:47:32 2013 +0100 +++ b/src/HOL/Orderings.thy Mon Feb 25 20:55:48 2013 +0100 @@ -965,6 +965,15 @@ shows "mono f \ x \ y \ f x \ f y" unfolding mono_def by iprover +lemma monoE: + fixes f :: "'a \ 'b\order" + assumes "mono f" + assumes "x \ y" + obtains "f x \ f y" +proof + from assms show "f x \ f y" by (simp add: mono_def) +qed + definition strict_mono :: "('a \ 'b\order) \ bool" where "strict_mono f \ (\x y. x < y \ f x < f y)" @@ -998,6 +1007,21 @@ 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 + lemma strict_mono_eq: assumes "strict_mono f" shows "f x = f y \ x = y" diff -r 05522141d244 -r 546a9a1c315d src/HOL/Power.thy --- a/src/HOL/Power.thy Mon Feb 25 17:47:32 2013 +0100 +++ b/src/HOL/Power.thy Mon Feb 25 20:55:48 2013 +0100 @@ -721,6 +721,18 @@ apply (erule dvd_imp_le, simp) done +lemma power2_nat_le_eq_le: + fixes m n :: nat + shows "m\ \ n\ \ m \ n" + by (auto intro: power2_le_imp_le power_mono) + +lemma power2_nat_le_imp_le: + fixes m n :: nat + assumes "m\ \ n" + shows "m \ n" + using assms by (cases m) (simp_all add: power2_eq_square) + + subsection {* Code generator tweak *} diff -r 05522141d244 -r 546a9a1c315d src/HOL/ROOT --- a/src/HOL/ROOT Mon Feb 25 17:47:32 2013 +0100 +++ b/src/HOL/ROOT Mon Feb 25 20:55:48 2013 +0100 @@ -455,7 +455,6 @@ Transfer_Int_Nat HarmonicSeries Refute_Examples - Landau Execute_Choice Summation Gauge_Integration diff -r 05522141d244 -r 546a9a1c315d src/HOL/Tools/Sledgehammer/sledgehammer_compress.ML --- a/src/HOL/Tools/Sledgehammer/sledgehammer_compress.ML Mon Feb 25 17:47:32 2013 +0100 +++ b/src/HOL/Tools/Sledgehammer/sledgehammer_compress.ML Mon Feb 25 20:55:48 2013 +0100 @@ -69,11 +69,10 @@ end (* compress top level steps - do not compress subproofs *) - fun compress_top_level on_top_level ctxt steps = + fun compress_top_level on_top_level ctxt n steps = let (* proof step vector *) val step_vect = steps |> map SOME |> Vector.fromList - val n = Vector.length step_vect val n_metis = add_metis_steps_top_level steps 0 val target_n_metis = Real.fromInt n_metis / isar_compress |> Real.round @@ -91,7 +90,7 @@ | SOME (By_Metis (subproofs, (lfs, _))) => maps (steps_of_proof #> maps refs) subproofs @ lookup_indices lfs) val refed_by_vect = - Vector.tabulate (n, K []) + Vector.tabulate (Vector.length step_vect, K []) |> fold_index (fn (i, step) => fold (update (cons i)) (refs step)) steps |> Vector.map rev (* after rev, indices are sorted in ascending order *) @@ -202,7 +201,7 @@ merge_steps metis_time step_vect refed_by_vect cand_tab n n_metis end - fun do_proof on_top_level ctxt (Proof (fix, assms,steps)) = + fun do_proof on_top_level ctxt (Proof (Fix fix, Assume assms, steps)) = let (* Enrich context with top-level facts *) val thy = Proof_Context.theory_of ctxt @@ -214,17 +213,18 @@ | enrich_with_step (Obtain (_, _, l, t, _)) = enrich_with_fact l t | enrich_with_step _ = I val enrich_with_steps = fold enrich_with_step - fun enrich_with_assms (Assume assms) = - fold (uncurry enrich_with_fact) assms + val enrich_with_assms = fold (uncurry enrich_with_fact) val rich_ctxt = ctxt |> enrich_with_assms assms |> enrich_with_steps steps + val n = List.length fix + List.length assms + List.length steps + (* compress subproofs and top-levl steps *) val ((steps, top_level_time), lower_level_time) = steps |> do_subproofs rich_ctxt - |>> compress_top_level on_top_level rich_ctxt + |>> compress_top_level on_top_level rich_ctxt n in - (Proof (fix, assms, steps), + (Proof (Fix fix, Assume assms, steps), add_preplay_time lower_level_time top_level_time) end diff -r 05522141d244 -r 546a9a1c315d src/HOL/ex/Landau.thy --- a/src/HOL/ex/Landau.thy Mon Feb 25 17:47:32 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,226 +0,0 @@ - -(* Author: Florian Haftmann, TU Muenchen *) - -header {* Comparing growth of functions on natural numbers by a preorder relation *} - -theory Landau -imports Main "~~/src/HOL/Library/Preorder" -begin - -text {* - We establish a preorder releation @{text "\"} on functions from - @{text "\"} to @{text "\"} such that @{text "f \ g \ f \ O(g)"}. -*} - -subsection {* Auxiliary *} - -lemma Ex_All_bounded: - fixes n :: nat - assumes "\n. \m\n. P m" - obtains m where "m \ n" and "P m" -proof - - from assms obtain q where m_q: "\m\q. P m" .. - let ?m = "max q n" - have "?m \ n" by auto - moreover from m_q have "P ?m" by auto - ultimately show thesis .. -qed - - -subsection {* The @{text "\"} relation *} - -definition less_eq_fun :: "(nat \ nat) \ (nat \ nat) \ bool" (infix "\" 50) where - "f \ g \ (\c n. \m\n. f m \ Suc c * g m)" - -lemma less_eq_fun_intro: - assumes "\c n. \m\n. f m \ Suc c * g m" - shows "f \ g" - unfolding less_eq_fun_def by (rule assms) - -lemma less_eq_fun_not_intro: - assumes "\c n. \m\n. Suc c * g m < f m" - shows "\ f \ g" - using assms unfolding less_eq_fun_def linorder_not_le [symmetric] - by blast - -lemma less_eq_fun_elim: - assumes "f \ g" - obtains n c where "\m. m \ n \ f m \ Suc c * g m" - using assms unfolding less_eq_fun_def by blast - -lemma less_eq_fun_not_elim: - assumes "\ f \ g" - obtains m where "m \ n" and "Suc c * g m < f m" - using assms unfolding less_eq_fun_def linorder_not_le [symmetric] - by blast - -lemma less_eq_fun_refl: - "f \ f" -proof (rule less_eq_fun_intro) - have "\n. \m\n. f m \ Suc 0 * f m" by auto - then show "\c n. \m\n. f m \ Suc c * f m" by blast -qed - -lemma less_eq_fun_trans: - assumes f_g: "f \ g" and g_h: "g \ h" - shows f_h: "f \ h" -proof - - from f_g obtain n\<^isub>1 c\<^isub>1 - where P1: "\m. m \ n\<^isub>1 \ f m \ Suc c\<^isub>1 * g m" - by (erule less_eq_fun_elim) - moreover from g_h obtain n\<^isub>2 c\<^isub>2 - where P2: "\m. m \ n\<^isub>2 \ g m \ Suc c\<^isub>2 * h m" - by (erule less_eq_fun_elim) - ultimately have "\m. m \ max n\<^isub>1 n\<^isub>2 \ f m \ Suc c\<^isub>1 * g m \ g m \ Suc c\<^isub>2 * h m" - by auto - moreover { - fix k l r :: nat - assume k_l: "k \ Suc c\<^isub>1 * l" and l_r: "l \ Suc c\<^isub>2 * r" - from l_r have "Suc c\<^isub>1 * l \ (Suc c\<^isub>1 * Suc c\<^isub>2) * r" - by (auto simp add: mult_le_cancel_left mult_assoc simp del: times_nat.simps mult_Suc_right) - with k_l have "k \ (Suc c\<^isub>1 * Suc c\<^isub>2) * r" by (rule preorder_class.order_trans) - } - ultimately have "\m. m \ max n\<^isub>1 n\<^isub>2 \ f m \ (Suc c\<^isub>1 * Suc c\<^isub>2) * h m" by auto - then have "\m. m \ max n\<^isub>1 n\<^isub>2 \ f m \ Suc ((Suc c\<^isub>1 * Suc c\<^isub>2) - 1) * h m" by auto - then show ?thesis unfolding less_eq_fun_def by blast -qed - - -subsection {* The @{text "\"} relation, the equivalence relation induced by @{text "\"} *} - -definition equiv_fun :: "(nat \ nat) \ (nat \ nat) \ bool" (infix "\" 50) where - "f \ g \ (\d c n. \m\n. g m \ Suc d * f m \ f m \ Suc c * g m)" - -lemma equiv_fun_intro: - assumes "\d c n. \m\n. g m \ Suc d * f m \ f m \ Suc c * g m" - shows "f \ g" - unfolding equiv_fun_def by (rule assms) - -lemma equiv_fun_not_intro: - assumes "\d c n. \m\n. Suc d * f m < g m \ Suc c * g m < f m" - shows "\ f \ g" - unfolding equiv_fun_def - by (auto simp add: assms linorder_not_le - simp del: times_nat.simps mult_Suc_right) - -lemma equiv_fun_elim: - assumes "f \ g" - obtains n d c - where "\m. m \ n \ g m \ Suc d * f m \ f m \ Suc c * g m" - using assms unfolding equiv_fun_def by blast - -lemma equiv_fun_not_elim: - fixes n d c - assumes "\ f \ g" - obtains m where "m \ n" - and "Suc d * f m < g m \ Suc c * g m < f m" - using assms unfolding equiv_fun_def - by (auto simp add: linorder_not_le, blast) - -lemma equiv_fun_less_eq_fun: - "f \ g \ f \ g \ g \ f" -proof - assume x_y: "f \ g" - then obtain n d c - where interv: "\m. m \ n \ g m \ Suc d * f m \ f m \ Suc c * g m" - by (erule equiv_fun_elim) - from interv have "\c n. \m \ n. f m \ Suc c * g m" by auto - then have f_g: "f \ g" by (rule less_eq_fun_intro) - from interv have "\d n. \m \ n. g m \ Suc d * f m" by auto - then have g_f: "g \ f" by (rule less_eq_fun_intro) - from f_g g_f show "f \ g \ g \ f" by auto -next - assume assm: "f \ g \ g \ f" - from assm less_eq_fun_elim obtain c n\<^isub>1 where - bound1: "\m. m \ n\<^isub>1 \ f m \ Suc c * g m" - by blast - from assm less_eq_fun_elim obtain d n\<^isub>2 where - bound2: "\m. m \ n\<^isub>2 \ g m \ Suc d * f m" - by blast - from bound2 have "\m. m \ max n\<^isub>1 n\<^isub>2 \ g m \ Suc d * f m" - by auto - with bound1 - have "\m \ max n\<^isub>1 n\<^isub>2. g m \ Suc d * f m \ f m \ Suc c * g m" - by auto - then - have "\d c n. \m\n. g m \ Suc d * f m \ f m \ Suc c * g m" - by blast - then show "f \ g" by (rule equiv_fun_intro) -qed - -subsection {* The @{text "\"} relation, the strict part of @{text "\"} *} - -definition less_fun :: "(nat \ nat) \ (nat \ nat) \ bool" (infix "\" 50) where - "f \ g \ f \ g \ \ g \ f" - -lemma less_fun_intro: - assumes "\c. \n. \m\n. Suc c * f m < g m" - shows "f \ g" -proof (unfold less_fun_def, rule conjI) - from assms obtain n - where "\m\n. Suc 0 * f m < g m" .. - then have "\m\n. f m \ Suc 0 * g m" by auto - then have "\c n. \m\n. f m \ Suc c * g m" by blast - then show "f \ g" by (rule less_eq_fun_intro) -next - show "\ g \ f" - proof (rule less_eq_fun_not_intro) - fix c n :: nat - from assms have "\n. \m\n. Suc c * f m < g m" by blast - then obtain m where "m \ n" and "Suc c * f m < g m" - by (rule Ex_All_bounded) - then show "\m\n. Suc c * f m < g m" by blast - qed -qed - -text {* - We would like to show (or refute) that @{text "f \ g \ f \ o(g)"}, - i.e.~@{prop "f \ g \ (\c. \n. \m>n. f m < Suc c * g m)"} but did not - manage to do so. -*} - - -subsection {* Assert that @{text "\"} is indeed a preorder *} - -interpretation fun_order: preorder_equiv less_eq_fun less_fun - where "preorder_equiv.equiv less_eq_fun = equiv_fun" -proof - - interpret preorder_equiv less_eq_fun less_fun proof - qed (simp_all add: less_fun_def less_eq_fun_refl, auto intro: less_eq_fun_trans) - show "class.preorder_equiv less_eq_fun less_fun" using preorder_equiv_axioms . - show "preorder_equiv.equiv less_eq_fun = equiv_fun" - by (simp add: fun_eq_iff equiv_def equiv_fun_less_eq_fun) -qed - - -subsection {* Simple examples *} - -lemma "(\_. n) \ (\n. n)" -proof (rule less_eq_fun_intro) - show "\c q. \m\q. n \ Suc c * m" - proof - - have "\m\n. n \ Suc 0 * m" by simp - then show ?thesis by blast - qed -qed - -lemma "(\n. n) \ (\n. Suc k * n)" -proof (rule equiv_fun_intro) - show "\d c n. \m\n. Suc k * m \ Suc d * m \ m \ Suc c * (Suc k * m)" - proof - - have "\m\n. Suc k * m \ Suc k * m \ m \ Suc c * (Suc k * m)" by simp - then show ?thesis by blast - qed -qed - -lemma "(\_. n) \ (\n. n)" -proof (rule less_fun_intro) - fix c - show "\q. \m\q. Suc c * n < m" - proof - - have "\m\Suc c * n + 1. Suc c * n < m" by simp - then show ?thesis by blast - qed -qed - -end