Coq による極限の定義
はしがき
この土日は極限の定義を Coq でしていました。ここに記録しておきます。
(2021-11-14)
無限数列による極限の定義
まず実数の無限数列を考えます。すなわち
として実数の無限数列を
と表し、この第 n 項を
と表します。ここで実数の無限数列の極限はつぎのように定義されます。
このとき
が成り立ちます。この記事ではこの命題の証明を目指します。
Coq による定義と証明
さきほど示した
のように = という記号でむすぶには、本来、さきに同値関係を定義せねばなりません。しかしそれはしんどいので、この記事ではひとまず
という命題を示すことを目標とします。
Require Import Coq.Reals.Reals.
Require Import Coq.Lists.Streams.
Open Scope R.
Import Streams.
Definition lim (xs : Stream R) (x : R) :=
forall epsilon : R,
epsilon > 0 ->
exists n0 : N,
forall n : N,
(n > n0)%N ->
let xn := Str_nth (A:=R) (N.to_nat n) xs in
R_dist xn x < epsilon.
Lemma const_stream : forall x : R, forall n : nat, Str_nth n (const x) = x.
Proof.
intros x n. induction n as [ | k H ].
unfold Str_nth, const. simpl. reflexivity.
unfold Str_nth, const. simpl. apply H.
Qed.
Lemma x_minus_x_is_zero : forall x : R, x - x = 0.
Proof.
unfold Rminus. apply Rplus_opp_r.
Qed.
Example ones : lim (const 1) 1.
Proof.
intros epsilon epsilon_is_greater_than_0. unfold Rgt in epsilon_is_greater_than_0.
apply ex_intro with 0%N.
intros n n_is_greater_than_n0.
rewrite (const_stream 1).
rewrite (R_dist_eq 1).
apply epsilon_is_greater_than_0.
Qed.
Lemma x_is_greater_than_0_implies_x_div_2_is_greater_than_0 : forall x : R, x > 0 -> x / 2 > 0.
assert (two_is_INR_2 : 2 = INR 2). auto.
assert (two_is_greater_than_0 : 2 > 0). rewrite two_is_INR_2. apply lt_0_INR. auto.
assert (two_inv_is_greater_than_0 : / 2 > 0). rewrite two_is_INR_2. apply (Rinv_0_lt_compat (INR 2) two_is_greater_than_0).
Proof.
intros x x_is_greater_than_0.
rewrite <- (Rmult_0_l (/ 2)).
unfold Rdiv.
apply (Rmult_gt_compat_r (/ 2) x 0 two_inv_is_greater_than_0 x_is_greater_than_0).
Qed.
Theorem lim_add :
forall xs ys : Stream R,
forall x y : R,
lim xs x ->
lim ys y ->
lim (zipWith (fun xn yn => xn + yn) xs ys) (x + y).
Proof.
intros xs ys x y lim_xs_x lim_ys_y.
intros epsilon epsilon_is_greater_than_0.
assert (epsilon_div_2_is_greater_than_0 : epsilon / 2 > 0).
apply (x_is_greater_than_0_implies_x_div_2_is_greater_than_0 epsilon epsilon_is_greater_than_0).
destruct (lim_xs_x (epsilon / 2) epsilon_div_2_is_greater_than_0) as [ n1 H1 ].
destruct (lim_ys_y (epsilon / 2) epsilon_div_2_is_greater_than_0) as [ n2 H2 ].
apply ex_intro with (N.max n1 n2).
intros n n_is_greater_than_n0.
assert (n1_is_less_than_n : (n1 < n)%N).
apply (N.le_lt_trans n1 (N.max n1 n2) n (N.le_max_l n1 n2) (N.gt_lt n (N.max n1 n2) n_is_greater_than_n0)).
assert (n2_is_less_than_n : (n2 < n)%N).
apply (N.le_lt_trans n2 (N.max n1 n2) n (N.le_max_r n1 n2) (N.gt_lt n (N.max n1 n2) n_is_greater_than_n0)).
assert (abs_xn_minus_x_is_less_than_epsilon_div_2 : R_dist (Str_nth (N.to_nat n) xs) x < epsilon / 2).
apply (H1 n (N.lt_gt n1 n n1_is_less_than_n)).
assert (abs_yn_minus_y_is_less_than_epsilon_div_2 : R_dist (Str_nth (N.to_nat n) ys) y < epsilon / 2).
apply (H2 n (N.lt_gt n2 n n2_is_less_than_n)).
rewrite (Str_nth_zipWith (fun xn yn => xn + yn) (N.to_nat n) xs ys).
rewrite (double_var epsilon).
apply
( let Ax := Str_nth (N.to_nat n) xs in
let Ay := Str_nth (N.to_nat n) ys in
let A := R_dist (Ax + Ay) (x + y) in
let Bx := R_dist Ax x in
let By := R_dist Ay y in
let B := Bx + By in
let Cx := epsilon / 2 in
let Cy := epsilon / 2 in
let C := Cx + Cy in
Rle_lt_trans
A
B
C
(R_dist_plus Ax x Ay y)
(Rplus_lt_compat
Bx Cx By Cy
abs_xn_minus_x_is_less_than_epsilon_div_2
abs_yn_minus_y_is_less_than_epsilon_div_2) ).
Qed.