Library Coq.romega.ReflOmegaCore
Module Type Int.
Parameter t :
Set.
Parameter Inline zero :
t.
Parameter Inline one :
t.
Parameter Inline plus :
t -> t -> t.
Parameter Inline opp :
t -> t.
Parameter Inline minus :
t -> t -> t.
Parameter Inline mult :
t -> t -> t.
Notation "0" :=
zero :
Int_scope.
Notation "1" :=
one :
Int_scope.
Infix "+" :=
plus :
Int_scope.
Infix "-" :=
minus :
Int_scope.
Infix "*" :=
mult :
Int_scope.
Notation "- x" := (
opp x) :
Int_scope.
Open Scope Int_scope.
First, Int is a ring:
Int should also be ordered:
Basic properties of this order
Compatibilities
We should have a way to decide the equality and the order
Up to here, these requirements could be fulfilled
by any totally ordered ring. Let's now be int-specific:
Btw, lt_0_1 could be deduced from this last axiom
Now we also require a division function.
It is deliberately underspecified, since that's enough
for the proofs below. But the most appropriate variant
(and the one needed to stay in sync with the omega engine)
is "Floor" (the historical version of Coq's
Z.div).
Of course, Z is a model for our abstract int
Properties of abstract integers
Primo, some consequences of being a ring theory...
Definition two := 1
+1.
Notation "2" :=
two :
Int_scope.
Aliases for properties packed in the ring record.
More facts about plus
More facts about mult
More facts about opp
Specialized distributivities
Secondo, some results about order (and equality)
Lemma lt_irrefl :
forall n,
~ n<n.
Lemma lt_antisym :
forall n m,
n<m -> m<n -> False.
Lemma lt_le_weak :
forall n m,
n<m -> n<=m.
Lemma le_refl :
forall n,
n<=n.
Lemma le_antisym :
forall n m,
n<=m -> m<=n -> n=m.
Lemma lt_eq_lt_dec :
forall n m,
{ n<m }+{ n=m }+{ m<n }.
Lemma lt_dec :
forall n m:
int,
{ n<m } + { ~n<m }.
Lemma lt_le_iff :
forall n m,
(n<m) <-> ~(m<=n).
Lemma le_dec :
forall n m:
int,
{ n<=m } + { ~n<=m }.
Lemma le_lt_dec :
forall n m,
{ n<=m } + { m<n }.
Definition beq i j :=
match compare i j with Eq =>
true |
_ =>
false end.
Infix "=?" :=
beq :
Int_scope.
Lemma beq_iff i j :
(i =? j) = true <-> i=j.
Lemma beq_reflect i j :
reflect (
i=j) (
i =? j).
Lemma eq_dec :
forall n m:
int,
{ n=m } + { n<>m }.
Definition blt i j :=
match compare i j with Lt =>
true |
_ =>
false end.
Infix "<?" :=
blt :
Int_scope.
Lemma blt_iff i j :
(i <? j) = true <-> i<j.
Lemma blt_reflect i j :
reflect (
i<j) (
i <? j).
Lemma le_is_lt_or_eq :
forall n m,
n<=m -> { n<m } + { n=m }.
Lemma le_neq_lt :
forall n m,
n<=m -> n<>m -> n<m.
Lemma le_trans :
forall n m p,
n<=m -> m<=p -> n<=p.
Lemma not_eq (
a b:
int) :
~ a <> b <-> a = b.
Order and operations
Lemmas specific to integers (they use le_lt_int)
Some decidabilities
The Coq side of the romega tactic
First, basic equations, disequations, inequations
Then, the supported logical connectors
Everything else is left as a propositional atom (and ignored).
Definition of goals as a list of hypothesis
Definition of lists of subgoals (set of open goals)
A single goal packed in a subgoal list
An absurd goal
Decidable equality on terms
Interpretations of terms (as integers).
Interpretation of predicats (as Coq propositions)
Intepretation of hypothesis lists (as Coq conjunctions)
Interpretation of conclusion + hypotheses
Here we use Coq implications : it's less easy to manipulate,
but handy to relate to the Coq original goal (cf. the use of
generalize, and lighter (no repetition of types in intermediate
conjunctions).
Equivalence between these two interpretations.
Interpretations of list of goals
Here again, two flavours...
Equivalence between the two flavours.
Stabiliy and validity of operations
An operation on terms is stable if the interpretation is unchanged.
An operation on one hypothesis is valid if this hypothesis implies
the result of this operation.
Same for lists of hypotheses, and for list of goals
Some results about these validities.
Valid operations on hypotheses
Extract an hypothesis from the list
Apply a valid operation on two hypotheses from the list, and
store the result in the list.
In-place modification of an hypothesis by application of
a valid operation.
A tactic for proving stability
Ltac loop t :=
match t with
| (?
X1 = ?
X2) =>
loop X1 ||
loop X2
| (
_ -> ?
X1) =>
loop X1
| (
interp_hyps _ _ ?
X1) =>
loop X1
| (
interp_list_hyps _ _ ?
X1) =>
loop X1
| (
interp_prop _ _ ?
X1) =>
loop X1
| (
interp_term _ ?
X1) =>
loop X1
| (
EqTerm ?
X1 ?
X2) =>
loop X1 ||
loop X2
| (
LeqTerm ?
X1 ?
X2) =>
loop X1 ||
loop X2
| (?
X1 + ?
X2)%
term =>
loop X1 ||
loop X2
| (?
X1 - ?
X2)%
term =>
loop X1 ||
loop X2
| (?
X1 * ?
X2)%
term =>
loop X1 ||
loop X2
| (
- ?
X1)%
term =>
loop X1
| (
Tint ?
X1) =>
loop X1
| (
if ?
X1 =? ?
X2 then _ else _) =>
let H :=
fresh "H"
in
case (
beq_reflect X1 X2);
intro H;
try (
rewrite H in *;
clear H);
simpl;
auto;
Simplify
| (
if ?
X1 <? ?
X2 then _ else _) =>
case (
blt_reflect X1 X2);
intro;
simpl;
auto;
Simplify
| (
if (?
X1 =? ?
X2)%
term then _ else _) =>
let H :=
fresh "H"
in
case (
eq_term_reflect X1 X2);
intro H;
try (
rewrite H in *;
clear H);
simpl;
auto;
Simplify
| (
if _ && _ then _ else _) =>
rewrite andb_if;
Simplify
| (
if negb _ then _ else _) =>
rewrite negb_if;
Simplify
|
match N.compare ?
X1 ?
X2 with _ =>
_ end =>
destruct (
N.compare_spec X1 X2);
Simplify
|
match ?
X1 with _ =>
_ end =>
destruct X1;
auto;
Simplify
|
_ =>
fail
end
with Simplify :=
match goal with
| |- ?
X1 =>
try loop X1
|
_ =>
idtac
end.
Operations on equation bodies
The operations below handle in priority
normalized terms, i.e.
terms of the form:
([v1]*Tint k1 + ([v2]*Tint k2 + (... + Tint cst)))
with
v1>v2>... and all
ki<>0.
See
normalize below for a way to put terms in this form.
These operations also produce a correct (but suboptimal)
result in case of non-normalized input terms, but this situation
should normally not happen when running
romega.
/!\ Do not modify this section (especially
fusion and
normalize)
without tweaking the corresponding functions in
refl_omega.ml.
Multiplication and sum by two constants. Invariant:
k1<>0.
Multiplication by a (non-nul) constant.
Adding a constant
Instead of using
scalar_norm_add t 1 k, the following
definition spares some computations.
Division by a constant
All the non-constant coefficients should be exactly dividable
Fusion of two equations.
From two normalized equations, this fusion will produce
a normalized output corresponding to the coefficiented sum.
Invariant:
k1<>0 and
k2<>0.
Term normalization.
Precondition: all
Tmult should be on at least one
Tint.
Postcondition: a normalized equivalent term (see below).
Normalization of a proposition.
The only basic facts left after normalization are
0 = ... or
0 <> ... or
0 <= ....
When a fact is in negative position, we factorize a
Tnot
out of it, and normalize the reversed fact inside.
/!\ Here again, do not change this code without corresponding
modifications in
refl_omega.ml.
A simple decidability checker
For us, everything is considered decidable except
propositional atoms
Tprop _.
Omega steps
The following inductive type describes steps as they can be
found in the trace coming from the decision procedure Omega.
We consider here only normalized equations
0=..., disequations
0<>... or inequations
0<=....
First, the final steps leading to a contradiction:
- O_BAD_CONSTANT i : hypothesis i has a constant body
and this constant is not compatible with the kind of i.
- O_NOT_EXACT_DIVIDE i k :
equation i can be factorized as some k*t+c with 0<c<k.
Now, the intermediate steps leading to a new hypothesis:
- O_DIVIDE i k cont :
the body of hypothesis i could be factorized as k*t+c
with either k<>0 and c=0 for a (dis)equation, or
0<k and c<k for an inequation. We change in-place the
body of i for t.
- O_SUM k1 i1 k2 i2 cont : creates a new hypothesis whose
kind depends on the kind of hypotheses i1 and i2, and
whose body is k1*body(i1) + k2*body(i2). Depending of the
situation, k1 or k2 might have to be positive or non-nul.
- O_MERGE_EQ i j cont :
inequations i and j have opposite bodies, we add an equation
with one these bodies.
- O_SPLIT_INEQ i cont1 cont2 :
disequation i is split into a disjonction of inequations.
Index of an hypothesis in the list
Actual resolution steps of an omega normalized goal
First, the final steps, leading to a contradiction
O_BAD_CONSTANT
O_NOT_EXACT_DIVIDE
Now, the steps generating a new equation.
O_DIVIDE
O_SUM. Invariant: k1 and k2 non-nul.
MERGE_EQ
O_SPLIT_INEQ (only step to produce two subgoals).
Replaying the resolution trace
Rules for decomposing the hypothesis
This type allows navigation in the logical constructors that
form the predicats of the hypothesis in order to decompose them.
This allows in particular to extract one hypothesis from a conjunction.
NB: negations are now silently traversed.
This type allows extracting useful components from hypothesis, either
hypothesis generated by splitting a disjonction, or equations.
The last constructor indicates how to solve the obtained system
via the use of the trace type of Omega t_omega
Selection of a basic fact inside an hypothesis.
Fixpoint extract_hyp_pos (
s :
list direction) (
p :
proposition) :
proposition :=
match p,
s with
|
Tand x y,
D_left :: l =>
extract_hyp_pos l x
|
Tand x y,
D_right :: l =>
extract_hyp_pos l y
|
Tnot x,
_ =>
extract_hyp_neg s x
|
_,
_ =>
p
end
with extract_hyp_neg (
s :
list direction) (
p :
proposition) :
proposition :=
match p,
s with
|
Tor x y,
D_left :: l =>
extract_hyp_neg l x
|
Tor x y,
D_right :: l =>
extract_hyp_neg l y
|
Timp x y,
D_left :: l =>
if decidability x then extract_hyp_pos l x else Tnot p
|
Timp x y,
D_right :: l =>
extract_hyp_neg l y
|
Tnot x,
_ =>
if decidability x then extract_hyp_pos s x else Tnot p
|
_,
_ =>
Tnot p
end.
Theorem extract_valid :
forall s :
list direction,
valid1 (
extract_hyp_pos s).
Attempt to shorten error messages if romega goes rogue...
NB: interp_list_goal _ _ BUG = False /\ True.
Split and extract in hypotheses
Reduction of subgoal list by discarding the contradictory subgoals.
Pushing the conclusion into the hypotheses.
The omega tactic : all steps together
For now, the above modular construction is instanciated on Z,
in order to retrieve the initial ROmega.