Timings for ring_pol.v
Require Import
HoTT.Classes.interfaces.abstract_algebra
HoTT.Classes.theory.additional_operations
HoTT.Classes.tactics.ring_quote
HoTT.Classes.theory.rings.
Generalizable Variables Vlt.
Local Set Universe Minimization ToSet.
Local Existing Instance almost_ring_semiring.
Local Existing Instance almostring_mor_sr_mor.
Context {C : Type@{UC} } {V : Type0 }.
Inductive Pol : Type@{UC} :=
| Pconst (c : C)
| PX (P : Pol) (v : V) (Q : Pol).
(* [C] is the scalar semiring: Z when working on rings,
N on semirings, other sometimes. *)
Context `{AlmostRing C} `{DecidablePaths C}.
(* [V] is the type of variables, ie we are defining polynomials [C[V]].
It has a computable compare so we can normalise polynomials. *)
Context `{Trichotomy@{Set Set Set} V Vlt}.
(* Polynomials are supposed (at the meta level) to be in normal form:
PX P v Q verifies
+ P <> 0
+ forall w in P, w <= v
+ forall w in Q, w < v *)
Fixpoint Peqb P Q : Bool :=
match P, Q with
| Pconst c, Pconst d => c =? d
| PX P1 v P2, PX Q1 w Q2 =>
andb (v =? w) (andb (Peqb P1 Q1) (Peqb P2 Q2))
| _, _ => false
end.
Global Instance Peqb_instance : Eqb Pol := Peqb.
Arguments Peqb_instance _ _ /.
Global Instance P0 : canonical_names.Zero Pol := Pconst 0.
Global Instance P1 : canonical_names.One Pol := Pconst 1.
Context {R : Type@{UR} } `{AlmostRing R}
(phi : C -> R) `{!AlmostRingPreserving phi}.
Notation Vars V := (V -> R).
Fixpoint eval (vs : Vars V) (P : Pol) : R :=
match P with
| Pconst c => phi c
| PX P v Q =>
(eval vs P) * (vs v) + (eval vs Q)
end.
Lemma andb_true : forall a b : Bool, andb a b = true -> a = true /\ b = true.
intros [|] [|];simpl;auto.
Lemma eval_eqb' : forall P Q : Pol, P =? Q = true ->
forall vs : Vars V, eval vs P = eval vs Q.
induction P as [c|P1 IHP1 v P2 IHP2];destruct Q as [d|Q1 w Q2];intros E vs;
change eqb with Peqb in E;simpl in E.
apply decide_eqb_ok;trivial.
destruct (false_ne_true E).
destruct (false_ne_true E).
apply compare_eqb_eq,tricho_compare_eq in E1.
Definition eval_eqb@{} := ltac:(first [exact eval_eqb'@{Ularge}|
exact eval_eqb']).
Lemma eval_0' : forall P, P =? 0 = true -> forall vs, eval vs P = 0.
induction P;simpl;intros E vs.
change eqb with Peqb in E;simpl in E.
apply decide_eqb_ok in E.
change eqb with Peqb in E;simpl in E.
destruct (false_ne_true E).
Definition eval_0@{} := ltac:(first [exact eval_0'@{Ularge}|
exact eval_0']).
Fixpoint addC c P :=
match P with
| Pconst d => Pconst (c + d)
| PX P v Q =>
PX P v (addC c Q)
end.
Lemma eval_addC vs : forall c P, eval vs (addC c P) = (phi c) + eval vs P.
rewrite (plus_comm (phi c)).
Fixpoint addX' c v Q :=
match Q with
| Pconst d => PX (Pconst c) v Q
| PX Q1 w Q2 =>
match v ?= w with
| LT =>
PX Q1 w (addX' c v Q2)
| EQ =>
PX (addC c Q1) v Q2
| GT => PX (Pconst c) v Q
end
end.
Definition addX c v Q := if c =? 0 then Q else addX' c v Q.
Lemma eval_addX'@{} vs : forall c (v:V) Q,
eval vs (addX' c v Q) = phi c * vs v + eval vs Q.
induction Q as [d|Q1 IH1 w Q2 IH2].
pose proof (tricho_compare_eq v w) as E.
destruct (v ?= w);[clear E|rewrite <-E by split;clear E w|clear E].
rewrite plus_mult_distr_r.
symmetry;apply plus_assoc.
Lemma eval_addX vs : forall c (v:V) Q,
eval vs (addX c v Q) = phi c * vs v + eval vs Q.
pose proof (decide_eqb_ok c 0) as E.
rewrite (fst E) by split.
rewrite (preserves_0 (f:=phi)).
rewrite mult_0_l,plus_0_l.
Definition PXguard@{} P v Q := if eqb P 0 then Q else PX P v Q.
Lemma eval_PXguard vs : forall P (v:V) Q,
eval vs (PXguard P v Q) = eval vs P * vs v + eval vs Q.
pose proof (eval_0 P) as E.
rewrite mult_0_l,plus_0_l.
Fixpoint mulC c P :=
match P with
| Pconst d => Pconst (c * d)
| PX P v Q =>
(* in some semirings we can have zero divisors, so P' might be zero *)
PXguard (mulC c P) v (mulC c Q)
end.
Lemma eval_mulC vs : forall c P, eval vs (mulC c P) = (phi c) * eval vs P.
induction P as [d | P1 IH1 v P2 IH2];simpl.
rewrite IH1,IH2,plus_mult_distr_l,mult_assoc.
(* if P <= v, P <> 0, and addP Q = P + Q then P * v + Q *)
Fixpoint add_aux addP P v Q :=
match Q with
| Pconst _ => PX P v Q
| PX Q1 w Q2 =>
match v ?= w with
| LT =>
PX Q1 w (add_aux addP P v Q2)
| EQ => PXguard (addP Q1) v Q2
| GT =>
PX P v Q
end
end.
Fixpoint add P Q :=
match P with
| Pconst c => addC c Q
| PX P1 v P2 => add_aux (add P1) P1 v (add P2 Q)
end.
Lemma eval_add_aux vs P addP
(Eadd : forall Q, eval vs (addP Q) = eval vs P + eval vs Q)
: forall (v:V) Q, eval vs (add_aux addP P v Q) = eval vs P * vs v + eval vs Q.
induction Q as [d|Q1 IH1 w Q2 IH2].
pose proof (tricho_compare_eq v w) as E.
destruct (v ?= w);[clear E|rewrite <-E by split;clear E w|clear E].
rewrite (plus_comm (eval vs Q1 * vs w)).
rewrite plus_mult_distr_r.
symmetry;apply plus_assoc.
Lemma eval_add' vs : forall P Q, eval vs (add P Q) = eval vs P + eval vs Q.
induction P as [c|P1 IH1 v P2 IH2];intros Q.
rewrite eval_add_aux;auto.
Definition eval_add@{} := ltac:(first [exact eval_add'@{Ularge}|
exact eval_add'@{}]).
Fixpoint mulX v P :=
match P with
| Pconst c => addX c v 0
| PX P1 w P2 =>
match v ?= w with
| LT =>
PX (mulX v P1) w (mulX v P2)
| _ => PX P v 0
end
end.
Lemma eval_mulX@{} vs : forall (v:V) (P:Pol), eval vs (mulX v P) = eval vs P * vs v.
induction P as [c|P1 IH1 w P2 IH2].
rewrite (preserves_0 (f:=phi)),plus_0_r.
pose proof (tricho_compare_eq v w) as E.
destruct (v ?= w);[clear E|rewrite <-E by split;clear E w|clear E].
rewrite plus_mult_distr_r,IH1,IH2.
rewrite <-2!mult_assoc;apply ap,mult_comm.
rewrite (preserves_0 (f:=phi)),plus_0_r.
rewrite (preserves_0 (f:=phi)),plus_0_r.
Definition mkPX P v Q := add (mulX v P) Q.
Lemma eval_mkPX vs : forall P v Q,
eval vs (mkPX P v Q) = (eval vs P) * (vs v) + eval vs Q.
rewrite eval_add,eval_mulX.
Fixpoint mul P Q :=
match P, Q with
| Pconst c, _ => mulC c Q
| _, Pconst d => mulC d P
| PX P1 v P2, PX Q1 w Q2 =>
(* P1 Q1 v w + P1 Q2 v + P2 Q1 w + P2 Q2 *)
add (mulX v (add (mulX w (mul P1 Q1)) (mul P1 Q2)))
(add (mulX w (mul P2 Q1)) (mul P2 Q2))
end.
Lemma eval_mul' vs : forall P Q, eval vs (mul P Q) = eval vs P * eval vs Q.
induction P as [c | P1 IHP1 v P2 IHP2];[apply eval_mulC|].
destruct Q as [d | Q1 w Q2].
change (mul (PX P1 v P2) (Pconst d)) with (mulC d (PX P1 v P2)).
rewrite plus_mult_distr_r,!plus_mult_distr_l.
repeat (rewrite eval_add || rewrite eval_mulX).
rewrite plus_mult_distr_r,(plus_mult_distr_l (eval vs P2)).
rewrite (mult_comm (vs v)).
rewrite <-mult_assoc,(mult_comm (vs v)),mult_assoc.
rewrite IHP1;reflexivity.
symmetry;apply mult_assoc.
Definition eval_mul@{} := ltac:(first [exact eval_mul'@{Ularge}|exact eval_mul'@{}]).
Fixpoint toPol (e: Expr V) :=
match e with
| Var v => PX 1 v 0
| Zero => 0
| One => 1
| Plus a b => add (toPol a) (toPol b)
| Mult a b => mul (toPol a) (toPol b)
| Neg a => mulC (almost_negate 1) (toPol a)
end.
Lemma eval_toPol@{} vs : forall e : Expr V,
eval vs (toPol e) = Quoting.eval _ vs e.
induction e as [v| | |a IHa b IHb|a IHa b IHb|a IHa];simpl.
rewrite (preserves_1 (f:=phi)),(preserves_0 (f:=phi)),plus_0_r,mult_1_l.
rewrite eval_add,IHa,IHb.
rewrite eval_mul,IHa,IHb.
rewrite (almostring_mor_neg (f:=phi)),preserves_1.
rewrite <-almost_ring_neg_pr.