Timings for field_of_fractions.v
Require Import HoTT.HIT.quotient.
Require Import
HoTT.Classes.interfaces.abstract_algebra
HoTT.Classes.theory.dec_fields.
Context `{Funext} `{Univalence} (R:Type@{UR})
`{IsIntegralDomain R} `{DecidablePaths R}.
Record Frac@{} : Type
:= frac { num: R; den: R; den_ne_0: PropHolds (den <> 0) }.
(* We used to have [den] and [den_nonzero] bundled,
which did work relatively nicely with Program, but the
extra messiness in proofs etc turned out not to be worth it. *)
Lemma Frac_ishset' : IsHSet Frac.
assert (E : sig (fun n : R => sig (fun d : R => d <> 0 )) <~> Frac).
apply (istrunc_equiv_istrunc _ E).
#[export] Instance Frac_ishset@{} : IsHSet Frac
:= ltac:(first [exact Frac_ishset'@{UR Ularge Set}|
exact Frac_ishset'@{}]).
Local Existing Instance den_ne_0.
#[export] Instance Frac_inject@{} : Cast R Frac.
#[export] Instance Frac_0@{} : Zero Frac := ('0 : Frac).
#[export] Instance Frac_1@{} : One Frac := ('1 : Frac).
Instance pl@{} : Plus Frac.
intros q r; refine (frac (num q * den r + num r * den q) (den q * den r) _).
Definition equiv@{} := fun x y => num x * den y = num y * den x.
#[export] Instance equiv_equiv_rel@{} : EquivRel equiv.
apply (mult_left_cancel (den y)).
rewrite !mult_assoc, !(mult_comm (den y)).
rewrite (mult_comm (den x)).
#[export] Instance equiv_dec@{} : forall x y: Frac, Decidable (equiv x y)
:= fun x y => decide_rel (=) (num x * den y) (num y * den x).
Lemma pl_respect@{} : forall q1 q2, equiv q1 q2 -> forall r1 r2, equiv r1 r2 ->
equiv (q1 + r1) (q2 + r2).
unfold equiv;intros q1 q2 Eq r1 r2 Er.
rewrite plus_mult_distr_r.
rewrite <-(associativity (num q1) (den r1)).
rewrite (associativity (den r1)), (mult_comm (den r1)), <-(associativity (den q2)).
rewrite (associativity (num q1)), Eq.
rewrite (mult_comm (den q2)), <-(associativity (num r1)), (associativity (den q1)).
rewrite (mult_comm (den q1)), <-(associativity (den r2)), (associativity (num r1)).
rewrite (mult_comm (den r1)), <-(associativity (num q2)), (associativity (den q1)).
rewrite (mult_comm (den q1)), <-(associativity (den r2)), (associativity (num q2)).
rewrite <-(associativity (num r2)), (associativity (den r1)),
(mult_comm _ (den q2)).
rewrite (mult_comm (den r1)), (associativity (num r2)).
apply symmetry;apply plus_mult_distr_r.
Lemma pl_comm@{} : forall q r, equiv (pl q r) (pl r q).
intros q r;unfold equiv;simpl.
rewrite (mult_comm (den r)), plus_comm.
Lemma pl_assoc@{} : forall q r t, equiv (pl q (pl r t)) (pl (pl q r) t).
intros;unfold equiv;simpl.
apply ap011;[|apply symmetry,associativity].
rewrite plus_mult_distr_r.
rewrite (plus_mult_distr_r _ _ (den t)).
apply ap011;[apply ap011|].
rewrite <-(associativity (num r)), <-(associativity (num r) (den q)).
rewrite (mult_comm (den t)).
rewrite (mult_comm (den q));apply symmetry,associativity.
Instance ml@{} : Mult Frac.
intros q r; refine (frac (num q * num r) (den q * den r) _).
Lemma ml_respect@{} : forall q1 q2, equiv q1 q2 -> forall r1 r2, equiv r1 r2 ->
equiv (q1 * r1) (q2 * r2).
unfold equiv;intros q1 q2 Eq r1 r2 Er.
rewrite <-(associativity (num q1)), (associativity (num r1)).
rewrite (mult_comm (num r1)), <-(associativity (den q2)), (associativity (num q1)).
rewrite <-(associativity (num q2)), (associativity (den q1)), (mult_comm (den q1)).
rewrite <-(simple_associativity (num r2)), <-(simple_associativity (num q2)).
Instance neg@{} : Negate Frac.
intros q;refine (frac (- num q) (den q) _).
Lemma neg_respect@{} : forall q r, equiv q r -> equiv (- q) (- r).
unfold equiv;simpl;intros q r E.
rewrite <-2!negate_mult_distr_l.
Lemma nonzero_num@{} x : ~ (equiv x 0) <-> num x <> 0.
split; intros E F; apply E.
rewrite mult_1_r, mult_0_l in F.
Lemma pl_0_l@{} x : equiv (0 + x) x.
rewrite mult_1_r, mult_0_l, mult_1_l, plus_0_l.
Lemma pl_0_r@{} x : equiv (x + 0) x.
rewrite 2!mult_1_r, mult_0_l, plus_0_r.
Lemma pl_neg_l@{} x : equiv (- x + x) 0.
rewrite mult_1_r, mult_0_l.
rewrite <-plus_mult_distr_r.
Lemma ml_assoc@{} q r t : equiv (ml q (ml r t)) (ml (ml q r) t).
rewrite (associativity (num q)), (associativity (den q)).
Instance dec_rec@{} : DecRecip Frac := fun x =>
match decide_rel (=) (num x) 0 with
| inl _ => 0
| inr P => frac (den x) (num x) P
end.
Lemma dec_recip_respect@{} : forall q r, equiv q r -> equiv (/ q) (/ r).
unfold equiv,dec_recip,dec_rec;intros q r E;simpl.
destruct (decide_rel paths (num q) 0) as [E1|E1],
(decide_rel paths (num r) 0) as [E2|E2];simpl.
rewrite E1 in E;rewrite mult_0_l in E.
apply (right_cancellation_ne_0 mult (den q));try solve_propholds.
rewrite mult_0_l;apply symmetry,E.
rewrite E2 in E;rewrite mult_0_l in E.
apply (right_cancellation_ne_0 mult (den r));try solve_propholds.
rewrite mult_0_l;trivial.
rewrite (mult_comm (den q)), (mult_comm (den r)).
Arguments Frac R {Rzero} : rename.
Arguments frac {R Rzero} _ _ _ : rename.
Arguments num {R Rzero} _ : rename.
Arguments den {R Rzero} _ : rename.
Arguments den_ne_0 {R Rzero} _ _ : rename.
Arguments equiv {R _ _} _ _.
Context {R1} `{IsIntegralDomain R1} `{DecidablePaths R1}.
Context {R2} `{IsIntegralDomain R2} `{DecidablePaths R2}.
Context `(f : R1 -> R2) `{!IsSemiRingPreserving f} `{!IsInjective f}.
Definition lift (x : Frac R1) : Frac R2.
apply (frac (f (num x)) (f (den x))).
Lemma lift_respects : forall q r, equiv q r -> equiv (lift q) (lift r).
unfold equiv;simpl;intros q r E.
rewrite <-2!preserves_mult.
(* NB: we need a separate IsHSet instance
so we don't need to depend on everything to define F. *)
Context `{Funext} `{Univalence} {R:Type@{UR} } `{IsHSet R} `{IsIntegralDomain R}
`{DecidablePaths R}.
Local Existing Instance den_ne_0.
(* Add Ring R: (stdlib_ring_theory R). *)
Definition F@{} := quotient equiv.
#[export] Instance class@{} : Cast (Frac R) F := class_of _.
#[export] Instance inject@{} : Cast R F := Compose class (Frac_inject _).
Definition path@{} {x y} : equiv x y -> ' x = ' y := related_classes_eq _.
Definition F_rect@{i} (P : F -> Type@{i}) {sP : forall x, IsHSet (P x)}
(dclass : forall x : Frac R, P (' x))
(dequiv : forall x y E, (path E) # (dclass x) = (dclass y))
: forall q, P q
:= quotient_ind equiv P dclass dequiv.
Definition F_compute P {sP} dclass dequiv x
: @F_rect P sP dclass dequiv (' x) = dclass x := 1.
Definition F_compute_path P {sP} dclass dequiv q r (E : equiv q r)
: apD (@F_rect P sP dclass dequiv) (path E) = dequiv q r E
:= quotient_ind_compute_path _ _ _ _ _ _ _ _.
Definition F_ind@{i} (P : F -> Type@{i}) {sP : forall x, IsHProp (P x)}
(dclass : forall x : Frac R, P (' x)) : forall x, P x.
apply (@F_rect P (fun _ => istrunc_hprop) dclass).
intros;apply path_ishprop.
Definition F_ind2@{i j} (P : F -> F -> Type@{i}) {sP : forall x y, IsHProp (P x y)}
(dclass : forall x y : Frac R, P (' x) (' y)) : forall x y, P x y.
apply (@F_ind (fun x => forall y, _)).
intros;apply istrunc_forall@{UR i j}.
apply (F_ind _);intros y.
Definition F_ind3@{i j} (P : F -> F -> F -> Type@{i})
{sP : forall x y z, IsHProp (P x y z)}
(dclass : forall x y z : Frac R, P (' x) (' y) (' z))
: forall x y z, P x y z.
apply (@F_ind (fun x => forall y z, _)).
intros;apply istrunc_forall@{UR j j}.
Definition F_rec@{i} {T : Type@{i} } {sT : IsHSet T}
: forall (dclass : Frac R -> T)
(dequiv : forall x y, equiv x y -> dclass x = dclass y),
F -> T
:= quotient_rec equiv.
Definition F_rec_compute T sT dclass dequiv x
: @F_rec T sT dclass dequiv (' x) = dclass x
:= 1.
Definition F_rec2@{i j} {T:Type@{i} } {sT : IsHSet T}
: forall (dclass : Frac R -> Frac R -> T)
(dequiv : forall x1 x2, equiv x1 x2 -> forall y1 y2, equiv y1 y2 ->
dclass x1 y1 = dclass x2 y2),
F -> F -> T
:= @quotient_rec2@{UR UR UR j i} _ _ _ _ _ (Build_HSet _).
Definition F_rec2_compute {T sT} dclass dequiv x y
: @F_rec2 T sT dclass dequiv (' x) (' y) = dclass x y
:= 1.
(* Relations, operations and constants *)
#[export] Instance F0@{} : Zero F := ('0 : F).
#[export] Instance F1@{} : One F := ('1 : F).
#[export] Instance Fplus@{} : Plus F.
refine (F_rec2 (fun x y => ' (Frac.pl _ x y)) _).
apply Frac.pl_respect;trivial.
Definition Fplus_compute@{} q r : (' q) + (' r) = ' (Frac.pl _ q r)
:= 1.
#[export] Instance Fneg@{} : Negate F.
refine (F_rec (fun x => ' (Frac.neg _ x)) _).
intros;apply path; eapply Frac.neg_respect;try apply _.
Definition Fneg_compute@{} q : - (' q) = ' (Frac.neg _ q) := 1.
#[export] Instance Fmult@{} : Mult F.
refine (F_rec2 (fun x y => ' (Frac.ml _ x y)) _).
apply Frac.ml_respect;trivial.
Definition Fmult_compute@{} q r : (' q) * (' r) = ' (Frac.ml _ q r)
:= 1.
Instance Fmult_comm@{} : Commutative Fplus.
intros;apply path, Frac.pl_comm.
Instance F_ring@{} : IsCRing F.
repeat split;
first [change sg_op with mult; change mon_unit with 1|
change sg_op with plus; change mon_unit with 0].
intros;apply path, Frac.pl_0_l.
intros;apply path, Frac.pl_0_r.
intros;apply path, Frac.pl_neg_l.
rewrite (commutativity (f:=plus)).
revert x;apply (F_ind _).
intros;apply path, Frac.pl_neg_l.
intros;apply path, Frac.ml_assoc.
rewrite (mult_comm (num y)), (mult_comm (den y)).
rewrite <-!(mult_assoc (num a)).
rewrite <-plus_mult_distr_l.
rewrite <-(mult_assoc (num a)).
rewrite (mult_comm (den a) (den c)), (mult_comm (den a) (den b)).
rewrite (mult_assoc (num b)), (mult_assoc (num c)).
rewrite <-plus_mult_distr_r.
rewrite <-(mult_assoc _ (den a) (den a * _)).
rewrite (mult_comm (den b)), <-mult_assoc.
rewrite (mult_comm (den a)).
#[export] Instance Fdec_rec@{} : DecRecip F.
refine (F_rec (fun x => ' (Frac.dec_rec _ x)) _).
apply Frac.dec_recip_respect;trivial.
Lemma classes_eq_related@{} : forall q r, ' q = ' r -> equiv q r.
apply classes_eq_related@{UR UR Ularge UR Ularge};apply _.
Lemma class_neq@{} : forall q r, ~ (equiv q r) -> ' q <> ' r.
intros q r E1 E2;apply E1;apply classes_eq_related, E2.
Lemma classes_neq_related@{} : forall q r, ' q <> ' r -> ~ (equiv q r).
intros q r E1 E2;apply E1,path,E2.
Lemma dec_recip_0@{} : / 0 = 0.
unfold Frac.dec_rec;simpl.
destruct (decide_rel paths 0 0) as [_|E].
Lemma dec_recip_nonzero_aux@{} : forall q, ' q <> 0 -> num q <> 0.
intros q E;apply classes_neq_related in E.
apply Frac.nonzero_num in E.
Lemma dec_recip_nonzero@{} : forall q (E : ' q <> 0),
/ (' q) = ' (frac (den q) (num q) (dec_recip_nonzero_aux q E)).
apply classes_neq_related, Frac.nonzero_num in E.
destruct (decide_rel paths (num q) 0) as [E'|?];[destruct E;apply E'|].
#[export] Instance F_field@{} : IsDecField F.
apply (F_ind (fun x => _ -> _)).
rewrite (dec_recip_nonzero _ E).
rewrite mult_1_r,mult_1_l.
Lemma dec_class@{} : forall q r, Decidable (class q = class r).
destruct (dec (equiv q r)) as [E|E].
apply (classes_eq_related _ _ E').
#[export] Instance F_dec@{} : DecidablePaths F.
Lemma mult_num_den@{} q :
' q = (' num q) / ' den q.
destruct (decide_rel paths (den q) 0) as [E|E];simpl.
Lemma recip_den_num@{} q :
/ ' q = (' den q) / 'num q.
unfold Frac.dec_rec;simpl.
destruct (decide_rel paths (num q) 0) as [E|E];simpl.
rewrite (mult_0_r (Azero:=Azero)), 2!mult_0_l.
rewrite mult_1_l,mult_1_r.
(* A final word about inject *)
#[export] Instance inject_sr_morphism@{} : IsSemiRingPreserving (cast R F).
repeat (split; try apply _).
change ((x + y) * (1 * 1) = (x * 1 + y * 1) * 1).
change ((x * y) * (1 * 1) = x * y * 1).
#[export] Instance inject_injective@{} : IsInjective (cast R F).
repeat (split; try apply _).
apply classes_eq_related in E.
rewrite 2!mult_1_r in E;trivial.
Context `{Funext} `{Univalence}.
Context {R1:Type@{UR1} } `{IsIntegralDomain R1} `{DecidablePaths R1}.
Context {R2:Type@{UR2} } `{IsIntegralDomain R2} `{DecidablePaths R2}.
Context `(f : R1 -> R2) `{!IsSemiRingPreserving f} `{!IsInjective f}.
Definition lift@{} : F R1 -> F R2.
apply (F_rec (fun x => class (Frac.lift f x))).
intros;apply path,Frac.lift_respects;trivial.
#[export] Instance lift_sr_morphism@{i} : IsSemiRingPreserving lift.
(* This takes a few seconds. *)
apply (F_ind2@{UR1 UR2 i} _).
(* very slow or doesn't terminate without the @ but fast with it *)
repeat (rewrite <-(preserves_mult (f:=f)) || rewrite <-(preserves_plus (f:=f))).
rewrite (preserves_0 (f:=f)).
apply (F_ind2@{UR1 UR2 i} _).
rewrite <-!(preserves_mult (f:=f)).
#[export] Instance lift_injective@{i} : IsInjective lift.
apply (F_ind2@{UR1 i i} (fun _ _ => _ -> _)).
apply classes_eq_related in E.
rewrite 2!(preserves_mult (f:=f)).