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.