(************************************************************************)
(*         *      The Rocq Prover / The Rocq Development Team           *)
(*  v      *         Copyright INRIA, CNRS and contributors             *)
(* <O___,, * (see version control and CREDITS file for authors & dates) *)
(*   \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)         *)
(************************************************************************)
Set Implicit Arguments.
(** * The order tactic *)
(** This tactic is designed to solve systems of (in)equations involving [eq], [lt], [le] and [~eq] on some type. This tactic is domain-agnostic; it will only use equivalence+order axioms, and not analyze elements of the domain. Hypothesis or goal of the form [~lt] or [~le] are initially turned into [le] and [lt], other parts of the goal are ignored. This initial preparation of the goal is the only moment where totality is used. In particular, the core of the tactic only proceeds by saturation of transitivity and similar properties, and does not perform case splitting. The tactic will fail if it doesn't solve the goal. *)
(** An abstract vision of the predicates. This allows a one-line statement for interesting transitivity properties: for instance [trans_ord OLE OLE = OLE] will imply later [le x y -> le y z -> le x z]. *)
Inductive ord : Set := OEQ | OLT | OLE.
Definition trans_ord o o' :=
match o, o' with
| OEQ, _ => o'
| _, OEQ => o
| OLE, OLE => OLE
| _, _ => OLT
end.
Local Infix "+" := trans_ord.
(** ** The tactic requirements : a total order  We need : - an equivalence [eq], - a strict order [lt] total and compatible with [eq], - a larger order [le] synonym for [lt\/eq].  This used to be provided here via a [TotalOrder], but for technical reasons related to extraction, we now ask for two separate parts: relations in a [EqLtLe] + properties in [IsTotalOrder]. Note that [TotalOrder = EqLtLe <+ IsTotalOrder] *)
Module Type IsTotalOrder (O:EqLtLe) :=
IsEq O <+ IsStrOrder O <+ LeIsLtEq O <+ LtIsTotal O.
(** ** Properties that will be used by the [order] tactic *)
Module OrderFacts (Import O:EqLtLe)(P:IsTotalOrder O).
Include EqLtLeNotation O.
(** Reflexivity rules *)

(* Specifications: *)
Lemma eq_refl : forall x, x==x.
Lemma neq_sym : forall x y, ~x==y -> ~y==x.
Definition eq_trans x y z : x==y -> y==z -> x==z := @trans OEQ OEQ x y z.