(* Title: HOL/ex/BigO.thy Authors: Jeremy Avigad and Kevin Donnelly; proofs tidied by LCP
*)
section \<open>Big O notation\<close>
theory BigO imports
Complex_Main "HOL-Library.Function_Algebras" "HOL-Library.Set_Algebras" begin
text\<open>
This library is designed to support asymptotic ``big O'' calculations,
i.e.~reasoning with expressions of the form \<open>f = O(g)\<close> and \<open>f = g + O(h)\<close>.
An earlier version of this library is described in detail in\<^cite>\<open>"Avigad-Donnelly"\<close>.
The main changes in this version are as follows:
\<^item> We have eliminated the \<open>O\<close> operator on sets. (Most uses of this seem to be inessential.) \<^item> We no longer use \<open>+\<close> as output syntax for \<open>+o\<close> \<^item> Lemmas involving \<open>sumr\<close> have been replaced by more general lemmas
involving `\<open>sum\<close>. \<^item> The library has been expanded, with e.g.~support for expressions of
the form \<open>f < g + O(h)\<close>.
Notealso since the Big O library includes rules that demonstrate set
inclusion, touse the automated reasoners effectively with the library one
should redeclare the theorem\<open>subsetI\<close> as an intro rule, rather than as an \<open>intro!\<close> rule, for example, using \<^theory_text>\<open>declare subsetI [del, intro]\<close>. \<close>
lemma bigo_mult3: "f \ O(h) \ g \ O(j) \ f * g \ O(h * j)" using bigo_mult mult.commute mult.commute set_times_intro subsetD by blast
lemma bigo_mult4 [intro]: "f \ k +o O(h) \ g * f \ (g * k) +o O(g * h)" by (metis bigo_mult3 bigo_refl left_diff_distrib' mult.commute set_minus_imp_plus set_plus_imp_minus)
lemma bigo_mult5: fixes f :: "'a \ 'b::linordered_field" assumes"\x. f x \ 0" shows"O(f * g) \ f *o O(g)" proof fix h assume"h \ O(f * g)" thenhave"(\x. 1 / (f x)) * h \ (\x. 1 / f x) *o O(f * g)" by auto alsohave"\ \ O((\x. 1 / f x) * (f * g))" by (rule bigo_mult2) alsohave"(\x. 1 / f x) * (f * g) = g" using assms by auto finallyhave"(\x. (1::'b) / f x) * h \ O(g)" . thenhave"f * ((\x. (1::'b) / f x) * h) \ f *o O(g)" by auto alsohave"f * ((\x. (1::'b) / f x) * h) = h" by (simp add: assms times_fun_def) finallyshow"h \ f *o O(g)" . qed
lemma bigo_mult6: "\x. f x \ 0 \ O(f * g) = f *o O(g)" for f :: "'a \ 'b::linordered_field" by (simp add: bigo_mult2 bigo_mult5 subset_antisym)
lemma bigo_mult7: "\x. f x \ 0 \ O(f * g) \ O(f) * O(g)" for f :: "'a \ 'b::linordered_field" by (metis bigo_mult6 bigo_refl mult.commute set_times_mono4)
lemma bigo_mult8: "\x. f x \ 0 \ O(f * g) = O(f) * O(g)" for f :: "'a \ 'b::linordered_field" by (simp add: bigo_mult bigo_mult7 subset_antisym)
lemma bigo_minus [intro]: "f \ O(g) \ - f \ O(g)" by (auto simp add: bigo_def fun_Compl_def)
lemma bigo_minus2: assumes"f \ g +o O(h)" shows "- f \ -g +o O(h)" proof - have"- f + g \ O(h)" by (metis assms bigo_minus minus_diff_eq set_plus_imp_minus uminus_add_conv_diff) thenshow ?thesis by (simp add: set_minus_imp_plus) qed
lemma bigo_plus_absorb_lemma1: assumes *: "f \ O(g)" shows"f +o O(g) \ O(g)" using assms bigo_plus_idemp set_plus_mono4 by blast
lemma bigo_plus_absorb_lemma2: assumes *: "f \ O(g)" shows"O(g) \ f +o O(g)" proof - from * have"- f \ O(g)" by auto thenhave"- f +o O(g) \ O(g)" by (elim bigo_plus_absorb_lemma1) thenhave"f +o (- f +o O(g)) \ f +o O(g)" by auto alsohave"f +o (- f +o O(g)) = O(g)" by (simp add: set_plus_rearranges) finallyshow ?thesis . qed
lemma bigo_plus_absorb [simp]: "f \ O(g) \ f +o O(g) = O(g)" by (simp add: bigo_plus_absorb_lemma1 bigo_plus_absorb_lemma2 subset_antisym)
lemma bigo_plus_absorb2 [intro]: "f \ O(g) \ A \ O(g) \ f +o A \ O(g)" using bigo_plus_absorb set_plus_mono by blast
lemma bigo_add_commute_imp: "f \ g +o O(h) \ g \ f +o O(h)" by (metis bigo_minus minus_diff_eq set_minus_imp_plus set_plus_imp_minus)
lemma bigo_add_commute: "f \ g +o O(h) \ g \ f +o O(h)" using bigo_add_commute_imp by blast
lemma bigo_const1: "(\x. c) \ O(\x. 1)" by (auto simp add: bigo_def ac_simps)
lemma bigo_const2 [intro]: "O(\x. c) \ O(\x. 1)" by (metis bigo_elt_subset bigo_const1)
lemma bigo_const3: "c \ 0 \ (\x. 1) \ O(\x. c)" for c :: "'a::linordered_field" by (metis bigo_bounded_alt le_numeral_extra(4) nonzero_divide_eq_eq zero_less_one_class.zero_le_one)
lemma bigo_const4: "c \ 0 \ O(\x. 1) \ O(\x. c)" for c :: "'a::linordered_field" by (metis bigo_elt_subset bigo_const3)
lemma bigo_const [simp]: "c \ 0 \ O(\x. c) = O(\x. 1)" for c :: "'a::linordered_field" by (metis equalityI bigo_const2 bigo_const4)
lemma bigo_const_mult1: "(\x. c * f x) \ O(f)" by (simp add: bigo_def) (metis abs_mult dual_order.refl)
lemma bigo_const_mult2: "O(\x. c * f x) \ O(f)" by (metis bigo_elt_subset bigo_const_mult1)
lemma bigo_const_mult3: "c \ 0 \ f \ O(\x. c * f x)" for c :: "'a::linordered_field" by (simp add: bigo_def) (metis abs_mult field_class.field_divide_inverse mult.commute nonzero_divide_eq_eq order_refl)
lemma bigo_const_mult4: "c \ 0 \ O(f) \ O(\x. c * f x)" for c :: "'a::linordered_field" by (simp add: bigo_const_mult3 bigo_elt_subset)
lemma bigo_const_mult [simp]: "c \ 0 \ O(\x. c * f x) = O(f)" for c :: "'a::linordered_field" by (simp add: bigo_const_mult2 bigo_const_mult4 subset_antisym)
lemma bigo_const_mult5 [simp]: "(\x. c) *o O(f) = O(f)" if "c \ 0" for c :: "'a::linordered_field" proof show"O(f) \ (\x. c) *o O(f)" using that apply (clarsimp simp add: bigo_def elt_set_times_def func_times) apply (rule_tac x = "\y. inverse c * x y" in exI) apply (simp add: mult.assoc [symmetric] abs_mult) apply (rule_tac x = "\inverse c\ * ca" in exI) apply auto done have"O(\x. c * f x) \ O(f)" by (simp add: bigo_const_mult2) thenshow"(\x. c) *o O(f) \ O(f)" using order_trans[OF bigo_mult2] by (force simp add: times_fun_def) qed
lemma bigo_const_mult6 [intro]: "(\x. c) *o O(f) \ O(f)" apply (auto intro!: simp add: bigo_def elt_set_times_def func_times) apply (rule_tac x = "ca * \c\" in exI) by (smt (verit, ccfv_SIG) ab_semigroup_mult_class.mult_ac(1) abs_abs abs_le_self_iff abs_mult le_cases3 mult.commute mult_left_mono)
lemma bigo_const_mult7 [intro]: assumes *: "f =o O(g)" shows"(\x. c * f x) =o O(g)" proof - from * have"(\x. c) * f =o (\x. c) *o O(g)" by auto alsohave"(\x. c) * f = (\x. c * f x)" by (simp add: func_times) alsohave"(\x. c) *o O(g) \ O(g)" by (auto del: subsetI) finallyshow ?thesis . qed
lemma bigo_compose1: "f =o O(g) \ (\x. f (k x)) =o O(\x. g (k x))" by (auto simp: bigo_def)
lemma bigo_compose2: "f =o g +o O(h) \ (\x. f (k x)) =o (\x. g (k x)) +o O(\x. h(k x))" by (smt (verit, best) set_minus_plus bigo_def fun_diff_def mem_Collect_eq)
subsection \<open>Sum\<close>
lemma bigo_sum_main: assumes"\x. \y \ A x. 0 \ h x y" and "\x. \y \ A x. \f x y\ \ c * h x y" shows"(\x. \y \ A x. f x y) =o O(\x. \y \ A x. h x y)" proof - have"(\i\A x. \f x i\) \ \c\ * sum (h x) (A x)" for x by (smt (verit, ccfv_threshold) assms abs_mult_pos abs_of_nonneg abs_of_nonpos dual_order.trans le_cases3 neg_0_le_iff_le sum_distrib_left sum_mono) thenshow ?thesis using assms by (fastforce simp add: bigo_def sum_nonneg intro: order_trans [OF sum_abs]) qed
lemma bigo_sum1: "\x y. 0 \ h x y \ \<exists>c. \<forall>x y. \<bar>f x y\<bar> \<le> c * h x y \<Longrightarrow>
(\<lambda>x. \<Sum>y \<in> A x. f x y) =o O(\<lambda>x. \<Sum>y \<in> A x. h x y)" by (metis (no_types) bigo_sum_main)
lemma bigo_sum2: "\y. 0 \ h y \ \<exists>c. \<forall>y. \<bar>f y\<bar> \<le> c * (h y) \<Longrightarrow>
(\<lambda>x. \<Sum>y \<in> A x. f y) =o O(\<lambda>x. \<Sum>y \<in> A x. h y)" by (rule bigo_sum1) auto
lemma bigo_sum3: "f =o O(h) \
(\<lambda>x. \<Sum>y \<in> A x. l x y * f (k x y)) =o O(\<lambda>x. \<Sum>y \<in> A x. \<bar>l x y * h (k x y)\<bar>)" apply (rule bigo_sum1) using abs_ge_zero apply blast apply (clarsimp simp: bigo_def) by (smt (verit, ccfv_threshold) abs_mult abs_not_less_zero mult.left_commute mult_le_cancel_left)
lemma bigo_sum4: "f =o g +o O(h) \
(\<lambda>x. \<Sum>y \<in> A x. l x y * f (k x y)) =o
(\<lambda>x. \<Sum>y \<in> A x. l x y * g (k x y)) +o
O(\<lambda>x. \<Sum>y \<in> A x. \<bar>l x y * h (k x y)\<bar>)" using bigo_sum3 [of "f-g" h l k A] apply (simp add: algebra_simps sum_subtractf) by (smt (verit) bigo_alt_def minus_apply set_minus_imp_plus set_plus_imp_minus mem_Collect_eq)
lemma bigo_sum5: "f =o O(h) \ \x y. 0 \ l x y \ \<forall>x. 0 \<le> h x \<Longrightarrow>
(\<lambda>x. \<Sum>y \<in> A x. l x y * f (k x y)) =o
O(\<lambda>x. \<Sum>y \<in> A x. l x y * h (k x y))" using bigo_sum3 [of f h l k A] by simp
lemma bigo_sum6: "f =o g +o O(h) \ \x y. 0 \ l x y \ \<forall>x. 0 \<le> h x \<Longrightarrow>
(\<lambda>x. \<Sum>y \<in> A x. l x y * f (k x y)) =o
(\<lambda>x. \<Sum>y \<in> A x. l x y * g (k x y)) +o
O(\<lambda>x. \<Sum>y \<in> A x. l x y * h (k x y))" using bigo_sum5 [of "f-g" h l k A] apply (simp add: algebra_simps sum_subtractf) by (smt (verit, del_insts) bigo_alt_def set_minus_imp_plus minus_apply set_plus_imp_minus mem_Collect_eq)
subsection \<open>Misc useful stuff\<close>
lemma bigo_useful_add: "f =o O(h) \ g =o O(h) \ f + g =o O(h)" using bigo_plus_idemp set_plus_intro by blast
lemma bigo_useful_const_mult: "c \ 0 \ (\x. c) * f =o O(h) \ f =o O(h)" for c :: "'a::linordered_field" using bigo_elt_subset bigo_mult6 by fastforce
lemma bigo_fix: "(\x::nat. f (x + 1)) =o O(\x. h (x + 1)) \ f 0 = 0 \ f =o O(h)" by (simp add: bigo_alt_def) (metis abs_eq_0_iff abs_ge_zero abs_mult abs_of_pos not0_implies_Suc)
lemma bigo_fix2: "(\x. f ((x::nat) + 1)) =o (\x. g(x + 1)) +o O(\x. h(x + 1)) \
f 0 = g 0 \<Longrightarrow> f =o g +o O(h)" apply (rule set_minus_imp_plus [OF bigo_fix]) apply (smt (verit, del_insts) bigo_alt_def fun_diff_def set_plus_imp_minus mem_Collect_eq) apply simp done
subsection \<open>Less than or equal to\<close>
definition lesso :: "('a \ 'b::linordered_idom) \ ('a \ 'b) \ 'a \ 'b" (infixl \ 70) where"f x. max (f x - g x) 0)"
lemma bigo_lesseq2: "f =o O(h) \ \x. \g x\ \ f x \ g =o O(h)" by (metis (mono_tags, lifting) abs_ge_zero abs_of_nonneg bigo_lesseq1 dual_order.trans)
lemma bigo_lesseq3: "f =o O(h) \ \x. 0 \ g x \ \x. g x \ f x \ g =o O(h)" by (meson bigo_bounded bigo_elt_subset subsetD)
lemma bigo_lesseq4: "f =o O(h) \ \x. 0 \ g x \ \x. g x \ \f x\ \ g =o O(h)" by (metis abs_of_nonneg bigo_lesseq1)
lemma bigo_lesso1: "\x. f x \ g x \ f by (smt (verit, del_insts) abs_ge_zero add_0 bigo_abs3 bigo_bounded diff_le_eq lesso_def max_def order_refl)
lemma bigo_lesso2: "f =o g +o O(h) \ \x. 0 \ k x \ \x. k x \ f x \ k unfolding lesso_def apply (rule bigo_lesseq4 [of "f-g"]) apply (erule set_plus_imp_minus) using max.cobounded2 apply blast by (smt (verit) abs_ge_zero abs_of_nonneg diff_ge_0_iff_ge diff_mono diff_self fun_diff_def order_refl max.coboundedI2 max_def)
lemma bigo_lesso3: "f =o g +o O(h) \ \x. 0 \ k x \ \x. g x \ k x \ f unfolding lesso_def apply (rule bigo_lesseq4 [of "f-g"]) apply (erule set_plus_imp_minus) using max.cobounded2 apply blast by (smt (verit) abs_eq_iff abs_ge_zero abs_if abs_minus_le_zero diff_left_mono fun_diff_def le_max_iff_disj order.trans order_eq_refl)
lemma bigo_lesso4: fixes k :: "'a \ 'b::linordered_field" assumes f: "f and g: "g =o h +o O(k)" shows"f proof - have"g - h \ O(k)" by (simp add: g set_plus_imp_minus) thenhave"(\x. \g x - h x\) \ O(k)" using bigo_abs5 by force thenhave\<section>: "(\<lambda>x. max (f x - g x) 0) + (\<lambda>x. \<bar>g x - h x\<bar>) \<in> O(k)" by (metis (mono_tags, lifting) bigo_lesseq1 bigo_useful_add dual_order.eq_iff f lesso_def) have"\max (f x - h x) 0\ \ ((\x. max (f x - g x) 0) + (\x. \g x - h x\)) x" for x by (auto simp add: func_plus fun_diff_def algebra_simps split: split_max abs_split) thenshow ?thesis by (smt (verit, ccfv_SIG) \<section> bigo_lesseq2 lesso_def) qed
lemma bigo_lesso5: assumes"f shows"\C. \x. f x \ g x + C * \h x\" proof - obtain c where"0 < c"and c: "\x. f x - g x \ c * \h x\" using assms by (auto simp: lesso_def bigo_alt_def) have"\max (f x - g x) 0\ = max (f x - g x) 0" for x by (auto simp add: algebra_simps) thenshow ?thesis by (metis c add.commute diff_le_eq) qed
lemma lesso_add: "f k (f + k) unfolding lesso_def using bigo_useful_add by (fastforce split: split_max intro: bigo_lesseq3)
lemma bigo_LIMSEQ1: "f \ 0" if f: "f =o O(g)" and g: "g \ 0" for f g :: "nat \ real" proof -
{ fix r::real assume"0 < r" obtain c::real where"0 < c"and rc: "\x. \f x\ \ c * \g x\" using f by (auto simp: LIMSEQ_iff bigo_alt_def) with g \<open>0 < r\<close> obtain no where "\<forall>n\<ge>no. \<bar>g n\<bar> < r/c" by (fastforce simp: LIMSEQ_iff) thenhave"\no. \n\no. \f n\ < r" by (metis \<open>0 < c\<close> mult.commute order_le_less_trans pos_less_divide_eq rc) } thenshow ?thesis by (auto simp: LIMSEQ_iff) qed
lemma bigo_LIMSEQ2: fixes f g :: "nat \ real" assumes"f =o g +o O(h)""h \ 0" and f: "f \ a" shows"g \ a" proof - have"f - g \ 0" using assms bigo_LIMSEQ1 set_plus_imp_minus by blast thenhave"(\n. f n - g n) \ 0" by (simp add: fun_diff_def) thenshow ?thesis using Lim_transform_eq f by blast qed
end
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.15Angebot
Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.