--- 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"
--- 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
--- 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
--- 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)
--- 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))"
--- 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)