Library Coq.Structures.OrdersTac
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.
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 sperate parts: relations in a
EqLtLe + properties in
IsTotalOrder. Note that
TotalOrder = EqLtLe <+ IsTotalOrder
Properties that will be used by the order tactic
Reflexivity rules
Symmetry rules
Transitivity rules : first, a generic formulation, then instances
(double) negation rules
MakeOrderTac : The functor providing the order tactic.
order_eq : replace x by y in all (in)equations hyps thanks
to equality EQ (where eq has been hidden in order to avoid
self-rewriting), then discard EQ.
Ltac order_rewr x eqn :=
let rewr H t :=
generalize t;
clear H;
intro H
in
match goal with
|
H :
x == _ |-
_ =>
rewr H (
eq_trans (
eq_sym eqn)
H);
order_rewr x eqn
|
H :
_ == x |-
_ =>
rewr H (
eq_trans H eqn);
order_rewr x eqn
|
H :
~x == _ |-
_ =>
rewr H (
eq_neq (
eq_sym eqn)
H);
order_rewr x eqn
|
H :
~_ == x |-
_ =>
rewr H (
neq_eq H eqn);
order_rewr x eqn
|
H :
x < _ |-
_ =>
rewr H (
eq_lt (
eq_sym eqn)
H);
order_rewr x eqn
|
H :
_ < x |-
_ =>
rewr H (
lt_eq H eqn);
order_rewr x eqn
|
H :
x <= _ |-
_ =>
rewr H (
eq_le (
eq_sym eqn)
H);
order_rewr x eqn
|
H :
_ <= x |-
_ =>
rewr H (
le_eq H eqn);
order_rewr x eqn
|
_ =>
clear eqn
end.
Ltac order_eq x y eqn :=
match x with
|
y =>
clear eqn
|
_ =>
change (
interp_ord OEQ x y)
in eqn;
order_rewr x eqn
end.
Goal preparation : We turn all negative hyps into positive ones
and try to prove False from the inverse of the current goal.
These steps require totality of our order. After this preparation,
order only deals with the context, and tries to prove False.
Hypotheses of the form A -> False are also folded in ~A
for convenience (i.e. cope with the mess left by intuition).
Ltac order_prepare :=
match goal with
|
H : ?
A ->
False |-
_ =>
change (
~A)
in H;
order_prepare
|
H :
~(?R ?
x ?
y) |-
_ =>
match R with
|
eq =>
fail 1
|
_ => (
change (
~x==y)
in H ||
apply not_gt_le in H ||
apply not_ge_lt in H ||
clear H ||
fail 1);
order_prepare
end
|
H : ?
R ?
x ?
y |-
_ =>
match R with
|
eq =>
fail 1
|
lt =>
fail 1
|
le =>
fail 1
|
_ => (
change (
x==y)
in H ||
change (
x<y)
in H ||
change (
x<=y)
in H ||
clear H ||
fail 1);
order_prepare
end
| |-
~ _ =>
intro;
order_prepare
| |-
_ ?
x ?
x =>
exact (
eq_refl x) ||
exact (
le_refl x) ||
exfalso
|
_ =>
(
apply not_neq_eq;
intro) ||
(
apply not_ge_lt;
intro) ||
(
apply not_gt_le;
intro) ||
exfalso
end.
We now try to prove False from the various < <= == != hypothesis
Ltac order_loop :=
match goal with
|
H : ?
x < ?x |-
_ =>
exact (
lt_irrefl H)
|
H :
~ ?x == ?x |-
_ =>
exact (
H (
eq_refl x))
|
H : ?
x <= ?x |-
_ =>
clear H;
order_loop
|
H : ?
x == ?y |-
_ =>
order_eq x y H;
order_loop
|
H1 : ?
x <= ?y,
H2 : ?
y <= ?x |-
_ =>
generalize (
le_antisym H1 H2);
clear H1 H2;
intro;
order_loop
|
H1: ?
x <= ?y,
H2:
~ ?x == ?y |-
_ =>
generalize (
le_neq_lt H1 H2);
clear H1 H2;
intro;
order_loop
|
H1: ?
x <= ?y,
H2:
~ ?y == ?x |-
_ =>
generalize (
le_neq_lt H1 (
neq_sym H2));
clear H1 H2;
intro;
order_loop
|
H1 : ?
x < ?y,
H2 : ?
y < ?z |-
_ =>
match goal with
|
H :
x < z |-
_ =>
fail 1
|
_ =>
generalize (
lt_trans H1 H2);
intro;
order_loop
end
|
H1 : ?
x <= ?y,
H2 : ?
y < ?z |-
_ =>
match goal with
|
H :
x < z |-
_ =>
fail 1
|
_ =>
generalize (
le_lt_trans H1 H2);
intro;
order_loop
end
|
H1 : ?
x < ?y,
H2 : ?
y <= ?z |-
_ =>
match goal with
|
H :
x < z |-
_ =>
fail 1
|
_ =>
generalize (
lt_le_trans H1 H2);
intro;
order_loop
end
|
H1 : ?
x <= ?y,
H2 : ?
y <= ?z |-
_ =>
match goal with
|
H :
x <= z |-
_ =>
fail 1
|
_ =>
generalize (
le_trans H1 H2);
intro;
order_loop
end
|
_ =>
idtac
end.
The complete tactic.