(* $Id: KeyLemma.v,v 1.33 2000/11/10 11:27:32 freek Exp $ *)

Require Export ZArith.
Require Export Compare.
Require Export CSumsReals.
Require Export NRootIR.

(* Tex_Prose
\section{Key Lemma}
*)

(* Tex_Prose
TO DO: Put next lemma in more appropriate place.
*)
(* Begin_Tex_Verb *)
Lemma maj_upto_eps : (a:nat->IR; n:nat; eps:IR)
        (lt (0) n) -> (Zero [:<] eps)
        -> (EX k | (le (1) k) /\ (le k n) /\
                (i:nat)(le (1) i) -> (le i n) -> (a i)[-]eps [:<] (a k)).
(* End_Tex_Verb *)
Intros.
Induction n.
ElimType False.
Omega.
Elim n.
Exists (1).
Repeat Split; Try Auto with arith.
Intros.
Generalize (le_antisym ?? H1 H2); Intro.
Rewrite <- H3.
Step_less_rht (a (1)) [+] Zero.
Step_less_lft (a (1)) [+] [--]eps.
Apply plus_resp_less_lft.
Step_less_rht [--](Zero::IR).
Apply min_resp_less.
Assumption.

Intros.
Elim H1; Intros.
Cut (a (S (S n0))) [-] eps [:<] (a (S (S n0))).
Intro.
Elim (cotrans_less_unfolded ??? H3 (a x)).
Intro.
Exists x.
Elim H2; Intros.
Elim H6; Intros.
Split.
Assumption.
Split.
Auto with arith.
Intros.
Elim (le_le_S_eq ?? H10); Intro.
Apply H8.
Assumption.
Auto with arith.
Rewrite H11.
Assumption.
Intro.
Exists (S (S n0)).
Repeat Split; Try Auto with arith.
Intros.
Elim (le_le_S_eq ?? H6); Intro.
Apply less_transitive_unfolded with (a x).
Elim H2; Intros.
Elim H9; Intros.
Apply H11.
Assumption.
Auto with arith.
Assumption.
Rewrite H7.
Assumption.
Step_Rat_less_rht (a (S (S n0))) [+] [--]Zero.
Step_less_lft (a (S (S n0))) [+] [--]eps.
Apply plus_resp_less_lft.
Apply min_resp_less.
Assumption.
Qed.

Section Key_Lemma.

(* Tex_Prose
\begin{convention}
Let \verb!a : nat->IR!, \verb!n : nat!, \verb!(lt (0) n)!,
\verb!eps : IR!, \verb!(Zero [:<] eps)!, \verb!(k:nat)(Zero [:<=] (a k))!,
\verb!(a n) [=] One!, \verb!a_0 : IR!, \verb!(eps [:<] a_0)!.
\end{convention}
*)
Variable a : nat->IR.
Variable n : nat.
Hypothesis gt_n_0 : (lt (0) n).
Variable eps : IR.
Hypothesis eps_pos : (Zero [:<] eps).
Hypothesis a_nonneg : (k:nat)(Zero [:<=] (a k)).
Hypothesis a_n_1 : (a n) [=] One.
Variable a_0 : IR.
Hypothesis eps_lt_a_0 : (eps [:<] a_0).

(* Begin_Tex_Verb *)
Lemma a_0_eps_pos : Zero [:<] a_0 [-] eps.
(* End_Tex_Verb *)
Apply shift_zero_less_minus.
Apply eps_lt_a_0.
Qed.

(* Begin_Tex_Verb *)
Lemma a_0_eps_fuzz : a_0 [-] eps [:<] a_0.
(* End_Tex_Verb *)
Apply shift_minus_less.
Apply shift_less_plus'.
Step_less_lft Zero::IR.
Apply eps_pos.
Qed.


(* Begin_Tex_Verb *)
Lemma lem_1a : (minus n (minus n (1))) = (1).
(* End_Tex_Verb *)
Cut (le (1) n).
Omega.
Auto with arith.
Qed.

(* Begin_Tex_Verb *)
Lemma lem_1b : (n,j:nat)(le (minus n (S j)) (minus n j)).
(* End_Tex_Verb *)
Intros.
Omega.
Qed.

