paulson@10751: (* Title : Series.thy paulson@10751: Author : Jacques D. Fleuriot paulson@10751: Copyright : 1998 University of Cambridge paulson@14416: paulson@14416: Converted to Isar and polished by lcp nipkow@15539: Converted to setsum and polished yet more by TNN avigad@16819: Additional contributions by Jeremy Avigad paulson@10751: *) paulson@10751: paulson@14416: header{*Finite Summation and Infinite Series*} paulson@10751: nipkow@15131: theory Series nipkow@15140: imports SEQ Lim nipkow@15131: begin nipkow@15561: wenzelm@19765: definition huffman@20692: sums :: "(nat \ 'a::real_normed_vector) \ 'a \ bool" huffman@20692: (infixr "sums" 80) wenzelm@19765: "f sums s = (%n. setsum f {0.. s" paulson@10751: huffman@20692: summable :: "(nat \ 'a::real_normed_vector) \ bool" wenzelm@19765: "summable f = (\s. f sums s)" paulson@14416: huffman@20692: suminf :: "(nat \ 'a::real_normed_vector) \ 'a" huffman@20688: "suminf f = (THE s. f sums s)" paulson@14416: nipkow@15546: syntax huffman@20692: "_suminf" :: "idt \ 'a \ 'a" ("\_. _" [0, 10] 10) nipkow@15546: translations nipkow@15546: "\i. b" == "suminf (%i. b)" nipkow@15546: paulson@14416: nipkow@15539: lemma sumr_diff_mult_const: nipkow@15539: "setsum f {0.. f(p) \ K) nipkow@15542: \ setsum f {0.. real n * K" nipkow@15542: using setsum_bounded[where A = "{0..i=0..<2*n. (-1) ^ Suc i) = (0::real)" paulson@15251: by (induct "n", auto) paulson@14416: nipkow@15539: (* FIXME this is an awful lemma! *) nipkow@15539: lemma sumr_one_lb_realpow_zero [simp]: nipkow@15539: "(\n=Suc 0..m=0..m=0.. 'a::ab_group_add" huffman@20692: shows "(\m=0..f. (\m=0..n f. setsum f {0::nat..m=0.. avigad@16819: (\n=Suc 0 ..< Suc n. if even(n) then 0 else avigad@16819: ((- 1) ^ ((n - (Suc 0)) div 2))/(real (fact n))) * a ^ n = avigad@16819: (\n=0.. summable f" paulson@14416: by (simp add: sums_def summable_def, blast) paulson@14416: paulson@14416: lemma summable_sums: "summable f ==> f sums (suminf f)" huffman@20688: apply (simp add: summable_def suminf_def sums_def) huffman@20688: apply (blast intro: theI LIMSEQ_unique) paulson@14416: done paulson@14416: paulson@14416: lemma summable_sumr_LIMSEQ_suminf: nipkow@15539: "summable f ==> (%n. setsum f {0.. (suminf f)" huffman@20688: by (rule summable_sums [unfolded sums_def]) paulson@14416: paulson@14416: (*------------------- paulson@14416: sum is unique paulson@14416: ------------------*) paulson@14416: lemma sums_unique: "f sums s ==> (s = suminf f)" paulson@14416: apply (frule sums_summable [THEN summable_sums]) paulson@14416: apply (auto intro!: LIMSEQ_unique simp add: sums_def) paulson@14416: done paulson@14416: avigad@16819: lemma sums_split_initial_segment: "f sums s ==> avigad@16819: (%n. f(n + k)) sums (s - (SUM i = 0..< k. f i))" avigad@16819: apply (unfold sums_def); avigad@16819: apply (simp add: sumr_offset); avigad@16819: apply (rule LIMSEQ_diff_const) avigad@16819: apply (rule LIMSEQ_ignore_initial_segment) avigad@16819: apply assumption avigad@16819: done avigad@16819: avigad@16819: lemma summable_ignore_initial_segment: "summable f ==> avigad@16819: summable (%n. f(n + k))" avigad@16819: apply (unfold summable_def) avigad@16819: apply (auto intro: sums_split_initial_segment) avigad@16819: done avigad@16819: avigad@16819: lemma suminf_minus_initial_segment: "summable f ==> avigad@16819: suminf f = s ==> suminf (%n. f(n + k)) = s - (SUM i = 0..< k. f i)" avigad@16819: apply (frule summable_ignore_initial_segment) avigad@16819: apply (rule sums_unique [THEN sym]) avigad@16819: apply (frule summable_sums) avigad@16819: apply (rule sums_split_initial_segment) avigad@16819: apply auto avigad@16819: done avigad@16819: avigad@16819: lemma suminf_split_initial_segment: "summable f ==> avigad@16819: suminf f = (SUM i = 0..< k. f i) + suminf (%n. f(n + k))" avigad@16819: by (auto simp add: suminf_minus_initial_segment) avigad@16819: paulson@14416: lemma series_zero: nipkow@15539: "(\m. n \ m --> f(m) = 0) ==> f sums (setsum f {0.. (\n. c * f n) sums (c * a)" ballarin@19279: by (auto simp add: sums_def setsum_right_distrib [symmetric] paulson@14416: intro!: LIMSEQ_mult intro: LIMSEQ_const) paulson@14416: huffman@20692: lemma summable_mult: huffman@20692: fixes c :: "'a::real_normed_algebra" huffman@20692: shows "summable f \ summable (%n. c * f n)"; avigad@16819: apply (unfold summable_def); avigad@16819: apply (auto intro: sums_mult); avigad@16819: done; avigad@16819: huffman@20692: lemma suminf_mult: huffman@20692: fixes c :: "'a::real_normed_algebra" huffman@20692: shows "summable f \ suminf (\n. c * f n) = c * suminf f"; avigad@16819: apply (rule sym); avigad@16819: apply (rule sums_unique); avigad@16819: apply (rule sums_mult); avigad@16819: apply (erule summable_sums); avigad@16819: done; avigad@16819: huffman@20692: lemma sums_mult2: huffman@20692: fixes c :: "'a::real_normed_algebra" huffman@20692: shows "f sums a \ (\n. f n * c) sums (a * c)" huffman@20692: by (auto simp add: sums_def setsum_left_distrib [symmetric] huffman@20692: intro!: LIMSEQ_mult LIMSEQ_const) avigad@16819: huffman@20692: lemma summable_mult2: huffman@20692: fixes c :: "'a::real_normed_algebra" huffman@20692: shows "summable f \ summable (\n. f n * c)" avigad@16819: apply (unfold summable_def) avigad@16819: apply (auto intro: sums_mult2) avigad@16819: done avigad@16819: huffman@20692: lemma suminf_mult2: huffman@20692: fixes c :: "'a::real_normed_algebra" huffman@20692: shows "summable f \ suminf f * c = (\n. f n * c)" huffman@20692: by (auto intro!: sums_unique sums_mult2 summable_sums) avigad@16819: huffman@20692: lemma sums_divide: huffman@20692: fixes c :: "'a::real_normed_field" huffman@20692: shows "f sums a \ (\n. f n / c) sums (a / c)" huffman@20692: by (simp add: divide_inverse sums_mult2) paulson@14416: huffman@20692: lemma summable_divide: huffman@20692: fixes c :: "'a::real_normed_field" huffman@20692: shows "summable f \ summable (\n. f n / c)" avigad@16819: apply (unfold summable_def); avigad@16819: apply (auto intro: sums_divide); avigad@16819: done; avigad@16819: huffman@20692: lemma suminf_divide: huffman@20692: fixes c :: "'a::real_normed_field" huffman@20692: shows "summable f \ suminf (\n. f n / c) = suminf f / c" avigad@16819: apply (rule sym); avigad@16819: apply (rule sums_unique); avigad@16819: apply (rule sums_divide); avigad@16819: apply (erule summable_sums); avigad@16819: done; avigad@16819: avigad@16819: lemma sums_add: "[| x sums x0; y sums y0 |] ==> (%n. x n + y n) sums (x0+y0)" avigad@16819: by (auto simp add: sums_def setsum_addf intro: LIMSEQ_add) avigad@16819: avigad@16819: lemma summable_add: "summable f ==> summable g ==> summable (%x. f x + g x)"; avigad@16819: apply (unfold summable_def); avigad@16819: apply clarify; avigad@16819: apply (rule exI); avigad@16819: apply (erule sums_add); avigad@16819: apply assumption; avigad@16819: done; avigad@16819: avigad@16819: lemma suminf_add: avigad@16819: "[| summable f; summable g |] avigad@16819: ==> suminf f + suminf g = (\n. f n + g n)" avigad@16819: by (auto intro!: sums_add sums_unique summable_sums) avigad@16819: paulson@14416: lemma sums_diff: "[| x sums x0; y sums y0 |] ==> (%n. x n - y n) sums (x0-y0)" nipkow@15536: by (auto simp add: sums_def setsum_subtractf intro: LIMSEQ_diff) paulson@14416: avigad@16819: lemma summable_diff: "summable f ==> summable g ==> summable (%x. f x - g x)"; avigad@16819: apply (unfold summable_def); avigad@16819: apply clarify; avigad@16819: apply (rule exI); avigad@16819: apply (erule sums_diff); avigad@16819: apply assumption; avigad@16819: done; paulson@14416: paulson@14416: lemma suminf_diff: paulson@14416: "[| summable f; summable g |] nipkow@15546: ==> suminf f - suminf g = (\n. f n - g n)" paulson@14416: by (auto intro!: sums_diff sums_unique summable_sums) paulson@14416: avigad@16819: lemma sums_minus: "f sums s ==> (%x. - f x) sums (- s)"; avigad@16819: by (simp add: sums_def setsum_negf LIMSEQ_minus); avigad@16819: avigad@16819: lemma summable_minus: "summable f ==> summable (%x. - f x)"; avigad@16819: by (auto simp add: summable_def intro: sums_minus); avigad@16819: avigad@16819: lemma suminf_minus: "summable f ==> suminf (%x. - f x) = - (suminf f)"; avigad@16819: apply (rule sym); avigad@16819: apply (rule sums_unique); avigad@16819: apply (rule sums_minus); avigad@16819: apply (erule summable_sums); avigad@16819: done; paulson@14416: paulson@14416: lemma sums_group: nipkow@15539: "[|summable f; 0 < k |] ==> (%n. setsum f {n*k.. real" huffman@20692: shows "\summable f; \m\n. 0 \ f m\ \ setsum f {0.. suminf f" paulson@14416: apply (drule summable_sums) paulson@14416: apply (simp add: sums_def) nipkow@15539: apply (cut_tac k = "setsum f {0.. real" huffman@20692: shows "\summable f; \m\n. 0 < f m\ \ setsum f {0.. real" huffman@20692: shows "\summable f; \n. 0 < f n\ \ 0 < suminf f" huffman@20692: by (drule_tac n="0" in series_pos_less, simp_all) huffman@20692: huffman@20692: lemma suminf_ge_zero: huffman@20692: fixes f :: "nat \ real" huffman@20692: shows "\summable f; \n. 0 \ f n\ \ 0 \ suminf f" huffman@20692: by (drule_tac n="0" in series_pos_le, simp_all) huffman@20692: huffman@20692: lemma sumr_pos_lt_pair: huffman@20692: fixes f :: "nat \ real" huffman@20692: shows "\summable f; huffman@20692: \d. 0 < f (k + (Suc(Suc 0) * d)) + f (k + ((Suc(Suc 0) * d) + 1))\ huffman@20692: \ setsum f {0.. (\n. x ^ n) sums (1 / (1 - x))" huffman@20692: proof - huffman@20692: assume less_1: "norm x < 1" huffman@20692: hence neq_1: "x \ 1" by auto huffman@20692: hence neq_0: "x - 1 \ 0" by simp huffman@20692: from less_1 have lim_0: "(\n. x ^ n) ----> 0" huffman@20692: by (rule LIMSEQ_power_zero) huffman@20692: hence "(\n. x ^ n / (x - 1) - 1 / (x - 1)) ----> 0 / (x - 1) - 1 / (x huffman@20692: - 1)" huffman@20692: using neq_0 by (intro LIMSEQ_divide LIMSEQ_diff LIMSEQ_const) huffman@20692: hence "(\n. (x ^ n - 1) / (x - 1)) ----> 1 / (1 - x)" huffman@20692: by (simp add: nonzero_minus_divide_right [OF neq_0] diff_divide_distrib) huffman@20692: thus "(\n. x ^ n) sums (1 / (1 - x))" huffman@20692: by (simp add: sums_def geometric_sum neq_1) huffman@20692: qed huffman@20692: huffman@20692: lemma summable_geometric: huffman@20692: fixes x :: "'a::{real_normed_field,recpower,division_by_zero}" huffman@20692: shows "norm x < 1 \ summable (\n. x ^ n)" huffman@20692: by (rule geometric_sums [THEN sums_summable]) paulson@14416: paulson@15085: text{*Cauchy-type criterion for convergence of series (c.f. Harrison)*} paulson@15085: nipkow@15539: lemma summable_convergent_sumr_iff: nipkow@15539: "summable f = convergent (%n. setsum f {0.. f ----> 0" huffman@20689: apply (drule summable_convergent_sumr_iff [THEN iffD1]) huffman@20692: apply (drule convergent_Cauchy) huffman@20689: apply (simp only: Cauchy_def LIMSEQ_def, safe) huffman@20689: apply (drule_tac x="r" in spec, safe) huffman@20689: apply (rule_tac x="M" in exI, safe) huffman@20689: apply (drule_tac x="Suc n" in spec, simp) huffman@20689: apply (drule_tac x="n" in spec, simp) huffman@20689: done huffman@20689: paulson@14416: lemma summable_Cauchy: huffman@20692: "summable (f::nat \ real) = nipkow@15539: (\e > 0. \N. \m \ N. \n. abs(setsum f {m.. 'b::real_normed_vector" huffman@20692: shows "norm (setsum f A) \ (\i\A. norm (f i))" huffman@20692: apply (case_tac "finite A") huffman@20692: apply (erule finite_induct) huffman@20692: apply simp huffman@20692: apply simp huffman@20692: apply (erule order_trans [OF norm_triangle_ineq add_left_mono]) huffman@20692: apply simp huffman@20692: done huffman@20692: paulson@14416: lemma summable_comparison_test: huffman@20692: fixes f :: "nat \ real" huffman@20692: shows "\\N. \n\N. \f n\ \ g n; summable g\ \ summable f" huffman@20692: apply (simp add: summable_Cauchy, safe) huffman@20692: apply (drule_tac x="e" in spec, safe) huffman@20692: apply (rule_tac x = "N + Na" in exI, safe) paulson@14416: apply (rotate_tac 2) paulson@14416: apply (drule_tac x = m in spec) paulson@14416: apply (auto, rotate_tac 2, drule_tac x = n in spec) nipkow@15539: apply (rule_tac y = "\k=m.. real" huffman@20692: shows "\\N. \n\N. \f n\ \ g n; summable g\ \ summable (\n. \f n\)" paulson@14416: apply (rule summable_comparison_test) nipkow@15543: apply (auto) paulson@14416: done paulson@14416: paulson@15085: text{*Limit comparison property for series (c.f. jrh)*} paulson@15085: paulson@14416: lemma summable_le: huffman@20692: fixes f g :: "nat \ real" huffman@20692: shows "\\n. f n \ g n; summable f; summable g\ \ suminf f \ suminf g" paulson@14416: apply (drule summable_sums)+ huffman@20692: apply (simp only: sums_def, erule (1) LIMSEQ_le) paulson@14416: apply (rule exI) nipkow@15539: apply (auto intro!: setsum_mono) paulson@14416: done paulson@14416: paulson@14416: lemma summable_le2: huffman@20692: fixes f g :: "nat \ real" huffman@20692: shows "\\n. \f n\ \ g n; summable g\ \ summable f \ suminf f \ suminf g" paulson@14416: apply (auto intro: summable_comparison_test intro!: summable_le) paulson@14416: apply (simp add: abs_le_interval_iff) paulson@14416: done paulson@14416: kleing@19106: (* specialisation for the common 0 case *) kleing@19106: lemma suminf_0_le: kleing@19106: fixes f::"nat\real" kleing@19106: assumes gt0: "\n. 0 \ f n" and sm: "summable f" kleing@19106: shows "0 \ suminf f" kleing@19106: proof - kleing@19106: let ?g = "(\n. (0::real))" kleing@19106: from gt0 have "\n. ?g n \ f n" by simp kleing@19106: moreover have "summable ?g" by (rule summable_zero) kleing@19106: moreover from sm have "summable f" . kleing@19106: ultimately have "suminf ?g \ suminf f" by (rule summable_le) kleing@19106: then show "0 \ suminf f" by (simp add: suminf_zero) kleing@19106: qed kleing@19106: kleing@19106: paulson@15085: text{*Absolute convergence imples normal convergence*} huffman@20692: lemma summable_rabs_cancel: huffman@20692: fixes f :: "nat \ real" huffman@20692: shows "summable (\n. \f n\) \ summable f" huffman@20692: apply (simp only: summable_Cauchy, safe) huffman@20692: apply (drule_tac x="e" in spec, safe) huffman@20692: apply (rule_tac x="N" in exI, safe) huffman@20692: apply (drule_tac x="m" in spec, safe) huffman@20692: apply (rule order_le_less_trans [OF setsum_abs]) huffman@20692: apply simp paulson@14416: done paulson@14416: paulson@15085: text{*Absolute convergence of series*} paulson@14416: lemma summable_rabs: huffman@20692: fixes f :: "nat \ real" huffman@20692: shows "summable (\n. \f n\) \ \suminf f\ \ (\n. \f n\)" nipkow@15536: by (auto intro: LIMSEQ_le LIMSEQ_imp_rabs summable_rabs_cancel summable_sumr_LIMSEQ_suminf) paulson@14416: paulson@14416: paulson@14416: subsection{* The Ratio Test*} paulson@14416: paulson@14416: lemma rabs_ratiotest_lemma: "[| c \ 0; abs x \ c * abs y |] ==> x = (0::real)" paulson@14416: apply (drule order_le_imp_less_or_eq, auto) paulson@14416: apply (subgoal_tac "0 \ c * abs y") paulson@14416: apply (simp add: zero_le_mult_iff, arith) paulson@14416: done paulson@14416: paulson@14416: lemma le_Suc_ex: "(k::nat) \ l ==> (\n. l = k + n)" paulson@14416: apply (drule le_imp_less_or_eq) paulson@14416: apply (auto dest: less_imp_Suc_add) paulson@14416: done paulson@14416: paulson@14416: lemma le_Suc_ex_iff: "((k::nat) \ l) = (\n. l = k + n)" paulson@14416: by (auto simp add: le_Suc_ex) paulson@14416: paulson@14416: (*All this trouble just to get 0 real" huffman@20692: shows "\\n\N. \f (Suc n)\ \ c * \f n\\ \ 0 < c \ summable f" paulson@14416: apply (simp (no_asm) add: linorder_not_le [symmetric]) paulson@14416: apply (simp add: summable_Cauchy) nipkow@15543: apply (safe, subgoal_tac "\n. N < n --> f (n) = 0") nipkow@15543: prefer 2 nipkow@15543: apply clarify nipkow@15543: apply(erule_tac x = "n - 1" in allE) nipkow@15543: apply (simp add:diff_Suc split:nat.splits) nipkow@15543: apply (blast intro: rabs_ratiotest_lemma) paulson@14416: apply (rule_tac x = "Suc N" in exI, clarify) nipkow@15543: apply(simp cong:setsum_ivl_cong) paulson@14416: done paulson@14416: paulson@14416: lemma ratio_test: huffman@20692: fixes f :: "nat \ real" huffman@20692: shows "\c < 1; \n\N. \f (Suc n)\ \ c * \f n\\ \ summable f" paulson@14416: apply (frule ratio_test_lemma2, auto) paulson@15234: apply (rule_tac g = "%n. (abs (f N) / (c ^ N))*c ^ n" paulson@15234: in summable_comparison_test) paulson@14416: apply (rule_tac x = N in exI, safe) paulson@14416: apply (drule le_Suc_ex_iff [THEN iffD1]) paulson@14416: apply (auto simp add: power_add realpow_not_zero) nipkow@15539: apply (induct_tac "na", auto) paulson@14416: apply (rule_tac y = "c*abs (f (N + n))" in order_trans) paulson@14416: apply (auto intro: mult_right_mono simp add: summable_def) paulson@14416: apply (simp add: mult_ac) paulson@15234: apply (rule_tac x = "abs (f N) * (1/ (1 - c)) / (c ^ N)" in exI) paulson@15234: apply (rule sums_divide) paulson@15234: apply (rule sums_mult) paulson@15234: apply (auto intro!: geometric_sums) paulson@14416: done paulson@14416: paulson@14416: paulson@15085: text{*Differentiation of finite sum*} paulson@14416: paulson@14416: lemma DERIV_sumr [rule_format (no_asm)]: paulson@14416: "(\r. m \ r & r < (m + n) --> DERIV (%x. f r x) x :> (f' r x)) nipkow@15539: --> DERIV (%x. \n=m.. (\r=m..