Timings for peano_naturals.v
Require Import
HoTT.Classes.interfaces.abstract_algebra
HoTT.Classes.interfaces.naturals
HoTT.Classes.interfaces.orders
HoTT.Classes.theory.rings
HoTT.Classes.orders.semirings
HoTT.Classes.theory.apartness.
Local Set Universe Minimization ToSet.
(* This should go away one Coq has universe cumulativity through inductives. *)
(* It's important that the universe [N] be free. Occasionally, Coq will choose universe variables in proofs that force [N] to be [Set]. To pinpoint where this happens, you can add the line [Constraint Set < N.] here, and see what fails below. *)
Let natpaths := @paths@{N} nat.
Arguments natpaths (_ _)%_nat_scope.
Definition natpaths_symm : Symmetric@{N N} natpaths.
unfold natpaths; exact _.
#[export] Instance nat_0: Zero@{N} nat := 0%nat.
#[export] Instance nat_1: One@{N} nat := 1%nat.
#[export] Instance nat_plus: Plus@{N} nat := Nat.Core.nat_add.
Notation mul := Nat.Core.nat_mul.
#[export] Instance nat_mult: Mult@{N} nat := Nat.Core.nat_mul.
Ltac simpl_nat :=
change (@plus nat _) with Nat.Core.nat_add;
change (@mult nat _) with Nat.Core.nat_mul;
simpl;
change Nat.Core.nat_add with (@plus nat Nat.Core.nat_add);
change Nat.Core.nat_mul with (@mult nat Nat.Core.nat_mul).
Local Instance add_0_l : LeftIdentity@{N N} (plus : Plus nat) 0 := fun _ => idpath.
Definition add_S_l a b : S a + b =N= S (a + b) := idpath.
Local Instance add_0_r : RightIdentity@{N N} (plus : Plus nat) (zero : Zero nat).
intros a; induction a as [| a IHa].
Lemma add_S_r : forall a b, a + S b =N= S (a + b).
intros a b; induction a as [| a IHa].
(** [forall a b c : nat, a + (b + c) = (a + b) + c]. The RHS is written [a + b + c]. *)
Local Instance add_assoc : Associative@{N} (plus : Plus nat).
intros a b c; induction a as [| a IHa].
change (S (a + (b + c)) = S (a + b + c)).
Local Instance add_comm : Commutative@{N N} (plus : Plus nat).
intros a b; induction a as [| a IHa].
Local Instance mul_0_l : LeftAbsorb@{N N} (mult : Mult nat) (zero : Zero nat)
:= fun _ => idpath.
Definition mul_S_l a b : (S a) * b =N= b + a * b := idpath.
Local Instance mul_1_l : LeftIdentity@{N N} (mult : Mult nat) (one : One nat)
:= add_0_r.
Local Instance mul_0_r : RightAbsorb@{N N} (mult : Mult nat) (zero : Zero nat).
intros a; induction a as [| a IHa].
Lemma mul_S_r a b : a * S b =N= a + a * b.
induction a as [| a IHa].
change (S (b + a * S b) = S (a + (b + a * b))).
rhs rapply (ap (fun x => x + _) (add_comm _ _)).
rhs rapply (add_assoc _ _ _)^.
Local Instance mul_1_r : RightIdentity@{N N} (mult : Mult nat) (one : One nat).
lhs napply (ap _ (mul_0_r a)).
Local Instance mul_comm : Commutative@{N N} (mult : Mult nat).
intros a b; induction a as [| a IHa].
change (b + a * b = b + b * a).
apply (ap (fun x => b + x)), IHa.
(** [a * (b + c) =N= a * b + a * c]. *)
Local Instance add_mul_distr_l
: LeftDistribute@{N} (mult : Mult nat) (plus : Plus nat).
intros a b c; induction a as [| a IHa].
change ((b + c) + a * (b + c) = (b + a * b) + (c + a * c)).
lhs rapply (add_assoc _ _ _)^.
rhs rapply (add_assoc _ _ _)^.
rhs rapply (ap (fun x => x + _) (add_comm _ _)).
rhs rapply (add_assoc _ _ _)^.
apply (ap (plus c)), IHa.
(** [(a + b) * c =N= a * c + b * c]. This also follows from [plus_mult_distr_r], which currently requires that we already have a semiring. It should be adjusted to not require associativity. *)
Local Instance add_mul_distr_r
: RightDistribute@{N} (mult : Mult nat) (plus : Plus nat).
lhs apply add_mul_distr_l.
apply ap011; apply mul_comm.
Local Instance mul_assoc : Associative@{N} (mult : Mult nat).
intros a b c; induction a as [| a IHa].
rhs apply add_mul_distr_r.
#[export] Instance S_neq_0 x : PropHolds (~ (S x =N= 0)).
change ((fun a => match a with S _ => Unit | 0%nat => Empty end) 0).
Definition pred x := match x with | 0%nat => 0 | S k => k end.
#[export] Instance S_inj : IsInjective@{N N} S
:= { injective := fun a b E => ap pred E }.
(** This is also in Spaces.Nat.Core. *)
#[export] Instance nat_dec: DecidablePaths@{N} nat.
apply (nat_rect@{N} (fun x => forall y, _)).
right;apply symmetric_neq,S_neq_0.
apply (injective S) in E.
#[export] Instance nat_set : IsTrunc@{N} 0 nat.
apply hset_pathcoll, pathcoll_decpaths, nat_dec.
Instance nat_semiring : IsSemiCRing@{N} nat.
repeat (split; try exact _).
(* Add Ring nat: (rings.stdlib_semiring_theory nat). *)
Lemma S_nat_plus_1 x : S x =N= x + 1.
Lemma S_nat_1_plus x : S x =N= 1 + x.
Lemma nat_induction (P : nat -> Type) :
P 0 -> (forall n, P n -> P (1 + n)) -> forall n, P n.
Lemma plus_eq_zero : forall a b : nat, a + b =N= 0 -> a =N= 0 /\ b =N= 0.
intros [|a];[intros [|b];auto|].
Lemma mult_eq_zero : forall a b : nat, a * b =N= 0 -> a =N= 0 |_| b =N= 0.
intros _;right;reflexivity.
Instance nat_zero_divisors : NoZeroDivisors nat.
intros x [Ex [y [Ey1 Ey2]]].
apply mult_eq_zero in Ey2.
Instance nat_plus_cancel_l : forall z:nat, LeftCancellation@{N} plus z.
intros a;induction a as [|a IHa];simpl_nat;intros b c E.
Instance nat_mult_cancel_l
: forall z : nat, PropHolds (~ (z =N= 0)) -> LeftCancellation@{N} (.*.) z.
intros a Ea b c E;revert b c a Ea E.
induction b as [|b IHb];intros [|c];simpl_nat;intros a Ea E.
rewrite mul_S_r in E;apply symmetry in E.
rewrite mul_0_r,mul_S_r in E.
apply (left_cancellation _ _) in E.
apply IHb with a;trivial.
#[export] Instance nat_le: Le@{N N} nat := Nat.Core.leq.
#[export] Instance nat_lt: Lt@{N N} nat := Nat.Core.lt.
Lemma le_plus : forall n k, n <= k + n.
Lemma le_exists : forall n m : nat,
iff@{N N N} (n <= m) (sig@{N N} (fun k => m =N= k + n)).
intros E;induction E as [|m E IH].
Lemma zero_least : forall a, 0 <= a.
induction a;constructor;auto.
Lemma le_S_S : forall a b : nat, iff@{N N N} (a <= b) (S a <= S b).
etransitivity;[apply le_exists|].
etransitivity;[|apply symmetry,le_exists].
split;intros [k E];exists k.
rewrite add_S_r in E;apply (injective _) in E.
Lemma lt_0_S : forall a : nat, 0 < S a.
Lemma le_S_either : forall a b, a <= S b -> a <= b |_| a = S b.
intros;left;apply zero_least.
apply (snd (le_S_S _ _)) in E.
destruct E as [|b E];auto.
Lemma le_lt_dec : forall a b : nat, a <= b |_| b < a.
intros;left;apply zero_least.
Lemma not_lt_0 : forall a, ~ (a < 0).
apply natpaths_symm,plus_eq_zero in E.
exact (S_neq_0 _ (snd E)).
Lemma lt_le : forall a b, a < b -> a <= b.
Local Instance nat_le_total : TotalRelation@{N N} (_:Le nat).
destruct (le_lt_dec a b);[left|right].
Local Instance nat_lt_irrefl : Irreflexive@{N N} (_:Lt nat).
apply (left_cancellation@{N} (+) x).
rewrite add_0_r, add_S_r,<-add_S_l.
Local Instance nat_le_hprop : is_mere_relation nat le.
intros m n;apply Trunc.hprop_allpath.
generalize (idpath (S n) : S n =N= S n).
change (forall n0 : nat,
S n =N= S n0 -> forall le_mn1 le_mn2 : m <= n0, le_mn1 = le_mn2).
induction (S n) as [|n0 IHn0].
intros ? E;destruct (S_neq_0 _ (natpaths_symm _ _ E)).
apply (injective S) in H.
rewrite <- H; intros le_mn1 le_mn2; clear n H.
pose (def_n2 := idpath n0);
path_via (paths_ind n0 (fun n _ => le m _) le_mn2 n0 def_n2).
generalize def_n2; revert le_mn1 le_mn2.
generalize n0 at 1 4 5 8; intros n1 le_mn1.
destruct le_mn1; intros le_mn2; destruct le_mn2.
rewrite (Trunc.path_ishprop def_n0 idpath).
intros def_n0; generalize le_mn2; rewrite <-def_n0; intros le_mn0.
destruct (irreflexivity nat_lt _ le_mn0).
destruct (irreflexivity nat_lt m0).
rewrite def_n0 in le_mn1;trivial.
pose proof (injective S _ _ def_n0) as E.
rewrite (Trunc.path_ishprop def_n0 idpath).
Local Instance nat_le_po : PartialOrder nat_le.
apply le_exists in E1;apply le_exists in E2.
destruct E1 as [k1 E1], E2 as [k2 E2].
apply le_exists in E1;apply le_exists in E2.
destruct E1 as [k1 E1], E2 as [k2 E2].
assert (k1 + k2 = 0) as E.
apply (left_cancellation (+) a).
rewrite (plus_comm a), (plus_assoc k2), (plus_comm k2).
rewrite Ek2,plus_0_l in E2.
Local Instance nat_strict : StrictOrder (_:Lt nat).
apply le_exists;apply le_exists in E1;apply le_exists in E2.
destruct E1 as [k1 E1], E2 as [k2 E2].
rewrite !add_S_r,add_S_l.
rewrite (add_assoc k2), (add_comm k2).
#[export] Instance nat_trichotomy : Trichotomy@{N N i} (lt:Lt nat).
destruct (le_lt_dec a b) as [[|]|E];auto.
#[export] Instance nat_apart : Apart@{N N} nat := fun n m => n < m |_| m < n.
Instance nat_apart_mere : is_mere_relation nat nat_apart.
intros;apply ishprop_sum;try exact _.
apply (irreflexivity nat_lt x).
Instance decidable_nat_apart x y : Decidable (nat_apart x y).
rapply decidable_sum@{N N N}; apply Nat.Core.decidable_lt.
#[export] Instance nat_trivial_apart : TrivialApart nat.
intros a b;split;intros E.
destruct E as [E|E];apply irrefl_neq in E;trivial.
apply symmetric_neq;trivial.
destruct (trichotomy _ a b) as [?|[?|?]];auto.
Lemma nat_not_lt_le : forall a b, ~ (a < b) -> b <= a.
destruct (le_lt_dec b a);auto.
Lemma nat_lt_not_le : forall a b : nat, a < b -> ~ (b <= a).
apply le_exists in E1;apply le_exists in E2.
destruct E1 as [k1 E1], E2 as [k2 E2].
apply (S_neq_0 (k1 + k2)).
apply (left_cancellation (+) a).
rewrite add_S_r;rewrite !add_S_r in E2.
rewrite (add_assoc a), (add_comm a), <-(add_assoc k1), (add_comm a).
rewrite (add_assoc k1), (add_comm k1), <-(add_assoc k2).
#[export] Instance nat_le_dec: forall x y : nat, Decidable (x ≤ y).
destruct (le_lt_dec a b).
Lemma S_gt_0 : forall a, 0 < S a.
intros;apply le_S_S,zero_least.
Lemma nonzero_gt_0 : forall a, ~ (a =N= 0) -> 0 < a.
Lemma nat_le_lt_trans : forall a b c : nat, a <= b -> b < c -> a < c.
apply le_exists in E1;apply le_exists in E2.
destruct E1 as [k1 E1],E2 as [k2 E2];rewrite E2,E1.
rewrite add_S_r,add_assoc.
Lemma lt_strong_cotrans : forall a b : nat, a < b -> forall c, a < c |_| c < b.
destruct (le_lt_dec c a) as [E2|E2].
apply nat_le_lt_trans with a;trivial.
Lemma nat_full' : FullPseudoSemiRingOrder nat_le nat_lt.
destruct (irreflexivity lt a).
intros a b E c;apply tr;apply lt_strong_cotrans;trivial.
apply nat_not_lt_le,le_exists in E.
destruct E as [k E];exists k;rewrite plus_comm;auto.
apply le_exists in E;destruct E as [k Hk].
rewrite add_S_r,<-add_S_l.
rewrite plus_assoc,(plus_comm z (S k)), <-plus_assoc.
apply le_exists in E;destruct E as [k E].
rewrite <-add_S_r,plus_assoc,(plus_comm k z),<-plus_assoc in E.
apply (left_cancellation plus _) in E.
apply trivial_apart in E.
destruct (dec (apart x₁ x₂)) as [?|ex];apply tr;auto.
destruct E as [E|E];[rewrite E in Ea|rewrite E in Eb];
apply (irreflexivity lt 0);trivial.
apply nat_lt_not_le in E2.
destruct (le_lt_dec a b);auto.
(* Coq pre 8.8 produces phantom universes, see GitHub Coq/Coq#1033. *)
Definition nat_full@{} := ltac:(first[exact nat_full'@{Ularge Ularge}|
exact nat_full'@{Ularge Ularge N}|
exact nat_full'@{}]).
Local Existing Instance nat_full.
Lemma le_nat_max_l n m : n <= Nat.Core.nat_max n m.
induction n as [|n' IHn];
intros m; induction m as [|m' IHm]; try reflexivity; cbn.
Lemma le_nat_max_r n m : m <= Nat.Core.nat_max n m.
induction n as [|n' IHn];
intros m; induction m as [|m' IHm]; try reflexivity; cbn.
Instance S_embedding : OrderEmbedding S.
#[export] Instance S_strict_embedding : StrictOrderEmbedding S.
#[export] Instance nat_naturals_to_semiring : NaturalsToSemiRing@{N i} nat :=
fun _ _ _ _ _ _ => fix f (n: nat) := match n with 0%nat => 0 | 1%nat => 1 |
S n' => 1 + f n' end.
Section for_another_semiring.
Context {R:Type@{U} } `{IsSemiCRing@{U} R}.
Notation toR := (naturals_to_semiring nat R).
(* Add Ring R: (rings.stdlib_semiring_theory R). *)
Local Definition f_S : forall x, toR (S x) = 1 + toR x.
Local Definition f_preserves_plus a a': toR (a + a') = toR a + toR a'.
change (toR a' = 0 + toR a').
change (toR (S (a + a')) = toR (S a) + toR a').
Local Definition f_preserves_mult a a': toR (a * a') = toR a * toR a'.
change (toR (a' + a * a') = (1 + toR a) * toR a').
rewrite f_preserves_plus, IHa.
rewrite plus_mult_distr_r,mult_1_l.
#[export] Instance nat_to_sr_morphism
: IsSemiRingPreserving (naturals_to_semiring nat R).
Lemma toR_unique (h : nat -> R) `{!IsSemiRingPreserving h} x :
naturals_to_semiring nat R x = h x.
apply symmetry,preserves_0.
change (1 + naturals_to_semiring nat R n = h (1+n)).
rewrite (preserves_plus (f:=h)).
apply ap10,ap,symmetry,preserves_1.
End for_another_semiring.
Lemma nat_naturals : Naturals@{N N N N N N N i} nat.
intros;apply toR_unique, _.
#[export] Existing Instance nat_naturals.
#[export] Instance nat_cut_minus: CutMinus@{N} nat := Nat.Core.nat_sub.
Lemma plus_minus : forall a b, cut_minus (a + b) b =N= a.
unfold cut_minus,nat_cut_minus.
intros a b;revert a;induction b as [|b IH].
intros [|a];simpl;try split.
change nat_plus with plus.
rewrite add_S_r,<-add_S_l;apply IH.
Lemma le_plus_minus : forall n m : nat, n <= m -> m =N= (n + (cut_minus m n)).
destruct E as [k E];rewrite E.
Lemma minus_ge : forall a b, a <= b -> cut_minus a b =N= 0.
unfold cut_minus,nat_cut_minus.
intros a b;revert a;induction b as [|b IH];intros [|a];simpl.
intros E;destruct (not_lt_0 _ E).
#[export] Instance nat_cut_minus_spec : CutMinusSpec@{N N} nat nat_cut_minus.
exact (le_plus_minus _ _ E).