Timings for Ordinals.v
From HoTT Require Import TruncType ExcludedMiddle Modalities.ReflectiveSubuniverse abstract_algebra.
From HoTT Require Import Universes.Smallness.
From HoTT Require Import Colimits.Quotient.
From HoTT Require Import HSet.
Local Close Scope trunc_scope.
Local Open Scope hprop_scope.
(** This file contains a definition of ordinals and some fundamental results,
roughly following the presentation in the HoTT book. *)
(** * Well-foundedness *)
Inductive Accessible {A} (R : Lt A) (a : A) :=
acc : (forall b, b < a -> Accessible R b) -> Accessible R a.
Instance ishprop_Accessible `{Funext} {A} (R : Lt A) (a : A) :
IsHProp (Accessible R a).
induction acc1 as [a acc1' IH].
apply path_forall; intros b.
apply path_forall; intros Hb.
Class WellFounded {A} (R : Relation A) :=
well_foundedness : forall a : A, Accessible R a.
Instance ishprop_WellFounded `{Funext} {A} (R : Relation A) :
IsHProp (WellFounded R).
apply hprop_allpath; intros H1 H2.
apply path_forall; intros a.
Class Extensional {A} (R : Lt A) :=
extensionality : forall a b : A, (forall c : A, c < a <-> c < b) -> a = b.
Instance ishprop_Extensional `{Funext} {A} `{IsHSet A} (R : Relation A)
: IsHProp (Extensional R).
Class IsOrdinal@{carrier relation} (A : Type@{carrier}) (R : Relation@{carrier relation} A) := {
ordinal_is_hset :: IsHSet A ;
ordinal_relation_is_mere :: is_mere_relation A R ;
ordinal_extensionality :: Extensional R ;
ordinal_well_foundedness :: WellFounded R ;
ordinal_transitivity :: Transitive R ;
}.
Instance ishprop_IsOrdinal `{Funext} A R
: IsHProp (IsOrdinal A R).
eapply istrunc_equiv_istrunc.
Record Ordinal@{carrier relation +} :=
{ ordinal_carrier : Type@{carrier}
; ordinal_relation :: Lt@{carrier relation} ordinal_carrier
; ordinal_property :: IsOrdinal@{carrier relation} ordinal_carrier (<)
}.
Coercion ordinal_as_hset (A : Ordinal) : HSet
:= Build_HSet (ordinal_carrier A).
Instance irreflexive_ordinal_relation A R
: IsOrdinal A R -> Irreflexive R.
induction (well_foundedness a) as [a _ IH].
apply (IH a); assumption.
Definition TypeWithRelation
:= { A : Type & Relation A }.
Coercion ordinal_as_type_with_relation (A : Ordinal) : TypeWithRelation
:= (A : Type; (<)).
(** * Paths in Ordinal *)
Definition equiv_Ordinal_to_sig
: Ordinal <~> { R : { A : Type & Relation A } & IsOrdinal _ R.2 }.
transitivity { A : Type & { R : Relation A & IsOrdinal A R } }.
apply equiv_sigma_assoc'.
Definition Isomorphism : TypeWithRelation -> TypeWithRelation -> Type
:= fun '(A; R__A) '(B; R__B) =>
{ f : A <~> B & forall a a', R__A a a' <-> R__B (f a) (f a') }.
Instance isomorphism_id : Reflexive Isomorphism.
Lemma isomorphism_inverse
: forall A B, Isomorphism A B -> Isomorphism B A.
intros [A R__A] [B R__B] [f H].
exists (equiv_inverse f).
rewrite <- (eisretr f b).
rewrite <- (eisretr f b').
(* We don't apply the symmetry tactic because that would introduce bad universe constraints *)
(** We state this first without using [Transitive] to allow more general universe variables. *)
Lemma transitive_Isomorphism
: forall A B C, Isomorphism A B -> Isomorphism B C -> Isomorphism A C.
intros [A R__A] [B R__B] [C R__C].
exists (equiv_compose' g f).
Instance isomorphism_compose_backwards : Transitive Isomorphism
:= transitive_Isomorphism.
Definition equiv_path_Ordinal `{Univalence} (A B : Ordinal)
: Isomorphism A B <~> A = B.
transitivity (equiv_Ordinal_to_sig A = equiv_Ordinal_to_sig B).
transitivity ((equiv_Ordinal_to_sig A).1 = (equiv_Ordinal_to_sig B).1).
exact (isequiv_pr1_path_hprop _ _).
transitivity (exist Relation A (<) = exist Relation B (<)).
transitivity { p : A = B :> Type & p # (<) = (<) }.
exact (equiv_path_sigma Relation
(exist Relation A (<))
(exist Relation B (<))).
srapply equiv_functor_sigma'.
exact (equiv_equiv_path A B).
apply (istrunc_equiv_istrunc (forall b b' : B, (p # (<)) b b' = (b < b'))).
transitivity (forall b : B, (p # lt) b = lt b).
apply equiv_functor_forall_id; intros b.
rewrite transport_arrow_toconst.
repeat rewrite transport_Vp.
rewrite transport_arrow_toconst.
apply path_iff_ishprop_uncurried.
specialize (H0 (transport idmap p^ b) (transport idmap p^ b')).
repeat rewrite transport_pV in H0.
Lemma path_Ordinal `{Univalence} (A B : Ordinal)
: forall f : A <~> B,
(forall a a' : A, a < a' <-> f a < f a')
-> A = B.
apply equiv_path_Ordinal.
Lemma trichotomy_ordinal `{ExcludedMiddle} {A : Ordinal} (a b : A)
: a < b \/ a = b \/ b < a.
induction (well_foundedness a) as [a _ IHa].
induction (well_foundedness b) as [b _ IHb].
destruct (LEM (merely (exists b', b' < b /\ (a = b' \/ a < b')))) as [H1 | H1]; try exact _.
transitivity b'; assumption.
destruct (LEM (merely (exists a', a' < a /\ (a' = b \/ b < a')))) as [H2 | H2]; try exact _.
transitivity a'; assumption.
apply LEM_to_DNE; try exact _.
refine (Trunc_rec _ (IHa c c_a b)).
apply LEM_to_DNE; try exact _.
refine (Trunc_rec _ (IHb c c_b)).
Lemma ordinal_has_minimal_hsolutions {lem : ExcludedMiddle} (A : Ordinal) (P : A -> HProp)
: merely (exists a, P a) -> merely (exists a, P a /\ forall b, P b -> a < b \/ a = b).
eapply merely_destruct; try exact H'.
induction (well_foundedness a) as [a _ IH].
destruct (LEM (merely (exists b, P b /\ b < a)) _) as [H|H].
eapply merely_destruct; try apply H.
specialize (trichotomy_ordinal a b).
eapply merely_destruct; try exact H1.
eapply merely_destruct; try exact H2.
(** * Simulations *)
(** We define the notion of simulations between arbitrary relations. For simplicity, most lemmas about simulations are formulated for ordinals only, even if they do not need all properties of ordinals. The only exception is [isordinal_simulation] which can be used to prove that a relation is an ordinal. *)
Class IsSimulation {A B : Type} {R__A : Lt A} {R__B : Lt B} (f : A -> B) :=
{ simulation_is_hom {a a'}
: a < a' -> f a < f a'
; simulation_is_merely_minimal {a b}
: b < f a -> hexists (fun a' => a' < a /\ f a' = b)
}.
Arguments simulation_is_hom {_ _ _ _} _ {_ _ _}.
Instance ishprop_IsSimulation `{Funext}
{A B : Ordinal} (f : A -> B) :
IsHProp (IsSimulation f).
eapply istrunc_equiv_istrunc.
Instance isinjective_simulation
{A : Type} {R : Lt A} `{IsOrdinal A R}
{B : Type} {Q : Lt B} `{IsOrdinal B Q}
(f : A -> B) {is_simulation : IsSimulation f}
: IsInjective f.
induction (well_foundedness a) as [a _ IHa].
induction (well_foundedness b) as [b _ IHb].
apply extensionality; intros c.
assert (fc_fa : f c < f a)
by exact (simulation_is_hom f c_a).
assert (fc_fb : f c < f b)
by (rewrite <- fa_fb; exact fc_fa).
assert (H1 : hexists (fun c' => c' < b /\ f c' = f c))
by exact (simulation_is_merely_minimal fc_fb).
intros (c' & c'_b & fc'_fc).
assert (fc_fb : f c < f b)
by exact (simulation_is_hom f c_b).
assert (fc_fa : f c < f a)
by (rewrite fa_fb; exact fc_fb).
assert (H1 : hexists (fun c' => c' < a /\ f c' = f c))
by exact (simulation_is_merely_minimal fc_fa).
intros (c' & c'_a & fc'_fc).
exact (transitivity a'_c' c'_a).
Lemma simulation_is_minimal
{A : Type} {R : Lt A} `{IsOrdinal A R}
{B : Type} {Q : Lt B} `{IsOrdinal B Q}
(f : A -> B) {is_simulation : IsSimulation f}
: forall {a b}, b < f a -> exists a', a' < a /\ f a' = b.
refine (Trunc_rec _ (simulation_is_merely_minimal H1)).
intros (a1 & ? & p) (a2 & ? & <-).
apply path_sigma_hprop; cbn.
Lemma path_simulation `{Funext}
{A B : Ordinal}
(f : A -> B) {is_simulation_f : IsSimulation f}
(g : A -> B) {is_simulation_g : IsSimulation g}
: f = g.
apply path_forall; intros a.
induction (well_foundedness a) as [a _ IH].
apply (extensionality (f a) (g a)).
destruct (simulation_is_minimal f b_fa) as (a' & a'_a & <-).
apply (simulation_is_hom g).
destruct (simulation_is_minimal g b_ga) as (a' & a'_a & <-).
apply (simulation_is_hom f).
Instance is_simulation_isomorphism
{A : Type} {R__A : Lt A}
{B : Type} {R__B : Lt B}
(f : Isomorphism (A; R__A) (B; R__B))
: IsSimulation f.1.
Instance ishprop_Isomorphism `{Funext} (A B : Ordinal)
: IsHProp (Isomorphism A B).
apply hprop_allpath; intros f g.
apply path_sigma_hprop; cbn.
apply path_simulation; exact _.
Instance ishset_Ordinal `{Univalence}
: IsHSet Ordinal.
apply (istrunc_equiv_istrunc (Isomorphism A B)).
apply equiv_path_Ordinal.
Lemma isordinal_simulation
{A : Type}
`{IsHSet A}
{R : Lt A}
{mere : is_mere_relation _ R}
{B : Type}
{Q : Lt B}
`{IsOrdinal B Q}
(f : A -> B)
`{IsInjective _ _ f}
{is_simulation : IsSimulation f}
: IsOrdinal A R.
refine (Trunc_rec _ (simulation_is_merely_minimal b_fa)).
apply (simulation_is_hom f).
refine (Trunc_rec _ (simulation_is_merely_minimal b_fa')).
apply (simulation_is_hom f).
remember (f a) as b eqn: fa_b.
induction (well_foundedness b) as [b _ IH].
constructor; intros a' a'_a.
apply (simulation_is_hom f).
assert (fa_fc : f a < f c).
apply (simulation_is_hom f).
apply (simulation_is_hom f).
refine (Trunc_rec _ (simulation_is_merely_minimal fa_fc)).
intros [a' [a'_c fa'_fa]].
apply (injective f) in fa'_fa.
(** * Initial segments *)
Definition initial_segment `{PropResizing}
{A : Type} {R : Lt A} `{IsOrdinal A R} (a : A)
: Ordinal.
srefine {| ordinal_carrier := {b : A & smalltype (b < a)}
; ordinal_relation := fun x y => x.1 < y.1
|};
try exact _.
srapply (isordinal_simulation pr1).
intros b a' a'_b; cbn in *.
exact ((equiv_smalltype _) b.2).
exact (transitivity a'_b b_a).
Notation "↓ a" := (initial_segment a) (at level 4, format "↓ a") : Ordinals.
(* 3 is the level of most unary postfix operators in the standard lib, e.g. f^-1 *)
Definition in_
`{PropResizing}
{A : Ordinal} {a : A}
(x : A) (H : x < a)
: ↓a
:= (x; (equiv_smalltype _)^-1 H).
Definition out
`{PropResizing}
{A : Ordinal} {a : A}
: ↓a -> A
:= pr1.
Definition initial_segment_property `{PropResizing}
{A : Ordinal} {a : A}
: forall x : ↓a, out x < a.
exact (equiv_smalltype _ (proj2 x)).
Instance is_simulation_out `{PropResizing}
{A : Ordinal} (a : A)
: IsSimulation (out : ↓a -> A).
apply initial_segment_property.
exists (in_ a' a'_a); cbn.
Instance isinjective_initial_segment `{Funext} `{PropResizing}
(A : Ordinal)
: IsInjective (initial_segment : A -> Ordinal).
enough (H1 : forall a1 a2 : A, ↓a1 = ↓a2 -> forall b : ↓a1, out b < a2).
apply extensionality; intros b.
exact (H1 a1 a2 p (in_ b b_a1)).
exact (H1 a2 a1 p^ (in_ b b_a2)).
assert (out = transport (fun B : Ordinal => B -> A) p^ out)
as ->.
rewrite transport_arrow_toconst.
apply initial_segment_property.
Lemma equiv_initial_segment_simulation
`{PropResizing}
{A : Type@{A}} {R : Lt@{_ R} A} `{IsOrdinal A R}
{B : Type@{B}} {Q : Lt@{_ Q} B} `{IsOrdinal B Q}
(f : A -> B) {is_simulation : IsSimulation f} (a : A)
: Isomorphism ↓(f a) ↓a.
apply isomorphism_inverse.
srapply equiv_adjointify.
apply (equiv_smalltype _)^-1.
rapply simulation_is_hom.
apply (equiv_smalltype _).
assert (x_fa : x.1 < f a).
exact ((equiv_smalltype _) x.2).
destruct (simulation_is_minimal f x_fa) as (a' & a'_a & _).
exact (a'; (equiv_smalltype _)^-1 a'_a).
apply path_sigma_hprop; cbn.
transparent assert (x_fa : (x.1 < f a)).
exact (equiv_smalltype _ x.2).
exact (snd (simulation_is_minimal f x_fa).2).
apply path_sigma_hprop; cbn.
transparent assert (x_a : (x.1 < a)).
exact (equiv_smalltype _ x.2).
unfold initial_segment_property.
exact (snd (simulation_is_minimal f (simulation_is_hom f x_a)).2).
intros [x x_a] [y y_a]; cbn.
exact (simulation_is_hom f).
destruct (simulation_is_minimal f fx_fy) as (a' & a'_y & p).
apply injective in p; try exact _.
Lemma path_initial_segment_simulation `{Univalence}
`{PropResizing}
{A : Type} {R : Lt A} `{IsOrdinal A R}
{B : Type} {Q : Lt B} `{IsOrdinal B Q}
(f : A -> B) {is_simulation : IsSimulation f} (a : A)
: ↓(f a) = ↓a.
apply equiv_path_Ordinal.
apply (equiv_initial_segment_simulation f).
(** * `Ordinal` is an ordinal *)
Instance lt_Ordinal@{carrier relation +} `{PropResizing}
: Lt Ordinal@{carrier relation}
:= fun A B => exists b : B, A = ↓b.
Instance is_mere_relation_lt_on_Ordinal `{Univalence} `{PropResizing}
: is_mere_relation Ordinal lt_Ordinal.
apply ishprop_sigma_disjoint.
apply (injective initial_segment).
Definition bound `{PropResizing}
{A B : Ordinal} (H : A < B)
: B
:= H.1.
(* We use this notation to hide the proof of A < B that `bound` takes as an argument *)
Notation "A ◁ B" := (@bound A B _) (at level 70) : Ordinals.
Definition bound_property `{PropResizing}
{A B : Ordinal} (H : A < B)
: A = ↓(bound H)
:= H.2.
Lemma isembedding_initial_segment `{PropResizing} `{Univalence}
{A : Ordinal} (a b : A)
: a < b <-> ↓a < ↓b.
exact (path_initial_segment_simulation out (in_ a a_b)).
assert (a = out (bound a_b))
as ->.
apply (injective initial_segment).
rewrite (path_initial_segment_simulation out).
apply initial_segment_property.
Instance Ordinal_is_ordinal `{PropResizing} `{Univalence}
: IsOrdinal Ordinal (<).
exact is_mere_relation_lt_on_Ordinal.
srapply equiv_adjointify.
assert (lt_B : forall a : A, ↓a < B).
exact (fun a => bound (lt_B a)).
assert (lt_A : forall b : B, ↓b < A).
exact (fun b => bound (lt_A b)).
apply (injective initial_segment).
repeat rewrite <- bound_property.
apply (injective initial_segment).
repeat rewrite <- bound_property.
apply isembedding_initial_segment.
repeat rewrite <- bound_property.
apply isembedding_initial_segment.
apply isembedding_initial_segment in a_a'.
repeat rewrite <- bound_property in a_a'.
apply isembedding_initial_segment in a_a'.
induction (well_foundedness a) as [a _ IH].
rewrite <- (path_initial_segment_simulation out).
apply initial_segment_property.
intros ? ? A [x ->] [a ->].
rewrite (path_initial_segment_simulation out).
(* This is analogous to the set-theoretic statement that an ordinal is the set of all smaller ordinals. *)
Lemma isomorphism_to_initial_segment `{PropResizing} `{Univalence}
(B : Ordinal@{A _})
: Isomorphism B ↓B.
srapply equiv_adjointify.
eapply equiv_smalltype in HC.
apply path_sigma_hprop; cbn.
apply isembedding_initial_segment.
(** But an ordinal isn't isomorphic to any initial segment of itself. *)
Lemma ordinal_initial `{PropResizing} `{Univalence} (O : Ordinal) (a : O)
: Isomorphism O ↓a -> Empty.
intros p % equiv_path_Ordinal.
enough (HO : O < O) by exact (irreflexive_ordinal_relation _ _ _ _ HO).
(** * Ordinal successor *)
Definition successor (A : Ordinal) : Ordinal.
set (carrier := (A + Unit)%type).
set (relation (x y : carrier) :=
match x, y with
| inl x, inl y => x < y
| inl x, inr _ => Unit
| inr _, inl y => Empty
| inr _, inr _ => Empty
end).
intros [x | ?] [y | ?]; cbn; exact _.
intros [x | []] [y | []] H.
enough (H0 : relation (inl x) (inl x)).
destruct (irreflexivity _ _ H0).
enough (H0 : relation (inl y) (inl y)).
destruct (irreflexivity _ _ H0).
assert (H : forall a, Accessible relation (inl a)).
induction (well_foundedness a) as [a _ IH].
constructor; intros [b | []]; cbn; intros H.
constructor; intros [b | []]; cbn; intros H0.
intros [x | []] [y | []] [z | []]; cbn; auto.
Lemma lt_successor `{PropResizing} `{Univalence} (A : Ordinal)
: A < successor A.
srapply equiv_adjointify.
intros [[a | []] Ha]; cbn in *.
apply equiv_smalltype in Ha.
assert (IsHProp (smalltype Unit)) by exact _.
destruct (equiv_smalltype _ Ha).
(** In the following, there are no constraints between [i] and [j]. *)
Context `{PropResizing} `{Funext} {A : Type@{i}} {B : HSet@{j}} (f : A -> B).
Local Definition qkfs := quotient_kernel_factor_small f.
Local Definition image : Type@{i} := qkfs.1.
Local Definition factor1 : A -> image := qkfs.2.1.
Local Definition factor2 : image -> B := qkfs.2.2.1.
Local Definition isinjective_factor2 : IsInjective factor2
:= isinj_embedding _ (snd (fst qkfs.2.2.2)).
Local Definition image_ind_prop (P : image -> Type@{k}) `{forall x, IsHProp (P x)}
(step : forall a : A, P (factor1 a))
: forall x : image, P x
:= Quotient_ind_hprop _ P step.
(** [factor2 o factor1 == f] is definitional, so we don't state that. *)
Definition limit `{Univalence} `{PropResizing}
{X : Type} (F : X -> Ordinal) : Ordinal.
set (f := fun x : {i : X & F i} => ↓x.2).
set (carrier := image f : Type@{i}).
set (relation := fun A B : carrier =>
smalltype (factor2 f A < factor2 f B)
: Type@{i}).
snapply (isordinal_simulation (factor2 f)).
apply isinjective_factor2.
apply equiv_smalltype in x_x'.
nrefine (image_ind_prop f _ _).
change (factor2 f (class_of _ a)) with (f a).
exists (factor1 f (a.1; out (bound B_fa))).
change (factor2 f (factor1 f ?A)) with (f A).
assert (↓(out (bound B_fa)) = B) as ->.
rewrite (path_initial_segment_simulation out).
Instance le_on_Ordinal : Le Ordinal :=
fun A B => exists f : A -> B, IsSimulation f.
Definition limit_is_upper_bound `{Univalence} `{PropResizing}
{X : Type} (F : X -> Ordinal)
: forall x, F x <= limit F.
set (f := fun x : {i : X & F i} => ↓x.2).
unfold le, le_on_Ordinal.
exists (fun u => factor1 f (x; u)).
change (smalltype (f (x; u) < f (x; v))).
apply isembedding_initial_segment.
nrefine (image_ind_prop f _ _).
change (smalltype (f a < f (x; u))) in a_u.
apply equiv_smalltype in a_u.
exists (out (bound a_u)).
apply initial_segment_property.
apply (isinjective_factor2 f); simpl.
change (factor2 f (factor1 f ?A)) with (f A).
rewrite (path_initial_segment_simulation out).
(** Any type equivalent to an ordinal is an ordinal, and we can change the universe that the relation takes values in. *)
(* TODO: Should factor this into two results: (1) Anything equivalent to an ordinal is an ordinal (with the relation landing in the same universe for both). (2) Under PropResizing, the universe that the relation takes values in can be changed. *)
Definition resize_ordinal@{i j +} `{PropResizing} (B : Ordinal@{i _}) (C : Type@{j}) (g : C <~> B)
: Ordinal@{j _}.
exists C (fun c1 c2 : C => smalltype (g c1 < g c2)).
snapply (isordinal_simulation g); only 2, 3, 4, 5: exact _.
exact (istrunc_equiv_istrunc B (equiv_inverse g)).
apply (equiv_smalltype _).
Lemma resize_ordinal_iso@{i j +} `{PropResizing} (B : Ordinal@{i _}) (C : Type@{j}) (g : C <~> B)
: Isomorphism (resize_ordinal B C g) B.
split; apply equiv_smalltype.