(* $Id: CPoly_ApZero.v,v 1.6 2000/11/10 11:27:27 freek Exp $ *)

Require Export CReals1.
Require Export CPoly_Degree.


Definition distinct1 :=
  [A:CSetoid; f:nat->A](i,j:nat)(~i=j) -> ((f i) [#] (f j)).

Syntactic Definition Distinct1 := (distinct1 ?).


Section Poly_Representation.

Variable R : CField.
Variable a_ : nat->R.
Hypothesis distinct_a_ : (Distinct1 a_).
Variable f : (cpoly_cring R).
Variable n : nat.
Hypothesis degree_f : (Degree_le n f).

Load Transparent_algebra.
Lemma poly_linear_shifted :
  (a:R)(f:(cpoly_cring R))
    (EX f' | (EX f'' | f [=] (_X_[-](_C_ a))[*]f'[+](_C_ f''))).
Intros.
Induction f0; Intros.
Exists (cpoly_zero R).
Exists Zero::R.
Simpl.
Algebra.
Elim Hrecf0. Intro g'. Intros.
Elim H. Intro g''. Intros.
Exists _X_[*]g'[+](_C_ g'').
Exists a[*]g''[+]s.
Step _X_[*]f0[+](_C_ s).
Step _X_[*]((_X_[-](_C_ a))[*]g'[+](_C_ g''))[+](_C_ s).
Apply eq_symmetric_unfolded.
Cut (_C_ a[*]g''[+]s) [=] (_C_ a)[*](_C_ g'')[+](_C_ s). Intro.
Step (_X_[-](_C_ a))[*](_X_[*]g'[+](_C_ g''))[+]
  ((_C_ a)[*](_C_ g'')[+](_C_ s)).
Rational.
Step_final (_C_ a[*]g'')[+](_C_ s).
Qed.
Load Opaque_algebra.

Lemma poly_linear_factor :
  (f:(cpoly_cring R))(a:R)(f!a [=] Zero) ->
    (EX f' | f [=] (_X_[-](_C_ a))[*]f').
Intros.
Elim (poly_linear_shifted a f0). Intro f'. Intros.
Elim H0. Intro f''. Intros.
Exists f'.
Cut (_C_ f'') [=] Zero. Intro.
Step (_X_[-](_C_ a))[*]f'[+](_C_ f'').
Step_final (_X_[-](_C_ a))[*]f'[+]Zero.
Step_rht (_C_ Zero::R).
Apply cpoly_const_eq.
Step Zero[+]f''.
Step Zero[*]f'!a[+]f''.
Step (a[-]a)[*]f'!a[+]f''.
Step (_X_!a[-](_C_ a)!a)[*]f'!a[+]f''.
Step (_X_[-](_C_ a))!a[*]f'!a[+]f''.
Step ((_X_[-](_C_ a))[*]f')!a[+]f''.
Step ((_X_[-](_C_ a))[*]f')!a[+](_C_ f'')!a.
Step ((_X_[-](_C_ a))[*]f'[+](_C_ f''))!a.
Step_final f0!a.
Qed.

Lemma zero_poly :
  (n:nat)
  (f:(cpoly_cring R))(Degree_le n f) ->
  ((i:nat)(le i n) -> (f!(a_ i) [=] Zero)) ->
    (f [=] Zero).
Intro.
Induction n0; Intros.
Elim (degree_le_zero ?? H). Intros.
Step (_C_ x).
Step_rht (_C_ Zero::R).
Apply cpoly_const_eq.
Apply eq_transitive_unfolded with f0!(a_ (0)).
Step_final (_C_ x)!(a_ (0)).
Apply H0.
Auto.
Cut f0!(a_ (S n0)) [=] Zero. Intro.
Elim (poly_linear_factor f0 (a_ (S n0)) H1). Intro f'. Intros.
Step (_X_[-](_C_ (a_ (S n0))))[*]f'.
Cut f' [=] Zero. Intro.
Step_final (_X_[-](_C_ (a_ (S n0))))[*]Zero.
Apply Hrecn0.
Apply Degree_le_mult_imp with (1) (_X_[-](_C_ (a_ (S n0)))).
Apply Degree_minus_lft with (0).
Apply Degree_le_c_.
Apply Degree_x_.
Auto.
Apply Degree_le_wd with f0.
Auto.
Auto.
Intros.
Apply mult_cancel_lft with ((a_ i)[-](a_ (S n0))).
Apply minus_ap_zero.
Apply distinct_a_.
Omega.
Step_rht Zero::R.
Cut (a_ i)[-](a_ (S n0)) [=] (_X_[-](_C_ (a_ (S n0))))!(a_ i). Intro.
Step (_X_[-](_C_ (a_ (S n0))))!(a_ i)[*]f'!(a_ i).
Step ((_X_[-](_C_ (a_ (S n0))))[*]f')!(a_ i).
Step f0!(a_ i).
Apply H0.
Omega.
Step_final (_X_!(a_ i))[-]((_C_ (a_ (S n0)))!(a_ i)).
Apply H0.
Auto.
Qed.

Lemma identical_poly :
  (f,g:(cpoly_cring R))(Degree_le n f) -> (Degree_le n g) ->
  ((i:nat)(le i n) -> (f!(a_ i) [=] g!(a_ i))) ->
    (f [=] g).
Intros.
Apply cg_inv_unique_2.
Apply zero_poly with n.
Apply Degree_le_minus; Auto.
Intros.
Step f0!(a_ i)[-]g!(a_ i).
Step_final f0!(a_ i)[-]f0!(a_ i).
Qed.

Definition poly_01_factor' := [n:nat](_X_[-](_C_ (a_ n))).

Lemma poly_01_factor'_degree :
  (n:nat)(Degree_le (1) (poly_01_factor' n)).
Intros.
Unfold poly_01_factor'.
Apply Degree_imp_Degree_le.
Apply Degree_minus_lft with (0).
Apply Degree_le_c_.
Apply Degree_x_.
Auto.
Qed.

Lemma poly_01_factor'_zero :
  (n:nat)((poly_01_factor' n)!(a_ n) [=] Zero).
Intros.
Unfold poly_01_factor'.
Step (_X_!(a_ n0))[-]((_C_ (a_ n0))!(a_ n0)).
Step_final (a_ n0)[-](a_ n0).
Qed.

Lemma poly_01_factor'_apzero :
  (n,i:nat)(~i = n) -> ((poly_01_factor' n)!(a_ i) [#] Zero).
Intros.
Unfold poly_01_factor'.
Step_ap_lft (_X_!(a_ i))[-]((_C_ (a_ n0))!(a_ i)).
Step_ap_lft (a_ i)[-](a_ n0).
Qed.

Hints Resolve poly_01_factor'_zero.

Definition poly_01_factor :=
  [n,i:nat; H:(~i = n)]
    (poly_01_factor' n)[*](_C_ One[/]((poly_01_factor' n)!(a_ i))[//]
      (poly_01_factor'_apzero n i H)).

Lemma poly_01_factor_degree :
  (n,i:nat; H:(~i = n))(Degree_le (1) (poly_01_factor n i H)).
Intros.
Unfold poly_01_factor.
Replace (1) with (plus (1) (0)).
Apply Degree_le_mult.
Apply poly_01_factor'_degree.
Apply Degree_le_c_.
Auto.
Qed.

Lemma poly_01_factor_zero :
  (n,i:nat; H:(~i = n))((poly_01_factor n i H)!(a_ n) [=] Zero).
Intros.
Unfold poly_01_factor.
Step ((poly_01_factor' n0)!(a_ n0))[*]
  ((_C_ One[/](poly_01_factor' n0)!(a_ i)[//]
    (poly_01_factor'_apzero n0 i H))!(a_ n0)).
Step_final Zero[*]((_C_ One[/](poly_01_factor' n0)!(a_ i)[//]
  (poly_01_factor'_apzero n0 i H))!(a_ n0)).
Qed.

Lemma poly_01_factor_one :
  (n,i:nat; H:(~i = n))((poly_01_factor n i H)!(a_ i) [=] One).
Intros.
Unfold poly_01_factor.
Step ((poly_01_factor' n0)!(a_ i))[*]
  ((_C_ One[/](poly_01_factor' n0)!(a_ i)[//]
    (poly_01_factor'_apzero n0 i H))!(a_ i)).
Step ((poly_01_factor' n0)!(a_ i))[*]
  (One[/](poly_01_factor' n0)!(a_ i)[//](poly_01_factor'_apzero n0 i H)).
Rational.
Qed.

Hints Resolve poly_01_factor_zero poly_01_factor_one : algebra.

Fixpoint poly_01 [i,n:nat] : (cpoly_cring R) :=
    Cases (eq_nat_dec i n) of
      (left _) => One
    | (right ne) => (poly_01_factor n i ne)
    end
  [*]
    Cases n of
      O => One
    | (S m) => (poly_01 i m)
    end.

Lemma poly_01_degree' :
  (n,i:nat)(Degree_le (S n) (poly_01 i n)).
Intros.
Induction n0. Intros.
Simpl.
Elim (eq_nat_dec i (0)); Intros.
Apply Degree_le_wd with (_C_ One::R).
Step_final One::(cpoly_cring R).
Apply degree_le_mon with (0).
Auto with arith.
Apply Degree_le_c_.
Apply Degree_le_wd with (poly_01_factor (0) i y).
Algebra.
Apply poly_01_factor_degree.
Simpl.
Elim (eq_nat_dec i (S n0)); Intro.
Apply degree_le_mon with (S n0).
Auto.
Apply Degree_le_wd with (poly_01 i n0).
Algebra.
Auto.
Replace (S (S n0)) with (plus (1) (S n0)).
Apply Degree_le_mult.
Apply poly_01_factor_degree.
Auto.
Auto.
Qed.

Lemma poly_01_degree :
  (n,i:nat)(le i n) -> (Degree_le n (poly_01 i n)).
Intros.
Induction n0; Intros.
Simpl.
Elim (eq_nat_dec i (0)); Intros.
Apply Degree_le_wd with (_C_ One::R).
Step_final One::(cpoly_cring R).
Apply Degree_le_c_.
Cut i=(0). Intro.
Elim (y H0).
Omega.
Simpl.
Elim (eq_nat_dec i (S n0)); Intro.
Apply Degree_le_wd with (poly_01 i n0).
Algebra.
Apply poly_01_degree'.
Pattern 1 (S n0).
Replace (S n0) with (plus (1) n0).
Apply Degree_le_mult.
Apply poly_01_factor_degree.
Apply Hrecn0.
Omega.
Auto.
Qed.

Lemma poly_01_zero :
  (n,i,j:nat)(le j n) -> (~j = i) -> ((poly_01 i n)!(a_ j) [=] Zero).
Intros.
Induction n0; Intros.
Rewrite <- (le_n_O_eq j H).
Rewrite <- (le_n_O_eq j H) in H0.
Simpl.
Elim (eq_nat_dec i (0)); Intros.
Rewrite y in H0.
Elim (H0 (refl_equal ? (0))).
Step ((poly_01_factor (0) i y)!(a_ (0)))[*](One!(a_ (0))).
Step ((poly_01_factor (0) i y)!(a_ (0)))[*]One.
Step ((poly_01_factor (0) i y)!(a_ (0))).
Apply poly_01_factor_zero.
Elim (eq_nat_dec j (S n0)); Intros.
Simpl.
Rewrite <- y.
Elim (eq_nat_dec i j); Intros.
Rewrite y0 in H0.
Elim (H0 (refl_equal ? j)).
Step ((poly_01_factor j i y0)!(a_ j))[*]((poly_01 i n0)!(a_ j)).
Step_final Zero[*]((poly_01 i n0)!(a_ j)).
Cut (le j n0). Intro.
Simpl.
Elim (eq_nat_dec i (S n0)); Intros.
Step (One!(a_ j))[*]((poly_01 i n0)!(a_ j)).
Step_final (One!(a_ j))[*]Zero.
Step ((poly_01_factor (S n0) i y0)!(a_ j))[*]((poly_01 i n0)!(a_ j)).
Step_final ((poly_01_factor (S n0) i y0)!(a_ j))[*]Zero.
Omega.
Qed.

Lemma poly_01_one :
  (n,i:nat)(poly_01 i n)!(a_ i) [=] One.
Intros.
Induction n0; Intros.
Simpl.
Elim (eq_nat_dec i (0)); Intros.
Step (One!(a_ i))[*](One!(a_ i)).
Step_final One[*]One::R.
Step ((poly_01_factor (0) i y)!(a_ i))[*](One!(a_ i)).
Step ((poly_01_factor (0) i y)!(a_ i))[*]One.
Step (poly_01_factor (0) i y)!(a_ i).
Apply poly_01_factor_one.
Simpl.
Elim (eq_nat_dec i (S n0)); Intros.
Step (One!(a_ i))[*]((poly_01 i n0)!(a_ i)).
Step One[*]((poly_01 i n0)!(a_ i)).
Step_final One[*]One::R.
Step ((poly_01_factor (S n0) i y)!(a_ i))[*]((poly_01 i n0)!(a_ i)).
Step ((poly_01_factor (S n0) i y)!(a_ i))[*]One.
Step (poly_01_factor (S n0) i y)!(a_ i).
Apply poly_01_factor_one.
Qed.

Hints Resolve poly_01_zero poly_01_one : algebra.

Lemma poly_representation'' :
  (a:nat->R)(i:nat)(le i n) ->
  ((j:nat)(~j = i) -> (a j) [=] Zero) ->
    (Sum (0) n a) [=] (a i).
Intro. Intro.
Elim i.
Intros.
Step (a (0))[+](Sum (1) n a).
Step_rht (a (0))[+]Zero.
Apply bin_op_wd_unfolded.
Algebra.
Apply sum_zero.
Auto with arith.
Intros.
Apply H0.
Omega.
Intro i'.
Intros.
Step (Sum (0) i' a)[+](Sum (S i') n a).
Step_rht Zero[+](a (S i')).
Apply bin_op_wd_unfolded.
Apply sum_zero.
Auto with arith.
Intros.
Apply H1.
Omega.
Step (a (S i'))[+](Sum (S (S i')) n a).
Step_rht (a (S i'))[+]Zero.
Apply bin_op_wd_unfolded.
Algebra.
Apply sum_zero.
Omega.
Intros.
Apply H1.
Omega.
Qed.

Lemma poly_representation' :
  (f_:nat->(cpoly_cring R))(k:nat)(le k n) ->
    (Sum (0) n [i:nat]((f_ i)[*](poly_01 i n)))!(a_ k) [=] (f_ k)!(a_ k).
Intros.
Apply eq_transitive_unfolded with
  (Sum (0) n [i:nat]((f_ i)[*](poly_01 i n))!(a_ k)).
Apply sum_cpoly_ap with f := [i:nat](f_ i)[*](poly_01 i n).
Step (Sum (0) n [i:nat](f_ i)!(a_ k)[*](poly_01 i n)!(a_ k)).
Step_rht (f_ k)!(a_ k)[*]One.
Step_rht (f_ k)!(a_ k)[*](poly_01 k n)!(a_ k).
Apply poly_representation'' with
  a := [i:nat](f_ i)!(a_ k)[*](poly_01 i n)!(a_ k).
Auto.
Intros.
Step_final (f_ j)!(a_ k)[*]Zero.
Qed.

Lemma poly_representation :
  f [=] (Sum (0) n [i:nat](_C_ f!(a_ i))[*](poly_01 i n)).
Apply identical_poly.
Auto.
Apply sum_degree_le. Auto with arith. Intros.
Replace n with (plus (0) n).
Apply Degree_le_mult.
Apply Degree_le_c_.
Apply poly_01_degree.
Auto.
Auto with arith.
Intros.
Apply eq_symmetric_unfolded.
Step_rht (_C_ f!(a_ i))!(a_ i).
Apply poly_representation' with f_ := [i:nat](_C_ f!(a_ i)).
Auto.
Qed.

Hints Resolve poly_representation : algebra.

Lemma poly_choose_apzero :
  (f [#] Zero) -> (EX i | (le i n) /\ (f!(a_ i) [#] Zero)).
Intros.
Cut (Sum (0) n [i:nat](_C_ f!(a_ i))[*](poly_01 i n)) [#] Zero. Intros.
Elim (sum_apzero ? [i:nat](_C_ f!(a_ i))[*](poly_01 i n) (0) n (le_O_n n) H0).
Intro i. Intros.
Elim H1. Intros. Elim H3. Intros.
Exists i.
Split.
Auto.
Apply poly_c_apzero.
Apply cring_mult_ap_zero with (poly_01 i n).
Auto.
Step_ap_lft f.
Qed.

End Poly_Representation.


Section Poly_ApZero_Interval.

Variable R: COrdField.

Lemma poly_apzero_interval :
  (f:(cpoly_cring R))(f [#] Zero) ->
  (a,b:R)(a [:<] b) ->
    (EX c | (a [:<] c) /\ (c [:<] b) /\ (f!c [#] Zero)).
Intros.
Elim (poly_ex_degree ? f). Intro n. Intros.
Cut Zero [:<] (Nring (plus n (2)))::R. Intros.
Cut (Nring (plus n (2))) [#] Zero::R. Intros.
Cut (Distinct1
  [i:nat](((Nring (plus i (1)))[*]a[+]
    ((Nring (plus n (2)))[-](Nring (plus i (1))))[*]b)[/]
    (Nring (plus n (2)))[//]H3)).
Intro.
Elim (poly_choose_apzero ?
  [i:nat](((Nring (plus i (1)))[*]a[+]
    ((Nring (plus n (2)))[-](Nring (plus i (1))))[*]b)[/]
    (Nring (plus n (2)))[//]H3)
  H4 f n H1 H).
Intro i. Intros.
Elim H5. Intros.
Exists (((Nring (plus i (1)))[*]a[+]
  ((Nring (plus n (2)))[-](Nring (plus i (1))))[*]b)[/]
    (Nring (plus n (2)))[//]H3).
Split.
Apply shift_less_div.
Auto.
Apply less_wdl with (Nring (plus i (1)))[*]a[+]
  ((Nring (plus n (2)))[-](Nring (plus i (1))))[*]a.
Apply plus_resp_less_lft.
Apply mult_resp_less_lft.
Auto.
Apply shift_zero_less_minus.
Apply nring_less.
Omega.
Rational.
Split.
Apply shift_div_less.
Auto.
Apply less_wdr with (Nring (plus i (1)))[*]b[+]
  ((Nring (plus n (2)))[-](Nring (plus i (1))))[*]b.
Apply plus_resp_less_rht.
Apply mult_resp_less_lft.
Auto.
Step_less_lft (Nring (0))::R.
Apply nring_less.
Omega.
Rational.
Auto.
Unfold distinct1.
Intros.
Apply zero_minus_apart.
Step_Rat_ap_lft (((Nring (plus i (1)))[-](Nring (plus j (1))))[*](a[-]b))[/]
  (Nring (plus n (2)))[//]H3.
Apply div_resp_ap_zero_rev.
Apply mult_resp_ap_zero.
Apply minus_ap_zero.
Apply nring_apart.
Omega.
Apply minus_ap_zero.
Apply less_imp_ap.
Auto.
Apply ap_symmetric_unfolded.
Apply less_imp_ap.
Auto.
Step_less_lft (Nring (0))::R.
Apply nring_less.
Omega.
Qed.

End Poly_ApZero_Interval.


