# HG changeset patch # User paulson <lp15@cam.ac.uk> # Date 1528035750 -3600 # Node ID 20375f232f3bfb7ebcea2e7efa2517cb2905f30d # Parent 0f19c98fa7be2a4b76fc5430621cc27cdccdb64b infinite product material diff -r 0f19c98fa7be -r 20375f232f3b src/HOL/Analysis/Brouwer_Fixpoint.thy --- a/src/HOL/Analysis/Brouwer_Fixpoint.thy Sat Jun 02 22:57:44 2018 +0100 +++ b/src/HOL/Analysis/Brouwer_Fixpoint.thy Sun Jun 03 15:22:30 2018 +0100 @@ -40,9 +40,7 @@ lemmas swap_apply1 = swap_apply(1) lemmas swap_apply2 = swap_apply(2) -lemmas lessThan_empty_iff = Iio_eq_empty_iff_nat lemmas Zero_notin_Suc = zero_notin_Suc_image -lemmas atMost_Suc_eq_insert_0 = Iic_Suc_eq_insert_0 lemma pointwise_minimal_pointwise_maximal: fixes s :: "(nat \<Rightarrow> nat) set" diff -r 0f19c98fa7be -r 20375f232f3b src/HOL/Analysis/Henstock_Kurzweil_Integration.thy --- a/src/HOL/Analysis/Henstock_Kurzweil_Integration.thy Sat Jun 02 22:57:44 2018 +0100 +++ b/src/HOL/Analysis/Henstock_Kurzweil_Integration.thy Sun Jun 03 15:22:30 2018 +0100 @@ -3925,55 +3925,42 @@ subsection \<open>Stronger form with finite number of exceptional points\<close> lemma fundamental_theorem_of_calculus_interior_strong: - fixes f :: "real \<Rightarrow> 'a::banach" - assumes "finite s" - and "a \<le> b" - and "continuous_on {a..b} f" - and "\<forall>x\<in>{a <..< b} - s. (f has_vector_derivative f'(x)) (at x)" - shows "(f' has_integral (f b - f a)) {a..b}" + fixes f :: "real \<Rightarrow> 'a::banach" + assumes "finite S" + and "a \<le> b" "\<And>x. x \<in> {a <..< b} - S \<Longrightarrow> (f has_vector_derivative f'(x)) (at x)" + and "continuous_on {a .. b} f" + shows "(f' has_integral (f b - f a)) {a .. b}" using assms -proof (induct "card s" arbitrary: s a b) - case 0 +proof (induction arbitrary: a b) +case empty then show ?case - by (force simp add: intro: fundamental_theorem_of_calculus_interior) + using fundamental_theorem_of_calculus_interior by force next - case (Suc n) - then obtain c s' where cs: "s = insert c s'" and n: "n = card s'" - by (metis card_eq_SucD) - then have "finite s'" - using \<open>finite s\<close> by force +case (insert x S) show ?case - proof (cases "c \<in> box a b") - case False - with \<open>finite s'\<close> show ?thesis - using cs n Suc - by (metis Diff_iff box_real(1) insert_iff) + proof (cases "x \<in> {a<..<b}") + case False then show ?thesis + using insert by blast next - let ?P = "\<lambda>i j. \<forall>x\<in>{i <..< j} - s'. (f has_vector_derivative f' x) (at x)" - case True - then have "a \<le> c" "c \<le> b" - by (auto simp: mem_box) - moreover have "?P a c" "?P c b" - using Suc.prems(4) True \<open>a \<le> c\<close> cs(1) by auto - moreover have "continuous_on {a..c} f" "continuous_on {c..b} f" - using \<open>continuous_on {a..b} f\<close> \<open>a \<le> c\<close> \<open>c \<le> b\<close> continuous_on_subset by fastforce+ - ultimately have "(f' has_integral f c - f a + (f b - f c)) {a..b}" - using Suc.hyps(1) \<open>finite s'\<close> \<open>n = card s'\<close> by (blast intro: has_integral_combine) - then show ?thesis - by auto + case True then have "a < x" "x < b" + by auto + have "(f' has_integral f x - f a) {a..x}" "(f' has_integral f b - f x) {x..b}" + using \<open>continuous_on {a..b} f\<close> \<open>a < x\<close> \<open>x < b\<close> continuous_on_subset by (force simp: intro!: insert)+ + then have "(f' has_integral f x - f a + (f b - f x)) {a..b}" + using \<open>a < x\<close> \<open>x < b\<close> has_integral_combine less_imp_le by blast + then show ?thesis + by simp qed qed corollary fundamental_theorem_of_calculus_strong: fixes f :: "real \<Rightarrow> 'a::banach" - assumes "finite s" + assumes "finite S" and "a \<le> b" + and vec: "\<And>x. x \<in> {a..b} - S \<Longrightarrow> (f has_vector_derivative f'(x)) (at x)" and "continuous_on {a..b} f" - and vec: "\<forall>x\<in>{a..b} - s. (f has_vector_derivative f'(x)) (at x)" shows "(f' has_integral (f b - f a)) {a..b}" - apply (rule fundamental_theorem_of_calculus_interior_strong[OF assms(1-3), of f']) - using vec apply (auto simp: mem_box) - done + by (rule fundamental_theorem_of_calculus_interior_strong [OF \<open>finite S\<close>]) (force simp: assms)+ proposition indefinite_integral_continuous_left: fixes f:: "real \<Rightarrow> 'a::banach" @@ -7242,7 +7229,6 @@ define f where "f = (\<lambda>k x. if x \<in> {inverse (of_nat (Suc k))..c} then x powr a else 0)" define F where "F = (\<lambda>k. if inverse (of_nat (Suc k)) \<le> c then c powr (a+1)/(a+1) - inverse (real (Suc k)) powr (a+1)/(a+1) else 0)" - { fix k :: nat have "(f k has_integral F k) {0..c}" @@ -7448,8 +7434,8 @@ lemma integrable_on_subinterval: fixes f :: "'n::ordered_euclidean_space \<Rightarrow> 'a::banach" - assumes "f integrable_on s" "{a..b} \<subseteq> s" + assumes "f integrable_on S" "{a..b} \<subseteq> S" shows "f integrable_on {a..b}" - using integrable_on_subcbox[of f s a b] assms by (simp add: cbox_interval) + using integrable_on_subcbox[of f S a b] assms by (simp add: cbox_interval) end diff -r 0f19c98fa7be -r 20375f232f3b src/HOL/Analysis/Infinite_Products.thy --- a/src/HOL/Analysis/Infinite_Products.thy Sat Jun 02 22:57:44 2018 +0100 +++ b/src/HOL/Analysis/Infinite_Products.thy Sun Jun 03 15:22:30 2018 +0100 @@ -50,21 +50,21 @@ by (rule tendsto_eq_intros refl | simp)+ qed auto -definition gen_has_prod :: "[nat \<Rightarrow> 'a::{t2_space, comm_semiring_1}, nat, 'a] \<Rightarrow> bool" - where "gen_has_prod f M p \<equiv> (\<lambda>n. \<Prod>i\<le>n. f (i+M)) \<longlonglongrightarrow> p \<and> p \<noteq> 0" +definition raw_has_prod :: "[nat \<Rightarrow> 'a::{t2_space, comm_semiring_1}, nat, 'a] \<Rightarrow> bool" + where "raw_has_prod f M p \<equiv> (\<lambda>n. \<Prod>i\<le>n. f (i+M)) \<longlonglongrightarrow> p \<and> p \<noteq> 0" text\<open>The nonzero and zero cases, as in \emph{Complex Analysis} by Joseph Bak and Donald J.Newman, page 241\<close> definition has_prod :: "(nat \<Rightarrow> 'a::{t2_space, comm_semiring_1}) \<Rightarrow> 'a \<Rightarrow> bool" (infixr "has'_prod" 80) - where "f has_prod p \<equiv> gen_has_prod f 0 p \<or> (\<exists>i q. p = 0 \<and> f i = 0 \<and> gen_has_prod f (Suc i) q)" + where "f has_prod p \<equiv> raw_has_prod f 0 p \<or> (\<exists>i q. p = 0 \<and> f i = 0 \<and> raw_has_prod f (Suc i) q)" definition convergent_prod :: "(nat \<Rightarrow> 'a :: {t2_space,comm_semiring_1}) \<Rightarrow> bool" where - "convergent_prod f \<equiv> \<exists>M p. gen_has_prod f M p" + "convergent_prod f \<equiv> \<exists>M p. raw_has_prod f M p" definition prodinf :: "(nat \<Rightarrow> 'a::{t2_space, comm_semiring_1}) \<Rightarrow> 'a" (binder "\<Prod>" 10) where "prodinf f = (THE p. f has_prod p)" -lemmas prod_defs = gen_has_prod_def has_prod_def convergent_prod_def prodinf_def +lemmas prod_defs = raw_has_prod_def has_prod_def convergent_prod_def prodinf_def lemma has_prod_subst[trans]: "f = g \<Longrightarrow> g has_prod z \<Longrightarrow> f has_prod z" by simp @@ -72,34 +72,39 @@ lemma has_prod_cong: "(\<And>n. f n = g n) \<Longrightarrow> f has_prod c \<longleftrightarrow> g has_prod c" by presburger -lemma gen_has_prod_nonzero [simp]: "\<not> gen_has_prod f M 0" - by (simp add: gen_has_prod_def) +lemma raw_has_prod_nonzero [simp]: "\<not> raw_has_prod f M 0" + by (simp add: raw_has_prod_def) -lemma gen_has_prod_eq_0: - fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}" - assumes p: "gen_has_prod f m p" and i: "f i = 0" "i \<ge> m" +lemma raw_has_prod_eq_0: + fixes f :: "nat \<Rightarrow> 'a::{semidom,t2_space}" + assumes p: "raw_has_prod f m p" and i: "f i = 0" "i \<ge> m" shows "p = 0" proof - have eq0: "(\<Prod>k\<le>n. f (k+m)) = 0" if "i - m \<le> n" for n - by (metis i that atMost_atLeast0 atMost_iff diff_add finite_atLeastAtMost prod_zero_iff) + proof - + have "\<exists>k\<le>n. f (k + m) = 0" + using i that by auto + then show ?thesis + by auto + qed have "(\<lambda>n. \<Prod>i\<le>n. f (i + m)) \<longlonglongrightarrow> 0" by (rule LIMSEQ_offset [where k = "i-m"]) (simp add: eq0) with p show ?thesis - unfolding gen_has_prod_def + unfolding raw_has_prod_def using LIMSEQ_unique by blast qed -lemma has_prod_0_iff: "f has_prod 0 \<longleftrightarrow> (\<exists>i. f i = 0 \<and> (\<exists>p. gen_has_prod f (Suc i) p))" +lemma has_prod_0_iff: "f has_prod 0 \<longleftrightarrow> (\<exists>i. f i = 0 \<and> (\<exists>p. raw_has_prod f (Suc i) p))" by (simp add: has_prod_def) lemma has_prod_unique2: - fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}" + fixes f :: "nat \<Rightarrow> 'a::{semidom,t2_space}" assumes "f has_prod a" "f has_prod b" shows "a = b" using assms - by (auto simp: has_prod_def gen_has_prod_eq_0) (meson gen_has_prod_def sequentially_bot tendsto_unique) + by (auto simp: has_prod_def raw_has_prod_eq_0) (meson raw_has_prod_def sequentially_bot tendsto_unique) lemma has_prod_unique: - fixes f :: "nat \<Rightarrow> 'a :: {idom,t2_space}" + fixes f :: "nat \<Rightarrow> 'a :: {semidom,t2_space}" shows "f has_prod s \<Longrightarrow> s = prodinf f" by (simp add: has_prod_unique2 prodinf_def the_equality) @@ -378,42 +383,55 @@ shows "abs_convergent_prod f" using assms unfolding abs_convergent_prod_def by (rule convergent_prod_offset) -lemma convergent_prod_ignore_initial_segment: - fixes f :: "nat \<Rightarrow> 'a :: {real_normed_field}" - assumes "convergent_prod f" - shows "convergent_prod (\<lambda>n. f (n + m))" +lemma raw_has_prod_ignore_initial_segment: + fixes f :: "nat \<Rightarrow> 'a :: real_normed_field" + assumes "raw_has_prod f M p" "N \<ge> M" + obtains q where "raw_has_prod f N q" proof - - from assms obtain M L - where L: "(\<lambda>n. \<Prod>k\<le>n. f (k + M)) \<longlonglongrightarrow> L" "L \<noteq> 0" and nz: "\<And>n. n \<ge> M \<Longrightarrow> f n \<noteq> 0" - by (auto simp: convergent_prod_altdef) - define C where "C = (\<Prod>k<m. f (k + M))" + have p: "(\<lambda>n. \<Prod>k\<le>n. f (k + M)) \<longlonglongrightarrow> p" and "p \<noteq> 0" + using assms by (auto simp: raw_has_prod_def) + then have nz: "\<And>n. n \<ge> M \<Longrightarrow> f n \<noteq> 0" + using assms by (auto simp: raw_has_prod_eq_0) + define C where "C = (\<Prod>k<N-M. f (k + M))" from nz have [simp]: "C \<noteq> 0" by (auto simp: C_def) - from L(1) have "(\<lambda>n. \<Prod>k\<le>n+m. f (k + M)) \<longlonglongrightarrow> L" + from p have "(\<lambda>i. \<Prod>k\<le>i + (N-M). f (k + M)) \<longlonglongrightarrow> p" by (rule LIMSEQ_ignore_initial_segment) - also have "(\<lambda>n. \<Prod>k\<le>n+m. f (k + M)) = (\<lambda>n. C * (\<Prod>k\<le>n. f (k + M + m)))" + also have "(\<lambda>i. \<Prod>k\<le>i + (N-M). f (k + M)) = (\<lambda>n. C * (\<Prod>k\<le>n. f (k + N)))" proof (rule ext, goal_cases) case (1 n) - have "{..n+m} = {..<m} \<union> {m..n+m}" by auto - also have "(\<Prod>k\<in>\<dots>. f (k + M)) = C * (\<Prod>k=m..n+m. f (k + M))" + have "{..n+(N-M)} = {..<(N-M)} \<union> {(N-M)..n+(N-M)}" by auto + also have "(\<Prod>k\<in>\<dots>. f (k + M)) = C * (\<Prod>k=(N-M)..n+(N-M). f (k + M))" unfolding C_def by (rule prod.union_disjoint) auto - also have "(\<Prod>k=m..n+m. f (k + M)) = (\<Prod>k\<le>n. f (k + m + M))" - by (intro ext prod.reindex_bij_witness[of _ "\<lambda>k. k + m" "\<lambda>k. k - m"]) auto - finally show ?case by (simp add: add_ac) + also have "(\<Prod>k=(N-M)..n+(N-M). f (k + M)) = (\<Prod>k\<le>n. f (k + (N-M) + M))" + by (intro ext prod.reindex_bij_witness[of _ "\<lambda>k. k + (N-M)" "\<lambda>k. k - (N-M)"]) auto + finally show ?case + using \<open>N \<ge> M\<close> by (simp add: add_ac) qed - finally have "(\<lambda>n. C * (\<Prod>k\<le>n. f (k + M + m)) / C) \<longlonglongrightarrow> L / C" + finally have "(\<lambda>n. C * (\<Prod>k\<le>n. f (k + N)) / C) \<longlonglongrightarrow> p / C" by (intro tendsto_divide tendsto_const) auto - hence "(\<lambda>n. \<Prod>k\<le>n. f (k + M + m)) \<longlonglongrightarrow> L / C" by simp - moreover from \<open>L \<noteq> 0\<close> have "L / C \<noteq> 0" by simp - ultimately show ?thesis - unfolding prod_defs by blast + hence "(\<lambda>n. \<Prod>k\<le>n. f (k + N)) \<longlonglongrightarrow> p / C" by simp + moreover from \<open>p \<noteq> 0\<close> have "p / C \<noteq> 0" by simp + ultimately show ?thesis + using raw_has_prod_def that by blast qed +corollary convergent_prod_ignore_initial_segment: + fixes f :: "nat \<Rightarrow> 'a :: real_normed_field" + assumes "convergent_prod f" + shows "convergent_prod (\<lambda>n. f (n + m))" + using assms + unfolding convergent_prod_def + apply clarify + apply (erule_tac N="M+m" in raw_has_prod_ignore_initial_segment) + apply (auto simp add: raw_has_prod_def add_ac) + done + corollary convergent_prod_ignore_nonzero_segment: fixes f :: "nat \<Rightarrow> 'a :: real_normed_field" assumes f: "convergent_prod f" and nz: "\<And>i. i \<ge> M \<Longrightarrow> f i \<noteq> 0" - shows "\<exists>p. gen_has_prod f M p" + shows "\<exists>p. raw_has_prod f M p" using convergent_prod_ignore_initial_segment [OF f] by (metis convergent_LIMSEQ_iff convergent_prod_iff_convergent le_add_same_cancel2 nz prod_defs(1) zero_order(1)) @@ -551,13 +569,13 @@ with L show ?thesis by (auto simp: prod_defs) qed -lemma gen_has_prod_cases: +lemma raw_has_prod_cases: fixes f :: "nat \<Rightarrow> 'a :: {idom,topological_semigroup_mult,t2_space}" - assumes "gen_has_prod f M p" - obtains i where "i<M" "f i = 0" | p where "gen_has_prod f 0 p" + assumes "raw_has_prod f M p" + obtains i where "i<M" "f i = 0" | p where "raw_has_prod f 0 p" proof - have "(\<lambda>n. \<Prod>i\<le>n. f (i + M)) \<longlonglongrightarrow> p" "p \<noteq> 0" - using assms unfolding gen_has_prod_def by blast+ + using assms unfolding raw_has_prod_def by blast+ then have "(\<lambda>n. prod f {..<M} * (\<Prod>i\<le>n. f (i + M))) \<longlonglongrightarrow> prod f {..<M} * p" by (metis tendsto_mult_left) moreover have "prod f {..<M} * (\<Prod>i\<le>n. f (i + M)) = prod f {..n+M}" for n @@ -572,8 +590,8 @@ qed ultimately have "(\<lambda>n. prod f {..n}) \<longlonglongrightarrow> prod f {..<M} * p" by (auto intro: LIMSEQ_offset [where k=M]) - then have "gen_has_prod f 0 (prod f {..<M} * p)" if "\<forall>i<M. f i \<noteq> 0" - using \<open>p \<noteq> 0\<close> assms that by (auto simp: gen_has_prod_def) + then have "raw_has_prod f 0 (prod f {..<M} * p)" if "\<forall>i<M. f i \<noteq> 0" + using \<open>p \<noteq> 0\<close> assms that by (auto simp: raw_has_prod_def) then show thesis using that by blast qed @@ -581,8 +599,8 @@ corollary convergent_prod_offset_0: fixes f :: "nat \<Rightarrow> 'a :: {idom,topological_semigroup_mult,t2_space}" assumes "convergent_prod f" "\<And>i. f i \<noteq> 0" - shows "\<exists>p. gen_has_prod f 0 p" - using assms convergent_prod_def gen_has_prod_cases by blast + shows "\<exists>p. raw_has_prod f 0 p" + using assms convergent_prod_def raw_has_prod_cases by blast lemma prodinf_eq_lim: fixes f :: "nat \<Rightarrow> 'a :: {idom,topological_semigroup_mult,t2_space}" @@ -648,7 +666,7 @@ qed lemma has_prod_finite: - fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}" + fixes f :: "nat \<Rightarrow> 'a::{semidom,t2_space}" assumes [simp]: "finite N" and f: "\<And>n. n \<notin> N \<Longrightarrow> f n = 1" shows "f has_prod (\<Prod>n\<in>N. f n)" @@ -668,7 +686,7 @@ moreover have "(\<lambda>n. prod f {..n}) \<longlonglongrightarrow> prod f N" by (rule LIMSEQ_offset[of _ "Suc (Max N)"]) (simp add: eq atLeast0LessThan del: add_Suc_right) ultimately show ?thesis - by (simp add: gen_has_prod_def has_prod_def) + by (simp add: raw_has_prod_def has_prod_def) next case False then obtain k where "k \<in> N" "f k = 0" @@ -692,8 +710,8 @@ (use Max.coboundedI [OF \<open>finite N\<close>] f in \<open>force+\<close>) finally show ?thesis . qed - have q: "gen_has_prod f (Suc (Max ?Z)) ?q" - proof (simp add: gen_has_prod_def) + have q: "raw_has_prod f (Suc (Max ?Z)) ?q" + proof (simp add: raw_has_prod_def) show "(\<lambda>n. \<Prod>i\<le>n. f (Suc (i + Max ?Z))) \<longlonglongrightarrow> ?q" by (rule LIMSEQ_offset[of _ "(Max N)"]) (simp add: eq) qed @@ -709,17 +727,20 @@ qed corollary has_prod_0: - fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}" + fixes f :: "nat \<Rightarrow> 'a::{semidom,t2_space}" assumes "\<And>n. f n = 1" shows "f has_prod 1" by (simp add: assms has_prod_cong) +lemma prodinf_zero[simp]: "prodinf (\<lambda>n. 1::'a::real_normed_field) = 1" + using has_prod_unique by force + lemma convergent_prod_finite: fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}" assumes "finite N" "\<And>n. n \<notin> N \<Longrightarrow> f n = 1" shows "convergent_prod f" proof - - have "\<exists>n p. gen_has_prod f n p" + have "\<exists>n p. raw_has_prod f n p" using assms has_prod_def has_prod_finite by blast then show ?thesis by (simp add: convergent_prod_def) @@ -759,12 +780,12 @@ assumes "convergent_prod f" shows "\<exists>p. f has_prod p" proof - - obtain M p where p: "gen_has_prod f M p" + obtain M p where p: "raw_has_prod f M p" using assms convergent_prod_def by blast then have "p \<noteq> 0" - using gen_has_prod_nonzero by blast + using raw_has_prod_nonzero by blast with p have fnz: "f i \<noteq> 0" if "i \<ge> M" for i - using gen_has_prod_eq_0 that by blast + using raw_has_prod_eq_0 that by blast define C where "C = (\<Prod>n<M. f n)" show ?thesis proof (cases "\<forall>n\<le>M. f n \<noteq> 0") @@ -781,7 +802,7 @@ by (metis (mono_tags, lifting) GreatestI_ex_nat nat_le_linear) have "f i \<noteq> 0" if "i > ?N" for i by (metis (mono_tags, lifting) Greatest_le_nat fnz leD linear that) - then have "\<exists>p. gen_has_prod f (Suc ?N) p" + then have "\<exists>p. raw_has_prod f (Suc ?N) p" using assms by (auto simp: intro!: convergent_prod_ignore_nonzero_segment) then show ?thesis unfolding has_prod_def using 0 by blast @@ -796,7 +817,7 @@ lemma convergent_prod_LIMSEQ: shows "convergent_prod f \<Longrightarrow> (\<lambda>n. \<Prod>i\<le>n. f i) \<longlonglongrightarrow> prodinf f" by (metis convergent_LIMSEQ_iff convergent_prod_has_prod convergent_prod_imp_convergent - convergent_prod_to_zero_iff gen_has_prod_eq_0 has_prod_def prodinf_eq_lim zero_le) + convergent_prod_to_zero_iff raw_has_prod_eq_0 has_prod_def prodinf_eq_lim zero_le) lemma has_prod_iff: "f has_prod x \<longleftrightarrow> convergent_prod f \<and> prodinf f = x" proof @@ -818,4 +839,494 @@ end +subsection \<open>Infinite products on ordered, topological monoids\<close> + +lemma LIMSEQ_prod_0: + fixes f :: "nat \<Rightarrow> 'a::{semidom,topological_space}" + assumes "f i = 0" + shows "(\<lambda>n. prod f {..n}) \<longlonglongrightarrow> 0" +proof (subst tendsto_cong) + show "\<forall>\<^sub>F n in sequentially. prod f {..n} = 0" + proof + show "prod f {..n} = 0" if "n \<ge> i" for n + using that assms by auto + qed +qed auto + +lemma LIMSEQ_prod_nonneg: + fixes f :: "nat \<Rightarrow> 'a::{linordered_semidom,linorder_topology}" + assumes 0: "\<And>n. 0 \<le> f n" and a: "(\<lambda>n. prod f {..n}) \<longlonglongrightarrow> a" + shows "a \<ge> 0" + by (simp add: "0" prod_nonneg LIMSEQ_le_const [OF a]) + + +context + fixes f :: "nat \<Rightarrow> 'a::{linordered_semidom,linorder_topology}" +begin + +lemma has_prod_le: + assumes f: "f has_prod a" and g: "g has_prod b" and le: "\<And>n. 0 \<le> f n \<and> f n \<le> g n" + shows "a \<le> b" +proof (cases "a=0 \<or> b=0") + case True + then show ?thesis + proof + assume [simp]: "a=0" + have "b \<ge> 0" + proof (rule LIMSEQ_prod_nonneg) + show "(\<lambda>n. prod g {..n}) \<longlonglongrightarrow> b" + using g by (auto simp: has_prod_def raw_has_prod_def LIMSEQ_prod_0) + qed (use le order_trans in auto) + then show ?thesis + by auto + next + assume [simp]: "b=0" + then obtain i where "g i = 0" + using g by (auto simp: prod_defs) + then have "f i = 0" + using antisym le by force + then have "a=0" + using f by (auto simp: prod_defs LIMSEQ_prod_0 LIMSEQ_unique) + then show ?thesis + by auto + qed +next + case False + then show ?thesis + using assms + unfolding has_prod_def raw_has_prod_def + by (force simp: LIMSEQ_prod_0 intro!: LIMSEQ_le prod_mono) +qed + +lemma prodinf_le: + assumes f: "f has_prod a" and g: "g has_prod b" and le: "\<And>n. 0 \<le> f n \<and> f n \<le> g n" + shows "prodinf f \<le> prodinf g" + using has_prod_le [OF assms] has_prod_unique f g by blast + end + + +lemma prod_le_prodinf: + fixes f :: "nat \<Rightarrow> 'a::{linordered_idom,linorder_topology}" + assumes "f has_prod a" "\<And>i. 0 \<le> f i" "\<And>i. i\<ge>n \<Longrightarrow> 1 \<le> f i" + shows "prod f {..<n} \<le> prodinf f" + by(rule has_prod_le[OF has_prod_If_finite_set]) (use assms has_prod_unique in auto) + +lemma prodinf_nonneg: + fixes f :: "nat \<Rightarrow> 'a::{linordered_idom,linorder_topology}" + assumes "f has_prod a" "\<And>i. 1 \<le> f i" + shows "1 \<le> prodinf f" + using prod_le_prodinf[of f a 0] assms + by (metis order_trans prod_ge_1 zero_le_one) + +lemma prodinf_le_const: + fixes f :: "nat \<Rightarrow> real" + assumes "convergent_prod f" "\<And>n. prod f {..<n} \<le> x" + shows "prodinf f \<le> x" + by (metis lessThan_Suc_atMost assms convergent_prod_LIMSEQ LIMSEQ_le_const2) + +lemma prodinf_eq_one_iff: + fixes f :: "nat \<Rightarrow> real" + assumes f: "convergent_prod f" and ge1: "\<And>n. 1 \<le> f n" + shows "prodinf f = 1 \<longleftrightarrow> (\<forall>n. f n = 1)" +proof + assume "prodinf f = 1" + then have "(\<lambda>n. \<Prod>i<n. f i) \<longlonglongrightarrow> 1" + using convergent_prod_LIMSEQ[of f] assms by (simp add: LIMSEQ_lessThan_iff_atMost) + then have "\<And>i. (\<Prod>n\<in>{i}. f n) \<le> 1" + proof (rule LIMSEQ_le_const) + have "1 \<le> prod f n" for n + by (simp add: ge1 prod_ge_1) + have "prod f {..<n} = 1" for n + by (metis \<open>\<And>n. 1 \<le> prod f n\<close> \<open>prodinf f = 1\<close> antisym f convergent_prod_has_prod ge1 order_trans prod_le_prodinf zero_le_one) + then have "(\<Prod>n\<in>{i}. f n) \<le> prod f {..<n}" if "n \<ge> Suc i" for i n + by (metis mult.left_neutral order_refl prod.cong prod.neutral_const prod_lessThan_Suc) + then show "\<exists>N. \<forall>n\<ge>N. (\<Prod>n\<in>{i}. f n) \<le> prod f {..<n}" for i + by blast + qed + with ge1 show "\<forall>n. f n = 1" + by (auto intro!: antisym) +qed (metis prodinf_zero fun_eq_iff) + +lemma prodinf_pos_iff: + fixes f :: "nat \<Rightarrow> real" + assumes "convergent_prod f" "\<And>n. 1 \<le> f n" + shows "1 < prodinf f \<longleftrightarrow> (\<exists>i. 1 < f i)" + using prod_le_prodinf[of f 1] prodinf_eq_one_iff + by (metis convergent_prod_has_prod assms less_le prodinf_nonneg) + +lemma less_1_prodinf2: + fixes f :: "nat \<Rightarrow> real" + assumes "convergent_prod f" "\<And>n. 1 \<le> f n" "1 < f i" + shows "1 < prodinf f" +proof - + have "1 < (\<Prod>n<Suc i. f n)" + using assms by (intro less_1_prod2[where i=i]) auto + also have "\<dots> \<le> prodinf f" + by (intro prod_le_prodinf) (use assms order_trans zero_le_one in \<open>blast+\<close>) + finally show ?thesis . +qed + +lemma less_1_prodinf: + fixes f :: "nat \<Rightarrow> real" + shows "\<lbrakk>convergent_prod f; \<And>n. 1 < f n\<rbrakk> \<Longrightarrow> 1 < prodinf f" + by (intro less_1_prodinf2[where i=1]) (auto intro: less_imp_le) + +lemma prodinf_nonzero: + fixes f :: "nat \<Rightarrow> 'a :: {idom,topological_semigroup_mult,t2_space}" + assumes "convergent_prod f" "\<And>i. f i \<noteq> 0" + shows "prodinf f \<noteq> 0" + by (metis assms convergent_prod_offset_0 has_prod_unique raw_has_prod_def has_prod_def) + +lemma less_0_prodinf: + fixes f :: "nat \<Rightarrow> real" + assumes f: "convergent_prod f" and 0: "\<And>i. f i > 0" + shows "0 < prodinf f" +proof - + have "prodinf f \<noteq> 0" + by (metis assms less_irrefl prodinf_nonzero) + moreover have "0 < (\<Prod>n<i. f n)" for i + by (simp add: 0 prod_pos) + then have "prodinf f \<ge> 0" + using convergent_prod_LIMSEQ [OF f] LIMSEQ_prod_nonneg 0 less_le by blast + ultimately show ?thesis + by auto +qed + +lemma prod_less_prodinf2: + fixes f :: "nat \<Rightarrow> real" + assumes f: "convergent_prod f" and 1: "\<And>m. m\<ge>n \<Longrightarrow> 1 \<le> f m" and 0: "\<And>m. 0 < f m" and i: "n \<le> i" "1 < f i" + shows "prod f {..<n} < prodinf f" +proof - + have "prod f {..<n} \<le> prod f {..<i}" + by (rule prod_mono2) (use assms less_le in auto) + then have "prod f {..<n} < f i * prod f {..<i}" + using mult_less_le_imp_less[of 1 "f i" "prod f {..<n}" "prod f {..<i}"] assms + by (simp add: prod_pos) + moreover have "prod f {..<Suc i} \<le> prodinf f" + using prod_le_prodinf[of f _ "Suc i"] + by (meson "0" "1" Suc_leD convergent_prod_has_prod f \<open>n \<le> i\<close> le_trans less_eq_real_def) + ultimately show ?thesis + by (metis le_less_trans mult.commute not_le prod_lessThan_Suc) +qed + +lemma prod_less_prodinf: + fixes f :: "nat \<Rightarrow> real" + assumes f: "convergent_prod f" and 1: "\<And>m. m\<ge>n \<Longrightarrow> 1 < f m" and 0: "\<And>m. 0 < f m" + shows "prod f {..<n} < prodinf f" + by (meson "0" "1" f le_less prod_less_prodinf2) + +lemma raw_has_prodI_bounded: + fixes f :: "nat \<Rightarrow> real" + assumes pos: "\<And>n. 1 \<le> f n" + and le: "\<And>n. (\<Prod>i<n. f i) \<le> x" + shows "\<exists>p. raw_has_prod f 0 p" + unfolding raw_has_prod_def add_0_right +proof (rule exI LIMSEQ_incseq_SUP conjI)+ + show "bdd_above (range (\<lambda>n. prod f {..n}))" + by (metis bdd_aboveI2 le lessThan_Suc_atMost) + then have "(SUP i. prod f {..i}) > 0" + by (metis UNIV_I cSUP_upper less_le_trans pos prod_pos zero_less_one) + then show "(SUP i. prod f {..i}) \<noteq> 0" + by auto + show "incseq (\<lambda>n. prod f {..n})" + using pos order_trans [OF zero_le_one] by (auto simp: mono_def intro!: prod_mono2) +qed + +lemma convergent_prodI_nonneg_bounded: + fixes f :: "nat \<Rightarrow> real" + assumes "\<And>n. 1 \<le> f n" "\<And>n. (\<Prod>i<n. f i) \<le> x" + shows "convergent_prod f" + using convergent_prod_def raw_has_prodI_bounded [OF assms] by blast + + +subsection \<open>Infinite products on topological monoids\<close> + +context + fixes f g :: "nat \<Rightarrow> 'a::{t2_space,topological_semigroup_mult,idom}" +begin + +lemma raw_has_prod_mult: "\<lbrakk>raw_has_prod f M a; raw_has_prod g M b\<rbrakk> \<Longrightarrow> raw_has_prod (\<lambda>n. f n * g n) M (a * b)" + by (force simp add: prod.distrib tendsto_mult raw_has_prod_def) + +lemma has_prod_mult_nz: "\<lbrakk>f has_prod a; g has_prod b; a \<noteq> 0; b \<noteq> 0\<rbrakk> \<Longrightarrow> (\<lambda>n. f n * g n) has_prod (a * b)" + by (simp add: raw_has_prod_mult has_prod_def) + +end + + +context + fixes f g :: "nat \<Rightarrow> 'a::real_normed_field" +begin + +lemma has_prod_mult: + assumes f: "f has_prod a" and g: "g has_prod b" + shows "(\<lambda>n. f n * g n) has_prod (a * b)" + using f [unfolded has_prod_def] +proof (elim disjE exE conjE) + assume f0: "raw_has_prod f 0 a" + show ?thesis + using g [unfolded has_prod_def] + proof (elim disjE exE conjE) + assume g0: "raw_has_prod g 0 b" + with f0 show ?thesis + by (force simp add: has_prod_def prod.distrib tendsto_mult raw_has_prod_def) + next + fix j q + assume "b = 0" and "g j = 0" and q: "raw_has_prod g (Suc j) q" + obtain p where p: "raw_has_prod f (Suc j) p" + using f0 raw_has_prod_ignore_initial_segment by blast + then have "Ex (raw_has_prod (\<lambda>n. f n * g n) (Suc j))" + using q raw_has_prod_mult by blast + then show ?thesis + using \<open>b = 0\<close> \<open>g j = 0\<close> has_prod_0_iff by fastforce + qed +next + fix i p + assume "a = 0" and "f i = 0" and p: "raw_has_prod f (Suc i) p" + show ?thesis + using g [unfolded has_prod_def] + proof (elim disjE exE conjE) + assume g0: "raw_has_prod g 0 b" + obtain q where q: "raw_has_prod g (Suc i) q" + using g0 raw_has_prod_ignore_initial_segment by blast + then have "Ex (raw_has_prod (\<lambda>n. f n * g n) (Suc i))" + using raw_has_prod_mult p by blast + then show ?thesis + using \<open>a = 0\<close> \<open>f i = 0\<close> has_prod_0_iff by fastforce + next + fix j q + assume "b = 0" and "g j = 0" and q: "raw_has_prod g (Suc j) q" + obtain p' where p': "raw_has_prod f (Suc (max i j)) p'" + by (metis raw_has_prod_ignore_initial_segment max_Suc_Suc max_def p) + moreover + obtain q' where q': "raw_has_prod g (Suc (max i j)) q'" + by (metis raw_has_prod_ignore_initial_segment max.cobounded2 max_Suc_Suc q) + ultimately show ?thesis + using \<open>b = 0\<close> by (simp add: has_prod_def) (metis \<open>f i = 0\<close> \<open>g j = 0\<close> raw_has_prod_mult max_def) + qed +qed + +lemma convergent_prod_mult: + assumes f: "convergent_prod f" and g: "convergent_prod g" + shows "convergent_prod (\<lambda>n. f n * g n)" + unfolding convergent_prod_def +proof - + obtain M p N q where p: "raw_has_prod f M p" and q: "raw_has_prod g N q" + using convergent_prod_def f g by blast+ + then obtain p' q' where p': "raw_has_prod f (max M N) p'" and q': "raw_has_prod g (max M N) q'" + by (meson raw_has_prod_ignore_initial_segment max.cobounded1 max.cobounded2) + then show "\<exists>M p. raw_has_prod (\<lambda>n. f n * g n) M p" + using raw_has_prod_mult by blast +qed + +lemma prodinf_mult: "convergent_prod f \<Longrightarrow> convergent_prod g \<Longrightarrow> prodinf f * prodinf g = (\<Prod>n. f n * g n)" + by (intro has_prod_unique has_prod_mult convergent_prod_has_prod) + +end + +context + fixes f :: "'i \<Rightarrow> nat \<Rightarrow> 'a::real_normed_field" + and I :: "'i set" +begin + +lemma has_prod_prod: "(\<And>i. i \<in> I \<Longrightarrow> (f i) has_prod (x i)) \<Longrightarrow> (\<lambda>n. \<Prod>i\<in>I. f i n) has_prod (\<Prod>i\<in>I. x i)" + by (induct I rule: infinite_finite_induct) (auto intro!: has_prod_mult) + +lemma prodinf_prod: "(\<And>i. i \<in> I \<Longrightarrow> convergent_prod (f i)) \<Longrightarrow> (\<Prod>n. \<Prod>i\<in>I. f i n) = (\<Prod>i\<in>I. \<Prod>n. f i n)" + using has_prod_unique[OF has_prod_prod, OF convergent_prod_has_prod] by simp + +lemma convergent_prod_prod: "(\<And>i. i \<in> I \<Longrightarrow> convergent_prod (f i)) \<Longrightarrow> convergent_prod (\<lambda>n. \<Prod>i\<in>I. f i n)" + using convergent_prod_has_prod_iff has_prod_prod prodinf_prod by force + +end + +subsection \<open>Infinite summability on real normed vector spaces\<close> + +context + fixes f :: "nat \<Rightarrow> 'a::real_normed_field" +begin + +lemma raw_has_prod_Suc_iff: "raw_has_prod f M (a * f M) \<longleftrightarrow> raw_has_prod (\<lambda>n. f (Suc n)) M a \<and> f M \<noteq> 0" +proof - + have "raw_has_prod f M (a * f M) \<longleftrightarrow> (\<lambda>i. \<Prod>j\<le>Suc i. f (j+M)) \<longlonglongrightarrow> a * f M \<and> a * f M \<noteq> 0" + by (subst LIMSEQ_Suc_iff) (simp add: raw_has_prod_def) + also have "\<dots> \<longleftrightarrow> (\<lambda>i. (\<Prod>j\<le>i. f (Suc j + M)) * f M) \<longlonglongrightarrow> a * f M \<and> a * f M \<noteq> 0" + by (simp add: ac_simps atMost_Suc_eq_insert_0 image_Suc_atMost prod_atLeast1_atMost_eq lessThan_Suc_atMost) + also have "\<dots> \<longleftrightarrow> raw_has_prod (\<lambda>n. f (Suc n)) M a \<and> f M \<noteq> 0" + proof safe + assume tends: "(\<lambda>i. (\<Prod>j\<le>i. f (Suc j + M)) * f M) \<longlonglongrightarrow> a * f M" and 0: "a * f M \<noteq> 0" + with tendsto_divide[OF tends tendsto_const, of "f M"] + show "raw_has_prod (\<lambda>n. f (Suc n)) M a" + by (simp add: raw_has_prod_def) + qed (auto intro: tendsto_mult_right simp: raw_has_prod_def) + finally show ?thesis . +qed + +lemma has_prod_Suc_iff: + assumes "f 0 \<noteq> 0" shows "(\<lambda>n. f (Suc n)) has_prod a \<longleftrightarrow> f has_prod (a * f 0)" +proof (cases "a = 0") + case True + then show ?thesis + proof (simp add: has_prod_def, safe) + fix i x + assume "f (Suc i) = 0" and "raw_has_prod (\<lambda>n. f (Suc n)) (Suc i) x" + then obtain y where "raw_has_prod f (Suc (Suc i)) y" + by (metis (no_types) raw_has_prod_eq_0 Suc_n_not_le_n raw_has_prod_Suc_iff raw_has_prod_ignore_initial_segment raw_has_prod_nonzero linear) + then show "\<exists>i. f i = 0 \<and> Ex (raw_has_prod f (Suc i))" + using \<open>f (Suc i) = 0\<close> by blast + next + fix i x + assume "f i = 0" and x: "raw_has_prod f (Suc i) x" + then obtain j where j: "i = Suc j" + by (metis assms not0_implies_Suc) + moreover have "\<exists> y. raw_has_prod (\<lambda>n. f (Suc n)) i y" + using x by (auto simp: raw_has_prod_def) + then show "\<exists>i. f (Suc i) = 0 \<and> Ex (raw_has_prod (\<lambda>n. f (Suc n)) (Suc i))" + using \<open>f i = 0\<close> j by blast + qed +next + case False + then show ?thesis + by (auto simp: has_prod_def raw_has_prod_Suc_iff assms) +qed + +lemma convergent_prod_Suc_iff: + assumes "\<And>k. f k \<noteq> 0" shows "convergent_prod (\<lambda>n. f (Suc n)) = convergent_prod f" +proof + assume "convergent_prod f" + then have "f has_prod prodinf f" + by (rule convergent_prod_has_prod) + moreover have "prodinf f \<noteq> 0" + by (simp add: \<open>convergent_prod f\<close> assms prodinf_nonzero) + ultimately have "(\<lambda>n. f (Suc n)) has_prod (prodinf f * inverse (f 0))" + by (simp add: has_prod_Suc_iff inverse_eq_divide assms) + then show "convergent_prod (\<lambda>n. f (Suc n))" + using has_prod_iff by blast +next + assume "convergent_prod (\<lambda>n. f (Suc n))" + then show "convergent_prod f" + using assms convergent_prod_def raw_has_prod_Suc_iff by blast +qed + +lemma raw_has_prod_inverse: + assumes "raw_has_prod f M a" shows "raw_has_prod (\<lambda>n. inverse (f n)) M (inverse a)" + using assms unfolding raw_has_prod_def by (auto dest: tendsto_inverse simp: prod_inversef [symmetric]) + +lemma has_prod_inverse: + assumes "f has_prod a" shows "(\<lambda>n. inverse (f n)) has_prod (inverse a)" +using assms raw_has_prod_inverse unfolding has_prod_def by auto + +lemma convergent_prod_inverse: + assumes "convergent_prod f" + shows "convergent_prod (\<lambda>n. inverse (f n))" + using assms unfolding convergent_prod_def by (blast intro: raw_has_prod_inverse elim: ) + +end + +context (* Separate contexts are necessary to allow general use of the results above, here. *) + fixes f :: "nat \<Rightarrow> 'a::real_normed_field" +begin + +lemma raw_has_prod_Suc_iff': "raw_has_prod f M a \<longleftrightarrow> raw_has_prod (\<lambda>n. f (Suc n)) M (a / f M) \<and> f M \<noteq> 0" + by (metis raw_has_prod_eq_0 add.commute add.left_neutral raw_has_prod_Suc_iff raw_has_prod_nonzero le_add1 nonzero_mult_div_cancel_right times_divide_eq_left) + +lemma has_prod_divide: "f has_prod a \<Longrightarrow> g has_prod b \<Longrightarrow> (\<lambda>n. f n / g n) has_prod (a / b)" + unfolding divide_inverse by (intro has_prod_inverse has_prod_mult) + +lemma convergent_prod_divide: + assumes f: "convergent_prod f" and g: "convergent_prod g" + shows "convergent_prod (\<lambda>n. f n / g n)" + using f g has_prod_divide has_prod_iff by blast + +lemma prodinf_divide: "convergent_prod f \<Longrightarrow> convergent_prod g \<Longrightarrow> prodinf f / prodinf g = (\<Prod>n. f n / g n)" + by (intro has_prod_unique has_prod_divide convergent_prod_has_prod) + +lemma prodinf_inverse: "convergent_prod f \<Longrightarrow> (\<Prod>n. inverse (f n)) = inverse (\<Prod>n. f n)" + by (intro has_prod_unique [symmetric] has_prod_inverse convergent_prod_has_prod) + +lemma has_prod_iff_shift: + assumes "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0" + shows "(\<lambda>i. f (i + n)) has_prod a \<longleftrightarrow> f has_prod (a * (\<Prod>i<n. f i))" + using assms +proof (induct n arbitrary: a) + case 0 + then show ?case by simp +next + case (Suc n) + then have "(\<lambda>i. f (Suc i + n)) has_prod a \<longleftrightarrow> (\<lambda>i. f (i + n)) has_prod (a * f n)" + by (subst has_prod_Suc_iff) auto + with Suc show ?case + by (simp add: ac_simps) +qed + +corollary has_prod_iff_shift': + assumes "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0" + shows "(\<lambda>i. f (i + n)) has_prod (a / (\<Prod>i<n. f i)) \<longleftrightarrow> f has_prod a" + by (simp add: assms has_prod_iff_shift) + +lemma has_prod_one_iff_shift: + assumes "\<And>i. i < n \<Longrightarrow> f i = 1" + shows "(\<lambda>i. f (i+n)) has_prod a \<longleftrightarrow> (\<lambda>i. f i) has_prod a" + by (simp add: assms has_prod_iff_shift) + +lemma convergent_prod_iff_shift: + shows "convergent_prod (\<lambda>i. f (i + n)) \<longleftrightarrow> convergent_prod f" + apply safe + using convergent_prod_offset apply blast + using convergent_prod_ignore_initial_segment convergent_prod_def by blast + +lemma has_prod_split_initial_segment: + assumes "f has_prod a" "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0" + shows "(\<lambda>i. f (i + n)) has_prod (a / (\<Prod>i<n. f i))" + using assms has_prod_iff_shift' by blast + +lemma prodinf_divide_initial_segment: + assumes "convergent_prod f" "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0" + shows "(\<Prod>i. f (i + n)) = (\<Prod>i. f i) / (\<Prod>i<n. f i)" + by (rule has_prod_unique[symmetric]) (auto simp: assms has_prod_iff_shift) + +lemma prodinf_split_initial_segment: + assumes "convergent_prod f" "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0" + shows "prodinf f = (\<Prod>i. f (i + n)) * (\<Prod>i<n. f i)" + by (auto simp add: assms prodinf_divide_initial_segment) + +lemma prodinf_split_head: + assumes "convergent_prod f" "f 0 \<noteq> 0" + shows "(\<Prod>n. f (Suc n)) = prodinf f / f 0" + using prodinf_split_initial_segment[of 1] assms by simp + +end + +context (* Separate contexts are necessary to allow general use of the results above, here. *) + fixes f :: "nat \<Rightarrow> 'a::real_normed_field" +begin + +lemma convergent_prod_inverse_iff: "convergent_prod (\<lambda>n. inverse (f n)) \<longleftrightarrow> convergent_prod f" + by (auto dest: convergent_prod_inverse) + +lemma convergent_prod_const_iff: + fixes c :: "'a :: {real_normed_field}" + shows "convergent_prod (\<lambda>_. c) \<longleftrightarrow> c = 1" +proof + assume "convergent_prod (\<lambda>_. c)" + then show "c = 1" + using convergent_prod_imp_LIMSEQ LIMSEQ_unique by blast +next + assume "c = 1" + then show "convergent_prod (\<lambda>_. c)" + by auto +qed + +lemma has_prod_power: "f has_prod a \<Longrightarrow> (\<lambda>i. f i ^ n) has_prod (a ^ n)" + by (induction n) (auto simp: has_prod_mult) + +lemma convergent_prod_power: "convergent_prod f \<Longrightarrow> convergent_prod (\<lambda>i. f i ^ n)" + by (induction n) (auto simp: convergent_prod_mult) + +lemma prodinf_power: "convergent_prod f \<Longrightarrow> prodinf (\<lambda>i. f i ^ n) = prodinf f ^ n" + by (metis has_prod_unique convergent_prod_imp_has_prod has_prod_power) + +end + +end diff -r 0f19c98fa7be -r 20375f232f3b src/HOL/Groups_Big.thy --- a/src/HOL/Groups_Big.thy Sat Jun 02 22:57:44 2018 +0100 +++ b/src/HOL/Groups_Big.thy Sun Jun 03 15:22:30 2018 +0100 @@ -1302,17 +1302,20 @@ by simp qed -lemma (in linordered_semidom) prod_nonneg: "(\<forall>a\<in>A. 0 \<le> f a) \<Longrightarrow> 0 \<le> prod f A" +context linordered_semidom +begin + +lemma prod_nonneg: "(\<forall>a\<in>A. 0 \<le> f a) \<Longrightarrow> 0 \<le> prod f A" by (induct A rule: infinite_finite_induct) simp_all -lemma (in linordered_semidom) prod_pos: "(\<forall>a\<in>A. 0 < f a) \<Longrightarrow> 0 < prod f A" +lemma prod_pos: "(\<forall>a\<in>A. 0 < f a) \<Longrightarrow> 0 < prod f A" by (induct A rule: infinite_finite_induct) simp_all -lemma (in linordered_semidom) prod_mono: +lemma prod_mono: "(\<And>i. i \<in> A \<Longrightarrow> 0 \<le> f i \<and> f i \<le> g i) \<Longrightarrow> prod f A \<le> prod g A" by (induct A rule: infinite_finite_induct) (force intro!: prod_nonneg mult_mono)+ -lemma (in linordered_semidom) prod_mono_strict: +lemma prod_mono_strict: assumes "finite A" "\<And>i. i \<in> A \<Longrightarrow> 0 \<le> f i \<and> f i < g i" "A \<noteq> {}" shows "prod f A < prod g A" using assms @@ -1324,6 +1327,42 @@ then show ?case by (force intro: mult_strict_mono' prod_nonneg) qed +end + +lemma prod_mono2: + fixes f :: "'a \<Rightarrow> 'b :: linordered_idom" + assumes fin: "finite B" + and sub: "A \<subseteq> B" + and nn: "\<And>b. b \<in> B-A \<Longrightarrow> 1 \<le> f b" + and A: "\<And>a. a \<in> A \<Longrightarrow> 0 \<le> f a" + shows "prod f A \<le> prod f B" +proof - + have "prod f A \<le> prod f A * prod f (B-A)" + by (metis prod_ge_1 A mult_le_cancel_left1 nn not_less prod_nonneg) + also from fin finite_subset[OF sub fin] have "\<dots> = prod f (A \<union> (B-A))" + by (simp add: prod.union_disjoint del: Un_Diff_cancel) + also from sub have "A \<union> (B-A) = B" by blast + finally show ?thesis . +qed + +lemma less_1_prod: + fixes f :: "'a \<Rightarrow> 'b::linordered_idom" + shows "finite I \<Longrightarrow> I \<noteq> {} \<Longrightarrow> (\<And>i. i \<in> I \<Longrightarrow> 1 < f i) \<Longrightarrow> 1 < prod f I" + by (induct I rule: finite_ne_induct) (auto intro: less_1_mult) + +lemma less_1_prod2: + fixes f :: "'a \<Rightarrow> 'b::linordered_idom" + assumes I: "finite I" "i \<in> I" "1 < f i" "\<And>i. i \<in> I \<Longrightarrow> 1 \<le> f i" + shows "1 < prod f I" +proof - + have "1 < f i * prod f (I - {i})" + using assms + by (meson DiffD1 leI less_1_mult less_le_trans mult_le_cancel_left1 prod_ge_1) + also have "\<dots> = prod f I" + using assms by (simp add: prod.remove) + finally show ?thesis . +qed + lemma (in linordered_field) abs_prod: "\<bar>prod f A\<bar> = (\<Prod>x\<in>A. \<bar>f x\<bar>)" by (induct A rule: infinite_finite_induct) (simp_all add: abs_mult) diff -r 0f19c98fa7be -r 20375f232f3b src/HOL/Set_Interval.thy --- a/src/HOL/Set_Interval.thy Sat Jun 02 22:57:44 2018 +0100 +++ b/src/HOL/Set_Interval.thy Sun Jun 03 15:22:30 2018 +0100 @@ -507,7 +507,7 @@ lemma Iio_eq_empty_iff: "{..< n::'a::{linorder, order_bot}} = {} \<longleftrightarrow> n = bot" by (auto simp: set_eq_iff not_less le_bot) -lemma Iio_eq_empty_iff_nat: "{..< n::nat} = {} \<longleftrightarrow> n = 0" +lemma lessThan_empty_iff: "{..< n::nat} = {} \<longleftrightarrow> n = 0" by (simp add: Iio_eq_empty_iff bot_nat_def) lemma mono_image_least: @@ -709,7 +709,7 @@ lemma lessThan_Suc_atMost: "lessThan (Suc k) = atMost k" by (simp add: lessThan_def atMost_def less_Suc_eq_le) -lemma Iic_Suc_eq_insert_0: "{.. Suc n} = insert 0 (Suc ` {.. n})" +lemma atMost_Suc_eq_insert_0: "{.. Suc n} = insert 0 (Suc ` {.. n})" unfolding lessThan_Suc_atMost[symmetric] lessThan_Suc_eq_insert_0[of "Suc n"] .. lemma UN_lessThan_UNIV: "(UN m::nat. lessThan m) = UNIV" @@ -803,7 +803,7 @@ lemma atLeast0_atMost_Suc_eq_insert_0: "{0..Suc n} = insert 0 (Suc ` {0..n})" - by (simp add: atLeast0AtMost Iic_Suc_eq_insert_0) + by (simp add: atLeast0AtMost atMost_Suc_eq_insert_0) subsubsection \<open>Intervals of nats with @{term Suc}\<close> @@ -2408,6 +2408,16 @@ "\<Prod>i\<le>n. t" \<rightleftharpoons> "CONST prod (\<lambda>i. t) {..n}" "\<Prod>i<n. t" \<rightleftharpoons> "CONST prod (\<lambda>i. t) {..<n}" +lemma prod_atLeast1_atMost_eq: + "prod f {Suc 0..n} = (\<Prod>k<n. f (Suc k))" +proof - + have "prod f {Suc 0..n} = prod f (Suc ` {..<n})" + by (simp add: image_Suc_lessThan) + also have "\<dots> = (\<Prod>k<n. f (Suc k))" + by (simp add: prod.reindex) + finally show ?thesis . +qed + lemma prod_int_plus_eq: "prod int {i..i+j} = \<Prod>{int i..int (i+j)}" by (induct j) (auto simp add: atLeastAtMostSuc_conv atLeastAtMostPlus1_int_conv) @@ -2441,7 +2451,7 @@ "prod f {Suc m..<Suc n} = prod (%i. f(Suc i)){m..<n}" by (simp add:prod_shift_bounds_nat_ivl[where k="Suc 0", simplified]) -lemma prod_lessThan_Suc: "prod f {..<Suc n} = prod f {..<n} * f n" +lemma prod_lessThan_Suc [simp]: "prod f {..<Suc n} = prod f {..<n} * f n" by (simp add: lessThan_Suc mult.commute) lemma prod_lessThan_Suc_shift:"(\<Prod>i<Suc n. f i) = f 0 * (\<Prod>i<n. f (Suc i))" diff -r 0f19c98fa7be -r 20375f232f3b src/HOL/Topological_Spaces.thy --- a/src/HOL/Topological_Spaces.thy Sat Jun 02 22:57:44 2018 +0100 +++ b/src/HOL/Topological_Spaces.thy Sun Jun 03 15:22:30 2018 +0100 @@ -1353,6 +1353,12 @@ lemma LIMSEQ_Suc_iff: "(\<lambda>n. f (Suc n)) \<longlonglongrightarrow> l = f \<longlonglongrightarrow> l" by (blast intro: LIMSEQ_imp_Suc LIMSEQ_Suc) +lemma LIMSEQ_lessThan_iff_atMost: + shows "(\<lambda>n. f {..<n}) \<longlonglongrightarrow> x \<longleftrightarrow> (\<lambda>n. f {..n}) \<longlonglongrightarrow> x" + apply (subst LIMSEQ_Suc_iff [symmetric]) + apply (simp only: lessThan_Suc_atMost) + done + lemma LIMSEQ_unique: "X \<longlonglongrightarrow> a \<Longrightarrow> X \<longlonglongrightarrow> b \<Longrightarrow> a = b" for a b :: "'a::t2_space" using trivial_limit_sequentially by (rule tendsto_unique)