Library mathcomp.ssreflect.order

(* (c) Copyright 2006-2019 Microsoft Corporation and Inria.                  
 Distributed under the terms of CeCILL-B.                                  *)

From HB Require Import structures.
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat choice seq.
From mathcomp Require Import path fintype tuple bigop finset div prime finfun.
From mathcomp Require Import finset.

Types equipped with order relations NB: See CONTRIBUTING.md for an introduction to HB concepts and commands. This files defines types equipped with order relations.

How to use orders in MathComp?

Use one of the following modules implementing different theories (all located in the module Order): Order.LTheory: partially ordered types and lattices excluding complement and totality related theorems Order.CTheory: complemented lattices including Order.LTheory Order.TTheory: totally ordered types including Order.LTheory Order.Theory: ordered types including all of the above theory modules To access the definitions, notations, and the theory from, say, "Order.Xyz", insert "Import Order.Xyz." at the top of your scripts. You can also "Import Order.Def." to enjoy shorter notations (e.g., min instead of Order.min, nondecreasing instead of Order.nondecreasing, etc.). In order to reason about abstract orders, notations are accessible by opening the scope "order_scope" bound to the delimiting key "O"; however, when dealing with another notation scope providing order notations for a concrete instance (e.g., "ring_scope"), it is not recommended to open "order_scope" at the same time.

Control of inference (parsing) and printing

One characteristic of ordered types is that one carrier type may have several orders. For example, natural numbers can be totally or partially ordered by the less than or equal relation, the divisibility relation, and their dual relations. Therefore, we need a way to control inference of ordered type instances and printing of generic relations and operations on ordered types. As a rule of thumb, we use the carrier type or its "alias" (named copy) to control inference (using canonical structures), and use a "display" to control the printing of notations. Each generic interface and operation for ordered types has, as its first argument, a "display" of type Order.disp_t. For example, the less than or equal relation has type: Order.le : forall {d : Order.disp_t} {T : porderType d}, rel T, where porderType d is the structure of partially ordered types with display d. (@Order.le dvd_display _ m n) is printed as m %| n because ordered type instances associated to the display dvd_display is intended to represent natural numbers partially ordered by the divisibility relation. We stress that order structure inference can be triggered only from the carrier type (or its alias), but not the display. For example, writing m %| n for m and n of type nat does not trigger an inference of the divisibility relation on natural numbers, which is associated to an alias natdvd for nat; such an inference should be triggered through the use of the corresponding alias, i.e., (m : natdvd) %| n. In other words, displays are merely used to inform the user and the notation mechanism of what the inference did; they are not additional input for the inference. See below for various aliases and their associated displays. NB: algebra/ssrnum.v provides the display ring_display to change the scope of the usual notations to ring_scope. Instantiating d with Disp tt tt or an unknown display will lead to a default display for notations. Alternative notation displays can be defined by : 1. declaring a new opaque definition of type unit. Using the idiom `Fact my_display : Order.disp_t. Proof. exact: Disp tt tt. Qed.` 2. using this symbol to tag canonical porderType structures using `HB.instance Definition _ := isPOrder.Build my_display my_type ...`, 3. declaring notations for the main operations of this library, by setting the first argument of the definition to the display, e.g. `Notation my_syndef_le x y := @Order.le my_display _ x y.` or `Notation "x <=< y" := @Order.lt my_display _ x y (at level ...).` Non overloaded notations will default to the default display. We suggest the user to refer to the example of natdvd below as a guideline example to add their own displays.

Interfaces

