linear arithmetic splits certain operators (e.g. min, max, abs)
2 Author : Jacques D. Fleuriot
3 Copyright : 1998 University of Cambridge
5 Converted to Isar and polished by lcp
6 Converted to setsum and polished yet more by TNN
7 Additional contributions by Jeremy Avigad
10 header{*Finite Summation and Infinite Series*}
16 declare atLeastLessThan_iff[iff]
17 declare setsum_op_ivl_Suc[simp]
20 sums :: "(nat => real) => real => bool" (infixr "sums" 80)
21 "f sums s = (%n. setsum f {0..<n}) ----> s"
23 summable :: "(nat=>real) => bool"
24 "summable f = (\<exists>s. f sums s)"
26 suminf :: "(nat=>real) => real"
27 "suminf f = (SOME s. f sums s)"
30 "_suminf" :: "idt => real => real" ("\<Sum>_. _" [0, 10] 10)
32 "\<Sum>i. b" == "suminf (%i. b)"
35 lemma sumr_diff_mult_const:
36 "setsum f {0..<n} - (real n*r) = setsum (%i. f i - r) {0..<n::nat}"
37 by (simp add: diff_minus setsum_addf real_of_nat_def)
39 lemma real_setsum_nat_ivl_bounded:
40 "(!!p. p < n \<Longrightarrow> f(p) \<le> K)
41 \<Longrightarrow> setsum f {0..<n::nat} \<le> real n * K"
42 using setsum_bounded[where A = "{0..<n}"]
43 by (auto simp:real_of_nat_def)
45 (* Generalize from real to some algebraic structure? *)
46 lemma sumr_minus_one_realpow_zero [simp]:
47 "(\<Sum>i=0..<2*n. (-1) ^ Suc i) = (0::real)"
50 (* FIXME this is an awful lemma! *)
51 lemma sumr_one_lb_realpow_zero [simp]:
52 "(\<Sum>n=Suc 0..<n. f(n) * (0::real) ^ n) = 0"
54 apply (case_tac [2] "n", auto)
58 "(\<Sum>m=0..<n::nat. setsum f {m * k ..< m*k + k}) = setsum f {0 ..< n * k}"
59 apply (subgoal_tac "k = 0 | 0 < k", auto)
61 apply (simp_all add: setsum_add_nat_ivl add_commute)
64 (* FIXME generalize? *)
66 "(\<Sum>m=0..<n::nat. f(m+k)::real) = setsum f {0..<n+k} - setsum f {0..<k}"
70 "\<forall>f. (\<Sum>m=0..<n::nat. f(m+k)::real) = setsum f {0..<n+k} - setsum f {0..<k}"
74 "setsum f {0::nat..<n+k} = (\<Sum>m=0..<n. f (m+k)::real) + setsum f {0..<k}"
75 by (simp add: sumr_offset)
78 "\<forall>n f. setsum f {0::nat..<n+k} =
79 (\<Sum>m=0..<n. f (m+k)::real) + setsum f {0..<k}"
80 by (simp add: sumr_offset)
83 lemma sumr_from_1_from_0: "0 < n ==>
84 (\<Sum>n=Suc 0 ..< Suc n. if even(n) then 0 else
85 ((- 1) ^ ((n - (Suc 0)) div 2))/(real (fact n))) * a ^ n =
86 (\<Sum>n=0..<Suc n. if even(n) then 0 else
87 ((- 1) ^ ((n - (Suc 0)) div 2))/(real (fact n))) * a ^ n"
88 by (rule_tac n1 = 1 in sumr_split_add [THEN subst], auto)
91 subsection{* Infinite Sums, by the Properties of Limits*}
93 (*----------------------
95 ---------------------*)
96 lemma sums_summable: "f sums l ==> summable f"
97 by (simp add: sums_def summable_def, blast)
99 lemma summable_sums: "summable f ==> f sums (suminf f)"
100 apply (simp add: summable_def suminf_def)
101 apply (blast intro: someI2)
104 lemma summable_sumr_LIMSEQ_suminf:
105 "summable f ==> (%n. setsum f {0..<n}) ----> (suminf f)"
106 apply (simp add: summable_def suminf_def sums_def)
107 apply (blast intro: someI2)
110 (*-------------------
113 lemma sums_unique: "f sums s ==> (s = suminf f)"
114 apply (frule sums_summable [THEN summable_sums])
115 apply (auto intro!: LIMSEQ_unique simp add: sums_def)
118 lemma sums_split_initial_segment: "f sums s ==>
119 (%n. f(n + k)) sums (s - (SUM i = 0..< k. f i))"
120 apply (unfold sums_def);
121 apply (simp add: sumr_offset);
122 apply (rule LIMSEQ_diff_const)
123 apply (rule LIMSEQ_ignore_initial_segment)
127 lemma summable_ignore_initial_segment: "summable f ==>
128 summable (%n. f(n + k))"
129 apply (unfold summable_def)
130 apply (auto intro: sums_split_initial_segment)
133 lemma suminf_minus_initial_segment: "summable f ==>
134 suminf f = s ==> suminf (%n. f(n + k)) = s - (SUM i = 0..< k. f i)"
135 apply (frule summable_ignore_initial_segment)
136 apply (rule sums_unique [THEN sym])
137 apply (frule summable_sums)
138 apply (rule sums_split_initial_segment)
142 lemma suminf_split_initial_segment: "summable f ==>
143 suminf f = (SUM i = 0..< k. f i) + suminf (%n. f(n + k))"
144 by (auto simp add: suminf_minus_initial_segment)
147 "(\<forall>m. n \<le> m --> f(m) = 0) ==> f sums (setsum f {0..<n})"
148 apply (simp add: sums_def LIMSEQ_def diff_minus[symmetric], safe)
149 apply (rule_tac x = n in exI)
150 apply (clarsimp simp add:setsum_diff[symmetric] cong:setsum_ivl_cong)
153 lemma sums_zero: "(%n. 0) sums 0";
154 apply (unfold sums_def);
156 apply (rule LIMSEQ_const);
159 lemma summable_zero: "summable (%n. 0)";
160 apply (rule sums_summable);
161 apply (rule sums_zero);
164 lemma suminf_zero: "suminf (%n. 0) = 0";
166 apply (rule sums_unique);
167 apply (rule sums_zero);
170 lemma sums_mult: "f sums a ==> (%n. c * f n) sums (c * a)"
171 by (auto simp add: sums_def setsum_right_distrib [symmetric]
172 intro!: LIMSEQ_mult intro: LIMSEQ_const)
174 lemma summable_mult: "summable f ==> summable (%n. c * f n)";
175 apply (unfold summable_def);
176 apply (auto intro: sums_mult);
179 lemma suminf_mult: "summable f ==> suminf (%n. c * f n) = c * suminf f";
181 apply (rule sums_unique);
182 apply (rule sums_mult);
183 apply (erule summable_sums);
186 lemma sums_mult2: "f sums a ==> (%n. f n * c) sums (a * c)"
187 apply (subst mult_commute)
188 apply (subst mult_commute);back;
189 apply (erule sums_mult)
192 lemma summable_mult2: "summable f ==> summable (%n. f n * c)"
193 apply (unfold summable_def)
194 apply (auto intro: sums_mult2)
197 lemma suminf_mult2: "summable f ==> suminf f * c = (\<Sum>n. f n * c)"
198 by (auto intro!: sums_unique sums_mult summable_sums simp add: mult_commute)
200 lemma sums_divide: "f sums a ==> (%n. (f n)/c) sums (a/c)"
201 by (simp add: real_divide_def sums_mult mult_commute [of _ "inverse c"])
203 lemma summable_divide: "summable f ==> summable (%n. (f n) / c)";
204 apply (unfold summable_def);
205 apply (auto intro: sums_divide);
208 lemma suminf_divide: "summable f ==> suminf (%n. (f n) / c) = (suminf f) / c";
210 apply (rule sums_unique);
211 apply (rule sums_divide);
212 apply (erule summable_sums);
215 lemma sums_add: "[| x sums x0; y sums y0 |] ==> (%n. x n + y n) sums (x0+y0)"
216 by (auto simp add: sums_def setsum_addf intro: LIMSEQ_add)
218 lemma summable_add: "summable f ==> summable g ==> summable (%x. f x + g x)";
219 apply (unfold summable_def);
222 apply (erule sums_add);
227 "[| summable f; summable g |]
228 ==> suminf f + suminf g = (\<Sum>n. f n + g n)"
229 by (auto intro!: sums_add sums_unique summable_sums)
231 lemma sums_diff: "[| x sums x0; y sums y0 |] ==> (%n. x n - y n) sums (x0-y0)"
232 by (auto simp add: sums_def setsum_subtractf intro: LIMSEQ_diff)
234 lemma summable_diff: "summable f ==> summable g ==> summable (%x. f x - g x)";
235 apply (unfold summable_def);
238 apply (erule sums_diff);
243 "[| summable f; summable g |]
244 ==> suminf f - suminf g = (\<Sum>n. f n - g n)"
245 by (auto intro!: sums_diff sums_unique summable_sums)
247 lemma sums_minus: "f sums s ==> (%x. - f x) sums (- s)";
248 by (simp add: sums_def setsum_negf LIMSEQ_minus);
250 lemma summable_minus: "summable f ==> summable (%x. - f x)";
251 by (auto simp add: summable_def intro: sums_minus);
253 lemma suminf_minus: "summable f ==> suminf (%x. - f x) = - (suminf f)";
255 apply (rule sums_unique);
256 apply (rule sums_minus);
257 apply (erule summable_sums);
261 "[|summable f; 0 < k |] ==> (%n. setsum f {n*k..<n*k+k}) sums (suminf f)"
262 apply (drule summable_sums)
263 apply (auto simp add: sums_def LIMSEQ_def sumr_group)
264 apply (drule_tac x = r in spec, safe)
265 apply (rule_tac x = no in exI, safe)
266 apply (drule_tac x = "n*k" in spec)
267 apply (auto dest!: not_leE)
268 apply (drule_tac j = no in less_le_trans, auto)
271 lemma sumr_pos_lt_pair_lemma:
272 "[|\<forall>d. - f (n + (d + d)) < (f (Suc (n + (d + d))) :: real) |]
273 ==> setsum f {0..<n+Suc(Suc 0)} \<le> setsum f {0..<Suc(Suc 0) * Suc no + n}"
274 apply (induct "no", auto)
275 apply (drule_tac x = "Suc no" in spec)
276 apply (simp add: add_ac)
279 lemma sumr_pos_lt_pair:
281 \<forall>d. 0 < (f(n + (Suc(Suc 0) * d))) + f(n + ((Suc(Suc 0) * d) + 1))|]
282 ==> setsum f {0..<n} < suminf f"
283 apply (drule summable_sums)
284 apply (auto simp add: sums_def LIMSEQ_def)
285 apply (drule_tac x = "f (n) + f (n + 1)" in spec)
286 apply (auto iff: real_0_less_add_iff)
287 --{*legacy proof: not necessarily better!*}
288 apply (rule_tac [2] ccontr, drule_tac [2] linorder_not_less [THEN iffD1])
289 apply (frule_tac [2] no=no in sumr_pos_lt_pair_lemma)
290 apply (drule_tac x = 0 in spec, simp)
291 apply (rotate_tac 1, drule_tac x = "Suc (Suc 0) * (Suc no) + n" in spec)
293 apply (subgoal_tac "suminf f + (f (n) + f (n + 1)) \<le>
294 setsum f {0 ..< Suc (Suc 0) * (Suc no) + n}")
295 apply (rule_tac [2] y = "setsum f {0..<n+ Suc (Suc 0)}" in order_trans)
296 prefer 3 apply assumption
297 apply (rule_tac [2] y = "setsum f {0..<n} + (f (n) + f (n + 1))" in order_trans)
301 text{*A summable series of positive terms has limit that is at least as
302 great as any partial sum.*}
305 "[| summable f; \<forall>m \<ge> n. 0 \<le> f(m) |] ==> setsum f {0..<n} \<le> suminf f"
306 apply (drule summable_sums)
307 apply (simp add: sums_def)
308 apply (cut_tac k = "setsum f {0..<n}" in LIMSEQ_const)
309 apply (erule LIMSEQ_le, blast)
310 apply (rule_tac x = n in exI, clarify)
311 apply (rule setsum_mono2)
315 lemma series_pos_less:
316 "[| summable f; \<forall>m \<ge> n. 0 < f(m) |] ==> setsum f {0..<n} < suminf f"
317 apply (rule_tac y = "setsum f {0..<Suc n}" in order_less_le_trans)
318 apply (rule_tac [2] series_pos_le, auto)
319 apply (drule_tac x = m in spec, auto)
322 text{*Sum of a geometric progression.*}
324 lemmas sumr_geometric = geometric_sum [where 'a = real]
326 lemma geometric_sums: "abs(x) < 1 ==> (%n. x ^ n) sums (1/(1 - x))"
327 apply (case_tac "x = 1")
328 apply (auto dest!: LIMSEQ_rabs_realpow_zero2
329 simp add: sumr_geometric sums_def diff_minus add_divide_distrib)
330 apply (subgoal_tac "1 / (1 + -x) = 0/ (x - 1) + - 1/ (x - 1) ")
332 apply (rule LIMSEQ_add, rule LIMSEQ_divide)
333 apply (auto intro: LIMSEQ_const simp add: diff_minus minus_divide_right LIMSEQ_rabs_realpow_zero2)
336 text{*Cauchy-type criterion for convergence of series (c.f. Harrison)*}
338 lemma summable_convergent_sumr_iff:
339 "summable f = convergent (%n. setsum f {0..<n})"
340 by (simp add: summable_def sums_def convergent_def)
342 lemma summable_Cauchy:
344 (\<forall>e > 0. \<exists>N. \<forall>m \<ge> N. \<forall>n. abs(setsum f {m..<n}) < e)"
345 apply (auto simp add: summable_convergent_sumr_iff Cauchy_convergent_iff [symmetric] Cauchy_def diff_minus[symmetric])
346 apply (drule_tac [!] spec, auto)
347 apply (rule_tac x = M in exI)
348 apply (rule_tac [2] x = N in exI, auto)
349 apply (cut_tac [!] m = m and n = n in less_linear, auto)
350 apply (frule le_less_trans [THEN less_imp_le], assumption)
351 apply (drule_tac x = n in spec, simp)
352 apply (drule_tac x = m in spec)
353 apply(simp add: setsum_diff[symmetric])
354 apply(subst abs_minus_commute)
355 apply(simp add: setsum_diff[symmetric])
356 apply(simp add: setsum_diff[symmetric])
359 text{*Comparison test*}
361 lemma summable_comparison_test:
362 "[| \<exists>N. \<forall>n \<ge> N. abs(f n) \<le> g n; summable g |] ==> summable f"
363 apply (auto simp add: summable_Cauchy)
364 apply (drule spec, auto)
365 apply (rule_tac x = "N + Na" in exI, auto)
367 apply (drule_tac x = m in spec)
368 apply (auto, rotate_tac 2, drule_tac x = n in spec)
369 apply (rule_tac y = "\<Sum>k=m..<n. abs(f k)" in order_le_less_trans)
370 apply (rule setsum_abs)
371 apply (rule_tac y = "setsum g {m..<n}" in order_le_less_trans)
372 apply (auto intro: setsum_mono simp add: abs_interval_iff)
375 lemma summable_rabs_comparison_test:
376 "[| \<exists>N. \<forall>n \<ge> N. abs(f n) \<le> g n; summable g |]
377 ==> summable (%k. abs (f k))"
378 apply (rule summable_comparison_test)
382 text{*Limit comparison property for series (c.f. jrh)*}
385 "[|\<forall>n. f n \<le> g n; summable f; summable g |] ==> suminf f \<le> suminf g"
386 apply (drule summable_sums)+
387 apply (auto intro!: LIMSEQ_le simp add: sums_def)
389 apply (auto intro!: setsum_mono)
393 "[|\<forall>n. abs(f n) \<le> g n; summable g |]
394 ==> summable f & suminf f \<le> suminf g"
395 apply (auto intro: summable_comparison_test intro!: summable_le)
396 apply (simp add: abs_le_interval_iff)
399 (* specialisation for the common 0 case *)
401 fixes f::"nat\<Rightarrow>real"
402 assumes gt0: "\<forall>n. 0 \<le> f n" and sm: "summable f"
403 shows "0 \<le> suminf f"
405 let ?g = "(\<lambda>n. (0::real))"
406 from gt0 have "\<forall>n. ?g n \<le> f n" by simp
407 moreover have "summable ?g" by (rule summable_zero)
408 moreover from sm have "summable f" .
409 ultimately have "suminf ?g \<le> suminf f" by (rule summable_le)
410 then show "0 \<le> suminf f" by (simp add: suminf_zero)
414 text{*Absolute convergence imples normal convergence*}
415 lemma summable_rabs_cancel: "summable (%n. abs (f n)) ==> summable f"
416 apply (auto simp add: summable_Cauchy)
417 apply (drule spec, auto)
418 apply (rule_tac x = N in exI, auto)
419 apply (drule spec, auto)
420 apply (rule_tac y = "\<Sum>n=m..<n. abs(f n)" in order_le_less_trans)
424 text{*Absolute convergence of series*}
426 "summable (%n. abs (f n)) ==> abs(suminf f) \<le> (\<Sum>n. abs(f n))"
427 by (auto intro: LIMSEQ_le LIMSEQ_imp_rabs summable_rabs_cancel summable_sumr_LIMSEQ_suminf)
430 subsection{* The Ratio Test*}
432 lemma rabs_ratiotest_lemma: "[| c \<le> 0; abs x \<le> c * abs y |] ==> x = (0::real)"
433 apply (drule order_le_imp_less_or_eq, auto)
434 apply (subgoal_tac "0 \<le> c * abs y")
435 apply (simp add: zero_le_mult_iff, arith)
438 lemma le_Suc_ex: "(k::nat) \<le> l ==> (\<exists>n. l = k + n)"
439 apply (drule le_imp_less_or_eq)
440 apply (auto dest: less_imp_Suc_add)
443 lemma le_Suc_ex_iff: "((k::nat) \<le> l) = (\<exists>n. l = k + n)"
444 by (auto simp add: le_Suc_ex)
446 (*All this trouble just to get 0<c *)
447 lemma ratio_test_lemma2:
448 "[| \<forall>n \<ge> N. abs(f(Suc n)) \<le> c*abs(f n) |]
449 ==> 0 < c | summable f"
450 apply (simp (no_asm) add: linorder_not_le [symmetric])
451 apply (simp add: summable_Cauchy)
452 apply (safe, subgoal_tac "\<forall>n. N < n --> f (n) = 0")
455 apply(erule_tac x = "n - 1" in allE)
456 apply (simp add:diff_Suc split:nat.splits)
457 apply (blast intro: rabs_ratiotest_lemma)
458 apply (rule_tac x = "Suc N" in exI, clarify)
459 apply(simp cong:setsum_ivl_cong)
463 "[| c < 1; \<forall>n \<ge> N. abs(f(Suc n)) \<le> c*abs(f n) |]
465 apply (frule ratio_test_lemma2, auto)
466 apply (rule_tac g = "%n. (abs (f N) / (c ^ N))*c ^ n"
467 in summable_comparison_test)
468 apply (rule_tac x = N in exI, safe)
469 apply (drule le_Suc_ex_iff [THEN iffD1])
470 apply (auto simp add: power_add realpow_not_zero)
471 apply (induct_tac "na", auto)
472 apply (rule_tac y = "c*abs (f (N + n))" in order_trans)
473 apply (auto intro: mult_right_mono simp add: summable_def)
474 apply (simp add: mult_ac)
475 apply (rule_tac x = "abs (f N) * (1/ (1 - c)) / (c ^ N)" in exI)
476 apply (rule sums_divide)
477 apply (rule sums_mult)
478 apply (auto intro!: geometric_sums)
482 text{*Differentiation of finite sum*}
484 lemma DERIV_sumr [rule_format (no_asm)]:
485 "(\<forall>r. m \<le> r & r < (m + n) --> DERIV (%x. f r x) x :> (f' r x))
486 --> DERIV (%x. \<Sum>n=m..<n::nat. f n x) x :> (\<Sum>r=m..<n. f' r x)"
488 apply (auto intro: DERIV_add)