(* Begin_Tex_Verb *)
Lemma lem_1c : (n,j:nat)(le (minus n j) n).
(* End_Tex_Verb *)
Intros.
Omega.
Qed.

(* Begin_Tex_Verb *)
Lemma lem_1:
  (EX t | (Zero [:<] t) /\ (EX k | (le (1) k) /\ (le k n) /\
        ((a k)[*]t[^]k [=] a_0[-]eps) /\
        (i:nat)(le (1) i) -> (le i n) -> ((a i)[*]t[^]i [:<] a_0))).
(* End_Tex_Verb *)
Proof.
Cut (j:nat)
let l = (minus n j) in (le (1) l) -> (le l n) ->
  (EX t | (Zero [:<] t) /\ (EX k | (le l k) /\ (le k n) /\
        ((a k)[*]t[^]k [=] a_0[-]eps) /\
        (i:nat)(le l i) -> (le i n) -> ((a i)[*]t[^]i [:<] a_0))).
Intro.
Replace (1) with (minus n (minus n (1))).
Apply H.
Rewrite lem_1a. Auto.
Rewrite lem_1a. Auto with arith.
Rewrite lem_1a. Auto.
Intro. Induction j.
Replace (minus n (0)) with n.
Intros.
Exists (nroot_fun (a_0 [-] eps) n a_0_eps_pos gt_n_0).
Split. Apply nroot_pos.
Exists n.
Split. Auto.
Split. Auto.
Split.
Step One[*](nroot_fun a_0[-]eps n a_0_eps_pos gt_n_0)[^]n.
Step_final (nroot_fun a_0[-]eps n a_0_eps_pos gt_n_0)[^]n.
Intros.
Replace i with n.
Step_less_lft One[*](nroot_fun a_0[-]eps n a_0_eps_pos gt_n_0)[^]n.
Step_less_lft (nroot_fun a_0[-]eps n a_0_eps_pos gt_n_0)[^]n.
Step_less_lft a_0[-]eps.
Apply a_0_eps_fuzz.
Apply le_antisym; Auto.
Auto with arith.
Intros.
Cut (le (1) (minus n j)). Intro.
Cut (le (minus n j) n). Intro.
Elim (Hrecj H1 H2). Intro t'. Intros.
Elim H3. Intros.
Elim H5. Intro k'. Intros.
Elim H6. Intros. Elim H8. Intros. Elim H10. Intros.
Cut (a_0[-]eps [:<] (a (minus n (S j)))[*]t'[^](minus n (S j))) \/
    ((a (minus n (S j)))[*]t'[^](minus n (S j)) [:<] a_0).
Intro.
Elim H13; Intro.
Cut Zero [:<] (a (minus n (S j))). Intro.
Cut (a (minus n (S j))) [#] Zero. Intro.
Cut Zero [:<] (a_0[-]eps)[/](a (minus n (S j)))[//]H16. Intro.
Cut (lt (0) (minus n (S j))). Intro.
Exists (nroot_fun
  ((a_0[-]eps)[/](a (minus n (S j)))[//]H16) (minus n (S j)) H17 H18).
Split. Apply nroot_pos.
Exists (minus n (S j)).
Split. Auto.
Split. Auto.
Split.
Step (a (minus n (S j)))[*]
  ((a_0[-]eps)[/](a (minus n (S j)))[//]H16).
Rational.
Intros.
Cut (lt (minus n (S j)) i) \/ (minus n (S j)) = i. Intro.
Elim H21. Intros.
Apply leEq_less_trans with (a i)[*]t'[^]i.
Apply mult_resp_leEq_lft.
Apply power_resp_leEq.
Apply nroot_pos.
Apply power_cancel_leEq with (minus n (S j)).
Auto with arith.
Apply less_leEq.
Auto.
Step_leEq_lft (a_0[-]eps)[/](a (minus n (S j)))[//]H16.
Apply mult_cancel_leEq with (a (minus n (S j))).
Auto.
Step_leEq_lft a_0[-]eps.
Step_leEq_rht (a (minus n (S j)))[*]t'[^](minus n (S j)).
Apply less_leEq.
Auto.
Apply a_nonneg.
Apply H12.
Replace (minus n j) with (S (minus n (S j))).
Auto with arith.
Rewrite minus_Sn_m.
Auto with arith.
Apply lt_le_S.
Apply lt_O_minus_lt.
Auto with arith.
Auto.
Intros.
Rewrite <- H22.
Step_less_lft (a (minus n (S j)))[*]
  ((a_0[-]eps)[/](a (minus n (S j)))[//]H16).
Step_less_lft a_0[-]eps.
Apply a_0_eps_fuzz.
Apply le_lt_or_eq.
Auto.
Auto with arith.
Apply div_resp_pos.
Auto.
Apply a_0_eps_pos.
Apply Greater_imp_ap.
Auto.
Cut Zero [:<] t'[^](minus n (S j)). Intro.
Cut t'[^](minus n (S j)) [#] Zero. Intro.
Step_less_rht ((a (minus n (S j)))[*]t'[^](minus n (S j)))[/]
  (t'[^](minus n (S j)))[//]H16.
Apply div_resp_pos.
Auto.
Apply less_transitive_unfolded with a_0[-]eps.
Apply a_0_eps_pos.
Auto.
Apply Greater_imp_ap.
Auto.
Apply nexp_resp_pos.
Auto.
Exists t'.
Split.
Auto.
Exists k'.
Split.
Apply le_trans with (minus n j).
Apply lem_1b.
Auto.
Split. Auto.
Split. Auto.
Intros.
Cut (lt (minus n (S j)) i) \/ (minus n (S j)) = i. Intro.
Elim H17; Intros.
Apply H12.
Replace (minus n j) with (S (minus n (S j))).
Auto with arith.
Rewrite minus_Sn_m.
Auto with arith.
Apply lt_le_S.
Apply lt_O_minus_lt.
Auto with arith.
Auto.
Rewrite <- H18.
Auto.
Apply le_lt_or_eq.
Auto.
Apply cotrans_less_unfolded.
Apply a_0_eps_fuzz.
Apply lem_1c.
Apply le_trans with (minus n (S j)).
Auto.
Apply lem_1b.
Qed.


(* Begin_Tex_Verb *)
Definition p3m := [i:nat](One[/]ThreeNZ)[^]i ::IR.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma p3m_pos : (i:nat)(Zero [:<] (p3m i)).
(* End_Tex_Verb *)
Intros.
Unfold p3m.
Apply nexp_resp_pos.
Apply div_resp_pos.
Apply pos_three.
Apply pos_one.
Qed.

(* Begin_Tex_Verb *)
Lemma p3m_S : (i:nat)((p3m (S i)) [=] (p3m i)[/]ThreeNZ).
(* End_Tex_Verb *)
Intros.
Unfold p3m.
Step (One[/]ThreeNZ)[^]i[*](One[/]ThreeNZ)::IR.
Rational.
Qed.

Hints Resolve p3m_S : algebra.

(* Begin_Tex_Verb *)
Lemma p3m_P : (i:nat)((p3m i) [=] (p3m (S i))[*]Three).
(* End_Tex_Verb *)
Intros.
Step_final ((p3m i)[/]ThreeNZ)[*]Three.
Qed.

(* Begin_Tex_Verb *)
Lemma p3m_aux : (i,j:nat)((p3m (S i))[^]j [=] (p3m j)[*](p3m i)[^]j).
(* End_Tex_Verb *)
Intros.
Unfold p3m.
Step_lft (One[/]ThreeNZ )[^](mult (S i) j)::IR.
Replace (mult (S i) j) with (plus j (mult i j)).
Step_final ((One[/]ThreeNZ)[^]j) [*] ((One[/]ThreeNZ) [^] (mult i j))::IR.
Reflexivity.
Qed.

(* Begin_Tex_Verb *)
Lemma p3m_pow : (i,j:nat)((p3m i)[^]j [=] (p3m (mult i j))).
(* End_Tex_Verb *)
Intros.
Unfold p3m.
Algebra.
Qed.

Hints Resolve p3m_aux : algebra.

(* Begin_Tex_Verb *)
Lemma p3m_0 : (p3m (0)) [=] One.
(* End_Tex_Verb *)
Unfold p3m.
Simpl.
Algebra.
Qed.

Hints Resolve p3m_0 : algebra.

(* Begin_Tex_Verb *)
Lemma third_pos : Zero::IR [:<] One[/]ThreeNZ.
(* End_Tex_Verb *)
Apply recip_resp_pos.
Apply pos_three.
Qed.

Hints Resolve third_pos : algebra.

(* Begin_Tex_Verb *)
Lemma third_less_one : One[/]ThreeNZ [:<] One::IR.
(* End_Tex_Verb *)
Step_Rat_less_rht One::IR[/]OneNZ.
Apply recip_resp_less.
Apply pos_one.
Apply one_less_three.
Qed.

Hints Resolve third_less_one : algebra.

(* Begin_Tex_Verb *)
Lemma p3m_mon : (i,j:nat)(lt i j) -> ((p3m j) [:<] (p3m i)).
(* End_Tex_Verb *)
Intros.
Unfold p3m.
Apply small_nexp_resp_lt; Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma p3m_mon' : (i,j:nat)(le i j) -> ((p3m j) [:<=] (p3m i)).
(* End_Tex_Verb *)
Intros.
Unfold p3m.
Apply small_nexp_resp_le; Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma p3m_small : (i:nat)((p3m i) [:<=] One).
(* End_Tex_Verb *)
Intro.
Step_leEq_rht (p3m (0)).
Apply p3m_mon'.
Auto with arith.
Qed.

(* Begin_Tex_Verb *)
Lemma p3m_smaller : (i:nat)(lt (0) i)->((p3m i) [:<] Half).
(* End_Tex_Verb *)
Intros.
Apply leEq_less_trans with (p3m (1)).
Apply p3m_mon'.
Auto with arith.
Unfold p3m.
Step_less_lft (One[/]ThreeNZ)::IR.
Unfold half.
Apply recip_resp_less.
Apply pos_two.
Apply two_less_three.
Qed.

(* Begin_Tex_Verb *)
Definition chfun [k:nat->nat; a,j:nat] : nat->nat := [i:nat]
  Cases (le_gt_dec i j) of
    (left _)  => (k i)
  | (right _) => a
  end.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma chfun_1 :
  (k:nat->nat; a,j:nat)(i:nat)(le i j) -> (k i) = ((chfun k a j) i).
(* End_Tex_Verb *)
Intros.
Unfold chfun.
Elim (le_gt_dec i j).
Auto.
Intros.
Elim (le_not_gt ?? H y).
Qed.

(* Begin_Tex_Verb *)
Lemma chfun_2 :
  (k:nat->nat; j:nat; a:nat)(i:nat)(lt j i) -> a = ((chfun k a j) i).
(* End_Tex_Verb *)
Intros.
Unfold chfun.
Elim (le_gt_dec i j).
Intros.
Elim (le_not_gt ?? y H).
Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma chfun_3 : (k:nat->nat; j:nat; a:nat)
        ((i:nat)(le (1) (k i)) /\ (le (k i) n)) ->
        (le (1) a) -> (le a n) ->
          (i:nat)(le (1) ((chfun k a j) i)) /\ (le ((chfun k a j) i) n).
(* End_Tex_Verb *)
Intros.
Unfold chfun.
Elim (le_gt_dec i j).
Auto.
Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma chfun_4 : (k:nat->nat; j:nat; a:nat)
        ((i:nat)(le (k (S i)) (k i))) ->
        (le a (k j)) ->
          (i:nat)(le ((chfun k a j) (S i)) ((chfun k a j) i)).
(* End_Tex_Verb *)
Intros.
Unfold chfun.
Elim (le_gt_dec i j); Elim (le_gt_dec (S i) j); Intros; Auto.
Cut i=j. Intro.
Rewrite H1.
Auto.
Omega.
Omega.
Qed.


(* Begin_Tex_Verb *)
Definition halfeps := Half[*]eps.
(* End_Tex_Verb *)

(* Begin_Tex_Verb *)
Lemma halfeps_pos : Zero [:<] halfeps.
(* End_Tex_Verb *)
Unfold halfeps.
Apply mult_resp_pos.
Apply pos_half.
Apply eps_pos.
Qed.

(* Begin_Tex_Verb *)
Lemma halfeps_halfeps : (x:IR)((x[-]halfeps)[-]halfeps [=] x[-]eps).
(* End_Tex_Verb *)
Intros.
Unfold halfeps.
Unfold half.
Rational.
Qed.

Hints Resolve halfeps_halfeps : algebra.

(* Begin_Tex_Verb *)
Lemma halfeps_eps : (x,y:IR)(x[-]halfeps [:<] y) -> (x[-]eps [:<] y).
(* End_Tex_Verb *)
Intros.
Step_less_lft (x[-]halfeps)[-]halfeps.
Apply less_transitive_unfolded with x[-]halfeps.
Apply shift_minus_less.
Apply shift_less_plus'.
Step_less_lft Zero::IR.
Apply halfeps_pos.
Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma halfeps_trans :
  (x,y,z:IR)(x[-]halfeps [:<] y) -> (y[-]halfeps [:<] z) -> (x[-]eps [:<] z).
(* End_Tex_Verb *)
Intros.
Step_less_lft (x[-]halfeps)[-]halfeps.
Apply less_transitive_unfolded with y[-]halfeps.
Apply minus_resp_less.
Auto.
Auto.
Qed.


(* Begin_Tex_Verb *)
Lemma Key_1a :
(i,j:nat; a,t:IR)
  a[*](t[*](p3m (S j)))[^]i [=] (p3m i)[*](a[*](t[*](p3m j))[^]i).
(* End_Tex_Verb *)
Intros.
Step a0[*](t[^]i[*](p3m (S j))[^]i).
Step a0[*](t[^]i[*]((p3m i)[*](p3m j)[^]i)).
Step_rht (p3m i)[*](a0[*](t[^]i[*](p3m j)[^]i)).
Rational.
Qed.

Hints Resolve Key_1a : algebra.

(* Begin_Tex_Verb *)
Lemma Key_1b : (k:nat)(le (1) k) -> ((p3m k)[*]eps [:<] halfeps).
(* End_Tex_Verb *)
Intros.
Unfold halfeps.
Apply mult_resp_less.
Apply p3m_smaller.
Auto with arith.
Apply eps_pos.
Qed.

(* Begin_Tex_Verb *)
Lemma Key_1 :
(i,k,j:nat; ai,ak,t:IR)
  (le (1) k) -> (lt k i) -> (Zero [:<=] ai) -> (Zero [:<] t) ->
  (ai[*](t[*](p3m j))[^]i[-]eps [:<] ak[*](t[*](p3m j))[^]k) ->
    (ai[*](t[*](p3m (S j)))[^]i[-]halfeps [:<] ak[*](t[*](p3m (S j)))[^]k).
(* End_Tex_Verb *)
Intros.
Apply less_transitive_unfolded with
  (p3m k)[*](ai[*](t[*](p3m j))[^]i)[-](p3m k)[*]eps.
Apply minus_resp_less_leEq.
Step_leEq_lft (p3m i)[*](ai[*](t[*](p3m j))[^]i).
Apply mult_resp_leEq_rht.
Apply less_leEq.
Apply p3m_mon.
Auto.
Step_leEq_lft ai[*]Zero.
Apply mult_resp_leEq_lft.
Apply less_leEq.
Apply nexp_resp_pos.
Apply mult_resp_pos.
Auto.
Apply p3m_pos.
Auto.
Apply Key_1b.
Auto.
Step_less_lft (p3m k)[*](ai[*](t[*](p3m j))[^]i[-]eps).
Step_less_rht (p3m k)[*](ak[*](t[*](p3m j))[^]k).
Apply mult_resp_less_lft.
Auto.
Apply p3m_pos.
Qed.

(* Begin_Tex_Verb *)
Lemma Key_2 :
(i,k,k',j:nat; ai,ak,ak',t:IR)
  (le (1) k) -> (lt k i) -> (Zero [:<=] ai) -> (Zero [:<] t) ->
  (ak[*](t[*](p3m (S j)))[^]k[-]halfeps [:<] ak'[*](t[*](p3m (S j)))[^]k') ->
  (ai[*](t[*](p3m j))[^]i[-]eps [:<] ak[*](t[*](p3m j))[^]k) ->
        (ai[*](t[*](p3m (S j)))[^]i[-]eps [:<] ak'[*](t[*](p3m (S j)))[^]k').
(* End_Tex_Verb *)
Intros.
Apply halfeps_trans with ak[*](t[*](p3m (S j)))[^]k.
Apply Key_1; Auto.
Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Key :
(EX t | (Zero [:<] t) /\
  (J : nat)
  (EX k : nat -> nat |
        ((i:nat)(le (1) (k i)) /\ (le (k i) n)) /\
        ((i:nat)(le (k (S i)) (k i))) /\
        (let k_0 = (k (0)) in
                (a k_0)[*]t[^]k_0 [=] a_0[-]eps) /\
        ((j:nat)(le j J) ->
          let k_j = (k j) in
          let r = t[*](p3m j) in
                (i:nat)(le (1) i) -> (le i n) ->
                        (a i)[*]r[^]i[-]eps [:<] (a k_j)[*]r[^]k_j))).
(* End_Tex_Verb *)
Proof.
Elim lem_1. Intro t. Intros.
Elim H. Intros.
Elim H1. Intro k_0. Intros.
Elim H2. Intros.
Elim H4. Intros.
Elim H6. Intros.
Exists t.
Split. Auto.
Intro.
Induction J.
Exists [j:nat]k_0.
Split. Auto.
Split. Auto.
Split. Auto.
Intros.
Rewrite <- (le_n_O_eq ? H9).
Replace (p3m (0)) with One::IR.
Step_less_rht (a k_0)[*](t[^]k_0[*]One[^]k_0).
Step_less_rht (a k_0)[*](t[^]k_0[*]One).
Step_less_rht (a k_0)[*]t[^]k_0.
Step_less_rht a_0[-]eps.
Apply minus_resp_less.
Step_less_lft (a i)[*](t[^]i[*]One[^]i).
Step_less_lft (a i)[*](t[^]i[*]One).
Step_less_lft (a i)[*]t[^]i.
Auto.
Auto.
Elim HrecJ. Intro k'. Intros.
Elim H9. Intros. Elim H11. Intros. Elim H13. Intros.
Cut (lt (0) (k' J)). Intro.
Elim (maj_upto_eps [i:nat](a i)[*](t[*](p3m (S J)))[^]i
  (k' J) halfeps H16 halfeps_pos).
Intro k_SJ. Intros.
Elim H17. Intros. Elim H19. Intros.
Exists (chfun k' k_SJ J).
Split. Intros.
Apply chfun_3. Auto. Auto.
Apply le_trans with (k' J).
Auto.
Elim (H10 J). Auto.
Split. Intros.
Apply chfun_4.
Auto.
Auto.
Split.
Replace (chfun k' k_SJ J (0)) with (k' (0)).
Auto.
Apply chfun_1.
Auto with arith.
Intros.
Cut (lt j (S J)) \/ j = (S J). Intro.
Elim H25; Intro.
Replace (chfun k' k_SJ J j) with (k' j).
Apply H15.
Apply lt_n_Sm_le. Auto.
Auto.
Auto.
Apply chfun_1.
Auto with arith.
Replace (chfun k' k_SJ J j) with k_SJ.
Rewrite H26.
Cut (le i (k' J)) \/ (lt (k' J) i). Intro.
Elim H27; Intro.
Apply halfeps_eps.
Apply H21.
Auto.
Auto.
Apply Key_2 with (k' J) (a (k' J)).
Auto.
Auto.
Auto.
Auto.
Auto.
Auto.
Apply le_or_lt.
Apply chfun_2.
Rewrite H26.
Auto.
Apply le_lt_or_eq.
Auto.
Elim (H10 J).
Auto.
Qed.

End Key_Lemma.

Hints Resolve p3m_S p3m_P p3m_pow : algebra.


