-
Notifications
You must be signed in to change notification settings - Fork 0
/
RStirling.v
420 lines (377 loc) · 11.6 KB
/
RStirling.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
(*
(C) Copyright 2010, COQTAIL team
Project Info: http://sourceforge.net/projects/coqtail/
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA.
*)
(** Proof of Stirling equivalence of factorial. *)
Require Import Reals.
Require Import Rsequence_facts.
Require Import Rseries_def.
Require Import Rseries_facts.
Require Import Rseries_usual.
Require Import Rpser.
Require Import Rintegral.
Require Import RTaylor.
Require Import Lia.
Require Import Lra.
Require Import Wallis.
Open Scope R_scope.
(** printing ~ ~ *)
(** Partial result : De Moivre approximation. *)
Section De_Moivre.
(* begin hide *)
Let Un n := (INR n) ^ n * exp (- (INR n)) * sqrt (INR n) / Rseq_fact n.
Let Vn n :=
match n with
| 0 => 0
| _ => ln (Un (S n) / Un n)
end.
Hint Resolve lt_0_INR : stirling.
Hint Resolve sqrt_lt_R0 : stirling.
Hint Resolve exp_pos : stirling.
Hint Resolve lt_O_fact : stirling.
Hint Resolve pow_lt : stirling.
Hint Resolve Rmult_lt_0_compat : stirling.
Hint Resolve Rinv_0_lt_compat : stirling.
Hint Resolve Rgt_not_eq : stirling.
Lemma Vn_O : Vn 0 = 0.
Proof.
unfold Vn; simpl; auto.
Qed.
Lemma Vn_S : forall n, (0 < n)%nat -> Vn n = ln (Un (S n) / Un n).
Proof.
intros n Hn.
unfold Vn.
destruct n; [apply False_ind; lia|].
reflexivity.
Qed.
Lemma ln_pow : forall r n, 0 < r -> ln (r ^ n) = INR n * ln r.
Proof.
intros r n Hr; induction n.
simpl; rewrite ln_1; rewrite Rmult_0_l; auto.
replace (r ^ S n) with (r * r ^ n) by reflexivity.
rewrite ln_mult.
rewrite S_INR; rewrite IHn; field.
assumption.
apply pow_lt; assumption.
Qed.
Lemma ln_sqrt : forall r, 0 < r -> ln (sqrt r) = ln r / 2.
Proof.
intros r Hr.
assert (H : 2 <> 0).
intros Hc; lra.
unfold Rdiv; rewrite Rmult_comm.
apply (Rmult_eq_reg_l 2); [|assumption].
rewrite <- Rmult_assoc.
rewrite Rinv_r; [|assumption].
rewrite Rmult_1_l.
replace 2 with (INR 2) by reflexivity.
rewrite <- ln_pow.
replace (sqrt r ^ 2) with (sqrt r * sqrt r) by field.
rewrite sqrt_def; [reflexivity|lra].
apply sqrt_lt_R0; assumption.
Qed.
Lemma Un_pos : forall n, (0 < n)%nat -> 0 < Un n.
Proof.
intros n Hn; unfold Un.
unfold Rseq_fact.
repeat apply Rmult_lt_0_compat; auto with stirling.
Qed.
Lemma Vn_simpl :
forall n, (0 < n)%nat -> Vn n = (INR n + / 2) * ln (1 + / INR n) - 1.
Proof.
intros n Hn.
rewrite Vn_S; [|assumption]; unfold Un, Rseq_fact, Rdiv.
assert (Hnpos : 0 < INR n).
apply lt_0_INR; assumption.
assert (HSnpos : 0 < INR (S n)).
apply lt_0_INR; constructor; assumption.
replace (1 + / INR n) with ((INR n + 1) * / INR n) by (field; auto with stirling).
rewrite fact_simpl.
repeat rewrite mult_INR.
repeat (rewrite ln_mult || rewrite ln_Rinv); auto 6 with stirling.
repeat rewrite ln_exp; auto with stirling.
repeat rewrite ln_pow; auto with stirling.
repeat rewrite ln_sqrt; auto with stirling.
repeat rewrite S_INR.
field.
lra.
Qed.
Let Tn n :=
match n with
| 0 => 0
| _ => (- 1) ^ (S n) / (INR n)
end.
Let Rn n := (/ INR n + - / 2 * (/ INR n) ^ 2 + / 3 * (/ INR n) ^ 3).
Let Sn n := ln (1 + / INR n) - Rn n.
Let Qn d n := Rseq_inv_poly d n.
Lemma Qn_S : forall d n, (0 < n)%nat -> Qn d n = (/ INR n) ^ d.
Proof.
intros d n H; unfold Qn.
destruct n; [apply False_ind; lia|reflexivity].
Qed.
Lemma ln_taylor_3 : Sn = O(Qn 4).
Proof.
unfold Sn, Rn in *.
eapply Rseq_big_O_asymptotic.
intros; eassumption.
exists 2%nat.
eapply Rseq_big_O_eq_compat.
3: eapply Rpser_big_O_partial_sum with
(Un := Tn) (pr := ln_plus_cv_radius)
(En := fun n => / INR (2 + n)) (N := 3%nat).
intros n ; unfold Rseq_shifts.
rewrite <- ln_plus_taylor_sum.
unfold Tn; apply Rplus_eq_compat_l.
unfold Rseq_pps. unfold Rseq_sum. unfold gt_pser. unfold Rseq_mult.
simpl; destruct n; simpl; field.
destruct n; intros Hc.
lra.
assert (H := pos_INR (S n)); lra.
rewrite Rabs_Rinv.
rewrite <- Rinv_1.
apply Rinv_1_lt_contravar; [apply Rle_refl|].
rewrite Rabs_right; [|apply Rle_ge; apply pos_INR].
replace (2 + n)%nat with (S (S n)) by lia.
repeat rewrite S_INR.
assert (H := pos_INR n); lra.
replace (2 + n)%nat with (S (S n)) by lia.
repeat rewrite S_INR.
intros Hc; assert (H := pos_INR n); lra.
apply Rseq_eq_refl.
lra.
apply Rseq_cv_pos_infty_inv_compat.
apply Rseq_cv_pos_infty_eq_compat with (Un := fun n => 2 + Rseq_poly 1 n).
intros n; replace (2 + n)%nat with (S (S n)) by lia.
do 2 rewrite S_INR; unfold Rseq_poly; ring.
eapply Rseq_cv_finite_plus_pos_infty_r.
apply Rseq_constant_cv.
apply Rseq_poly_cv; auto.
Qed.
Lemma Vn_maj : Vn = O(Qn 2).
Proof.
eapply Rseq_big_O_asymptotic.
intros; eassumption.
exists 1%nat.
eapply Rseq_big_O_eq_compat
with (Un := fun n => (INR (1 + n) + / 2) * Sn (1 + n) + / 12 * Qn 2 (1 + n) + / 6 * Qn 3 (1 + n)).
intros n ; unfold Rseq_shifts.
set (p := (1 + n)%nat).
assert (Hp : INR p <> 0).
unfold p.
replace (1 + n)%nat with (S n) by auto.
auto with real.
rewrite Vn_simpl; [|unfold p; lia].
replace (ln (1 + / INR p)) with (Sn p + Rn p).
repeat (rewrite Qn_S; [|unfold p; lia]).
unfold Rn.
field; assumption.
unfold Sn, Rn; field; assumption.
apply Rseq_eq_refl.
repeat apply Rseq_big_O_plus_compat_l.
eapply Rseq_big_O_eq_compat with (Vn := fun n => INR (1 + n) * Qn 3 (1 + n)) (Un := fun n => (INR (1 + n) + / 2) * Sn (1 + n)).
reflexivity.
intros n; unfold Rseq_shifts ; repeat (rewrite Qn_S; [|lia]).
rewrite <- tech_pow_Rmult.
field; replace (1 + n)%nat with (S n) by auto; auto with real.
apply Rseq_big_O_mult_compat.
exists 2; split; [lra|].
exists 0%nat; intros n Hn.
assert (Hle : 1 <= INR (1 + n)).
replace (1 + n)%nat with (S n) by auto.
rewrite S_INR.
assert (H := pos_INR n); lra.
rewrite Rabs_right; [|lra].
rewrite Rabs_right; [|lra].
lra.
destruct ln_taylor_3 as [K [HK [N HN]]].
exists K; split; [assumption|].
exists (S N); intros n Hn.
eapply Rle_trans.
apply HN; lia.
apply Rmult_le_compat_l; [lra|].
assert (Hle : 1 <= INR (1 + n)).
replace (1 + n)%nat with (S n) by auto.
rewrite S_INR.
assert (H := pos_INR n); lra.
assert (Qn 4 (1 + n) = Qn 1 (1 + n) * Qn 3 (1 + n)) as ->; swap 1 2.
rewrite Rabs_mult.
rewrite <- Rmult_1_l.
apply Rmult_le_compat_r; [apply Rabs_pos|].
rewrite Qn_S; [|lia]; rewrite pow_1.
rewrite Rabs_right; [|left; apply Rinv_0_lt_compat; lra].
apply (Rmult_le_reg_l (INR (1 + n))); [lra|].
rewrite Rinv_r; [|intros Hc; lra].
rewrite Rmult_1_r; assumption.
repeat (rewrite Qn_S; [|lia]).
repeat rewrite <- tech_pow_Rmult.
field; intros Hc; lra.
apply Rseq_big_O_Rmult_compat_l; apply Rseq_big_O_refl.
apply Rseq_big_O_Rmult_compat_l.
exists 1; split; [lra|].
exists 0%nat; intros n _ ; unfold Rseq_shifts.
rewrite Rmult_1_l.
assert (HINR : 0 < INR (1 + n)).
replace (1 + n)%nat with (S n) by lia.
rewrite S_INR; assert (H := pos_INR n); lra.
repeat (rewrite Qn_S; [|lia]).
rewrite Rabs_right; [|apply Rle_ge; apply pow_le; auto with real].
rewrite Rabs_right; [|apply Rle_ge; apply pow_le; auto with real].
repeat rewrite <- tech_pow_Rmult; rewrite pow_O.
repeat apply Rmult_le_compat_l; auto with real.
rewrite Rmult_1_r.
apply (Rmult_le_reg_l (INR (1 + n))); auto.
rewrite Rinv_r; [|auto with stirling].
rewrite Rmult_1_r.
replace (1 + n)%nat with (S n) by auto.
rewrite S_INR.
assert (H := pos_INR n); lra.
Qed.
Lemma Rser_cv_Riemann : {l | Rser_abs_cv (Qn 2) l}.
Proof.
apply Rser_cv_inv_poly; lia.
Qed.
Lemma Rser_cv_Vn : {l | Rser_cv Vn l}.
Proof.
apply Rser_abs_cv_cv.
eapply Rser_big_O_cv; [apply Vn_maj|].
apply Rser_cv_Riemann.
Qed.
Lemma Vn_ser_eq : forall n, sum_f_R0 Vn n = ln (Un (S n)) - ln (Un 1).
Proof.
intros n.
induction n.
unfold Vn; simpl; ring.
simpl sum_f_R0; rewrite IHn.
unfold Rdiv; rewrite ln_mult.
rewrite ln_Rinv; [ring|].
apply Un_pos; lia.
apply Un_pos; lia.
apply Rinv_0_lt_compat; apply Un_pos; lia.
Qed.
Lemma Un_cv : {l | Rseq_cv Un l & 0 < l}.
Proof.
assert (Hcv : {l | Rseq_cv (fun n => ln (Un n)) l}).
destruct Rser_cv_Vn as [l Hl].
exists (l + ln (Un 1)).
eapply Rseq_cv_asymptotic.
intros Xn HX; pattern Xn; apply HX.
exists 1%nat; intros eps Heps.
destruct (Hl eps Heps) as [N HN].
exists N; intros n Hn.
unfold R_dist, Rseq_shifts.
replace (1 + n)%nat with (S n) by lia.
replace (ln (Un (S n)) - (l + (ln (Un 1))))
with (ln (Un (S n)) - ln (Un 1) - l) by ring.
rewrite <- Vn_ser_eq.
apply HN; assumption.
destruct Hcv as [l Hl].
exists (exp l).
eapply Rseq_cv_asymptotic.
intros Xn HX; pattern Xn; apply HX.
exists 1%nat.
eapply Rseq_cv_eq_compat with (fun n => exp (ln (Un (S n)))).
intros n; rewrite exp_ln.
replace (S n) with (1 + n)%nat by lia; reflexivity.
apply Un_pos; lia.
apply Rseq_cv_continuity_compat.
intros eps Heps.
destruct (Hl eps Heps) as [N HN].
exists N; intros n Hn.
apply HN; lia.
apply derivable_continuous_pt.
apply derivable_exp.
apply exp_pos.
Qed.
(* end hide *)
Lemma De_Moivre_equiv : {C | Rseq_fact ~ (fun n => C * (INR n) ^ n * exp (- (INR n)) * sqrt (INR n)) & 0 < C}.
Proof.
destruct Un_cv as [l Hl Hp].
exists (/ l).
apply Rseq_equiv_sym.
apply Rseq_equiv_1.
intros n; apply not_0_INR.
apply fact_neq_0.
apply Rseq_equiv_sym.
intros eps Heps.
destruct (Hl (eps * / 2 * l)) as [N HN].
apply Rmult_lt_0_compat; [lra|assumption].
exists N; intros n Hn.
unfold Rseq_constant, Rseq_minus, Rseq_div.
rewrite (Rabs_right 1); [|lra].
rewrite Rmult_1_r.
rewrite Rabs_minus_sym.
apply Rle_trans with (eps / 2); [left|lra].
apply (Rmult_lt_reg_l l); [assumption|].
pattern l at 1; rewrite <- Rabs_right; [|lra].
rewrite <- Rabs_mult.
rewrite (Rmult_comm l (eps / 2)).
replace (l * (/ l * INR n ^ n * exp (- INR n) * sqrt (INR n) / Rseq_fact n - 1))
with (INR n ^ n * exp (- INR n) * sqrt (INR n) / Rseq_fact n - l).
apply HN; assumption.
field; split.
intro; lra.
apply not_0_INR; apply fact_neq_0.
apply Rinv_0_lt_compat; assumption.
Qed.
End De_Moivre.
(* begin hide *)
Lemma exp_pow x n : (exp x) ^ n = exp (x* (INR n)).
Proof.
induction n.
ring_simplify.
rewrite Rmult_0_r, exp_0; reflexivity.
simpl pow.
replace (S n)%R with (n+1)%nat by lia.
rewrite plus_INR.
replace (INR 1) with R1 by trivial.
ring_simplify (x * (INR n + R1)).
rewrite exp_plus, IHn.
auto with *.
Qed.
(* end hide *)
(** Final result : Stirling approximation. *)
Section Stirling.
Local Coercion INR : nat >-> R.
Lemma Stirling_equiv : Rseq_fact ~ (fun n => sqrt (2 * PI) * (INR n) ^ n * exp (- (INR n)) * sqrt (INR n)).
Proof.
destruct De_Moivre_equiv as [l Hl].
assert(l^2/(2*PI) = 1) as Heq.
eapply Rseq_cv_unique.
apply Wallis_quotient_lim2.
auto with *.
assert (Hrw : (fun n => l * n ^ n * exp (-n) * sqrt n) == (fun n => ((n / exp R1) ^ n * sqrt n * l))).
intro n.
rewrite exp_Ropp.
replace (exp n) with (exp (R1*n)) by auto with *.
rewrite <- (exp_pow R1 n).
unfold Rdiv; rewrite Rpow_mult_distr, Rinv_pow.
field.
assert (H := exp_pos 1); auto with *.
eapply Rseq_equiv_eq_compat.
apply Rseq_eq_refl.
apply Hrw.
trivial.
apply Wallis_quotient_lim1.
replace l with (sqrt(2*PI)) in Hl.
apply Hl.
assert(HPI := PI_RGT_0).
apply sqrt_lem_1.
lra.
auto with *.
replace (l*l) with ((l^2 / (2*PI))* (2*PI)).
rewrite Heq; ring.
unfold Rdiv, Rsqr; field; auto with *.
Qed.
End Stirling.