MathClasses.interfaces.orders

Require Import abstract_algebra.


Class PartialOrder `{Ae : Equiv A} (Ale : Le A) : Prop :=
  { po_setoid : Setoid A
  ; po_proper:> Proper ((=) ==> (=) ==> iff) (≤)
  ; po_preorder:> PreOrder (≤)
  ; po_antisym:> AntiSymmetric (≤) }.

Class TotalOrder `{Ae : Equiv A} (Ale : Le A) : Prop :=
  { total_order_po :> PartialOrder (≤)
  ; total_order_total :> TotalRelation (≤) }.

Class MeetSemiLatticeOrder `{Ae : Equiv A} (Ale : Le A) `{Meet A} : Prop :=
  { meet_sl_order :> PartialOrder (≤)
  ; meet_lb_l : ∀ x y, x ⊓ y ≤ x
  ; meet_lb_r : ∀ x y, x ⊓ y ≤ y
  ; meet_glb : ∀ x y z, z ≤ x → z ≤ y → z ≤ x ⊓ y }.

Class JoinSemiLatticeOrder `{Ae : Equiv A} (Ale : Le A) `{Join A} : Prop :=
  { join_sl_order :> PartialOrder (≤)
  ; join_ub_l : ∀ x y, x ≤ x ⊔ y
  ; join_ub_r : ∀ x y, y ≤ x ⊔ y
  ; join_lub : ∀ x y z, x ≤ z → y ≤ z → x ⊔ y ≤ z }.

Class LatticeOrder `{Ae : Equiv A} (Ale : Le A) `{Meet A} `{Join A} : Prop :=
  { lattice_order_meet :> MeetSemiLatticeOrder (≤)
  ; lattice_order_join :> JoinSemiLatticeOrder (≤) }.

Class StrictSetoidOrder `{Ae : Equiv A} (Alt : Lt A) : Prop :=
  { strict_setoid_order_setoid : Setoid A
  ; strict_setoid_order_proper :> Proper ((=) ==> (=) ==> iff) (<)
  ; strict_setoid_order_strict :> StrictOrder (<) }.

Class PseudoOrder `{Ae : Equiv A} `{Aap : Apart A} (Alt : Lt A) : Prop :=
  { pseudo_order_setoid : StrongSetoid A
  ; pseudo_order_antisym : ∀ x y, ¬(x < y ∧ y < x)
  ; pseudo_order_cotrans :> CoTransitive (<)
  ; apart_iff_total_lt : ∀ x y, x ≶ y ↔ x < y ∨ y < x }.

Class FullPartialOrder `{Ae : Equiv A} `{Aap : Apart A} (Ale : Le A) (Alt : Lt A) : Prop :=
  { strict_po_setoid : StrongSetoid A
  ; strict_po_po :> PartialOrder (≤)
  ; strict_po_trans :> Transitive (<)
  ; lt_iff_le_apart : ∀ x y, x < y ↔ x ≤ y ∧ x ≶ y }.

Class FullPseudoOrder `{Ae : Equiv A} `{Aap : Apart A} (Ale : Le A) (Alt : Lt A) : Prop :=
  { full_pseudo_order_pseudo :> PseudoOrder Alt
  ; le_iff_not_lt_flip : ∀ x y, x ≤ y ↔ ¬y < x }.

