What prevents Coq from performing a trivial rewrite? - coq

After clearing all superfluous hypotheses, I have the following goal in Coq:
1 focused subgoals (unfocused: 1-1-1-0-0)
, subgoal 1 (ID 14043)
in_contents : list byte
H0 : Zlength in_contents = 1
============================
0 <= 0 < Zlength in_contents
And, for context:
Print byte.
byte = {b : Z | 0 <= b < 256}
: Set
However, rewrite H0 gives:
Error: Found no subterm matching "Zlength in_contents" in the current
goal.
However, I can do this ridiculous proof:
split; try omega.
change ((1-1) < Zlength in_contents); rewrite <- H0; omega.
I'm sure that I must be missing something fundamental here.
(Even more oddly, this works fine:)
Example what : forall (in_contents:list byte), Zlength in_contents = 1 -> 0 <= 0 < Zlength in_contents.
Proof.
intros in_contents H0.
rewrite H0.
omega.
Qed.

as others have mentioned, it is likely that the rewrite is obstructed by some hidden terms in your goal or hypotheses. There are two common sources for this kind of problems:
Coercions:
Coercions (automatic type castings) are hidden by default by the Coq pretty printer. An example illustrating the issue is:
Section CRew.
Variable (A B : Type) (f : A -> B).
Coercion f : A >-> B.
Variable (x y : A).
Hypothesis H : #eq B x y.
Print H.
Lemma L1 : x = y.
(* rewrite H. fail *) Abort.
Set Printing Coercions.
Print H. (* H : f x = f y *)
End CRew.
In this case, H is really specifying an equality between f x and f
y but it is shown as x = y.
Implicit Arguments
Another common source of confusion is the implicit arguments feature. Again, have a look at this code.
Section IARew.
Definition U := fun (_ : nat) => nat.
Variable (f : forall x, U x -> B).
Arguments f [x] y.
Hypothesis H : eq (#f 1 2) (#f 2 3).
Print H.
Lemma L2 : (#f 2 2) = (#f 2 3).
(* rewrite H. Fail. *) Abort.
Set Printing Implicit.
Print H.
End IARew.
Here, #f 1 2 and #f 2 2 are shown as f 2, leading to a confusion.
I hope it helps, you can run the examples at:
https://x80.org/collacoq/eqosecuzar.coq

Related

Make two arbitrary variables the same in Coq

I have the following coq code:
Theorem filter_exercise : forall (X : Type) (l lf : list X) (test : X -> bool)
(x : X),
filter test l = x :: lf ->
test x = true.
Proof.
intros X l lf test x eq.
induction l as [|l' l].
- inversion eq.
- inversion eq as [H].
Which gives me:
X : Type
l' : X
l, lf : list X
test : X -> bool
x : X
eq : filter test (l' :: l) = x :: lf
testEq : test x = false
IHl : filter test l = x :: lf -> false = true
============================
filter test l = (if test l' then l' :: filter test l else filter test l)
Here, if I could just say that because test x = false and both x and l' are universally quantified variables of type X, then I'd be done with the proof.
However, that's a semantic argument, and I'm not sure how to do that in Coq. Am I going down the wrong path?
EDIT
For posterity, this is the solution I ultimately obtained:
Theorem filter_exercise : forall (X : Type) (l lf : list X) (test : X -> bool)
(x : X),
filter test l = x :: lf ->
test x = true.
Proof.
intros X l lf test x eq.
induction l as [|l' l].
- inversion eq.
- simpl in eq. destruct (test l') eqn:testl'.
+ inversion eq. rewrite <- H0. apply testl'.
+ apply IHl. apply eq.
Qed.
I am not sure what you mean by "semantic argument", but this proof strategy is not correct, neither on paper nor in Coq. Consider, for instance, the following statement:
Lemma faulty : forall n m : nat, even n -> even m.
Proof. Admitted.
By your logic, if n is even, then m should also be even, since both are universally quantified variables of type nat. However, precisely because they are universally quantified, they can instantiated to different values of nat, thus yielding obviously contradictory statements. For instance, if we instantiate faulty with 2 and 1, we should be able to conclude that 1 is even, which is not true.
Your argument that test x = false -> test l' = false is not true, as both variables x and l are universally quantified, and thus can have any value. You could just have a specific relationship between both variables in your hypothesis, but here it is not the case, except the relationship filter test (l' :: l) = x :: lf, that tells you that x could be an element of l which has not been filtered by test (but it also might be l').
You should not use inversion here, as your problem is really simple. You idea to perform an induction is fine however :
Try first to simplify several hypothesis.
Then see if there are different cases to deal with, and use destruct when needed (on the value of test l' in this problem)
You should be able to solve the problem then (the most complicated tactic you might have to use is injection)

Understanding specialize tactic

Trying to comprehend the answer of #keep_learning I walked through this code step by step:
Inductive nostutter {X:Type} : list X -> Prop :=
| ns_nil : nostutter []
| ns_one : forall (x : X), nostutter [x]
| ns_cons: forall (x : X) (h : X) (t : list X), nostutter (h::t) -> x <> h -> nostutter (x::h::t).
Example test_nostutter_4: not (nostutter [3;1;1;4]).
Proof.
intro.
inversion_clear H.
inversion_clear H0.
unfold not in H2.
(* We are here *)
specialize (H2 eq_refl).
apply H2.
Qed.
Here is what we have before excuting specialize
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : 1 = 1 -> False
============================
False
Here is eq Prop whose constructor eq_refl is used in specialize:
Inductive eq (A:Type) (x:A) : A -> Prop :=
eq_refl : x = x :>A
where "x = y :> A" := (#eq A x y) : type_scope.
I can't explain, how this command works:
specialize (H2 eq_refl).
I read about specialize in reference manual, but the explanation there is too broad. As far as I understand it sees that "1 = 1" expression in H2 satisfies eq_refl constructor and therefore eq proposition is True. Then it simplifies the expression:
True -> False => False
And we get
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : False
============================
False
Can somebody provide me a minimal example with explanation of what is specialize doing, so I could freely use it?
Update
Trying to imitate how specialize works using apply I did the following:
Example specialize {A B: Type} (H: A -> B) (a: A): B.
Proof.
apply H in a.
This gives:
A : Type
B : Type
H : A -> B
a : B
============================
B
Almost the same as specialize, only different hypothesis name.
In test_nostutter_4 theorem I tried this and it worked:
remember (#eq_refl nat 1) as Heq.
apply H2 in Heq as H3.
It gives us:
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : 1 = 1 -> False
Heq : 1 = 1
H3 : False
HeqHeq : Heq = eq_refl
============================
False
This one was more complex, we had to introduce a new hypothesis Heq. But we got what we need - H3 at the end.
Does specialize internally use something like remember? Or is it possible to solve it with apply but without remember?
specialize, in its simplest form, simply replaces a given hypothesis with that hypothesis applied to some other term.
In this proof,
Example specialize {A B: Type} (H: A -> B) (a: A): B.
Proof.
specialize (H a).
exact H.
Qed.
we initially have the hypothesis H: A -> B. When we call specialize (H a), we apply H to a (apply as in function application). This gives us something of type B. specialize then gets rid of the old H for us and replaces it with the result of the application. It gives the new hypothesis the same name: H.
In your case, we have H2: 1 = 1 -> False, which is a function from the type 1 = 1 to the type False. That means that H2 applied to eq_refl is of type False, i.e. H2 eq_refl: False. When we use the tactic specialize (H2 eq_refl)., the old H2 is cleared and replaced by a new term (H2 eq_refl) whose type is False. It keeps the old name H2, though.
specialize is useful when you're sure that you're only going to use a hypothesis once, since it automatically gets rid of the old hypothesis. One disadvantage is that the old name may not fit the meaning of the new hypothesis. However, in your case and in my example, H is a generic enough name that it works either way.
To your update...
specialize is a core tactic defined directly in the ltac plugin. It doesn't use any other tactic internally, since it is its internals.
If you want to keep a hypothesis, you can use the as modifier, which works for both specialize and apply. In the proof
Example specialize {A B: Type} (H: A -> B) (a: A): B.
Proof.
if you do specialize (H a) as H0., instead of clearing H, it'll introduce a new hypothesis H0: B. apply H in a as H0. has the same effect.

How to unfold a Coq fixpoint by one iteration

I have the following in my proof environment:
1 subgoal
a, b : nat
H : (fix loop (m : nat) : nat :=
match (m - a) with
| 0 => m
| S m' => loop m'
end) b = 0
G : (b - a) = 0
Clearly, H is equivalent to
match (b - a) with
| 0 => b
| S m' => loop m'
end = 0
Which would then allow me to rewrite using G.
But since it is trapped in there, represented as (m - a), I cannot rewrite using G.
How do I unfold a fixpoint out by one iteration?
Edit: The following code will set up the proof environment. Just ignore the admit statements. Your goal is not to prove the statement (which is trivial) but to "unfold" the fixpoint.
From mathcomp Require Import all.
Goal forall a b : nat,
modn b a = 0 -> True.
Proof.
intros a b H.
unfold modn in H.
destruct a.
+ admit.
+ simpl in H.
assert ((b - a) = 0) as G.
- admit.
- unfold modn_rec in H.
To unfold a fixpoint you need to destruct its decreasing argument.
destruct b; simpl in H.
If you want to keep a single case, you'll have to prove the equality you mention in a separate lemma or assertion.
assert (Hfix : (fix loop m := match ... end) b = match ... end)

forall equality in Coq

I am trying to prove the following equality:
Lemma Foo (A : Type) (n : nat) (gen : forall p : nat, p < S n -> A)
(ic0 : 0 < S n) (ic1 : 0 mod S n < S n):
gen (n - n) ic1 = gen 0 ic0.
The n-n is 0 by Nat.sub_diag and 0 mod S n is also 0 by Nat.mod_0_l. However I could not easily apply these lemmas to types. I tried usual trick of remember/rewrite/subst but subst part fails:
remember (gen (n-n)) as Q.
remember (n-n) as Q1.
rewrite Nat.sub_diag in HeqQ1.
subst.
P.S. This question may use a better title. Please suggest.
The subst tactic fails because remember is buggy; I have reported this bug here. (As a sanity, check, finishing a goal with abstract admit, where admit comes from Coq.Compat.AdmitAxiom, should never fail with a type error. If it does, that means there's a bug in Coq (or a plugin you're using).)
Here is a working proof (tested in 8.6.1 and 8.7+beta2):
Require Import Coq.Arith.Arith.
Lemma Foo (A : Type) (n : nat) (gen : forall p : nat, p < S n -> A)
(ic0 : 0 < S n) (ic1 : 0 mod S n < S n):
gen (n - n) ic1 = gen 0 ic0.
Proof.
revert ic0 ic1; simpl; rewrite Nat.sub_diag; intros ic0 ic1.
apply f_equal, le_unique.
Qed.
Note that you got lucky, in some sense, that n - n and 0 mod S n are judgmentally equal. Using simpl exposes this fact, and allows rewrite to work.

How do I prove 'S x > 0' from scratch in Coq?

How do I prove the simple fact
forall x:nat, S x > 0.
?
My logic is that
For any nat n, either n > 0 or n = 0.
S x = 0 leads to a contradiction.
My main problem is that I can't memorize all these trivial theorems/lemma about nat, and I don't know the Search commands well enough.
I've tried to 'destruct gt' or the '>' constructor, or do some inversion on 'gt'. But I couldn't figure out the syntax or whether this is even the right direction.
Any help (except heavy things like omega) is highly appreciated.
Here is another approach (based on your observation about the natural numbers).
First of all, we need to import a module which contains many facts about natural numbers (without this import Search won't find what we are going to look for):
Require Import Coq.Arith.Arith.
Now, let's look for the lemma, which states that any nat is either 0 or greater than 0:
Search ({_ = 0} + {_}).
This search results in
zerop: forall n : nat, {n = 0} + {0 < n},
which is Coq's parlance for the previously observed fact.
Using that zerop lemma we can finally prove our goal:
Goal forall x:nat, S x > 0.
intros x.
destruct (zerop (S x)).
(* subcase S x = 0 *)
discriminate. (* deals with the contradiction *)
(* subcase S x > 0 *)
assumption.
Qed.
By the way, there is a lemma in the standard library (as of Coq v8.5), which states exactly the same thing, as your lemma:
Search (S _ > 0).
This results in gt_Sn_O: forall n : nat, S n > 0, and you can just look at the implementation of this lemma in the standard library (which in its turn uses a couple of lemmas).
Here a few commands that may help you:
Unset Printing Notations. in order to be able to see what symbols correspond to
Print ID. to see what the identifier ID is
unfold ID. to replace ID by its definition
SearchAbout (ID (CON ?m) ?n) to look for results involving ID apply to CON of a subterm and any other subterm (if you reuse the same ?m placeholder, the search will only return results where the corresponding subterms match).
In your case for instance, this could lead to this interactive session:
Unset Printing Notations.
Goal forall x:nat, S x > 0.
intro x.
Print gt.
unfold gt.
Print lt.
unfold lt.
Print le.
SearchAbout (le (S ?m) (S ?n)).
apply le_n_S.
SearchAbout (le 0 ?m).
apply le_0_n.
Qed.
I propose an alternative solution based on a computational encoding of the < operator:
From mathcomp
Require Import ssreflect ssrbool ssrfun eqtype ssrnat.
Lemma test n : 0 < n.+1.
Proof. by []. Qed.
How does this work? Indeed, this works because we define the < operation as a function:
(m < n) = (m.+1 <= n) = (m.+1 - n == 0)
when applied to your lemma, it becomes:
(0 < n.+1) = (0.+1 <= n.+1) = (1 - n.+1 == 0) = (0 - n == 0) = (0 == 0) = true