We provide the following interfaces for types equipped with an order: porderType d == the type of partially ordered types The HB class is called POrder. bPOrderType d == porderType with a bottom element (\bot) The HB class is called BPOrder. tPOrderType d == porderType with a top element (\top) The HB class is called TPOrder. tbPOrderType d == porderType with both a top and a bottom The HB class is called TBPOrder. meetSemilatticeType d == the type of meet semilattices The HB class is called MeetSemilattice. bMeetSemilatticeType d == meetSemilatticeType with a bottom element The HB class is called BMeetSemilattice. tMeetSemilatticeType d == meetSemilatticeType with a top element The HB class is called TMeetSemilattice. tbMeetSemilatticeType d == meetSemilatticeType with both a top and a bottom The HB class is called TBMeetSemilattice. joinSemilatticeType d == the type of join semilattices The HB class is called JoinSemilattice. bJoinSemilatticeType d == joinSemilatticeType with a bottom element The HB class is called BJoinSemilattice. tJoinSemilatticeType d == joinSemilatticeType with a top element The HB class is called TJoinSemilattice. tbJoinSemilatticeType d == joinSemilatticeType with both a top and a bottom The HB class is called TBJoinSemilattice. latticeType d == the type of lattices The HB class is called Lattice. bLatticeType d == latticeType with a bottom element The HB class is called BLattice. tLatticeType d == latticeType with a top element The HB class is called TLattice. tbLatticeType d == latticeType with both a top and a bottom The HB class is called TBLattice. distrLatticeType d == the type of distributive lattices The HB class is called DistrLattice. bDistrLatticeType d == distrLatticeType with a bottom element The HB class is called BDistrLattice. tDistrLatticeType d == distrLatticeType with a top element The HB class is called TDistrLattice. tbDistrLatticeType d == distrLatticeType with both a top and a bottom The HB class is called TBDistrLattice. orderType d == the type of totally ordered types The HB class is called Total. bOrderType d == orderType with a bottom element The HB class is called BTotal. tOrderType d == orderType with a top element The HB class is called TTotal. tbOrderType d == orderType with both a top and a bottom The HB class is called TBTotal. cDistrLatticeType d == the type of relatively complemented distributive lattices, where each interval [a, b] is equipped with a complement operation The HB class is called CDistrLattice. cbDistrLatticeType d == the type of sectionally complemented distributive lattices, equipped with a bottom, a relative complement operation, and a difference operation, i.e., a complement operation for each interval of the form [\bot, b] The HB class is called CBDistrLattice. ctDistrLatticeType d == the type of dually sectionally complemented distributive lattices, equipped with a top, a relative complement operation, and a dual difference operation, i.e. a complement operation for each interval of the form [a, \top] The HB class is called CTDistrLattice. ctbDistrLatticeType d == the type of complemented distributive lattices, equipped with top, bottom, difference, dual difference, and complement The HB class is called CTBDistrLattice. finPOrderType d == the type of partially ordered finite types The HB class is called FinPOrder. finBPOrderType d == finPOrderType with a bottom element The HB class is called FinBPOrder. finTPOrderType d == finPOrderType with a top element The HB class is called FinTPOrder. finTBPOrderType d == finPOrderType with both a top and a bottom The HB class is called FinTBPOrder. finMeetSemilatticeType d == the type of finite meet semilattice types The HB class is called FinMeetSemilattice. finBMeetSemilatticeType d == finMeetSemilatticeType with a bottom element Note that finTMeetSemilatticeType is just finTBLatticeType. The HB class is called FinBMeetSemilattice. finJoinSemilatticeType d == the type of finite join semilattice types The HB class is called FinJoinSemilattice. finTJoinSemilatticeType d == finJoinSemilatticeType with a top element Note that finBJoinSemilatticeType is just finTBLatticeType. The HB class is called FinTJoinSemilattice. finLatticeType d == the type of finite lattices The HB class is called FinLattice. finTBLatticeType d == the type of nonempty finite lattices The HB class is called FinTBLattice. finDistrLatticeType d == the type of finite distributive lattices The HB class is called FinDistrLattice. finTBDistrLatticeType d == the type of nonempty finite distributive lattices The HB class is called FinTBDistrLattice. finOrderType d == the type of totally ordered finite types The HB class is called FinTotal. finTBOrderType d == the type of nonempty totally ordered finite types The HB class is called FinTBTotal. finCDistrLatticeType d == the type of finite relatively complemented distributive lattices The HB class is called FinCDistrLattice. finCTBDistrLatticeType d == the type of finite complemented distributive lattices The HB class is called FinCTBDistrLattice. and their joins with subType: subPOrder d T P d' == join of porderType d' and subType (P : pred T) such that val is monotonic The HB class is called SubPOrder. meetSubLattice d T P d' == join of latticeType d' and subType (P : pred T) such that val is monotonic and a morphism for meet The HB class is called MeetSubLattice. joinSubLattice d T P d' == join of latticeType d' and subType (P : pred T) such that val is monotonic and a morphism for join The HB class is called JoinSubLattice. subLattice d T P d' == join of JoinSubLattice and MeetSubLattice The HB class is called SubLattice. bJoinSubLattice d T P d' == join of JoinSubLattice and BLattice such that val is a morphism for \bot The HB class is called BJoinSubLattice. tMeetSubLattice d T P d' == join of MeetSubLattice and TLattice such that val is a morphism for \top The HB class is called TMeetSubLattice. bSubLattice d T P d' == join of SubLattice and BLattice such that val is a morphism for \bot The HB class is called BSubLattice. tSubLattice d T P d' == join of SubLattice and TLattice such that val is a morphism for \top The HB class is called BSubLattice. subOrder d T P d' == join of orderType d' and subLatticeType d T P d' The HB class is called SubOrder. subPOrderLattice d T P d' == join of SubPOrder and Lattice The HB class is called SubPOrderLattice. subPOrderBLattice d T P d' == join of SubPOrder and BLattice The HB class is called SubPOrderBLattice. subPOrderTLattice d T P d' == join of SubPOrder and TLattice The HB class is called SubPOrderTLattice. subPOrderTBLattice d T P d' == join of SubPOrder and TBLattice The HB class is called SubPOrderTBLattice. meetSubBLattice d T P d' == join of MeetSubLattice and BLattice The HB class is called MeetSubBLattice. meetSubTLattice d T P d' == join of MeetSubLattice and TLattice The HB class is called MeetSubTLattice. meetSubTBLattice d T P d' == join of MeetSubLattice and TBLattice The HB class is called MeetSubTBLattice. joinSubBLattice d T P d' == join of JoinSubLattice and BLattice The HB class is called JoinSubBLattice. joinSubTLattice d T P d' == join of JoinSubLattice and TLattice The HB class is called JoinSubTLattice. joinSubTBLattice d T P d' == join of JoinSubLattice and TBLattice The HB class is called JoinSubTBLattice. subBLattice d T P d' == join of SubLattice and BLattice The HB class is called SubBLattice. subTLattice d T P d' == join of SubLattice and TLattice The HB class is called SubTLattice. subTBLattice d T P d' == join of SubLattice and TBLattice The HB class is called SubTBLattice. bJoinSubTLattice d T P d' == join of BJoinSubLattice and TBLattice The HB class is called BJoinSubTLattice. tMeetSubBLattice d T P d' == join of TMeetSubLattice and TBLattice The HB class is called TMeetSubBLattice. bSubTLattice d T P d' == join of BSubLattice and TBLattice The HB class is called BSubTLattice. tSubBLattice d T P d' == join of TSubLattice and TBLattice The HB class is called TSubBLattice. tbSubBLattice d T P d' == join of BSubLattice and TSubLattice The HB class is called TBSubLattice. Morphisms between the above structures: OrderMorphism.type d T d' T' == nondecreasing function between two porder := {omorphism T -> T'} MeetLatticeMorphism.type d T d' T', JoinLatticeMorphism.type d T d' T', LatticeMorphism.type d T d' T' == nondecreasing function between two lattices which are morphism for meet, join, and meet/join respectively BLatticeMorphism.type d T d' T' := {blmorphism T -> T'}, TLatticeMorphism.type d T d' T' := {tlmorphism T -> T'}, TBLatticeMorphism.type d T d' T' := {tblmorphism T -> T'} == nondecreasing function between two lattices with bottom/top which are morphism for bottom/top Closedness predicates for the algebraic structures: meetLatticeClosed d T == predicate closed under meet on T : latticeType d The HB class is MeetLatticeClosed. joinLatticeClosed d T == predicate closed under join on T : latticeType d The HB class is JoinLatticeClosed. latticeClosed d T == predicate closed under meet and join The HB class is JoinLatticeClosed. bLatticeClosed d T == predicate that contains bottom The HB class is BLatticeClosed. tLatticeClosed d T == predicate that contains top The HB class is TLatticeClosed. tbLatticeClosed d T == predicate that contains top and bottom the HB class ie TBLatticeClosed. bJoinLatticeClosed d T == predicate that contains bottom and is closed under join The HB class is BJoinLatticeClosed. tMeetLatticeClosed d T == predicate that contains top and is closed under meet The HB class is TMeetLatticeClosed.

Useful lemmas:

On orderType, leP, ltP, and ltgtP are the three main lemmas for case analysis. On porderType, one may use comparableP, comparable_leP, comparable_ltP, and comparable_ltgtP, which are the four main lemmas for case analysis.

Order relations and operations:

In general, an overloaded relation or operation on ordered types takes the following arguments: 1. a display d of type Order.disp_t, 2. an instance T of the minimal structure it operates on, and 3. operands. Here is the exhaustive list of all such operations together with their default notation (defined in order_scope unless specified otherwise). For T of type porderType d, x and y of type T, and C of type bool: x <= y := @Order.le d T x y <-> x is less than or equal to y. x < y := @Order.lt d T x y <-> x is less than y, i.e., (y != x) && (x <= y). x >= y := y <= x <-> x is greater than or equal to y. x > y := y < x <-> x is greater than y. x >=< y := @Order.comparable d T x y (:= (x <= y) || (y <= x)) <-> x and y are comparable. x >< y := ~~ x >=< y <-> x and y are incomparable. x <= y ?= iff C := @Order.leif d T x y C (:= (x <= y) * ((x == y) = C)) <-> x is less than y, or equal iff C is true. x < y ?<= if C := @Order.lteif d T x y C (:= if C then x <= y else x < y) <-> x is smaller than y, and strictly if C is false. Order.min x y := if x < y then x else y Order.max x y := if x < y then y else x f \min g == the function x |-> Order.min (f x) (g x); f \min g simplifies on application. f \max g == the function x |-> Order.max (f x) (g x); f \max g simplifies on application. nondecreasing f <-> the function f : T -> T' is nondecreasing, where T and T' are porderType := {homo f : x y / x <= y} Unary (partially applied) versions of order notations: >= y := @Order.le d T y == a predicate characterizing elements greater than or equal to y > y := @Order.lt d T y <= y := @Order.ge d T y < y := @Order.gt d T y >=< y := [pred x | @Order.comparable d T x y] >< y := [pred x | ~~ @Order.comparable d T x y] 0-ary versions of order notations (in function_scope): <=%O := @Order.le d T <%O := @Order.lt d T >=%O := @Order.ge d T >%O := @Order.gt d T >=<%O := @Order.comparable d T <?=%O := @Order.leif d T <?<=%O := @Order.lteif d T
  • > These conventions are compatible with Haskell's, where ((< y) x) = (x < y) = ((<) x y), except that we write <%O instead of (<).
For T of type bPOrderType d: \bot := @Order.bottom d T == the bottom element of type T For T of type tPOrderType d: \top := @Order.top d T == the top element of type T For T of type meetSemilatticeType d, and x, y of type T: x `&` y := @Order.meet d T x y == the meet of x and y For T of type joinSemilatticeType d, and x, y of type T: x `|` y := @Order.join d T x y == the join of x and y For T of type tMeetSemilatticeType d: \meet_<range> e := \big[Order.meet / Order.top]_<range> e == iterated meet of a meet-semilattice with a top For T of type bJoinSemilatticeType d: \join_<range> e := \big[Order.join / Order.bottom]_<range> e == iterated join of a join-semilattice with a bottom For T of type cDistrLatticeType d, and x, y, z of type T: rcompl x y z == the (relative) complement of z in [x, y] For T of type cbDistrLatticeType d, and x, y of type T: x `\` y := @Order.diff d T x y == the (sectional) complement of y in [\bot, x], i.e., rcompl \bot x y For T of type ctDistrLatticeType d, and x, y of type T: codiff x y == the (dual sectional) complement of y in [x, \top], i.e., rcompl x \top y For T of type ctbDistrLatticeType d, and x of type T: ~` x := @Order.compl d T x == the complement of x in [\bot, \top], i.e., rcompl \bot \top x For porderType we provide the following operations: [arg min_(i < i0 | P) M] == a value i : T minimizing M : R, subject to the condition P (i may appear in P and M), and provided P holds for i0. [arg max_(i > i0 | P) M] == a value i maximizing M subject to P and provided P holds for i0. [arg min_(i < i0 in A) M] == an i \in A minimizing M if i0 \in A. [arg max_(i > i0 in A) M] == an i \in A maximizing M if i0 \in A. [arg min_(i < i0) M] == an i : T minimizing M, given i0 : T. [arg max_(i > i0) M] == an i : T maximizing M, given i0 : T. with head symbols Order.arg_min and Order.arg_max The user may use extremumP or extremum_inP to eliminate them.
  • > patterns for contextual rewriting: leLHS := (X in (X <= _)%O)%pattern leRHS := (X in (_ <= X)%O)%pattern ltLHS := (X in (X < _)%O)%pattern ltRHS := (X in (_ < X)%O)%pattern
We provide aliases for various types and their displays: natdvd := nat (associated with display dvd_display) == an alias for nat which is canonically ordered using divisibility predicate dvdn Notation %|, %<|, gcd, lcm are used instead of <=, <, meet and join. T^d := dual T, where dual is a new definition for (fun T => T) (associated with dual_display d where d is a display) == an alias for T, such that if T is canonically ordered, then T^d is canonically ordered with the dual order, and displayed with an extra ^d in the notation, i.e., <=^d, <^d, >=<^d, ><^d, `&`^d, `|`^d are used and displayed instead of <=, <, >=<, ><, `&`, `|` T *prod[d] T' := T * T' == an alias for the cartesian product such that, if T and T' are canonically ordered, then T *prod[d] T' is canonically ordered in product order, i.e., (x1, x2) <= (y1, y2) = (x1 <= y1) && (x2 <= y2), and displayed in display d T *p T' := T *prod[prod_display d d' ] T' where d and d' are the displays of T and T', respectively, and prod_display adds an extra ^p to all notations T *lexi[d] T' := T * T' == an alias for the cartesian product such that, if T and T' are canonically ordered, then T *lexi[d] T' is canonically ordered in lexicographic order, i.e., (x1, x2) <= (y1, y2) = (x1 <= y1) && ((x1 >= y1) ==> (x2 <= y2)) and (x1, x2) < (y1, y2) = (x1 <= y1) && ((x1 >= y1) ==> (x2 < y2)) and displayed in display d T *l T' := T *lexi[lexi_display d d' ] T' where d and d' are the displays of T and T', respectively, and lexi_display adds an extra ^l to all notations seqprod_with d T := seq T == an alias for seq, such that if T is canonically ordered, then seqprod_with d T is canonically ordered in product order, i.e., [:: x1, .., xn] <= [y1, .., yn] = (x1 <= y1) && ... && (xn <= yn) and displayed in display d n.-tupleprod[d] T == same with n.tuple T seqprod T := seqprod_with (seqprod_display d) T where d is the display of T, and seqprod_display adds an extra ^sp to all notations n.-tupleprod T := n.-tuple[seqprod_display d] T where d is the display of T seqlexi_with d T := seq T == an alias for seq, such that if T is canonically ordered, then seqprod_with d T is canonically ordered in lexicographic order, i.e., [:: x1, .., xn] <= [y1, .., yn] = (x1 <= x2) && ((x1 >= y1) ==> ((x2 <= y2) && ...)) and displayed in display d n.-tuplelexi[d] T == same with n.tuple T seqlexi T := lexiprod_with (seqlexi_display d) T where d is the display of T, and seqlexi_display adds an extra ^sl to all notations n.-tuplelexi T := n.-tuple[seqlexi_display d] T where d is the display of T {subset[d] T} := {set T} == an alias for set which is canonically ordered by the subset order and displayed in display d {subset T} := {subset[subset_display] T} The following notations are provided to build substructures: [SubChoice_isSubPOrder of U by <: with disp] == [SubChoice_isSubPOrder of U by <: ] == porderType mixin for a subType whose base type is a porderType [SubPOrder_isSubLattice of U by <: with disp] == [SubPOrder_isSubLattice of U by <: ] == [SubChoice_isSubLattice of U by <: with disp] == [SubChoice_isSubLattice of U by <: ] == latticeType mixin for a subType whose base type is a latticeType and whose predicate is a latticeClosed [SubPOrder_isBSubLattice of U by <: with disp] == [SubPOrder_isBSubLattice of U by <: ] == [SubChoice_isBSubLattice of U by <: with disp] == [SubChoice_isBSubLattice of U by <: ] == blatticeType mixin for a subType whose base type is a blatticeType and whose predicate is both a latticeClosed and a bLatticeClosed [SubPOrder_isTSubLattice of U by <: with disp] == [SubPOrder_isTSubLattice of U by <: ] == [SubChoice_isTSubLattice of U by <: with disp] == [SubChoice_isTSubLattice of U by <: ] == tlatticeType mixin for a subType whose base type is a tlatticeType and whose predicate is both a latticeClosed and a tLatticeClosed [SubPOrder_isTBSubLattice of U by <: with disp] == [SubPOrder_isTBSubLattice of U by <: ] == [SubChoice_isTBSubLattice of U by <: with disp] == [SubChoice_isTBSubLattice of U by <: ] == tblatticeType mixin for a subType whose base type is a tblatticeType and whose predicate is both a latticeClosed and a tbLatticeClosed [SubLattice_isSubOrder of U by <: with disp] == [SubLattice_isSubOrder of U by <: ] == [SubPOrder_isSubOrder of U by <: with disp] == [SubPOrder_isSubOrder of U by <: ] == [SubChoice_isSubOrder of U by <: with disp] == [SubChoice_isSubOrder of U by <: ] == orderType mixin for a subType whose base type is an orderType [POrder of U by <: ] == porderType mixin for a subType whose base type is a porderType [Order of U by <: ] == orderType mixin for a subType whose base type is an orderType We provide expected instances of ordered types for bool, nat (for leq and and dvdn), 'I_n, 'I_n.+1 (with a top and bottom), nat for dvdn, T *prod[disp] T', T *lexi[disp] T', {t : T & T' x} (with lexicographic ordering), seqprod_with d T (using product order), seqlexi_with d T (with lexicographic ordering), n.-tupleprod[disp] (using product order), n.-tuplelexi[d] T (with lexicographic ordering), on {subset[disp] T} (using subset order) and all possible finite type instances. (Use `HB.about type` to discover the instances on type.) In order to get a canonical order on prod, seq, tuple or set, one may import modules DefaultProdOrder or DefaultProdLexiOrder, DefaultSeqProdOrder or DefaultSeqLexiOrder, DefaultTupleProdOrder or DefaultTupleLexiOrder, and DefaultSetSubsetOrder. We also provide specialized versions of some theorems from path.v. We provide Order.enum_val, Order.enum_rank, and Order.enum_rank_in, which are monotonic variations of enum_val, enum_rank, and enum_rank_in whenever the type is porderType, and their monotonicity is provided if this order is total. The theory is in the module Order (Order.enum_valK, Order.enum_rank_inK, etc) but Order.Enum can be imported to shorten these. We provide an opaque monotonous bijection tagnat.sig / tagnat.rank between the finite types {i : 'I_n & 'I_(p_ i)} and 'I_(\sum_i p_ i): tagnat.sig : 'I_(\sum_i p_ i) -> {i : 'I_n & 'I_(p_ i)} tagnat.rank : {i : 'I_n & 'I_(p_ i)} -> 'I_(\sum_i p_ i) tagnat.sig1 : 'I_(\sum_i p_ i) -> 'I_n tagnat.sig2 : forall p : 'I_(\sum_i p_ i), 'I_(p_ (tagnat.sig1 p)) tagnat.Rank : forall i, 'I_(p_ i) -> 'I_(\sum_i p_ i) Acknowledgments: This file is based on prior work by D. Dreyer, G. Gonthier, A. Nanevski, P-Y Strub, B. Ziliani

Set Implicit Arguments.

Declare Scope order_scope.

Delimit Scope order_scope with O.
Local Open Scope order_scope.

Reserved Notation "<= y" (at level 35).
Reserved Notation ">= y" (at level 35).
Reserved Notation "< y" (at level 35).
Reserved Notation "> y" (at level 35).
Reserved Notation "<= y :> T" (at level 35, y at next level).
Reserved Notation ">= y :> T" (at level 35, y at next level).
Reserved Notation "< y :> T" (at level 35, y at next level).
Reserved Notation "> y :> T" (at level 35, y at next level).
Reserved Notation "x >=< y" (at level 70, no associativity).
Reserved Notation ">=< y" (at level 35).
Reserved Notation ">=< y :> T" (at level 35, y at next level).
Reserved Notation "x >< y" (at level 70, no associativity).
Reserved Notation ">< x" (at level 35).
Reserved Notation ">< y :> T" (at level 35, y at next level).
Reserved Notation "f \min g" (at level 50, left associativity).
Reserved Notation "f \max g" (at level 50, left associativity).

Reserved Notation "x < y ?<= 'if' c" (at level 70, y, c at next level,
  format "x '[hv' < y '/' ?<= 'if' c ']'").
Reserved Notation "x < y ?<= 'if' c :> T" (at level 70, y, c at next level,
  format "x '[hv' < y '/' ?<= 'if' c :> T ']'").

Reserved notations for bottom/top elements
Reserved Notation "\bot" (at level 0).
Reserved Notation "\top" (at level 0).

Reserved notations for lattice operations
Reserved Notation "A `&` B" (at level 48, left associativity).
Reserved Notation "A `|` B" (at level 52, left associativity).
Reserved Notation "A `\` B" (at level 50, left associativity).
Reserved Notation "~` A" (at level 35, right associativity).

Reserved notations for dual order
Reserved Notation "x <=^d y" (at level 70, y at next level).
Reserved Notation "x >=^d y" (at level 70, y at next level).
Reserved Notation "x <^d y" (at level 70, y at next level).
Reserved Notation "x >^d y" (at level 70, y at next level).
Reserved Notation "x <=^d y :> T" (at level 70, y at next level).
Reserved Notation "x >=^d y :> T" (at level 70, y at next level).
Reserved Notation "x <^d y :> T" (at level 70, y at next level).
Reserved Notation "x >^d y :> T" (at level 70, y at next level).
Reserved Notation "<=^d y" (at level 35).
Reserved Notation ">=^d y" (at level 35).
Reserved Notation "<^d y" (at level 35).
Reserved Notation ">^d y" (at level 35).
Reserved Notation "<=^d y :> T" (at level 35, y at next level).
Reserved Notation ">=^d y :> T" (at level 35, y at next level).
Reserved Notation "<^d y :> T" (at level 35, y at next level).
Reserved Notation ">^d y :> T" (at level 35, y at next level).
Reserved Notation "x >=<^d y" (at level 70, no associativity).
Reserved Notation ">=<^d y" (at level 35).
Reserved Notation ">=<^d y :> T" (at level 35, y at next level).
Reserved Notation "x ><^d y" (at level 70, no associativity).
Reserved Notation "><^d x" (at level 35).
Reserved Notation "><^d y :> T" (at level 35, y at next level).

Reserved Notation "x <=^d y <=^d z" (at level 70, y, z at next level).
Reserved Notation "x <^d y <=^d z" (at level 70, y, z at next level).
Reserved Notation "x <=^d y <^d z" (at level 70, y, z at next level).
Reserved Notation "x <^d y <^d z" (at level 70, y, z at next level).
Reserved Notation "x <=^d y ?= 'iff' c" (at level 70, y, c at next level,
  format "x '[hv' <=^d y '/' ?= 'iff' c ']'").
Reserved Notation "x <=^d y ?= 'iff' c :> T" (at level 70, y, c at next level,
  format "x '[hv' <=^d y '/' ?= 'iff' c :> T ']'").
Reserved Notation "x <^d y ?<= 'if' c" (at level 70, y, c at next level,
  format "x '[hv' <^d y '/' ?<= 'if' c ']'").
Reserved Notation "x <^d y ?<= 'if' c :> T" (at level 70, y, c at next level,
  format "x '[hv' <^d y '/' ?<= 'if' c :> T ']'").

Reserved Notation "\bot^d" (at level 0).
Reserved Notation "\top^d" (at level 0).

Reserved Notation "A `&^d` B" (at level 48, left associativity).
Reserved Notation "A `|^d` B" (at level 52, left associativity).
Reserved Notation "A `\^d` B" (at level 50, left associativity).
Reserved Notation "~^d` A" (at level 35, right associativity).

Reserved notations for product ordering of prod
Reserved Notation "x <=^p y" (at level 70, y at next level).
Reserved Notation "x >=^p y" (at level 70, y at next level).
Reserved Notation "x <^p y" (at level 70, y at next level).
Reserved Notation "x >^p y" (at level 70, y at next level).
Reserved Notation "x <=^p y :> T" (at level 70, y at next level).
Reserved Notation "x >=^p y :> T" (at level 70, y at next level).
Reserved Notation "x <^p y :> T" (at level 70, y at next level).
Reserved Notation "x >^p y :> T" (at level 70, y at next level).
Reserved Notation "<=^p y" (at level 35).
Reserved Notation ">=^p y" (at level 35).
Reserved Notation "<^p y" (at level 35).
Reserved Notation ">^p y" (at level 35).
Reserved Notation "<=^p y :> T" (at level 35, y at next level).
Reserved Notation ">=^p y :> T" (at level 35, y at next level).
Reserved Notation "<^p y :> T" (at level 35, y at next level).
Reserved Notation ">^p y :> T" (at level 35, y at next level).
Reserved Notation "x >=<^p y" (at level 70, no associativity).
Reserved Notation ">=<^p x" (at level 35).
Reserved Notation ">=<^p y :> T" (at level 35, y at next level).
Reserved Notation "x ><^p y" (at level 70, no associativity).
Reserved Notation "><^p x" (at level 35).
Reserved Notation "><^p y :> T" (at level 35, y at next level).

Reserved Notation "x <=^p y <=^p z" (at level 70, y, z at next level).
Reserved Notation "x <^p y <=^p z" (at level 70, y, z at next level).
Reserved Notation "x <=^p y <^p z" (at level 70, y, z at next level).
Reserved Notation "x <^p y <^p z" (at level 70, y, z at next level).
Reserved Notation "x <=^p y ?= 'iff' c" (at level 70, y, c at next level,
  format "x '[hv' <=^p y '/' ?= 'iff' c ']'").
Reserved Notation "x <=^p y ?= 'iff' c :> T" (at level 70, y, c at next level,
  format "x '[hv' <=^p y '/' ?= 'iff' c :> T ']'").

Reserved Notation "\bot^p" (at level 0).
Reserved Notation "\top^p" (at level 0).

Reserved Notation "A `&^p` B" (at level 48, left associativity).
Reserved Notation "A `|^p` B" (at level 52, left associativity).
Reserved Notation "A `\^p` B" (at level 50, left associativity).
Reserved Notation "~^p` A" (at level 35, right associativity).

Reserved notations for product ordering of seq
Reserved Notation "x <=^sp y" (at level 70, y at next level).
Reserved Notation "x >=^sp y" (at level 70, y at next level).
Reserved Notation "x <^sp y" (at level 70, y at next level).
Reserved Notation "x >^sp y" (at level 70, y at next level).
Reserved Notation "x <=^sp y :> T" (at level 70, y at next level).
Reserved Notation "x >=^sp y :> T" (at level 70, y at next level).
Reserved Notation "x <^sp y :> T" (at level 70, y at next level).
Reserved Notation "x >^sp y :> T" (at level 70, y at next level).
Reserved Notation "<=^sp y" (at level 35).
Reserved Notation ">=^sp y" (at level 35).
Reserved Notation "<^sp y" (at level 35).
Reserved Notation ">^sp y" (at level 35).
Reserved Notation "<=^sp y :> T" (at level 35, y at next level).
Reserved Notation ">=^sp y :> T" (at level 35, y at next level).
Reserved Notation "<^sp y :> T" (at level 35, y at next level).
Reserved Notation ">^sp y :> T" (at level 35, y at next level).
Reserved Notation "x >=<^sp y" (at level 70, no associativity).
Reserved Notation ">=<^sp x" (at level 35).
Reserved Notation ">=<^sp y :> T" (at level 35, y at next level).
Reserved Notation "x ><^sp y" (at level 70, no associativity).
Reserved Notation "><^sp x" (at level 35).
Reserved Notation "><^sp y :> T" (at level 35, y at next level).

Reserved Notation "x <=^sp y <=^sp z" (at level 70, y, z at next level).
Reserved Notation "x <^sp y <=^sp z" (at level 70, y, z at next level).
Reserved Notation "x <=^sp y <^sp z" (at level 70, y, z at next level).
Reserved Notation "x <^sp y <^sp z" (at level 70, y, z at next level).
Reserved Notation "x <=^sp y ?= 'iff' c" (at level 70, y, c at next level,
  format "x '[hv' <=^sp y '/' ?= 'iff' c ']'").
Reserved Notation "x <=^sp y ?= 'iff' c :> T" (at level 70, y, c at next level,
  format "x '[hv' <=^sp y '/' ?= 'iff' c :> T ']'").

Reserved Notation "\bot^sp" (at level 0).
Reserved Notation "\top^sp" (at level 0).

Reserved Notation "A `&^sp` B" (at level 48, left associativity).
Reserved Notation "A `|^sp` B" (at level 52, left associativity).
Reserved Notation "A `\^sp` B" (at level 50, left associativity).
Reserved Notation "~^sp` A" (at level 35, right associativity).

Reserved notations for lexicographic ordering of prod
Reserved Notation "x <=^l y" (at level 70, y at next level).
Reserved Notation "x >=^l y" (at level 70, y at next level).
Reserved Notation "x <^l y" (at level 70, y at next level).
Reserved Notation "x >^l y" (at level 70, y at next level).
Reserved Notation "x <=^l y :> T" (at level 70, y at next level).
Reserved Notation "x >=^l y :> T" (at level 70, y at next level).
Reserved Notation "x <^l y :> T" (at level 70, y at next level).
Reserved Notation "x >^l y :> T" (at level 70, y at next level).
Reserved Notation "<=^l y" (at level 35).
Reserved Notation ">=^l y" (at level 35).
Reserved Notation "<^l y" (at level 35).
Reserved Notation ">^l y" (at level 35).
Reserved Notation "<=^l y :> T" (at level 35, y at next level).
Reserved Notation ">=^l y :> T" (at level 35, y at next level).
Reserved Notation "<^l y :> T" (at level 35, y at next level).
Reserved Notation ">^l y :> T" (at level 35, y at next level).
Reserved Notation "x >=<^l y" (at level 70, no associativity).
Reserved Notation ">=<^l x" (at level 35).
Reserved Notation ">=<^l y :> T" (at level 35, y at next level).
Reserved Notation "x ><^l y" (at level 70, no associativity).
Reserved Notation "><^l x" (at level 35).
Reserved Notation "><^l y :> T" (at level 35, y at next level).

Reserved Notation "x <=^l y <=^l z" (at level 70, y, z at next level).
Reserved Notation "x <^l y <=^l z" (at level 70, y, z at next level).
Reserved Notation "x <=^l y <^l z" (at level 70, y, z at next level).
Reserved Notation "x <^l y <^l z" (at level 70, y, z at next level).
Reserved Notation "x <=^l y ?= 'iff' c" (at level 70, y, c at next level,
  format "x '[hv' <=^l y '/' ?= 'iff' c ']'").
Reserved Notation "x <=^l y ?= 'iff' c :> T" (at level 70, y, c at next level,
  format "x '[hv' <=^l y '/' ?= 'iff' c :> T ']'").

Reserved Notation "\bot^l" (at level 0).
Reserved Notation "\top^l" (at level 0).

Reserved Notation "A `&^l` B" (at level 48, left associativity).
Reserved Notation "A `|^l` B" (at level 52, left associativity).
Reserved Notation "A `\^l` B" (at level 50, left associativity).
Reserved Notation "~^l` A" (at level 35, right associativity).

Reserved notations for lexicographic ordering of seq
Reserved Notation "x <=^sl y" (at level 70, y at next level).
Reserved Notation "x >=^sl y" (at level 70, y at next level).
Reserved Notation "x <^sl y" (at level 70, y at next level).
Reserved Notation "x >^sl y" (at level 70, y at next level).
Reserved Notation "x <=^sl y :> T" (at level 70, y at next level).
Reserved Notation "x >=^sl y :> T" (at level 70, y at next level).
Reserved Notation "x <^sl y :> T" (at level 70, y at next level).
Reserved Notation "x >^sl y :> T" (at level 70, y at next level).
Reserved Notation "<=^sl y" (at level 35).
Reserved Notation ">=^sl y" (at level 35).
Reserved Notation "<^sl y" (at level 35).
Reserved Notation ">^sl y" (at level 35).
Reserved Notation "<=^sl y :> T" (at level 35, y at next level).
Reserved Notation ">=^sl y :> T" (at level 35, y at next level).
Reserved Notation "<^sl y :> T" (at level 35, y at next level).
Reserved Notation ">^sl y :> T" (at level 35, y at next level).
Reserved Notation "x >=<^sl y" (at level 70, no associativity).
Reserved Notation ">=<^sl x" (at level 35).
Reserved Notation ">=<^sl y :> T" (at level 35, y at next level).
Reserved Notation "x ><^sl y" (at level 70, no associativity).
Reserved Notation "><^sl x" (at level 35).
Reserved Notation "><^sl y :> T" (at level 35, y at next level).

Reserved Notation "x <=^sl y <=^sl z" (at level 70, y, z at next level).
Reserved Notation "x <^sl y <=^sl z" (at level 70, y, z at next level).
Reserved Notation "x <=^sl y <^sl z" (at level 70, y, z at next level).
Reserved Notation "x <^sl y <^sl z" (at level 70, y, z at next level).
Reserved Notation "x <=^sl y ?= 'iff' c" (at level 70, y, c at next level,
  format "x '[hv' <=^sl y '/' ?= 'iff' c ']'").
Reserved Notation "x <=^sl y ?= 'iff' c :> T" (at level 70, y, c at next level,
  format "x '[hv' <=^sl y '/' ?= 'iff' c :> T ']'").

Reserved Notation "\bot^sl" (at level 0).
Reserved Notation "\top^sl" (at level 0).

Reserved Notation "A `&^sl` B" (at level 48, left associativity).
Reserved Notation "A `|^sl` B" (at level 52, left associativity).
Reserved Notation "A `\^sl` B" (at level 50, left associativity).
Reserved Notation "~^sl` A" (at level 35, right associativity).

Reserved notations for divisibility
Reserved Notation "x %<| y" (at level 70, no associativity).

Reserved Notation "\gcd_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \gcd_ i '/ ' F ']'").
Reserved Notation "\gcd_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \gcd_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\gcd_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \gcd_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\gcd_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \gcd_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\gcd_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \gcd_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\gcd_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \gcd_ ( i | P ) '/ ' F ']'").
Reserved Notation "\gcd_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\gcd_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\gcd_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \gcd_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\gcd_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \gcd_ ( i < n ) F ']'").
Reserved Notation "\gcd_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \gcd_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\gcd_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \gcd_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\lcm_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \lcm_ i '/ ' F ']'").
Reserved Notation "\lcm_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \lcm_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\lcm_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \lcm_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\lcm_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \lcm_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\lcm_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \lcm_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\lcm_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \lcm_ ( i | P ) '/ ' F ']'").
Reserved Notation "\lcm_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\lcm_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\lcm_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \lcm_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\lcm_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \lcm_ ( i < n ) F ']'").
Reserved Notation "\lcm_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \lcm_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\lcm_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \lcm_ ( i 'in' A ) '/ ' F ']'").

Reserved notations for iterative meet and join
Reserved Notation "\meet_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \meet_ i '/ ' F ']'").
Reserved Notation "\meet_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \meet_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\meet_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \meet_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\meet_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \meet_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\meet_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \meet_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\meet_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \meet_ ( i | P ) '/ ' F ']'").
Reserved Notation "\meet_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\meet_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\meet_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \meet_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\meet_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \meet_ ( i < n ) F ']'").
Reserved Notation "\meet_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \meet_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\meet_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \meet_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\join_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \join_ i '/ ' F ']'").
Reserved Notation "\join_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \join_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\join_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \join_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\join_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \join_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\join_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \join_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\join_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \join_ ( i | P ) '/ ' F ']'").
Reserved Notation "\join_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\join_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\join_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \join_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\join_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \join_ ( i < n ) F ']'").
Reserved Notation "\join_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \join_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\join_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \join_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\min_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \min_ i '/ ' F ']'").
Reserved Notation "\min_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \min_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\min_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \min_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\min_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \min_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\min_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \min_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\min_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \min_ ( i | P ) '/ ' F ']'").
Reserved Notation "\min_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\min_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\min_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \min_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\min_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \min_ ( i < n ) F ']'").
Reserved Notation "\min_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \min_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\min_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \min_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\max_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \max_ i '/ ' F ']'").
Reserved Notation "\max_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \max_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\max_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \max_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\max_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \max_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\max_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \max_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\max_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \max_ ( i | P ) '/ ' F ']'").
Reserved Notation "\max_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\max_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\max_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \max_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\max_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \max_ ( i < n ) F ']'").
Reserved Notation "\max_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \max_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\max_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \max_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\meet^d_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \meet^d_ i '/ ' F ']'").
Reserved Notation "\meet^d_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \meet^d_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\meet^d_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \meet^d_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\meet^d_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \meet^d_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\meet^d_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \meet^d_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\meet^d_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \meet^d_ ( i | P ) '/ ' F ']'").
Reserved Notation "\meet^d_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\meet^d_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\meet^d_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \meet^d_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\meet^d_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \meet^d_ ( i < n ) F ']'").
Reserved Notation "\meet^d_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \meet^d_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\meet^d_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \meet^d_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\join^d_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \join^d_ i '/ ' F ']'").
Reserved Notation "\join^d_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \join^d_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\join^d_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \join^d_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\join^d_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \join^d_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\join^d_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \join^d_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\join^d_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \join^d_ ( i | P ) '/ ' F ']'").
Reserved Notation "\join^d_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\join^d_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\join^d_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \join^d_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\join^d_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \join^d_ ( i < n ) F ']'").
Reserved Notation "\join^d_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \join^d_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\join^d_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \join^d_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\min^d_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \min^d_ i '/ ' F ']'").
Reserved Notation "\min^d_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \min^d_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\min^d_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \min^d_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\min^d_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \min^d_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\min^d_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \min^d_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\min^d_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \min^d_ ( i | P ) '/ ' F ']'").
Reserved Notation "\min^d_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\min^d_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\min^d_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \min^d_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\min^d_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \min^d_ ( i < n ) F ']'").
Reserved Notation "\min^d_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \min^d_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\min^d_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \min^d_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\max^d_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \max^d_ i '/ ' F ']'").
Reserved Notation "\max^d_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \max^d_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\max^d_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \max^d_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\max^d_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \max^d_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\max^d_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \max^d_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\max^d_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \max^d_ ( i | P ) '/ ' F ']'").
Reserved Notation "\max^d_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\max^d_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\max^d_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \max^d_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\max^d_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \max^d_ ( i < n ) F ']'").
Reserved Notation "\max^d_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \max^d_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\max^d_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \max^d_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\meet^p_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \meet^p_ i '/ ' F ']'").
Reserved Notation "\meet^p_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \meet^p_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\meet^p_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \meet^p_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\meet^p_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \meet^p_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\meet^p_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \meet^p_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\meet^p_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \meet^p_ ( i | P ) '/ ' F ']'").
Reserved Notation "\meet^p_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\meet^p_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\meet^p_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \meet^p_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\meet^p_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \meet^p_ ( i < n ) F ']'").
Reserved Notation "\meet^p_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \meet^p_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\meet^p_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \meet^p_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\join^p_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \join^p_ i '/ ' F ']'").
Reserved Notation "\join^p_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \join^p_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\join^p_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \join^p_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\join^p_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \join^p_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\join^p_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \join^p_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\join^p_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \join^p_ ( i | P ) '/ ' F ']'").
Reserved Notation "\join^p_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\join^p_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\join^p_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \join^p_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\join^p_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \join^p_ ( i < n ) F ']'").
Reserved Notation "\join^p_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \join^p_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\join^p_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \join^p_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\meet^sp_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \meet^sp_ i '/ ' F ']'").
Reserved Notation "\meet^sp_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \meet^sp_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\meet^sp_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \meet^sp_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\meet^sp_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \meet^sp_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\meet^sp_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \meet^sp_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\meet^sp_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \meet^sp_ ( i | P ) '/ ' F ']'").
Reserved Notation "\meet^sp_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\meet^sp_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\meet^sp_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \meet^sp_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\meet^sp_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \meet^sp_ ( i < n ) F ']'").
Reserved Notation "\meet^sp_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \meet^sp_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\meet^sp_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \meet^sp_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "\join^sp_ i F"
  (at level 41, F at level 41, i at level 0,
           format "'[' \join^sp_ i '/ ' F ']'").
Reserved Notation "\join^sp_ ( i <- r | P ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \join^sp_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\join^sp_ ( i <- r ) F"
  (at level 41, F at level 41, i, r at level 50,
           format "'[' \join^sp_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\join^sp_ ( m <= i < n | P ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \join^sp_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\join^sp_ ( m <= i < n ) F"
  (at level 41, F at level 41, i, m, n at level 50,
           format "'[' \join^sp_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\join^sp_ ( i | P ) F"
  (at level 41, F at level 41, i at level 50,
           format "'[' \join^sp_ ( i | P ) '/ ' F ']'").
Reserved Notation "\join^sp_ ( i : t | P ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\join^sp_ ( i : t ) F"
  (at level 41, F at level 41, i at level 50).
Reserved Notation "\join^sp_ ( i < n | P ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \join^sp_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\join^sp_ ( i < n ) F"
  (at level 41, F at level 41, i, n at level 50,
           format "'[' \join^sp_ ( i < n ) F ']'").
Reserved Notation "\join^sp_ ( i 'in' A | P ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \join^sp_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\join^sp_ ( i 'in' A ) F"
  (at level 41, F at level 41, i, A at level 50,
           format "'[' \join^sp_ ( i 'in' A ) '/ ' F ']'").

Reserved Notation "'{' 'omorphism' U '->' V '}'"
  (at level 0, U at level 98, V at level 99,
   format "{ 'omorphism' U -> V }").
Reserved Notation "'{' 'mlmorphism' U '->' V '}'"
  (at level 0, U at level 98, V at level 99,
   format "{ 'mlmorphism' U -> V }").
Reserved Notation "'{' 'jlmorphism' U '->' V '}'"
  (at level 0, U at level 98, V at level 99,
   format "{ 'jlmorphism' U -> V }").
Reserved Notation "'{' 'lmorphism' U '->' V '}'"
  (at level 0, U at level 98, V at level 99,
   format "{ 'lmorphism' U -> V }").
Reserved Notation "'{' 'blmorphism' U '->' V '}'"
  (at level 0, U at level 98, V at level 99,
   format "{ 'blmorphism' U -> V }").
Reserved Notation "'{' 'tlmorphism' U '->' V '}'"
  (at level 0, U at level 98, V at level 99,
   format "{ 'tlmorphism' U -> V }").
Reserved Notation "'{' 'tblmorphism' U '->' V '}'"
  (at level 0, U at level 98, V at level 99,
   format "{ 'tblmorphism' U -> V }").

Module Order.

#[projections(primitive)] Record disp_t := Disp {d1 : unit; d2 : unit}.

#[key="T", primitive]
HB.mixin Record isDuallyPOrder (d : disp_t) T of Equality T := {
  le : rel T;
  lt : rel T;
  lt_def : ∀ x y, lt x y = (y != x) && (le x y);
  gt_def : ∀ x y, lt y x = (y != x) && (le y x);
  le_refl : reflexive le;
  ge_refl : reflexive (fun x y ⇒ le y x);
  le_anti : antisymmetric le;
  ge_anti : antisymmetric (fun x y ⇒ le y x);
  le_trans : transitive le;
  ge_trans : transitive (fun x y ⇒ le y x);
}.

#[short(type="porderType")]
HB.structure Definition POrder (d : disp_t) :=
  { T of Choice T & isDuallyPOrder d T }.

#[key="T", primitive]
HB.mixin Record hasBottom d T of POrder d T := {
  bottom : T;
  le0x : ∀ x, le bottom x;
}.

#[key="T", primitive]
HB.mixin Record hasTop d T of POrder d T := {
  top : T;
  lex1 : ∀ x, le x top;
}.

#[short(type="bPOrderType")]
HB.structure Definition BPOrder d := { T of hasBottom d T & POrder d T }.
#[short(type="tPOrderType")]
HB.structure Definition TPOrder d := { T of hasTop d T & POrder d T }.
#[short(type="tbPOrderType")]
HB.structure Definition TBPOrder d := { T of hasTop d T & BPOrder d T }.

Module POrderExports.
Arguments le_trans {d s} [_ _ _].
End POrderExports.
Bind Scope order_scope with POrder.sort.

Section POrderDef.

Variable (disp : disp_t) (T : porderType disp).

Local Notation "x <= y" := (le x y) : order_scope.
Local Notation "x < y" := (lt x y) : order_scope.

Definition comparable : rel T := fun (x y : T) ⇒ (x ≤ y) || (y ≤ x).
Local Notation "x >=< y" := (comparable x y) : order_scope.
Local Notation "x >< y" := (~~ (x >=< y)) : order_scope.

Definition ge : simpl_rel T := [rel x y | y ≤ x].
Definition gt : simpl_rel T := [rel x y | y < x].
Definition leif (x y : T) C : Prop := ((x ≤ y) × ((x == y) = C))%type.

Definition le_of_leif x y C (le_xy : @leif x y C) := le_xy.1 : le x y.

Definition lteif (x y : T) C := if C then x ≤ y else x < y.

Variant le_xor_gt (x y : T) :
  T → T → T → T → bool → bool → Set :=
  | LeNotGt of x ≤ y : le_xor_gt x y x x y y true false
  | GtNotLe of y < x : le_xor_gt x y y y x x false true.

Variant lt_xor_ge (x y : T) :
  T → T → T → T → bool → bool → Set :=
  | LtNotGe of x < y : lt_xor_ge x y x x y y false true
  | GeNotLt of y ≤ x : lt_xor_ge x y y y x x true false.

Definition min (x y : T) := if x < y then x else y.
Definition max (x y : T) := if x < y then y else x.

Variant compare (x y : T) :
   T → T → T → T →
   bool → bool → bool → bool → bool → bool → Set :=
  | CompareLt of x < y : compare x y
    x x y y false false false true false true
  | CompareGt of y < x : compare x y
    y y x x false false true false true false
  | CompareEq of x = y : compare x y
    x x x x true true true true false false.

Variant incompare (x y : T) :
   T → T → T → T →
  bool → bool → bool → bool → bool → bool → bool → bool → Set :=
  | InCompareLt of x < y : incompare x y
    x x y y false false false true false true true true
  | InCompareGt of y < x : incompare x y
    y y x x false false true false true false true true
  | InCompare of x >< y : incompare x y
    x y y x false false false false false false false false
  | InCompareEq of x = y : incompare x y
    x x x x true true true true false false true true.

Definition arg_min {I : finType} := @extremum T I le.
Definition arg_max {I : finType} := @extremum T I ge.

Lifted min/max operations.
Section LiftedPOrder.
Variable T' : Type.
Implicit Type f : T' → T.
Definition min_fun f g x := min (f x) (g x).
Definition max_fun f g x := max (f x) (g x).
End LiftedPOrder.

Definition nondecreasing disp' (T' : porderType disp') (f : T → T') : Prop :=
  {homo f : x y / x ≤ y}.

End POrderDef.

Arguments ge {_ _}.
Arguments gt {_ _}.
Arguments min {_ _}.
Arguments max {_ _}.
Arguments comparable {_ _}.
Arguments min_fun {_ _ _} f g _ /.
Arguments max_fun {_ _ _} f g _ /.

Module Import Def.

Notation nondecreasing := nondecreasing.
Notation min := min.
Notation max := max.

End Def.

Module Import POSyntax.

Notation "<=%O" := le : function_scope.
Notation ">=%O" := ge : function_scope.
Notation "<%O" := lt : function_scope.
Notation ">%O" := gt : function_scope.
Notation "<?=%O" := leif : function_scope.
Notation "<?<=%O" := lteif : function_scope.
Notation ">=<%O" := comparable : function_scope.
Notation "><%O" := (fun x y ⇒ ~~ (comparable x y)) : function_scope.

Notation "<= y" := (ge y) : order_scope.
Notation "<= y :> T" := (≤ (y : T)) (only parsing) : order_scope.
Notation ">= y" := (le y) : order_scope.
Notation ">= y :> T" := (≥ (y : T)) (only parsing) : order_scope.

Notation "< y" := (gt y) : order_scope.
Notation "< y :> T" := (< (y : T)) (only parsing) : order_scope.
Notation "> y" := (lt y) : order_scope.
Notation "> y :> T" := (> (y : T)) (only parsing) : order_scope.

Notation "x <= y" := (le x y) : order_scope.
Notation "x <= y :> T" := ((x : T) ≤ (y : T)) (only parsing) : order_scope.
Notation "x >= y" := (y ≤ x) (only parsing) : order_scope.
Notation "x >= y :> T" := ((x : T) ≥ (y : T)) (only parsing) : order_scope.

Notation "x < y" := (lt x y) : order_scope.
Notation "x < y :> T" := ((x : T) < (y : T)) (only parsing) : order_scope.
Notation "x > y" := (y < x) (only parsing) : order_scope.
Notation "x > y :> T" := ((x : T) > (y : T)) (only parsing) : order_scope.

Notation "x <= y <= z" := ((x ≤ y) && (y ≤ z)) : order_scope.
Notation "x < y <= z" := ((x < y) && (y ≤ z)) : order_scope.
Notation "x <= y < z" := ((x ≤ y) && (y < z)) : order_scope.
Notation "x < y < z" := ((x < y) && (y < z)) : order_scope.

Notation "x <= y ?= 'iff' C" := (leif x y C) : order_scope.
Notation "x <= y ?= 'iff' C :> T" := ((x : T) ≤ (y : T) ?= iff C)
  (only parsing) : order_scope.

Notation "x < y ?<= 'if' C" := (lteif x y C) : order_scope.
Notation "x < y ?<= 'if' C :> T" := ((x : T) < (y : T) ?<= if C)
  (only parsing) : order_scope.

Notation ">=< y" := [pred x | comparable x y] : order_scope.
Notation ">=< y :> T" := (>=< (y : T)) (only parsing) : order_scope.
Notation "x >=< y" := (comparable x y) : order_scope.

Notation ">< y" := [pred x | ~~ comparable x y] : order_scope.
Notation ">< y :> T" := (>< (y : T)) (only parsing) : order_scope.
Notation "x >< y" := (~~ (comparable x y)) : order_scope.

Notation "[ 'arg' 'min_' ( i < i0 | P ) F ]" :=
    (arg_min i0 (fun i ⇒ P%B) (fun i ⇒ F))
  (at level 0, i, i0 at level 10,
   format "[ 'arg' 'min_' ( i < i0 | P ) F ]") : order_scope.

Notation "[ 'arg' 'min_' ( i < i0 'in' A ) F ]" :=
    [arg min_(i < i0 | i \in A) F]
  (at level 0, i, i0 at level 10,
   format "[ 'arg' 'min_' ( i < i0 'in' A ) F ]") : order_scope.

Notation "[ 'arg' 'min_' ( i < i0 ) F ]" := [arg min_(i < i0 | true) F]
  (at level 0, i, i0 at level 10,
   format "[ 'arg' 'min_' ( i < i0 ) F ]") : order_scope.

Notation "[ 'arg' 'max_' ( i > i0 | P ) F ]" :=
     (arg_max i0 (fun i ⇒ P%B) (fun i ⇒ F))
  (at level 0, i, i0 at level 10,
   format "[ 'arg' 'max_' ( i > i0 | P ) F ]") : order_scope.

Notation "[ 'arg' 'max_' ( i > i0 'in' A ) F ]" :=
    [arg max_(i > i0 | i \in A) F]
  (at level 0, i, i0 at level 10,
   format "[ 'arg' 'max_' ( i > i0 'in' A ) F ]") : order_scope.

Notation "[ 'arg' 'max_' ( i > i0 ) F ]" := [arg max_(i > i0 | true) F]
  (at level 0, i, i0 at level 10,
   format "[ 'arg' 'max_' ( i > i0 ) F ]") : order_scope.

Notation "f \min g" := (min_fun f g) : function_scope.
Notation "f \max g" := (max_fun f g) : function_scope.

Notation leLHS := (X in (X ≤ _)%O)%pattern.
Notation leRHS := (X in (_ ≤ X)%O)%pattern.
Notation ltLHS := (X in (X < _)%O)%pattern.
Notation ltRHS := (X in (_ < X)%O)%pattern.

Notation "\bot" := bottom : order_scope.
Notation "\top" := top : order_scope.

End POSyntax.

Module POCoercions.
Coercion le_of_leif : leif >-> is_true.
End POCoercions.

#[key="T", primitive]
HB.mixin Record POrder_isMeetSemilattice d T of POrder d T := {
  meet : T → T → T;
  lexI : ∀ x y z, (x ≤ meet y z) = (x ≤ y) && (x ≤ z);
}.

#[key="T", primitive]
HB.mixin Record POrder_isJoinSemilattice d T of POrder d T := {
  join : T → T → T;
  leUx : ∀ x y z, (join x y ≤ z) = (x ≤ z) && (y ≤ z);
}.

#[short(type="meetSemilatticeType")]
HB.structure Definition MeetSemilattice d :=
  { T of POrder d T & POrder_isMeetSemilattice d T }.

#[short(type="bMeetSemilatticeType")]
HB.structure Definition BMeetSemilattice d :=
  { T of MeetSemilattice d T & hasBottom d T }.

#[short(type="tMeetSemilatticeType")]
HB.structure Definition TMeetSemilattice d :=
  { T of MeetSemilattice d T & hasTop d T }.

#[short