Section order_maps.
  Context {A B : Type} {Ae: Equiv A} {Ale: Le A} {Alt: Lt A} {Be: Equiv B} {Ble: Le B} {Blt: Lt B} (f : A → B).

  Class Order_Morphism :=
    { order_morphism_mor : Setoid_Morphism f
    ; order_morphism_po_a : PartialOrder Ale
    ; order_morphism_po_b : PartialOrder Ble }.

  Class StrictOrder_Morphism :=
    { strict_order_morphism_mor : Setoid_Morphism f
    ; strict_order_morphism_so_a : StrictSetoidOrder Alt
    ; strict_order_morphism_so_b : StrictSetoidOrder Blt }.

  Class OrderPreserving :=
    { order_preserving_morphism :> Order_Morphism
    ; order_preserving : `(x ≤ y → f x ≤ f y) }.

  Class OrderReflecting :=
    { order_reflecting_morphism :> Order_Morphism
    ; order_reflecting : `(f x ≤ f y → x ≤ y) }.

  Class OrderEmbedding :=
    { order_embedding_preserving :> OrderPreserving
    ; order_embedding_reflecting :> OrderReflecting }.

  Class OrderIsomorphism `{!Inverse f} :=
    { order_iso_embedding :> OrderEmbedding
    ; order_iso_surjective :> Surjective f }.

  Class StrictlyOrderPreserving :=
    { strictly_order_preserving_morphism :> StrictOrder_Morphism
    ; strictly_order_preserving : `(x < y → f x < f y) }.

  Class StrictlyOrderReflecting :=
    { strictly_order_reflecting_morphism :> StrictOrder_Morphism
    ; strictly_order_reflecting : `(f x < f y → x < y) }.

  Class StrictOrderEmbedding :=
    { strict_order_embedding_preserving :> StrictlyOrderPreserving
    ; strict_order_embedding_reflecting :> StrictlyOrderReflecting }.
End order_maps.

Hint Extern 4 (?f _ ≤ ?f _) ⇒ apply (order_preserving f).
Hint Extern 4 (?f _ < ?f _) ⇒ apply (strictly_order_preserving f).

Class SemiRingOrder `{Equiv A} `{Plus A} `{Mult A}
    `{Zero A} `{One A} (Ale : Le A) :=
  { srorder_po :> PartialOrder Ale
  ; srorder_semiring : SemiRing A
  ; srorder_partial_minus : ∀ x y, x ≤ y → ∃ z, y = x + z
  ; srorder_plus :> ∀ z, OrderEmbedding (z +)
  ; nonneg_mult_compat : ∀ x y, PropHolds (0 ≤ x) → PropHolds (0 ≤ y) → PropHolds (0 ≤ x × y) }.

Class StrictSemiRingOrder `{Equiv A} `{Plus A} `{Mult A}
    `{Zero A} `{One A} (Alt : Lt A) :=
  { strict_srorder_so :> StrictSetoidOrder Alt
  ; strict_srorder_semiring : SemiRing A
  ; strict_srorder_partial_minus : ∀ x y, x < y → ∃ z, y = x + z
  ; strict_srorder_plus :> ∀ z, StrictOrderEmbedding (z +)
  ; pos_mult_compat : ∀ x y, PropHolds (0 < x) → PropHolds (0 < y) → PropHolds (0 < x × y) }.

Class PseudoSemiRingOrder `{Equiv A} `{Apart A} `{Plus A}
    `{Mult A} `{Zero A} `{One A} (Alt : Lt A) :=
  { pseudo_srorder_strict :> PseudoOrder Alt
  ; pseudo_srorder_semiring : SemiRing A
  ; pseudo_srorder_partial_minus : ∀ x y, ¬y < x → ∃ z, y = x + z
  ; pseudo_srorder_plus :> ∀ z, StrictOrderEmbedding (z +)
  ; pseudo_srorder_mult_ext :> StrongSetoid_BinaryMorphism (.*.)
  ; pseudo_srorder_pos_mult_compat : ∀ x y, PropHolds (0 < x) → PropHolds (0 < y) → PropHolds (0 < x × y) }.

Class FullPseudoSemiRingOrder `{Equiv A} `{Apart A} `{Plus A}
    `{Mult A} `{Zero A} `{One A} (Ale : Le A) (Alt : Lt A) :=
  { full_pseudo_srorder_pso :> PseudoSemiRingOrder Alt
  ; full_pseudo_srorder_le_iff_not_lt_flip : ∀ x y, x ≤ y ↔ ¬y < x }.

Hint Extern 7 (PropHolds (0 < _ × _)) ⇒ eapply @pos_mult_compat : typeclass_instances.
Hint Extern 7 (PropHolds (0 ≤ _ × _)) ⇒ eapply @nonneg_mult_compat : typeclass_instances.