Skip to content

Instantly share code, notes, and snippets.

@mukeshtiwari
Created October 29, 2023 13:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mukeshtiwari/a35f9615472cc6130105c5df7dcca0e5 to your computer and use it in GitHub Desktop.
Save mukeshtiwari/a35f9615472cc6130105c5df7dcca0e5 to your computer and use it in GitHub Desktop.
Require Import Field_theory
Ring_theory List NArith
Ring Field Utf8 Lia Coq.Arith.PeanoNat.
Import ListNotations.
Section Computation.
Variable
(R : Type)
(rO rI:R)
(radd rmul rsub : R -> R -> R)
(ropp : R -> R)
(rdiv : R -> R -> R)
(rinv : R -> R).
Variable RRing :
ring_theory rO rI radd rmul rsub ropp eq.
Variable Rfield :
field_theory rO rI radd rmul rsub ropp rdiv rinv eq.
Add Field cField : Rfield.
Add Ring cRing : RRing.
(* power theory *)
Variable Cpow : Type.
Variable Cp_phi : N -> Cpow.
Variable rpow : R -> Cpow -> R.
Variable pow_th : power_theory rI rmul eq Cp_phi rpow.
(* Field notations *)
Local Notation "0" := rO : R_scope.
Local Notation "1" := rI : R_scope.
Local Infix "+" := radd : R_scope.
Local Infix "-" := rsub : R_scope.
Local Infix "*" := rmul : R_scope.
Local Infix "/" := rdiv : R_scope.
Notation "- x" := (ropp x) : R_scope.
Notation "/ x" := (rinv x) : R_scope.
Local Open Scope R_scope.
(* closed form of polynomial *)
Fixpoint mul_closed_poly (l : list R) (x : R) : R :=
match l with
| [] => 1
| h :: t => (h - x) * mul_closed_poly t x
end.
(* generate k combinations of list l *)
Fixpoint gen_comb (l : list R) (k : nat) : list (list R) :=
match k with
| O => [[]]
| S k' => match l with
| [] => []
| h :: t => List.map (fun u => h :: u) (gen_comb t k') ++
gen_comb t k
end
end.
Definition add_rlist (l : list R) :=
List.fold_left (λ a b, a + b) l 0.
Definition mul_rlist (l : list R) :=
List.fold_left (λ a b, a * b) l 1.
Fixpoint compute_poly_simp (l : list R)
(x : R) (k : nat) : R :=
match k with
| O => pow_N 1 rmul (-x) (N.of_nat (List.length l))
| S k' => (pow_N 1 rmul (-x) (N.of_nat (Nat.sub (List.length l) k))) *
(add_rlist (List.map mul_rlist (gen_comb l k))) +
compute_poly_simp l x k'
end.
Variable u x₁ x₂ x₃ x₄ : R.
Eval compute in mul_closed_poly [x₁; x₂] u.
Fixpoint take {A : Type} (n : nat) (l : list A) : list A :=
match n with
| O => []
| S n' => match l with
| [] => []
| h :: t => h :: (take n' t)
end
end.
Fixpoint drop {A : Type} (n : nat) (l : list A) : list A :=
match n with
| O => l
| S n' => match l with
| [] => []
| h :: t => drop n' t
end
end.
Fixpoint zip_with {A B C : Type} (f : A -> B -> C) (l₁ : list A)
(l₂ : list B) : list C :=
match l₁, l₂ with
| h₁ :: t₁, h₂ :: t₂ => (f h₁ h₂) :: (zip_with f t₁ t₂)
| _, _ => []
end.
Lemma take_nt :
forall n (t : list R),
n ≤ length t ->
n ≤ length (take n t).
Proof.
induction n.
+ intros ? Hn.
simpl.
nia.
+ intros ? Hn.
simpl.
destruct t.
- (* impossible *)
simpl in Hn.
nia.
- (* inductive case *)
simpl in Hn.
simpl.
apply Le.le_n_S.
eapply IHn;
try nia.
Qed.
(* Not in Coq library! *)
(* If two lists have the same length and they pointwise equal,
then they are same list*)
Lemma nth_ext_error {A : Type} :
forall (l l' : list A),
length l = length l' ->
(forall n, n < length l -> nth_error l n = nth_error l' n) -> l = l'.
Proof.
induction l.
+ destruct l'.
simpl;
intros Hl Hn.
reflexivity.
simpl;
intros Hl Hn.
nia.
+ destruct l'.
simpl;
intros Hl Hn.
nia.
simpl;
intros Hl Hn.
assert (Ht : O < S (length l)) by
nia.
pose proof (Hn O Ht) as Hp.
simpl in Hp.
f_equal.
inversion Hp.
reflexivity.
apply IHl.
nia.
intros ? Hnn.
assert (Hv : S n < S (length l)) by
nia.
pose proof (Hn _ Hv).
simpl in H.
exact H.
Qed.
Lemma take_drop_inv {A : Type} :
forall (n : nat) (l : list A),
(take n l ++ drop n l = l).
Proof.
induction n.
- simpl; intros ?; reflexivity.
- simpl; intros ?.
destruct l.
+ reflexivity.
+ simpl. rewrite IHn.
reflexivity.
Qed.
Lemma take_all :
forall l : list R, (take (length l) l) = l.
Proof.
induction l.
simpl; reflexivity.
simpl; rewrite IHl;
reflexivity.
Qed.
Lemma drop_all :
forall l : list R, (drop (length l) l) = [].
Proof.
induction l.
simpl; reflexivity.
simpl; rewrite IHl;
reflexivity.
Qed.
Fixpoint list_upto (n : nat) : list nat :=
match n with
| O => [O]
| S n' => n :: list_upto n'
end.
Lemma test_inv :
let l := [x₁; x₂; x₃; x₄] in
let n := 2%nat in
compute_poly_simp (take n l) u n *
mul_closed_poly (drop n l) u = mul_closed_poly l u.
Proof.
compute.
ring_simplify.
ring.
Qed.
Lemma test_inv_2 :
let t := [x₂; x₃; x₄] in
let n := 2%nat in
let h := x₁ in
let y := u in
compute_poly_simp (take (S n) (h :: t)) y (S n) =
compute_poly_simp (take n t) y n * (h - y).
Proof.
simpl.
ring_simplify.
unfold add_rlist, mul_rlist.
simpl.
ring_simplify.
ring.
Qed.
Definition populate_poly_terms (l : list R)
(x : R) (k : nat) : list (nat * nat * R * R) :=
List.map (fun w =>
(Nat.sub (List.length l) w, w,
pow_N 1 rmul (-x) (N.of_nat (Nat.sub (List.length l) w)),
add_rlist (List.map mul_rlist (gen_comb l w))))
(list_upto k).
Definition eval_populate_poly (l : list R)
(x : R) (k : nat) : R :=
List.fold_left (fun a '(_, _, u, v) => a + u * v)
(populate_poly_terms l x k) 0.
Fact tmp_3 : eval_populate_poly [x₂; x₃] u 2 =
compute_poly_simp [x₂; x₃] u 2.
Proof.
simpl.
unfold eval_populate_poly.
simpl.
unfold add_rlist,
mul_rlist.
simpl.
ring_simplify.
ring.
Qed.
Lemma populate_poly_term_rewrite :
forall h t x n,
populate_poly_terms (h :: t) x (S n) =
[(Nat.sub (List.length (h :: t)) (S n), S n,
pow_N 1 rmul (-x) (N.of_nat (Nat.sub (List.length (h :: t)) (S n))),
add_rlist (List.map mul_rlist (gen_comb (h :: t) (S n))))] ++
(populate_poly_terms (h :: t) x n).
Proof.
intros *.
simpl; reflexivity.
Qed.
Lemma fold_left_acc :
forall (l : list (nat * nat * R * R)) (a : R),
fold_left (fun a '(_, _, u, v) => a + u * v) l a =
a + fold_left (fun a '(_, _, u, v) => a + u * v) l 0.
Proof.
induction l.
+ intros ?.
simpl;
ring.
+ intros ?;
simpl.
rewrite IHl.
destruct a as [[[an bn] cn] dn].
rewrite <-Radd_assoc.
f_equal.
rewrite <-IHl.
assert (Ha : 0 + cn * dn = cn * dn).
ring.
rewrite Ha.
reflexivity.
exact RRing.
Qed.
Lemma populate_poly_term_compute_poly :
forall n l x,
n <= List.length l ->
eval_populate_poly l x n = compute_poly_simp l x n.
Proof.
induction n.
+ intros ? ? Hl.
simpl.
unfold eval_populate_poly.
simpl.
ring_simplify.
assert (Ht: (gen_comb l 0) = [[]]).
unfold gen_comb.
(* weird! not simplifying *)
destruct l.
reflexivity.
reflexivity.
rewrite Ht;
clear Ht.
simpl.
unfold add_rlist,
mul_rlist.
simpl.
ring_simplify.
assert (Ht: ((length l - 0) = length l)%nat).
nia.
rewrite Ht; clear Ht.
reflexivity.
+ intros ? ? Hl.
destruct l as [|h t].
simpl in Hl;
nia.
simpl in Hl.
simpl.
assert (Hnt : n <= List.length (h :: t)).
simpl; nia.
specialize (IHn _ x Hnt).
rewrite <-IHn.
unfold eval_populate_poly.
rewrite populate_poly_term_rewrite.
rewrite List.fold_left_app.
simpl.
remember ((
pow_N 1 rmul (- x) (N.of_nat (length t - n)) *
add_rlist (map mul_rlist (map (λ u0 : list R, h :: u0)
(gen_comb t n) ++ gen_comb t (S n))))) as a.
ring_simplify.
remember ((populate_poly_terms (h :: t) x n)) as pl.
rewrite fold_left_acc.
ring.
Qed.
Definition mul_polyterm_populate_terms (l : list R)
(x : R) (k : nat) (y : R) : list (nat * nat * R * R) :=
List.map (fun '(a, b, u, t) => (a, S b, u, y * t))
(populate_poly_terms l x k).
Lemma fold_nested_map_first :
forall (l : list (nat * nat * R * R)) (y : R),
List.fold_left (fun a '(_, _, u, v) => a + u * v)
(List.map (fun '(a, b, u, t) => (a, S b, u, y * t)) l) 0 =
y * List.fold_left (fun a '(_, _, u, v) => a + u * v) l 0.
Proof.
induction l as [|(((au, bu), cu), du) l].
+ intros ?;
simpl;
ring.
+ intros ?.
simpl.
rewrite fold_left_acc.
rewrite IHl.
remember (fold_left
(λ (a : R) '(y0, v), let '(y1, u0) := y0 in let '(_, _) := y1 in a + u0 * v)
l 0) as fl.
rewrite fold_left_acc;
subst.
ring.
Qed.
Lemma connect_mul_polyterm_with_poly_term :
forall l x k y,
List.fold_left (fun a '(_, _, u, v) => a + u * v)
(mul_polyterm_populate_terms l x k y) 0 =
y * List.fold_left (fun a '(_, _, u, v) => a + u * v)
(populate_poly_terms l x k) 0.
Proof.
intros *.
unfold mul_polyterm_populate_terms.
eapply fold_nested_map_first.
Qed.
Lemma connect_mul_polyterm_with_evalpoly :
forall l x k y,
List.fold_left (fun a '(_, _, u, v) => a + u * v)
(mul_polyterm_populate_terms l x k y) 0 =
y * eval_populate_poly l x k.
Proof.
intros *.
unfold eval_populate_poly.
unfold mul_polyterm_populate_terms.
eapply fold_nested_map_first.
Qed.
(* multiply every term *)
Definition mul_polypow_populate_terms (l : list R)
(x : R) (k : nat) (y : R) : list (nat * nat * R * R) :=
List.map (fun '(a, b, u, t) => (S a, b, y * u, t))
(populate_poly_terms l x k).
Lemma fold_nested_map_second :
forall (l : list (nat * nat * R * R)) (y : R),
List.fold_left (fun a '(_, _, u, v) => a + u * v)
(List.map (fun '(a, b, u, t) => (S a, b, y * u, t)) l) 0 =
y * List.fold_left (fun a '(_, _, u, v) => a + u * v) l 0.
Proof.
induction l as [|(((au, bu), cu), du) l].
+ intros ?;
simpl;
ring.
+ intros ?.
simpl.
rewrite fold_left_acc.
rewrite IHl.
remember (fold_left
(λ (a : R) '(y0, v), let '(y1, u0) := y0 in let '(_, _) := y1 in a + u0 * v)
l 0) as fl.
rewrite fold_left_acc;
subst.
ring.
Qed.
Lemma connect_mul_polypow_with_poly_term:
forall l x k y,
List.fold_left (fun a '(_, _, u, v) => a + u * v)
(mul_polypow_populate_terms l x k y) 0 =
y * List.fold_left (fun a '(_, _, u, v) => a + u * v)
(populate_poly_terms l x k) 0.
Proof.
intros *.
unfold mul_polypow_populate_terms.
eapply fold_nested_map_second.
Qed.
Lemma connect_mul_polypow_with_evalpoly :
forall l x k y,
List.fold_left (fun a '(_, _, u, v) => a + u * v)
(mul_polypow_populate_terms l x k y) 0 =
y * eval_populate_poly l x k.
Proof.
intros *.
unfold mul_polyterm_populate_terms.
eapply fold_nested_map_second.
Qed.
(*
compute_poly_simp u y n * (h - y) = compute_poly_simp (h :: u) y (S n)
*)
Eval compute in populate_poly_terms [x₂; x₃] u 2.
(*
[(0, 2, 1, 0 + 1 * x₂ * x₃);
(1, 1, - u, 0 + 1 * x₂ + 1 * x₃);
(2, 0, - u * - u, 0 + 1)]
*)
Eval compute in mul_polyterm_populate_terms [x₂; x₃] u 2 x₁.
(*
[(0, 3, 1, x₁ * (0 + 1 * x₂ * x₃));
(1, 2, - u, x₁ * (0 + 1 * x₂ + 1 * x₃));
(2, 1, - u * - u, x₁ * (0 + 1))]
*)
(* align the two polynomials *)
Definition append_mul_polyterm_populate_terms (l : list R)
(x : R) (n : nat) (y : R) :=
mul_polyterm_populate_terms l x n y ++
[(S n, O, pow_N 1 rmul (-x) (N.of_nat (S n)), 0)].
Eval compute in append_mul_polyterm_populate_terms [x₂; x₃] u 2 x₁.
(*
[(0, 3, 1, x₁ * (0 + 1 * x₂ * x₃));
(1, 2, - u, x₁ * (0 + 1 * x₂ + 1 * x₃));
(2, 1, - u * - u, x₁ * (0 + 1));
(3, 0, - u * (- u * - u), 0)] (* This one is newly added term *)
*)
Eval compute in mul_polypow_populate_terms [x₂; x₃] u 2 (-u).
(*
[(1, 2, - u * 1, 0 + 1 * x₂ * x₃);
(2, 1, - u * - u, 0 + 1 * x₂ + 1 * x₃);
(3, 0, - u * (- u * - u), 0 + 1)]
*)
Definition append_mul_polypow_populate_terms (l : list R)
(x : R) (n : nat) (y : R) :=
[(O, S n, 1, 0)] ++
mul_polypow_populate_terms l x n y.
Eval compute in append_mul_polypow_populate_terms [x₂; x₃] u 2 (-u).
(*
[(0, 3, 1, 0);
(1, 2, - u * 1, 0 + 1 * x₂ * x₃);
(2, 1, - u * - u, 0 + 1 * x₂ + 1 * x₃);
(3, 0, - u * (- u * - u), 0 + 1)]
*)
(* If I add the polynomials
(i) append_mul_polyterm_populate_terms [x₂; x₃] x 2 x₁ and
(ii) append_mul_polypow_populate_terms [x₂; x₃] x 2 (-x),
then I will get (iii) populate_poly_terms [x₁; x₂; x₃] x 3.
*)
Definition add_polynomials (l : list R)
(x : R) (n : nat) (y : R) :=
zip_with
(fun '(a, b, u, v) '(_, _, _, w) => (a, b, u, v + w))
(append_mul_polyterm_populate_terms l x n y)
(append_mul_polypow_populate_terms l x n (-x)).
Eval compute in add_polynomials [x₂; x₃] u 2 x₁.
(*
[(0, 3, 1, x₁ * (0 + 1 * x₂ * x₃) + 0);
(1, 2, - u, x₁ * (0 + 1 * x₂ + 1 * x₃) + (0 + 1 * x₂ * x₃));
(2, 1, - u * - u, x₁ * (0 + 1) + (0 + 1 * x₂ + 1 * x₃));
(3, 0, - u * (- u * - u), 0 + (0 + 1))]
*)
Eval compute in populate_poly_terms [x₁; x₂; x₃] u 3.
(*
[(0, 3, 1, 0 + 1 * x₁ * x₂ * x₃);
(1, 2, - u, 0 + 1 * x₁ * x₂ + 1 * x₁ * x₃ + 1 * x₂ * x₃);
(2, 1, - u * - u, 0 + 1 * x₁ + 1 * x₂ + 1 * x₃);
(3, 0, - u * (- u * - u), 0 + 1)]
*)
(*
In order to show to that
add_polynomials l x n y is equal to
populate_poly_terms (y :: l) x (S n),
I need to show that:
(i) their lenghts are equal, and
(ii) they are pointwise equal.
nth_ext_error {A : Type} :
forall (l l' : list A),
length l = length l' ->
(forall n, n < length l ->
nth_error l n = nth_error l' n) -> l = l'.
*)
Lemma list_upto_length : forall n : nat,
List.length (list_upto n) = S n.
Proof.
induction n.
- simpl; reflexivity.
- simpl; rewrite IHn;
reflexivity.
Qed.
Lemma populate_poly_terms_length :
forall n l y,
List.length (populate_poly_terms l y n) = S n.
Proof.
intros ? ? ?.
unfold populate_poly_terms.
rewrite map_length.
apply list_upto_length.
Qed.
Lemma zip_length_min : forall {X Y Z : Type}
(f : X -> Y -> Z) l l',
length (zip_with f l l') = min (length l) (length l').
Proof.
induction l;
destruct l';
simpl; eauto.
Qed.
Lemma zip_length : forall {X Y Z : Type} (f : X -> Y -> Z)
l l', length l = length l' -> length (zip_with f l l') = length l.
Proof.
intros * H.
rewrite zip_length_min.
rewrite H.
rewrite Min.min_idempotent.
eauto.
Qed.
Lemma add_polynomials_length :
forall n l x y,
List.length
(add_polynomials l x n y) = S (S n).
Proof.
intros ? ? ? ?.
unfold add_polynomials.
rewrite zip_length.
unfold append_mul_polyterm_populate_terms.
unfold mul_polyterm_populate_terms,
populate_poly_terms.
rewrite map_map.
rewrite app_length.
rewrite map_length.
simpl.
rewrite list_upto_length.
nia.
unfold append_mul_polypow_populate_terms,
append_mul_polyterm_populate_terms,
mul_polypow_populate_terms,
mul_polyterm_populate_terms,
populate_poly_terms.
repeat rewrite map_map.
rewrite app_length.
simpl.
repeat rewrite map_length.
nia.
Qed.
Lemma add_polynomials_populate_poly_terms_same_length :
forall n l x y,
List.length (add_polynomials l x n y) =
List.length (populate_poly_terms (y :: l) x (S n)).
Proof.
intros ? ? ? ?.
rewrite add_polynomials_length.
rewrite populate_poly_terms_length.
reflexivity.
Qed.
Lemma zip_list_index_some {A B C : Type}
(f : A -> B -> C) :
forall (l₁ : list A) (l₂ : list B)
k t w,
List.length l₁ = List.length l₂ ->
(k < List.length l₁)%nat ->
Some t = List.nth_error l₁ k ->
Some w = List.nth_error l₂ k ->
List.nth_error (zip_with f l₁ l₂) k = Some (f t w).
Proof.
induction l₁.
- simpl; intros ? ? ? ? ? Hl Hk Hw.
lia.
- simpl; intros ? ? ? ? Hl Hk Hw Hv.
destruct l₂.
simpl in Hl.
lia.
simpl in Hl.
inversion Hl as [Hlt]; clear Hl.
destruct k.
simpl. simpl in Hw.
simpl in Hv.
inversion Hw; inversion Hv; subst.
reflexivity.
simpl.
assert (Hwt : (k < List.length l₁)%nat) by lia.
clear Hk.
apply IHl₁; assumption.
Qed.
Lemma list_elem_nth : forall n k : nat,
(k < List.length (list_upto n))%nat ->
(List.nth_error (list_upto n) k = Some (n - k))%nat.
Proof.
induction n;simpl.
+ intros [|]; intro H; simpl.
reflexivity. lia.
+ intros ? Hk.
destruct k.
- simpl. reflexivity.
- simpl. apply IHn.
lia.
Qed.
Lemma nth_append_polyterms :
forall n l x y k,
k < S (S n) ->
(n <= List.length l) ->
nth_error (append_mul_polyterm_populate_terms l x n y) k =
if k <? S n then
Some ((length l - n + k)%nat,
Nat.sub (S n) k,
pow_N 1 rmul (- x) (N.of_nat (length l - n + k)),
y * add_rlist (map mul_rlist (gen_comb l (Nat.sub n k))))
else
Some (S n, O, pow_N 1 rmul (- x) (N.of_nat (S n)), 0).
Proof.
intros * Hk Hn.
assert (Htt: k < S n \/ k = S n).
nia.
unfold append_mul_polyterm_populate_terms,
mul_polyterm_populate_terms,
populate_poly_terms.
rewrite map_map.
destruct Htt as [Htt | Htt].
apply Nat.ltb_lt in Htt.
rewrite Htt.
rewrite nth_error_app1.
erewrite map_nth_error.
f_equal.
f_equal.
f_equal.
f_equal.
assert (Hkt: k <= length l).
eapply Nat.ltb_lt in Htt.
nia.
assert (Hkw : k <= n).
apply Nat.ltb_lt in Htt.
nia.
nia.
assert (Hkt: k <= length l).
eapply Nat.ltb_lt in Htt.
nia.
assert (Hkw : k <= n).
apply Nat.ltb_lt in Htt.
nia.
nia.
assert (Hkt: k <= length l).
eapply Nat.ltb_lt in Htt.
nia.
assert (Hwt : k <= n).
apply Nat.ltb_lt in Htt.
nia.
f_equal.
nia.
erewrite list_elem_nth.
reflexivity.
rewrite list_upto_length.
eapply Nat.ltb_lt in Htt.
nia.
rewrite map_length.
eapply Nat.ltb_lt in Htt.
rewrite list_upto_length.
nia.
rewrite Htt, Nat.ltb_irrefl.
rewrite nth_error_app2.
rewrite map_length.
rewrite list_upto_length.
assert (Hnt : (S n - S n = O)%nat).
nia.
rewrite Hnt.
simpl.
reflexivity.
rewrite map_length,
list_upto_length.
nia.
Qed.
Lemma nth_append_polyterms_expanded :
forall n l x y k,
k < S (S n) ->
(n <= List.length l) ->
nth_error (append_mul_polyterm_populate_terms l x n y) k =
if k =? O then
Some ((length l - n)%nat,
Nat.sub (S n) 0,
pow_N 1 rmul (- x) (N.of_nat (length l - n )),
y * add_rlist (map mul_rlist (gen_comb l n)))
else if k <? S n then
Some ((length l - n + k)%nat,
Nat.sub (S n) k,
pow_N 1 rmul (- x) (N.of_nat (length l - n + k)),
y * add_rlist (map mul_rlist (gen_comb l (Nat.sub n k))))
else
Some (S n, O, pow_N 1 rmul (- x) (N.of_nat (S n)), 0).
Proof.
intros * Hk Hn.
pose proof nth_append_polyterms n l x y k Hk Hn as Hp.
assert (Hkt : k = O ∨ 1 <= k <= n ∨ k = S n).
nia.
destruct Hkt as [Hkt | [Hkt | Hkt]].
rewrite Hkt.
rewrite Hkt in Hp.
assert (Htt : 0 =? 0 = true).
apply Nat.eqb_refl.
rewrite Htt;
clear Htt.
assert (Htt: 0 <? S n = true).
apply Nat.ltb_lt;
try nia.
rewrite Htt in Hp.
rewrite Nat.add_0_r in Hp.
repeat rewrite Nat.sub_0_r in Hp.
exact Hp.
assert (Htt : k =? 0 = false).
apply Nat.eqb_neq.
nia.
rewrite Htt; clear Htt.
assert (Htt: k <? S n = true).
apply Nat.ltb_lt;
try nia.
rewrite Htt in Hp.
rewrite Htt.
exact Hp.
assert (Htt : k =? 0 = false).
apply Nat.eqb_neq.
nia.
rewrite Htt; clear Htt.
assert (Hsn : k <? S n = false).
rewrite Hkt.
apply Nat.ltb_irrefl.
rewrite Hsn in Hp.
rewrite Hsn.
exact Hp.
Qed.
Lemma nth_append_polypow :
forall n l x k,
k < S (S n) ->
n <= List.length l ->
nth_error (append_mul_polypow_populate_terms l x n (-x)) k =
if k =? O then
Some (O, S n, 1, 0)
else
Some (S (length l - (n - (k - 1))),
(n - (k - 1))%nat,
-x * pow_N 1 rmul (- x) (N.of_nat (length l - (n - (k - 1)))),
add_rlist (map mul_rlist (gen_comb l (n - (k - 1))))).
Proof.
intros * Hk Hn.
assert (Htt: k = O \/ S O <= k).
nia.
unfold append_mul_polypow_populate_terms,
mul_polypow_populate_terms,
populate_poly_terms.
rewrite map_map.
destruct Htt as [Htt | Htt].
rewrite Htt.
rewrite Nat.eqb_refl.
rewrite nth_error_app1.
simpl.
reflexivity.
simpl; nia.
assert (Hz: k =? O = false).
rewrite Nat.eqb_neq.
nia.
rewrite Hz; clear Hz.
rewrite nth_error_app2.
simpl.
erewrite map_nth_error.
f_equal.
erewrite list_elem_nth.
reflexivity.
rewrite list_upto_length.
nia.
simpl.
nia.
Qed.
Lemma nth_append_polypow_expanded :
forall n l x k,
k < S (S n) ->
n <= List.length l ->
nth_error (append_mul_polypow_populate_terms l x n (-x)) k =
if k =? O then
Some (O, S n, 1, 0)
else if k <? S n then
Some (S (length l - (n - (k - 1))),
(n - (k - 1))%nat,
-x * pow_N 1 rmul (- x) (N.of_nat (length l - (n - (k - 1)))),
add_rlist (map mul_rlist (gen_comb l (n - (k - 1)))))
else (* k = S n *)
Some ((length l - n + S n)%nat, O,
-x * pow_N 1 rmul (- x) (N.of_nat (length l)), 1).
Proof.
intros * Hk Hn.
pose proof nth_append_polypow n l x k Hk Hn as Hp.
assert (Hkt : k = O ∨ 1 <= k <= n ∨ k = S n).
nia.
destruct Hkt as [Hkt | [Hkt | Hkt]].
rewrite Hkt.
rewrite Hkt in Hp.
assert (Htt : 0 =? 0 = true).
apply Nat.eqb_refl.
rewrite Htt;
rewrite Htt in Hp;
clear Htt.
exact Hp.
assert (Htt : k =? 0 = false).
apply Nat.eqb_neq.
nia.
rewrite Htt;
rewrite Htt in Hp;
clear Htt.
assert (Htt: k <? S n = true).
apply Nat.ltb_lt;
try nia.
rewrite Htt.
exact Hp.
assert (Htt : k =? 0 = false).
apply Nat.eqb_neq.
nia.
rewrite Htt;
rewrite Htt in Hp;
clear Htt.
assert (Hsn : k <? S n = false).
rewrite Hkt.
apply Nat.ltb_irrefl.
rewrite Hsn.
rewrite Hkt in Hp.
rewrite Hkt.
rewrite Hp.
repeat f_equal.
nia.
nia.
nia.
simpl.
rewrite Nat.sub_0_r.
rewrite Nat.sub_diag.
unfold add_rlist,
mul_rlist.
destruct l;
simpl; ring.
Qed.
Lemma gen_comb_emp :
forall l n,
List.length l <= n ->
gen_comb l (S n) = [].
Proof.
induction l.
+ intros ? Hn.
simpl;
reflexivity.
+ intros ? Hn.
simpl.
destruct n.
simpl in Hn.
nia.
simpl in Hn.
assert (Hln₁ : length l <= n).
nia.
assert (Hln₂ : length l <= S n).
nia.
specialize (IHl _ Hln₁) as Ha.
specialize (IHl _ Hln₂) as Hb.
rewrite Ha, Hb.
reflexivity.
Qed.
Lemma gen_comb_equal :
forall l n,
n = List.length l ->
gen_comb l n = [l].
Proof.
induction l.
+ intros ? Hn.
simpl in Hn;
rewrite Hn;
simpl;
reflexivity.
+ intros ? Hn.
simpl in Hn.
destruct n.
nia.
simpl.
rewrite gen_comb_emp.
rewrite List.app_nil_r.
inversion Hn as (Hni).
specialize (IHl _ Hni).
rewrite <-Hni.
rewrite IHl.
simpl.
reflexivity.
nia.
Qed.
Lemma fold_left_gen_mul :
forall l y v,
y * fold_left (λ a b : R, a * b) l v =
fold_left (λ a b : R, a * b) l (v * y).
Proof.
induction l.
+ intros ? ?.
simpl; ring.
+ intros ? ?.
simpl.
rewrite IHl.
f_equal.
ring.
Qed.
Lemma gen_comb_rewrite :
forall n l y,
n = length l ->
y * add_rlist (map mul_rlist (gen_comb l n)) =
add_rlist (map mul_rlist (gen_comb (y :: l) (S n))).
Proof.
intros * Hn.
simpl.
rewrite gen_comb_emp,
List.app_nil_r.
rewrite gen_comb_equal.
simpl.
unfold add_rlist,
mul_rlist.
simpl.
ring_simplify.
rewrite fold_left_gen_mul.
reflexivity.
nia.
nia.
Qed.
Lemma tmp_4 :
let l := [x₂; x₃; x₄] in
let n := 3%nat in
let y := x₁ in
y * add_rlist (map mul_rlist (gen_comb l n)) =
add_rlist (map mul_rlist (gen_comb (y :: l) (S n))).
Proof.
simpl.
unfold add_rlist, mul_rlist.
simpl.
ring.
Qed.
Lemma sum_rlist_acc :
forall (l : list R) (a : R),
fold_left (fun acc u => acc + u) l a =
a + fold_left (fun acc u => acc + u) l 0.
Proof.
induction l.
+ intros ?.
simpl;
ring.
+ intros ?;
simpl.
rewrite IHl.
rewrite <-Radd_assoc.
f_equal.
rewrite <-IHl.
assert (Ha : 0 + a = a).
ring.
rewrite Ha.
reflexivity.
exact RRing.
Qed.
Lemma add_rlist_dist :
forall l₁ l₂,
add_rlist (l₁ ++ l₂) = add_rlist l₁ + add_rlist l₂.
Proof.
induction l₁.
+ intros *.
simpl.
unfold add_rlist.
simpl.
ring.
+ intros *.
unfold add_rlist in * |- *.
simpl.
rewrite sum_rlist_acc.
remember (fold_left (λ acc u0 : R, acc + u0) (l₁ ++ l₂) 0) as fl.
rewrite sum_rlist_acc.
subst.
rewrite IHl₁.
ring.
Qed.
Lemma add_rlist_dist_cons :
forall (l : list R) (a : R),
add_rlist (a :: l) = add_rlist [a] + add_rlist l.
Proof.
intros l a.
unfold add_rlist.
simpl.
assert (Ha : (0 + a = a)).
ring.
rewrite sum_rlist_acc.
ring.
Qed.
Lemma fold_left_map :
forall gl y,
y * add_rlist (map mul_rlist gl) =
add_rlist (map mul_rlist (map (λ u : list R, y :: u) gl)).
Proof.
induction gl.
+ intros ?.
simpl.
unfold add_rlist.
simpl.
ring.
+ intros ?.
simpl.
rewrite add_rlist_dist_cons.
ring_simplify.
rewrite IHgl.
remember (y * add_rlist [mul_rlist a]) as ya.
rewrite add_rlist_dist_cons.
subst.
f_equal.
unfold add_rlist,
mul_rlist.
simpl.
ring_simplify.
rewrite fold_left_gen_mul.
ring.
Qed.
(* I don't know how to prove this one yet! *)
Lemma thomas_has_proof_for_this :
forall k n l y,
k <= n ->
n = length l ->
y * add_rlist (map mul_rlist (gen_comb l (n - k))) +
add_rlist (map mul_rlist (gen_comb l (S n - k))) =
add_rlist (map mul_rlist (gen_comb (y :: l) (S n - k))).
Proof.
induction k.
+ intros * Hk Hn.
simpl.
rewrite Nat.sub_0_r.
rewrite gen_comb_emp,
List.app_nil_r.
rewrite gen_comb_equal.
simpl.
unfold add_rlist,
mul_rlist.
simpl.
ring_simplify.
rewrite fold_left_gen_mul.
reflexivity.
nia.
nia.
+ intros * Hk Hn.
destruct n.
- nia.
- repeat rewrite Nat.sub_succ.
assert (Hkt : k <= n).
nia.
destruct l.
simpl in Hn.
nia.
simpl in Hn.
rewrite <-Minus.minus_Sn_m.
remember (r :: l) as rl.
assert (Htt :
gen_comb (y :: rl) (S (n - k)) =
List.map (fun u => y :: u) (gen_comb rl (n - k)) ++ gen_comb rl (S (n - k))).
reflexivity.
rewrite Htt.
rewrite map_app.
rewrite add_rlist_dist.
f_equal.
apply fold_left_map.
nia.
Qed.
Lemma tmp_5 :
let l := [x₂; x₃; x₄] in
let n := 3%nat in
let k := 1%nat in (* 1 <= k <= n *)
let y := x₁ in
y * add_rlist (map mul_rlist (gen_comb l (n - k))) +
add_rlist (map mul_rlist (gen_comb l (n - (k - 1)))) =
add_rlist (map mul_rlist (gen_comb (y :: l) (S n - k))).
Proof.
simpl.
unfold add_rlist,
mul_rlist.
simpl.
ring.
Qed.
Lemma pow_N_rewrite :
forall k x,
1 <= k ->
pow_N 1 rmul (- x) (N.of_nat k) =
- x * pow_N 1 rmul (- x) (N.of_nat (k - 1)).
Proof.
induction k.
+ intros * Hk.
nia.
+ intros * Hk.
destruct k.
simpl.
ring.
assert (Hkt : 1 <= S k).
nia.
specialize (IHk x Hkt).
simpl in *.
rewrite pow_pos_succ.
reflexivity.
constructor;
try eauto.
intros xt yt zt Ha Hb.
rewrite Ha;
exact Hb.
intros xt yt Ha.
unfold Morphisms.respectful.
intros xa ya Hx.
rewrite Ha, Hx.
reflexivity.
intros xa ya za.
ring.
Qed.
Lemma nth_error_nil : forall {t} i,
@nth_error t nil i = None.
Proof.
induction i; auto.
Qed.
Lemma nth_error_length : forall {t} l n x,
@nth_error t l n = Some x -> n < length l.
Proof.
intros.
generalize dependent x.
generalize dependent l.
induction n.
induction l.
- intros.
inversion H.
- intros.
simpl.
apply PeanoNat.Nat.lt_0_succ.
- intros.
destruct l.
rewrite nth_error_nil in H.
inversion H.
inversion H.
apply IHn in H1.
simpl.
apply Lt.lt_n_S.
assumption.
Qed.
Lemma append_mul_polyterm_populate_terms_length:
forall n l x y,
length (append_mul_polyterm_populate_terms l x n y) = S (S n).
Proof.
intros *.
unfold append_mul_polyterm_populate_terms.
rewrite app_length.
simpl.
unfold mul_polyterm_populate_terms.
rewrite map_length.
unfold populate_poly_terms.
rewrite map_length.
rewrite list_upto_length.
nia.
Qed.
Lemma append_mul_polyterm_polypow_first_three_term_same :
forall n k l x y a₁ b₁ u₁ v₁ a₂ b₂ u₂ v₂,
n = List.length l ->
Some (a₁, b₁, u₁, v₁) =
List.nth_error (append_mul_polyterm_populate_terms l x n y) k ->
Some (a₂, b₂, u₂, v₂) =
List.nth_error (append_mul_polypow_populate_terms l x n (-x)) k ->
a₁ = a₂ ∧ b₁ = b₂ ∧ u₁ = u₂ ∧
(v₁ + v₂ = add_rlist (List.map mul_rlist (gen_comb (y :: l) b₁))).
Proof.
intros * Hn Ha Hb.
symmetry in Ha.
symmetry in Hb.
pose proof @nth_error_length _ ((append_mul_polyterm_populate_terms l x n y)) k
(a₁, b₁, u₁, v₁) Ha as Hnel.
rewrite append_mul_polyterm_populate_terms_length in Hnel.
rewrite nth_append_polyterms in Ha.
rewrite nth_append_polypow in Hb.
assert (Hkt : k = O ∨ 1 <= k <= n ∨ k = S n).
nia.
destruct Hkt as [Hkt | [Hkt | Hkt]].
rewrite Hkt in Ha, Hb.
assert (Htt : 0 =? 0 = true).
apply Nat.eqb_refl.
rewrite Htt in Hb;
clear Htt.
assert (Htt : 0 <? S n = true).
apply Nat.ltb_lt;
nia.
rewrite Htt in Ha.
inversion Ha;
inversion Hb;
subst.
repeat split;
try nia.
rewrite Nat.sub_diag.
simpl; reflexivity.
rewrite Nat.sub_0_r.
rewrite gen_comb_rewrite.
ring.
reflexivity.
assert (Hsn : k <? S n = true).
apply Nat.ltb_lt.
nia.
rewrite Hsn in Ha; clear Hsn.
assert (Hwt : k =? 0 = false).
apply Nat.eqb_neq.
nia.
rewrite Hwt in Hb.
clear Hwt.
inversion Ha;
inversion Hb;
subst.
repeat split.
try nia.
destruct k;
simpl in Hkt;
try nia.
rewrite Nat.sub_diag.
assert (Htt : (length l - (length l - (k - 1)) = k - 1)%nat).
nia.
rewrite Htt; clear Htt.
apply pow_N_rewrite.
nia.
assert (Htt : ((length l - (k - 1)) = S (length l) - k)%nat).
nia.
rewrite Htt; clear Htt.
apply thomas_has_proof_for_this;
try nia.
assert (Hwt : k =? 0 = false).
apply Nat.eqb_neq.
nia.
rewrite Hwt in Hb.
assert (Hsn : k <? S n = false).
rewrite Hkt.
apply Nat.ltb_irrefl.
rewrite Hsn in Ha; clear Hsn.
assert (Htt : (k - 1 = n)%nat).
nia.
rewrite Htt in Hb.
rewrite Nat.sub_diag in Hb.
rewrite Nat.sub_0_r in Hb.
rewrite <-Hn in Hb.
split.
assert (Ha₁ : a₁ = S n).
inversion Ha; subst; reflexivity.
assert (Ha₂ : a₂ = S n).
inversion Hb; subst; reflexivity.
subst; reflexivity.
split.
inversion Ha; inversion Hb;
subst; reflexivity.
split.
assert (u₁ = pow_N 1 rmul (- x) (N.of_nat (S n))).
inversion Ha; subst;
reflexivity.
assert (u₂ = - x * pow_N 1 rmul (- x) (N.of_nat n)).
inversion Hb; subst;
reflexivity.
subst.
pose proof (pow_N_rewrite (S (length l)) x).
assert (1 <= S (length l))%nat.
nia.
specialize (H H0).
assert ( S (length l) - 1 = length l)%nat.
nia.
rewrite H1 in H.
exact H.
assert (Hbb : b₁ = O).
inversion Ha;
subst;
reflexivity.
rewrite Hbb.
simpl.
inversion Ha;
inversion Hb;
subst.
simpl.
destruct l.
simpl.
ring.
simpl.
ring.
nia.
nia.
nia.
nia.
Qed.
Lemma append_mul_polypow_populate_terms_lenght:
forall n l x,
length (append_mul_polypow_populate_terms l x n (- x)) = S (S n).
Proof.
intros *.
unfold append_mul_polypow_populate_terms,
mul_polypow_populate_terms,
populate_poly_terms.
simpl.
rewrite map_map,
map_length,
list_upto_length.
nia.
Qed.
Lemma populate_poly_terms_nth_terms :
forall k n l x,
k < S n ->
n <= length l ->
nth_error (populate_poly_terms l x n) k =
Some ((length l - n + k)%nat,
Nat.sub n k,
pow_N 1 rmul (-x) (N.of_nat (length l - n + k)),
add_rlist (List.map mul_rlist (gen_comb l (Nat.sub n k)))).
Proof.
intros * Hk Hn.
unfold populate_poly_terms.
erewrite map_nth_error.
f_equal.
instantiate (1 := Nat.sub n k).
f_equal.
f_equal.
f_equal.
nia.
assert (Hkt : k <= n).
nia.
f_equal.
nia.
rewrite list_elem_nth.
f_equal.
rewrite list_upto_length.
nia.
Qed.
Lemma add_polynomials_populate_poly_terms_pointwise_same :
forall k n l x y,
k < S (S n) ->
(n = List.length l) ->
nth_error (add_polynomials l x n y) k =
nth_error (populate_poly_terms (y :: l) x (S n)) k.
Proof.
intros * Hk Hn.
assert (Hnn: n <= length l).
nia.
assert(Hnpt :
length (append_mul_polyterm_populate_terms l x n y) = S (S n)).
erewrite append_mul_polyterm_populate_terms_length;
reflexivity.
assert(Hnpp:
length (append_mul_polypow_populate_terms l x n (- x)) = S (S n)).
erewrite append_mul_polypow_populate_terms_lenght;
reflexivity.
assert (Hkt : k = O ∨ 1 <= k <= n ∨ k = S n).
nia.
destruct Hkt as [Hkt | [Hkt | Hkt]].
rewrite Hkt.
assert (Ha: nth_error (append_mul_polyterm_populate_terms l x n y) k =
Some ((length l - n + k)%nat,
Nat.sub (S n) k,
pow_N 1 rmul (- x) (N.of_nat (length l - n + k)),
y * add_rlist (map mul_rlist (gen_comb l (Nat.sub n k))))).
rewrite Hkt.
erewrite nth_append_polyterms.
assert (Hsn : 0 <? S n = true).
apply Nat.ltb_lt.
nia.
rewrite Hsn; clear Hsn.
repeat f_equal.
nia.
nia.
assert (Hb : nth_error (append_mul_polypow_populate_terms l x n (- x)) k =
Some (O, S n, 1, 0)).
rewrite Hkt.
rewrite nth_append_polypow.
assert (Hsn : 0 =? 0 = true).
apply Nat.eqb_refl.
rewrite Hsn; clear Hsn.
reflexivity.
nia.
nia.
symmetry in Ha;
symmetry in Hb.
pose proof @zip_list_index_some _ _ _
(fun '(a, b, u, v) '(_, _, _, w) => (a, b, u, v + w))
(append_mul_polyterm_populate_terms l x n y)
(append_mul_polypow_populate_terms l x n (- x))
k as Hz.
rewrite Hnpt, Hnpp in Hz.
specialize (Hz _ _ eq_refl Hk Ha Hb).
unfold add_polynomials.
rewrite Hkt in Hz.
rewrite Hz.
rewrite populate_poly_terms_nth_terms.
repeat f_equal.
repeat rewrite Nat.sub_0_r.
ring_simplify.
eapply gen_comb_rewrite;
exact Hn.
nia.
simpl; nia.
destruct Hkt as [Hktl Hktr].
assert (Ha: nth_error (append_mul_polyterm_populate_terms l x n y) k =
Some ((length l - n + k)%nat,
Nat.sub (S n) k,
pow_N 1 rmul (- x) (N.of_nat (length l - n + k)),
y * add_rlist (map mul_rlist (gen_comb l (Nat.sub n k))))).
rewrite nth_append_polyterms.
assert (Hsn : k <? S n = true).
apply Nat.ltb_lt.
nia.
rewrite Hsn; clear Hsn.
repeat f_equal.
nia.
nia.
assert (Hb : nth_error (append_mul_polypow_populate_terms l x n (- x)) k =
Some (S (length l - (n - (k - 1))),
(n - (k - 1))%nat,
-x * pow_N 1 rmul (- x) (N.of_nat (length l - (n - (k - 1)))),
add_rlist (map mul_rlist (gen_comb l (n - (k - 1)))))).
rewrite nth_append_polypow.
assert (Hkt : k =? 0 = false).
apply Nat.eqb_neq.
nia.
rewrite Hkt; clear Hkt.
f_equal.
nia.
nia.
symmetry in Ha.
symmetry in Hb.
pose proof @zip_list_index_some _ _ _
(fun '(a, b, u, v) '(_, _, _, w) => (a, b, u, v + w))
(append_mul_polyterm_populate_terms l x n y)
(append_mul_polypow_populate_terms l x n (- x))
k as Hz.
rewrite Hnpt, Hnpp in Hz.
specialize (Hz _ _ eq_refl Hk Ha Hb).
unfold add_polynomials.
rewrite Hz.
rewrite populate_poly_terms_nth_terms.
repeat f_equal.
assert (Htt : ((n - (k - 1)) = S n - k)%nat).
nia.
rewrite Htt; clear Htt.
eapply thomas_has_proof_for_this.
nia.
nia.
nia.
simpl; nia.
rewrite Hkt.
assert (Ha: nth_error (append_mul_polyterm_populate_terms l x n y) k =
Some (S n, O, pow_N 1 rmul (- x) (N.of_nat (S n)), 0)).
rewrite nth_append_polyterms.
assert (Hsn : k <? S n = false).
rewrite Hkt.
apply Nat.ltb_irrefl.
rewrite Hsn; clear Hsn.
repeat f_equal.
nia.
nia.
assert (Hb : nth_error (append_mul_polypow_populate_terms l x n (- x)) k =
Some (S (length l - (n - (k - 1))),
(n - (k - 1))%nat,
-x * pow_N 1 rmul (- x) (N.of_nat (length l - (n - (k - 1)))),
add_rlist (map mul_rlist (gen_comb l (n - (k - 1)))))).
rewrite nth_append_polypow.
assert (Hwt : k =? 0 = false).
apply Nat.eqb_neq.
nia.
rewrite Hwt; clear Hwt.
f_equal.
nia.
nia.
symmetry in Ha.
symmetry in Hb.
pose proof @zip_list_index_some _ _ _
(fun '(a, b, u, v) '(_, _, _, w) => (a, b, u, v + w))
(append_mul_polyterm_populate_terms l x n y)
(append_mul_polypow_populate_terms l x n (- x))
k as Hz.
rewrite Hnpt, Hnpp in Hz.
specialize (Hz _ _ eq_refl Hk Ha Hb).
unfold add_polynomials.
rewrite Hkt in Hz.
rewrite Hz.
rewrite populate_poly_terms_nth_terms.
repeat f_equal.
simpl.
rewrite <-Hn.
nia.
nia.
simpl.
rewrite <-Hn.
nia.
assert (Hsnt : ((n - (S n - 1)) = O)%nat).
nia.
rewrite Hsnt; clear Hsnt.
rewrite Nat.sub_diag.
simpl.
destruct l.
simpl.
ring_simplify.
reflexivity.
simpl.
ring_simplify.
reflexivity.
nia.
simpl; nia.
Qed.
Lemma add_polynomials_populate_poly_terms_same :
forall n l x y,
n = length l ->
add_polynomials l x n y = populate_poly_terms (y :: l) x (S n).
Proof.
intros ? ? ? ? Hn.
eapply @nth_ext_error.
apply add_polynomials_populate_poly_terms_same_length.
intros nt Hnt.
eapply add_polynomials_populate_poly_terms_pointwise_same.
rewrite add_polynomials_length in Hnt.
nia.
nia.
Qed.
Lemma take_nt_rewrite {A : Type} :
forall n (t : list A),
n ≤ length t ->
n = length (take n t).
Proof.
induction n.
+ intros ? Hn.
simpl.
reflexivity.
+ intros ? Hn.
simpl.
destruct t.
simpl in Hn; nia.
simpl in Hn.
simpl.
f_equal.
apply IHn.
nia.
Qed.
Fact tmp_6 :
let nt := [x₂; x₃; x₄] in
let n := 3%nat in
let y := x₁ in
let h := u in
fold_left
(λ (a : R) '(y0, v), let '(y1, u0) := y0 in let '(_, _) := y1 in a + u0 * v)
(populate_poly_terms nt y n) 0 * (h - y) =
fold_left
(λ (a : R) '(y0, v), let '(y1, u0) := y0 in let '(_, _) := y1 in a + u0 * v)
(populate_poly_terms (h :: nt) y (S n)) 0.
Proof.
simpl.
compute.
ring_simplify.
ring.
Qed.
Fact tmp_7 :
let nt := [x₂; x₃] in
let n := 2%nat in
let y := x₁ in
let h := u in
fold_left (λ (a : R) '(y0, v), let '(y1, u0) := y0 in let '(_, _) := y1 in a + u0 * v)
(populate_poly_terms nt y n) 0 * (h - y) =
fold_left (λ (a : R) '(y0, v), let '(y1, u0) := y0 in let '(_, _) := y1 in a + u0 * v)
(zip_with
(λ '(y0, v),
let
'(y1, u0) := y0 in
let
'(a, b) := y1 in
λ '(y2, w), let '(y3, _) := y2 in let '(_, _) := y3 in (a, b, u0, v + w))
(append_mul_polyterm_populate_terms nt y n h)
(append_mul_polypow_populate_terms nt y n (- y))) 0.
Proof.
simpl.
unfold add_rlist,
mul_rlist.
simpl.
ring_simplify.
ring.
Qed.
Lemma nth_error_and_map :
forall (l₁ l₂ : list (nat * nat * R * R)),
List.length l₁ = List.length l₂ ->
(forall k (ul₁ ul₂ vl₁ vl₂ : R) i₁ i₂ j₁ j₂,
Some (i₁, j₁, ul₁, vl₁) = List.nth_error l₁ k ->
Some (i₂, j₂, ul₂, vl₂) = List.nth_error l₂ k ->
ul₁ = ul₂) ->
List.map (fun '(_, _, x, _) => x) l₁ =
List.map (fun '(_, _, y, _) => y) l₂.
Proof.
induction l₁ as [|(((au, bu), cu), du) l₁].
+ intros * Ha Hf.
destruct l₂.
reflexivity.
simpl in Ha.
nia.
+ intros * Ha Hf.
destruct l₂ as [|(((av, bv), cv), dv) l₂].
simpl in Ha.
nia.
simpl.
f_equal.
exact (Hf O cu cv du dv au av bu bv eq_refl eq_refl).
apply IHl₁.
simpl in Ha.
nia.
intros * Hc Hd.
exact (Hf (S k) ul₁ ul₂ vl₁ vl₂ i₁ i₂ j₁ j₂ Hc Hd).
Qed.
Lemma fold_left_zip_reduce :
forall (l₁ l₂ : list (nat * nat * R * R)),
List.length l₁ = List.length l₂ ->
(List.map (fun '(_, _, x, _) => x) l₁ =
List.map (fun '(_, _, y, _) => y) l₂) ->
fold_left (fun acc '(_, _, u, v) => acc + u * v)
(zip_with (fun '(a, b, u₁, v₁) '(_, _, _, v₂) =>
(a, b, u₁, v₁ + v₂)) l₁ l₂) 0 =
fold_left (fun accl '(al, bl, ul, vl) => accl + ul * vl)
l₁ 0 +
fold_left (fun accr '(ar, br, ur, vr) => accr + ur * vr)
l₂ 0.
Proof.
induction l₁ as [|(((au, bu), cu), du) l₁].
+ intros * Ha Hb.
simpl in Ha.
destruct l₂.
simpl in Ha.
simpl.
ring.
simpl in Ha.
nia.
+ intros * Ha Hb.
destruct l₂ as [|(((av, bv), cv), dv) l₂].
simpl in Ha.
nia.
simpl in Ha.
simpl.
simpl in Hb.
inversion Hb.
rewrite fold_left_acc.
remember (fold_left
(λ (a : R) '(y, v), let '(y0, u0) := y in let '(_, _) := y0 in a + u0 * v)
(zip_with
(λ '(y, v₁),
let
'(y0, u₁) := y in
let
'(a, b) := y0 in
λ '(y1, v₂),
let '(y2, _) := y1 in let '(_, _) := y2 in (a, b, u₁, v₁ + v₂))
l₁ l₂) 0) as fl₁.
rewrite fold_left_acc.
remember (fold_left
(λ (a : R) '(y, v), let '(y0, u0) := y in let '(_, _) := y0 in a + u0 * v)
l₁ 0 ) as fl₂.
rewrite fold_left_acc.
subst.
rewrite IHl₁.
ring_simplify.
ring.
nia.
assumption.
Qed.
Lemma equal_terms_map :
forall n nt y h,
n = List.length nt ->
map (λ '(y0, _), let '(y1, x) := y0 in let '(_, _) := y1 in x)
(append_mul_polyterm_populate_terms nt y n h) =
map (λ '(y0, _), let '(y2, y1) := y0 in let '(_, _) := y2 in y1)
(append_mul_polypow_populate_terms nt y n (- y)).
Proof.
intros * Hn.
eapply nth_error_and_map.
rewrite append_mul_polyterm_populate_terms_length.
rewrite append_mul_polypow_populate_terms_lenght.
reflexivity.
intros * Ha Hb.
destruct (append_mul_polyterm_polypow_first_three_term_same
_ _ _ _ _ _ _ _ _ _ _ _ _ Hn Ha Hb) as (_ & _ & Hc & _).
exact Hc.
Qed.
Lemma comp_gen_ind_rewrite :
forall n h t y,
(n = length t)%nat ->
compute_poly_simp (take n t) y n * (h - y) =
compute_poly_simp (take (S n) (h :: t)) y (S n).
Proof.
intros ? ? ? ? Hn.
assert (Hnt : n <= length t).
nia.
pose proof take_nt _ _ Hnt.
assert(Htt: take (S n) (h :: t) = h :: take n t).
reflexivity.
rewrite Htt;
clear Htt.
remember (take n t) as nt.
rewrite <-populate_poly_term_compute_poly.
rewrite <-populate_poly_term_compute_poly.
unfold eval_populate_poly.
assert (Hwt : n = length nt).
rewrite Heqnt.
apply take_nt_rewrite;
try assumption.
pose proof add_polynomials_populate_poly_terms_same
n nt y h Hwt as Hp.
rewrite <-Hp.
unfold add_polynomials.
rewrite fold_left_zip_reduce.
unfold append_mul_polyterm_populate_terms,
append_mul_polypow_populate_terms.
rewrite fold_left_app.
simpl.
rewrite connect_mul_polyterm_with_evalpoly.
assert (Htt: 0 + 1 * 0 = 0).
ring.
rewrite Htt; clear Htt.
rewrite connect_mul_polypow_with_evalpoly.
unfold eval_populate_poly.
ring.
rewrite append_mul_polypow_populate_terms_lenght.
rewrite append_mul_polyterm_populate_terms_length.
reflexivity.
eapply equal_terms_map;
try assumption.
simpl; nia.
nia.
Qed.
Lemma compute_simp_gen :
forall n l y,
(n = List.length l)%nat ->
compute_poly_simp (take n l) y n *
mul_closed_poly (drop n l) y = mul_closed_poly l y.
Proof.
induction n.
+ simpl.
intros ? ? Ha.
ring_simplify.
reflexivity.
+ intros ? ? Ha.
assert (Hwt : S n <= length l).
nia.
assert (Ht : exists h t, l = h :: t). (* S n <= lenght l*)
destruct l.
simpl in Ha.
nia.
exists r, l.
reflexivity.
destruct Ht as (h & t & Hl).
rewrite Hl.
rewrite Hl in Ha, Hwt.
simpl in Ha, Hwt.
apply Nat.succ_le_mono in Hwt.
rewrite <-comp_gen_ind_rewrite.
simpl.
inversion Ha as [Hb].
specialize (IHn t y Hb).
rewrite drop_all.
simpl.
rewrite <-IHn.
rewrite Hb.
rewrite drop_all.
simpl.
ring.
nia.
Qed.
Lemma compute_simp :
forall l y,
compute_poly_simp l y (List.length l) = mul_closed_poly l y.
Proof.
intros ? ?.
assert(Ht: length l = length l).
nia.
pose proof compute_simp_gen (List.length l)
l y Ht as Hr.
rewrite take_all, drop_all in Hr.
simpl in Hr.
ring [Hr].
Qed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment