(*************************************************************************)
(* Copyright (C) 2012 - 2016 (Draft)                                     *)
(* C. Cohen                                                              *)
(* Based on prior works by                                               *)
(* D. Dreyer, G. Gonthier, A. Nanevski, P-Y Strub, B. Ziliani            *)
(*                                                                       *)
(* This program is free software: you can redistribute it and/or modify  *)
(* it under the terms of the GNU General Public License as published by  *)
(* the Free Software Foundation, either version 3 of the License, or     *)
(* (at your option) any later version.                                   *)
(*                                                                       *)
(* This program is distributed in the hope that it will be useful,       *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
(* GNU General Public License for more details.                          *)
(*                                                                       *)
(* You should have received a copy of the GNU General Public License     *)
(* along with this program.  If not, see <http://www.gnu.org/licenses/>. *)
(*************************************************************************)
From mathcomp
From mathcomp
(*****************************************************************************)
(* This files definies a ordered and decidable relations on a                *)
(* type as canonical structure.  One need to import Order.Theory to get      *)
(* the theory of such relations. The scope order_scope (%O) contains         *)
(* fancier notation for this kind of ordeering.                              *)
(*                                                                           *)
(*          porderType == the type of partially ordered types                *)
(*           orderType == the type of totally ordered types                  *)
(*         latticeType == the type of distributive lattices                  *)
(*        blatticeType == ... with a bottom elemnt                           *)
(*        tlatticeType == ... with a top element                             *)
(*       tblatticeType == ... with both a top and a bottom                   *)
(*       cblatticeType == ... with a complement to, and bottom               *)
(*      tcblatticeType == ... with a top, bottom, and general complement     *)
(*                                                                           *)
(* Each of these structure take a first argument named display, of type unit *)
(* instanciating it with tt or an unknown key will lead to a default display *)
(* Optionally, one can configure the display by setting one owns notation    *)
(* on operators instanciated for their particular display                    *)
(* One example of this is the reverse display ^r, every notation with the    *)
(* suffix ^r (e.g. x <=^r y) is about the reversal order, in order not to    *)
(* confuse the normal order with its reversal.                               *)
(*                                                                           *)
(* PorderType pord_mixin == builds an ordtype from a a partial order mixin   *)
(*                          containing le, lt and refl, antisym, trans of le *)
(* LatticeType lat_mixin == builds a distributive lattice from a porderType  *)
(*                          meet and join and axioms                         *)
(*    OrderType le_total == builds an order type from a lattice              *)
(*                          and from a proof of totality                     *)
(*                  ...                                                      *)
(*                                                                           *)
(* We provide a canonical structure of orderType for natural numbers (nat)   *)
(* for finType and for pairs of ordType by lexicographic orderering.         *)
(*                                                                           *)
(* leP ltP ltgtP are the three main lemmas for case analysis                 *)
(*                                                                           *)
(* We also provide specialized version of some theorems from path.v.         *)
(*                                                                           *)
(* There are three distinct uses of the symbols <, <=, > and >=:             *)
(*    0-ary, unary (prefix) and binary (infix).                              *)
(* 0. <%O, <=%O, >%O, >=%O stand respectively for lt, le, gt and ge.         *)
(* 1. (< x),  (<= x), (> x),  (>= x) stand respectively for                  *)
(*    (gt x), (ge x), (lt x), (le x).                                        *)
(*    So (< x) is a predicate characterizing elements smaller than x.        *)
(* 2. (x < y), (x <= y), ... mean what they are expected to.                 *)
(*  These convention are compatible with haskell's,                          *)
(*   where ((< y) x) = (x < y) = ((<) x y),                                  *)
(*   except that we write <%O instead of (<).                                *)
(*****************************************************************************)
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
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 ">=< x" (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 "x <=^r y" (at level 70, y at next level).
Reserved Notation "x >=^r y" (at level 70, y at next level, only parsing).
Reserved Notation "x <^r y" (at level 70, y at next level).
Reserved Notation "x >^r y" (at level 70, y at next level, only parsing).
Reserved Notation "x <=^r y :> T" (at level 70, y at next level).
Reserved Notation "x >=^r y :> T" (at level 70, y at next level, only parsing).
Reserved Notation "x <^r y :> T" (at level 70, y at next level).
Reserved Notation "x >^r y :> T" (at level 70, y at next level, only parsing).
Reserved Notation "<=^r y" (at level 35).
Reserved Notation ">=^r y" (at level 35).
Reserved Notation "<^r y" (at level 35).
Reserved Notation ">^r y" (at level 35).
Reserved Notation "<=^r y :> T" (at level 35, y at next level).
Reserved Notation ">=^r y :> T" (at level 35, y at next level).
Reserved Notation "<^r y :> T" (at level 35, y at next level).
Reserved Notation ">^r y :> T" (at level 35, y at next level).
Reserved Notation "x >=<^r y" (at level 70, no associativity).
Reserved Notation ">=<^r x" (at level 35).
Reserved Notation ">=<^r y :> T" (at level 35, y at next level).
Reserved Notation "x ><^r y" (at level 70, no associativity).
Reserved Notation "><^r x" (at level 35).
Reserved Notation "><^r y :> T" (at level 35, y at next level).
Reserved Notation "x <=^r y <=^r z" (at level 70, y, z at next level).
Reserved Notation "x <^r y <=^r z" (at level 70, y, z at next level).
Reserved Notation "x <=^r y <^r z" (at level 70, y, z at next level).
Reserved Notation "x <^r y <^r z" (at level 70, y, z at next level).
Reserved Notation "x <=^r y ?= 'iff' c" (at level 70, y, c at next level,
format "x '[hv'  <=^r  y '/'  ?=  'iff'  c ']'").
Reserved Notation "x <=^r y ?= 'iff' c :> T" (at level 70, y, c at next level,
format "x '[hv'  <=^r  y '/'  ?=  'iff'  c  :> T ']'").
(* Reserved notation 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 notation for reverse lattice operations. *)
Reserved Notation "A `&^r` B"  (at level 48, left associativity).
Reserved Notation "A `|^r` B" (at level 52, left associativity).
Reserved Notation "A `\^r` B" (at level 50, left associativity).
Reserved Notation "~^r` A" (at level 35, right associativity).
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,
only parsing).
Reserved Notation "\meet_ ( i : t ) F"
(at level 41, F at level 41, i at level 50,
only parsing).
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,
only parsing).
Reserved Notation "\join_ ( i : t ) F"
(at level 41, F at level 41, i at level 50,
only parsing).
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 "\meet^r_ i F"
(at level 41, F at level 41, i at level 0,
format "'[' \meet^r_ i '/  '  F ']'").
Reserved Notation "\meet^r_ ( i <- r | P ) F"
(at level 41, F at level 41, i, r at level 50,
format "'[' \meet^r_ ( i  <-  r  |  P ) '/  '  F ']'").
Reserved Notation "\meet^r_ ( i <- r ) F"
(at level 41, F at level 41, i, r at level 50,
format "'[' \meet^r_ ( i  <-  r ) '/  '  F ']'").
Reserved Notation "\meet^r_ ( m <= i < n | P ) F"
(at level 41, F at level 41, i, m, n at level 50,
format "'[' \meet^r_ ( m  <=  i  <  n  |  P ) '/  '  F ']'").
Reserved Notation "\meet^r_ ( m <= i < n ) F"
(at level 41, F at level 41, i, m, n at level 50,
format "'[' \meet^r_ ( m  <=  i  <  n ) '/  '  F ']'").
Reserved Notation "\meet^r_ ( i | P ) F"
(at level 41, F at level 41, i at level 50,
format "'[' \meet^r_ ( i  |  P ) '/  '  F ']'").
Reserved Notation "\meet^r_ ( i : t | P ) F"
(at level 41, F at level 41, i at level 50,
only parsing).
Reserved Notation "\meet^r_ ( i : t ) F"
(at level 41, F at level 41, i at level 50,
only parsing).
Reserved Notation "\meet^r_ ( i < n | P ) F"
(at level 41, F at level 41, i, n at level 50,
format "'[' \meet^r_ ( i  <  n  |  P ) '/  '  F ']'").
Reserved Notation "\meet^r_ ( i < n ) F"
(at level 41, F at level 41, i, n at level 50,
format "'[' \meet^r_ ( i  <  n )  F ']'").
Reserved Notation "\meet^r_ ( i 'in' A | P ) F"
(at level 41, F at level 41, i, A at level 50,
format "'[' \meet^r_ ( i  'in'  A  |  P ) '/  '  F ']'").
Reserved Notation "\meet^r_ ( i 'in' A ) F"
(at level 41, F at level 41, i, A at level 50,
format "'[' \meet^r_ ( i  'in'  A ) '/  '  F ']'").
Reserved Notation "\join^r_ i F"
(at level 41, F at level 41, i at level 0,
format "'[' \join^r_ i '/  '  F ']'").
Reserved Notation "\join^r_ ( i <- r | P ) F"
(at level 41, F at level 41, i, r at level 50,
format "'[' \join^r_ ( i  <-  r  |  P ) '/  '  F ']'").
Reserved Notation "\join^r_ ( i <- r ) F"
(at level 41, F at level 41, i, r at level 50,
format "'[' \join^r_ ( i  <-  r ) '/  '  F ']'").
Reserved Notation "\join^r_ ( m <= i < n | P ) F"
(at level 41, F at level 41, i, m, n at level 50,
format "'[' \join^r_ ( m  <=  i  <  n  |  P ) '/  '  F ']'").
Reserved Notation "\join^r_ ( m <= i < n ) F"
(at level 41, F at level 41, i, m, n at level 50,
format "'[' \join^r_ ( m  <=  i  <  n ) '/  '  F ']'").
Reserved Notation "\join^r_ ( i | P ) F"
(at level 41, F at level 41, i at level 50,
format "'[' \join^r_ ( i  |  P ) '/  '  F ']'").
Reserved Notation "\join^r_ ( i : t | P ) F"
(at level 41, F at level 41, i at level 50,
only parsing).
Reserved Notation "\join^r_ ( i : t ) F"
(at level 41, F at level 41, i at level 50,
only parsing).
Reserved Notation "\join^r_ ( i < n | P ) F"
(at level 41, F at level 41, i, n at level 50,
format "'[' \join^r_ ( i  <  n  |  P ) '/  '  F ']'").
Reserved Notation "\join^r_ ( i < n ) F"
(at level 41, F at level 41, i, n at level 50,
format "'[' \join^r_ ( i  <  n )  F ']'").
Reserved Notation "\join^r_ ( i 'in' A | P ) F"
(at level 41, F at level 41, i, A at level 50,
format "'[' \join^r_ ( i  'in'  A  |  P ) '/  '  F ']'").
Reserved Notation "\join^r_ ( i 'in' A ) F"
(at level 41, F at level 41, i, A at level 50,
format "'[' \join^r_ ( i  'in'  A ) '/  '  F ']'").
Fact unit_irrelevance (x y : unit) : x = y.

Lemma lt_leAnge x y : (x < y) = (x <= y) && ~~ (y <= x).