Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************)
(*         *   The Coq Proof Assistant / The Coq Development Team       *)
(*  v      *   INRIA, CNRS and contributors - Copyright 1999-2018       *)
(* <O___,, *       (see CREDITS file for the list of authors)           *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)

Require Import Bool Basics OrdersTac.
Require Export Orders.

Set Implicit Arguments.
Unset Strict Implicit.

Properties of compare

Module Type CompareFacts (Import O:DecStrOrder').

 Local Infix "?=" := compare (at level 70, no associativity).

 
x, y:t

(x ?= y) = Eq <-> x == y
x, y:t

(x ?= y) = Eq <-> x == y
case compare_spec; intro H; split; try easy; intro EQ; contradict H; rewrite EQ; apply irreflexivity. Qed.
x, y:t

(x ?= y) = Eq -> x == y
x, y:t

(x ?= y) = Eq -> x == y
apply compare_eq_iff. Qed.
x, y:t

(x ?= y) = Lt <-> x < y
x, y:t

(x ?= y) = Lt <-> x < y
case compare_spec; intro H; split; try easy; intro LT; contradict LT; rewrite H; apply irreflexivity. Qed.
x, y:t

(x ?= y) = Gt <-> y < x
x, y:t

(x ?= y) = Gt <-> y < x
case compare_spec; intro H; split; try easy; intro LT; contradict LT; rewrite H; apply irreflexivity. Qed.
x, y:t

(x ?= y) <> Lt <-> ~ x < y
x, y:t

(x ?= y) <> Lt <-> ~ x < y
rewrite compare_lt_iff; intuition. Qed.
x, y:t

(x ?= y) <> Gt <-> ~ y < x
x, y:t

(x ?= y) <> Gt <-> ~ y < x
rewrite compare_gt_iff; intuition. Qed. Hint Rewrite compare_eq_iff compare_lt_iff compare_gt_iff : order.

Proper (eq ==> eq ==> Logic.eq) compare

Proper (eq ==> eq ==> Logic.eq) compare
x, x':t
Hxx':x == x'
y, y':t
Hyy':y == y'

(x ?= y) = (x' ?= y')
case (compare_spec x' y'); autorewrite with order; now rewrite Hxx', Hyy'. Qed.
x:t

(x ?= x) = Eq
x:t

(x ?= x) = Eq
case compare_spec; intros; trivial; now elim irreflexivity with x. Qed.
x, y:t

(y ?= x) = CompOpp (x ?= y)
x, y:t

(y ?= x) = CompOpp (x ?= y)
case (compare_spec x y); simpl; autorewrite with order; trivial; now symmetry. Qed. End CompareFacts.

Properties of OrderedTypeFull

Module OrderedTypeFullFacts (Import O:OrderedTypeFull').

 Module OrderTac := OTF_to_OrderTac O.
 Ltac order := OrderTac.order.
 Ltac iorder := intuition order.

 

Proper (eq ==> eq ==> iff) le

Proper (eq ==> eq ==> iff) le
repeat red; iorder. Qed.

PreOrder le

PreOrder le
split; red; order. Qed.

PartialOrder eq le

PartialOrder eq le
compute; iorder. Qed.

Antisymmetric t eq le

Antisymmetric t eq le
apply partial_order_antisym; auto with *. Qed.

forall x y : t, x <= y <-> ~ y < x

forall x y : t, x <= y <-> ~ y < x
iorder. Qed.

forall x y : t, x < y <-> ~ y <= x

forall x y : t, x < y <-> ~ y <= x
iorder. Qed.

forall x y : t, x <= y \/ y < x

forall x y : t, x <= y \/ y < x
x, y:t

x <= y \/ y < x
rewrite le_lteq; destruct (O.compare_spec x y); auto. Qed.

forall x y : t, x < y \/ y <= x

forall x y : t, x < y \/ y <= x
x, y:t

x < y \/ y <= x
rewrite le_lteq; destruct (O.compare_spec x y); iorder. Qed.

forall x y : t, x == y <-> x <= y <= x

forall x y : t, x == y <-> x <= y <= x
iorder. Qed. Include CompareFacts O.
x, y:t

(x ?= y) <> Gt <-> x <= y
x, y:t

(x ?= y) <> Gt <-> x <= y
x, y:t

(x ?= y) <> Gt <-> ~ y < x
apply compare_ngt_iff. Qed.
x, y:t

(x ?= y) <> Lt <-> y <= x
x, y:t

(x ?= y) <> Lt <-> y <= x
x, y:t

(x ?= y) <> Lt <-> ~ x < y
apply compare_nlt_iff. Qed. End OrderedTypeFullFacts.

Properties of OrderedType

Module OrderedTypeFacts (Import O: OrderedType').

  Module OrderTac := OT_to_OrderTac O.
  Ltac order := OrderTac.order.

  Declare Scope order.
  Notation "x <= y" := (~lt y x) : order.
  Infix "?=" := compare (at level 70, no associativity) : order.

  Local Open Scope order.

  Tactic Notation "elim_compare" constr(x) constr(y) :=
   destruct (compare_spec x y).

  Tactic Notation "elim_compare" constr(x) constr(y) "as" ident(h) :=
   destruct (compare_spec x y) as [h|h|h].
The following lemmas are either re-phrasing of eq_equiv and lt_strorder or immediately provable by order. Interest: compatibility, test of order, etc
  Definition eq_refl (x:t) : x==x := Equivalence_Reflexive x.

  Definition eq_sym (x y:t) : x==y -> y==x := Equivalence_Symmetric x y.

  Definition eq_trans (x y z:t) : x==y -> y==z -> x==z :=
   Equivalence_Transitive x y z.

  Definition lt_trans (x y z:t) : x<y -> y<z -> x<z :=
   StrictOrder_Transitive x y z.

  Definition lt_irrefl (x:t) : ~x<x := StrictOrder_Irreflexive x.

  Include CompareFacts O.
  Notation compare_le_iff := compare_ngt_iff (only parsing).
  Notation compare_ge_iff := compare_nlt_iff (only parsing).
For compatibility reasons
  Definition eq_dec := eq_dec.

  

forall x y : t, {x < y} + {y <= x}

forall x y : t, {x < y} + {y <= x}
intros x y; destruct (CompSpec2Type (compare_spec x y)); [ right | left | right ]; order. Defined. Definition eqb x y : bool := if eq_dec x y then true else false.

forall (x y : t) (B : Type) (b b' : B), (if eq_dec x y then b else b') = match x ?= y with | Eq => b | _ => b' end

forall (x y : t) (B : Type) (b b' : B), (if eq_dec x y then b else b') = match x ?= y with | Eq => b | _ => b' end
intros; destruct eq_dec; elim_compare x y; auto; order. Qed.

forall x y : t, eqb x y = match x ?= y with | Eq => true | _ => false end

forall x y : t, eqb x y = match x ?= y with | Eq => true | _ => false end
unfold eqb; intros; apply if_eq_dec. Qed.

Proper (eq ==> eq ==> Logic.eq) eqb

Proper (eq ==> eq ==> Logic.eq) eqb
x, x':t
Hxx':x == x'
y, y':t
Hyy':y == y'

eqb x y = eqb x' y'
rewrite 2 eqb_alt, Hxx', Hyy'; auto. Qed. End OrderedTypeFacts.

Tests of the order tactic

Is it at least capable of proving some basic properties ?
Module OrderedTypeTest (Import O:OrderedType').
  Module Import MO := OrderedTypeFacts O.
  Local Open Scope order.
  
x, y:t

x < y -> x ~= y
x, y:t

x < y -> x ~= y
order. Qed.
x, y, z:t

x < y -> y == z -> x < z
x, y, z:t

x < y -> y == z -> x < z
order. Qed.
x, y, z:t

x == y -> y < z -> x < z
x, y, z:t

x == y -> y < z -> x < z
order. Qed.
x, y, z:t

x <= y -> y == z -> x <= z
x, y, z:t

x <= y -> y == z -> x <= z
order. Qed.
x, y, z:t

x == y -> y <= z -> x <= z
x, y, z:t

x == y -> y <= z -> x <= z
order. Qed.
x, y, z:t

x ~= y -> y == z -> x ~= z
x, y, z:t

x ~= y -> y == z -> x ~= z
order. Qed.
x, y, z:t

x == y -> y ~= z -> x ~= z
x, y, z:t

x == y -> y ~= z -> x ~= z
order. Qed.
x, y, z:t

x <= y -> y < z -> x < z
x, y, z:t

x <= y -> y < z -> x < z
order. Qed.
x, y, z:t

x < y -> y <= z -> x < z
x, y, z:t

x < y -> y <= z -> x < z
order. Qed.
x, y, z:t

x <= y -> y <= z -> x <= z
x, y, z:t

x <= y -> y <= z -> x <= z
order. Qed.
x, y:t

x <= y -> y <= x -> x == y
x, y:t

x <= y -> y <= x -> x == y
order. Qed.
x, y:t

x <= y -> x ~= y -> x < y
x, y:t

x <= y -> x ~= y -> x < y
order. Qed.
x, y:t

x ~= y -> y ~= x
x, y:t

x ~= y -> y ~= x
order. Qed.
x, y:t

x < y -> x <= y
x, y:t

x < y -> x <= y
order. Qed.
x, y:t

y < x -> x ~= y
x, y:t

y < x -> x ~= y
order. Qed.
x, y:t

x == y -> y <= x
x, y:t

x == y -> y <= x
order. Qed.
x, y:t

x == y -> x <= y
x, y:t

x == y -> x <= y
order. Qed.
x, y:t

x < y -> x <= y
x, y:t

x < y -> x <= y
order. Qed.
x, y:t

x == y <-> y <= x /\ x <= y
x, y:t

x == y <-> y <= x /\ x <= y
intuition; order. Qed. End OrderedTypeTest.

Reversed OrderedTypeFull.

we can switch the orientation of the order. This is used for example when deriving properties of min out of the ones of max (see GenericMinMax).
Module OrderedTypeRev (O:OrderedTypeFull) <: OrderedTypeFull.

Definition t := O.t.
Definition eq := O.eq.
Instance eq_equiv : Equivalence eq.
Definition eq_dec := O.eq_dec.

Definition lt := flip O.lt.
Definition le := flip O.le.


StrictOrder lt

StrictOrder lt
unfold lt; auto with *. Qed.

Proper (eq ==> eq ==> iff) lt

Proper (eq ==> eq ==> iff) lt
unfold lt; auto with *. Qed.

forall x y : O.t, le x y <-> lt x y \/ eq x y

forall x y : O.t, le x y <-> lt x y \/ eq x y
x, y:O.t

O.le y x <-> O.lt y x \/ eq x y
rewrite O.le_lteq; intuition. Qed. Definition compare := flip O.compare.

forall x y : O.t, CompSpec eq lt x y (compare x y)

forall x y : O.t, CompSpec eq lt x y (compare x y)
x, y:O.t

CompSpec O.eq (fun x0 y0 : O.t => O.lt y0 x0) x y (O.compare y x)
destruct (O.compare_spec y x); auto with relations. Qed. End OrderedTypeRev. Unset Implicit Arguments.

Order relations derived from a compare function.

We factorize here some common properties for ZArith, NArith and co, where lt and le are defined in terms of compare. Note that we do not require anything here concerning compatibility of compare w.r.t eq, nor anything concerning transitivity.
Module Type CompareBasedOrder (Import E:EqLtLe')(Import C:HasCmp E).
 Include CmpNotation E C.
 Include IsEq E.
 Axiom compare_eq_iff : forall x y, (x ?= y) = Eq <-> x == y.
 Axiom compare_lt_iff : forall x y, (x ?= y) = Lt <-> x < y.
 Axiom compare_le_iff : forall x y, (x ?= y) <> Gt <-> x <= y.
 Axiom compare_antisym : forall x y, (y ?= x) = CompOpp (x ?= y).
End CompareBasedOrder.

Module Type CompareBasedOrderFacts
 (Import E:EqLtLe')
 (Import C:HasCmp E)
 (Import O:CompareBasedOrder E C).

 
x, y:t

CompareSpec (x == y) (x < y) (y < x) (x ?= y)
x, y:t

CompareSpec (x == y) (x < y) (y < x) (x ?= y)
x, y:t
H:(x ?= y) = Eq

x == y
x, y:t
H:(x ?= y) = Lt
x < y
x, y:t
H:(x ?= y) = Gt
y < x
x, y:t
H:(x ?= y) = Eq

x == y
now apply compare_eq_iff.
x, y:t
H:(x ?= y) = Lt

x < y
now apply compare_lt_iff.
x, y:t
H:(x ?= y) = Gt

y < x
x, y:t
H:(y ?= x) = CompOpp Gt

y < x
now apply compare_lt_iff. Qed.
x, y:t

(x ?= y) = Eq -> x == y
x, y:t

(x ?= y) = Eq -> x == y
apply compare_eq_iff. Qed.
x:t

(x ?= x) = Eq
x:t

(x ?= x) = Eq
now apply compare_eq_iff. Qed.
x, y:t

(x ?= y) = Gt <-> y < x
x, y:t

(x ?= y) = Gt <-> y < x
now rewrite <- compare_lt_iff, compare_antisym, CompOpp_iff. Qed.
x, y:t

(x ?= y) <> Lt <-> y <= x
x, y:t

(x ?= y) <> Lt <-> y <= x
now rewrite <- compare_le_iff, compare_antisym, CompOpp_iff. Qed.
x, y:t

(x ?= y) <> Gt <-> ~ y < x
x, y:t

(x ?= y) <> Gt <-> ~ y < x
rewrite compare_gt_iff; intuition. Qed.
x, y:t

(x ?= y) <> Lt <-> ~ x < y
x, y:t

(x ?= y) <> Lt <-> ~ x < y
rewrite compare_lt_iff; intuition. Qed.
x, y:t

(x ?= y) = Gt <-> ~ x <= y
x, y:t

(x ?= y) = Gt <-> ~ x <= y
x, y:t

(x ?= y) = Gt <-> ~ (x ?= y) <> Gt
destruct compare; split; easy || now destruct 1. Qed.
x, y:t

(x ?= y) = Lt <-> ~ y <= x
x, y:t

(x ?= y) = Lt <-> ~ y <= x
now rewrite <- compare_nle_iff, compare_antisym, CompOpp_iff. Qed.
x:t

~ x < x
x:t

~ x < x
now rewrite <- compare_lt_iff, compare_refl. Qed.
n, m:t

n <= m <-> n < m \/ n == m
n, m:t

n <= m <-> n < m \/ n == m
n, m:t

(n ?= m) <> Gt <-> (n ?= m) = Lt \/ (n ?= m) = Eq
destruct (n ?= m); now intuition. Qed. End CompareBasedOrderFacts.
Basic facts about boolean comparisons
Module Type BoolOrderFacts
 (Import E:EqLtLe')
 (Import C:HasCmp E)
 (Import F:HasBoolOrdFuns' E)
 (Import O:CompareBasedOrder E C)
 (Import S:BoolOrdSpecs E F).

Include CompareBasedOrderFacts E C O.
Nota : apart from eqb_compare below, facts about eqb are in BoolEqualityFacts
Alternate specifications based on BoolSpec and reflect
x, y:t

reflect (x <= y) (x <=? y)
x, y:t

reflect (x <= y) (x <=? y)
x, y:t

x <= y <-> x <=? y = true
x, y:t

x <=? y = true <-> x <= y
apply leb_le. Defined.
x, y:t

BoolSpec (x <= y) (y < x) (x <=? y)
x, y:t

BoolSpec (x <= y) (y < x) (x <=? y)
x, y:t
n:~ x <= y

y < x
now rewrite <- compare_lt_iff, compare_nge_iff. Qed.
x, y:t

reflect (x < y) (x <? y)
x, y:t

reflect (x < y) (x <? y)
x, y:t

x < y <-> x <? y = true
x, y:t

x <? y = true <-> x < y
apply ltb_lt. Defined.
x, y:t

BoolSpec (x < y) (y <= x) (x <? y)
x, y:t

BoolSpec (x < y) (y <= x) (x <? y)
x, y:t
n:~ x < y

y <= x
now rewrite <- compare_le_iff, compare_ngt_iff. Qed.
Negated variants of the specifications
x, y:t

x <=? y = false <-> ~ x <= y
x, y:t

x <=? y = false <-> ~ x <= y
now rewrite <- not_true_iff_false, leb_le. Qed.
x, y:t

x <=? y = false <-> y < x
x, y:t

x <=? y = false <-> y < x
now rewrite leb_nle, <- compare_lt_iff, compare_nge_iff. Qed.
x, y:t

x <? y = false <-> ~ x < y
x, y:t

x <? y = false <-> ~ x < y
now rewrite <- not_true_iff_false, ltb_lt. Qed.
x, y:t

x <? y = false <-> y <= x
x, y:t

x <? y = false <-> y <= x
now rewrite ltb_nlt, <- compare_le_iff, compare_ngt_iff. Qed.
Basic equality laws for boolean tests
x:t

x <=? x = true
x:t

x <=? x = true
x:t

x <= x
x:t

x < x \/ x == x
now right. Qed.
x, y:t

y <=? x = negb (x <? y)
x, y:t

y <=? x = negb (x <? y)
x, y:t

y <=? x = true <-> negb (x <? y) = true
now rewrite negb_true_iff, leb_le, ltb_ge. Qed.
x:t

x <? x = false
x:t

x <? x = false
x:t

x <= x
x:t

x < x \/ x == x
now right. Qed.
x, y:t

y <? x = negb (x <=? y)
x, y:t

y <? x = negb (x <=? y)
x, y:t

y <? x = true <-> negb (x <=? y) = true
now rewrite negb_true_iff, ltb_lt, leb_gt. Qed.
Relation between compare and the boolean comparisons
x, y:t

(x =? y) = match x ?= y with | Eq => true | _ => false end
x, y:t

(x =? y) = match x ?= y with | Eq => true | _ => false end
x, y:t

(x =? y) = true <-> match x ?= y with | Eq => true | _ => false end = true
x, y:t

(x ?= y) = Eq <-> match x ?= y with | Eq => true | _ => false end = true
now destruct compare. Qed.
x, y:t

x <? y = match x ?= y with | Lt => true | _ => false end
x, y:t

x <? y = match x ?= y with | Lt => true | _ => false end
x, y:t

x <? y = true <-> match x ?= y with | Lt => true | _ => false end = true
x, y:t

(x ?= y) = Lt <-> match x ?= y with | Lt => true | _ => false end = true
now destruct compare. Qed.
x, y:t

x <=? y = match x ?= y with | Gt => false | _ => true end
x, y:t

x <=? y = match x ?= y with | Gt => false | _ => true end
x, y:t

x <=? y = true <-> match x ?= y with | Gt => false | _ => true end = true
x, y:t

(x ?= y) <> Gt <-> match x ?= y with | Gt => false | _ => true end = true
now destruct compare. Qed. End BoolOrderFacts.