As elementary as it seems, I can't solve the following problem. There's this inductive type for even naturals and a proven lemma expressing that adding two even numbers yields an even number.
Inductive even : nat -> Prop :=
| O_even : even 0
| plus_2_even : forall n:nat, even n -> even (S (S n)).
Lemma lm_even1: forall n p:nat, even n -> even p -> even (n + p).
I'd like to prove the special case that n + 2 is even:
Lemma lm_even2: forall n: nat, even n -> even (n + 2).
The more general lm_even1 would come handy here but I keep failing with my efforts using apply, rewrite etc. to express that lm_even2 is the same statement with "p = 2". Help would be appreciated.
You might get a better answer if you show us what you've tried (explicitly). There's a short proof with just apply and one or two other basic tactics, but maybe you have a misunderstanding somewhere. Fixing that misunderstanding would be more helpful for you in the long term.
We should start by introducing all the premises. There's a good reason for this that I'll discuss below.
Lemma lm_even2: forall n: nat, even n -> even (n + 2).
Proof.
intros.
Now the proof state is
1 subgoal
n : nat
H : even n
______________________________________(1/1)
even (n + 2)
Now we're in a position to apply lm_even1.. apply term. attempts to unify the type of term with the goal, possibly filling in arguments to term from left to right (if it's some kind of function).
So, for example, apply lm_even1. would first try to unify with the full type
forall n p : nat, even n -> even p -> even (n + p)
Then it'll try with some variable to be determined as the first argument (of type nat):
forall p : nat, even ?n -> even p -> even (?n + p)
Then the same for p: even ?n -> even ?p -> even (?n + ?p). Next, since this is still a function type, it can continue by filling in the argument of type even ?n with some unknown variable: even ?p -> even (?n + ?p) and finally, even (?n + ?p).
The only one of those that could match the goal is the last one: even (?n + ?p) with ?n = n and ?p = 2. If we hadn't introduced the variables, this wouldn't work at all because none of the other types match the original goal.
Lemma lm_even2: forall n: nat, even n -> even (n + 2).
Proof.
intros.
apply lm_even1.
Now the proof state is
2 subgoals
n : nat
H : even n
______________________________________(1/2)
even n
______________________________________(2/2)
even 2
So we have two goals: even n and even 2. Both should be fairly easy to reach using the premises and the definition of even.
Related
Theorem ev_plus_plus : forall n m p,
even (n+m) -> even (n+p) -> even (m+p).
Proof.
intros n m p Hnm Hnp.
We get this:
1 subgoal (ID 189)
n, m, p : nat
Hnm : even (n + m)
Hnp : even (n + p)
============================
even (m + p)
Also we have a previously proven theorem:
ev_sum
: forall n m : nat, even n -> even m -> even (n + m)
We know that (n+m) is even and (n+p) is even.
How to create a new hypothesis in the context by applying ev_sum to Hnm and Hnp:
Hsum: even((n+m) + (n+p))
?
You have several options for this.
You can use pose proof like this:
pose proof (ev_sum _ _ Hnm Hnp) as Hsum.
it will do what you expect.
It allows you to give a term and add it as a hypothesis.
Another option is to use eapply ... in.
For instance you can do
eapply ev_sum in Hnm.
And then you have to give it Hnp in one of the subgoals.
I have the following Lemma with an incomplete proof:
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros.
reflexivity.
Qed.
This proof fails with
Unable to unify "n + 1" with "S n".
It seems like eq_S would be the way to prove this, but I can't apply it (it doesn't recognize n + 1 as S n: Error: Unable to find an instance for the variable y.). I've also tried ring, but it can't find a relation. When I use rewrite, it just reduces to the same final goal.
How can I finish this proof?
This is related to the way (+) is defined. You can access (+)'s underlying definition by turning notations off (in CoqIDE that's in View > Display notations), seeing that the notation (+) corresponds to the function Nat.add and then calling Print Nat.add which gives you:
Nat.add =
fix add (n m : nat) {struct n} : nat :=
match n with
| O => m
| S p => S (add p m)
end
You can see that (+) is defined by matching on its first argument which in n + 1 is the variable n. Because n does not start with either O or S (it's not "constructor-headed"), the match cannot reduce. Which means you won't be able to prove the equality just by saying that the two things compute to the same normal form (which is what reflexivity claims).
Instead you need to explain to coq why it is the case that for any n the equality will hold true. A classic move in the case of a recursive function like Nat.add is to proceed with a proof by induction. And it does indeed do the job here:
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros. induction n.
- reflexivity.
- simpl. rewrite <- IHn. reflexivity.
Qed.
Another thing you can do is notice that 1 on the other hand is constructor-headed which means that the match would fire if only you had 1 + n rather than n + 1. Well, we're in luck because in the standard library someone already has proven that Nat.add is commutative so we can just use that:
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros.
rewrite (Nat.add_comm n 1).
reflexivity.
Qed.
A last alternative: using SearchAbout (?n + 1), we can find all the theorems talking about the pattern ?n + 1 for some variable ?n (the question mark is important here). The first result is the really relevant lemma:
Nat.add_1_r: forall n : nat, n + 1 = S n
Here is what I am trying to prove:
A : Type
i : nat
index_f : nat → nat
n : nat
ip : n < i
partial_index_f : nat → option nat
L : partial_index_f (index_f n) ≡ Some n
V : ∀ i0 : nat, i0 < i → option A
l : ∀ z : nat, partial_index_f (index_f n) ≡ Some z → z < i
============================
V n ip
≡ match
partial_index_f (index_f n) as fn
return (partial_index_f (index_f n) ≡ fn → option A)
with
| Some z => λ p : partial_index_f (index_f n) ≡ Some z, V z (l z p)
| None => λ _ : partial_index_f (index_f n) ≡ None, None
end eq_refl
The obvious next step is either rewrite L or destruct (partial_index_f (index_f n). Trying to applying rewrite gives me an error:
Error: Abstracting over the term "partial_index_f (index_f n)"
leads to a term
"λ o : option nat,
V n ip
≡ match o as fn return (o ≡ fn → option A) with
| Some z => λ p : o ≡ Some z, V z (l z p)
| None => λ _ : o ≡ None, None
end eq_refl" which is ill-typed.
I do not understand what is causing this problem. I also would like to understand how I can deal with it in general.
I was able to prove it using the following steps, but I am not sure this is the best way:
destruct (partial_index_f (index_f n)).
inversion L.
generalize (l n0 eq_refl).
intros. subst n0.
replace l0 with ip by apply proof_irrelevance.
reflexivity.
congruence.
In Coq's theory, when you perform a rewrite with an equation, you have to generalize over the side of the equation that you want to replace. In your case, you want to replace partial_index_f (index_f n), so Coq tries to generalize that, as you can tell from the error message you got.
Now, if your goal contains something whose type mentions the thing that you want to replace, you might run into trouble, because this generalization might make the goal become ill-typed. (Notice that that type does not exactly occur in the goal, hence Coq does not try to deal with it like it does when something occurs in the goal.) Going back to your case, your l function has type ∀ z : nat, partial_index_f (index_f n) ≡ Some z → z < i, which mentions partial_index_f (index_f n), the term you want to replace. In the first branch of your match, you apply this function to the o = Some z hypothesis that you abstracted over. On the original goal, o was the thing you wanted to replace, but when Coq tries to generalize, the two do not match anymore, hence the error message.
I can't try to fix the problem on my own, but you can solve issues like this usually by generalizing over the term in your context that mentions the term you are replacing, because then its type will show in the goal, associated to a universally quantified variable. This might not help if your term is defined globally and you need it to have a certain shape after the rewrite in order to be able to perform additional reasoning steps, in which case you will probably have to generalize over the lemmas that you need as well.
Inspired by another question on StackOverflow, I defined a dense vector to be a vector with option A type elements that only contains Some _ elements, and no None elements.
Require Import Vector.
Section Dense.
Variable A:Type.
Inductive Is_dense : forall n, t (option A) n -> Prop :=
| snil : Is_dense 0 (nil _)
| scons: forall n s, Is_dense n s -> forall a, Is_dense (S n) (cons _ (Some a) _ s).
How can I prove the following two lemmas?
Lemma Is_dense_tl: forall n (s: t (option A) (S n)),
Is_dense (S n) s -> Is_dense n (tl s).
and
Lemma dense_hd: forall n (s: t (option A) (S n)), Is_dense (S n) s -> A.
And also, in the first lemma, when I do inversion s. I get the elements h n' X that were used by s's constructor, but how can I get an equality stating s = cons (option A) h n' X?
Because of type dependency, inversion can't directly generate what you expect, because it is not true in general. However, it is true for a large family of types, whose equality is decidable. In your case, you can apply Eqdep_dec.inj_pair2_eq_dec to get the equality you want, if you provide the fact that equality upon nat is decidable (and it is).
Here is the proof for the first lemma:
Lemma Is_dense_tl: forall n (s: t (option A) (S n)),
Is_dense (S n) s -> Is_dense n (tl s).
Proof.
intros n s hs.
inversion hs; subst; clear hs.
apply Eqdep_dec.inj_pair2_eq_dec in H0.
- now rewrite <- H0; simpl.
- (* insert proof of decidablity *) admit.
Qed.
EDIT: About your comment about the second lemma.
The main difference between your two lemmas is that the first one tries to prove the property Is_dense n (tl s) which lives in Prop, whereas the second one tries to exhibit a term of type A. In short, the former creates a term of sort Prop, the latter a term of sort Type.
To avoid inconsistency in Coq's logic, there is a hierarchy to organize the sorts, which is (not exactly, but to give you the rough idea) Prop: Set Set:Type_0 and Type_n: Type_n+1. On top of this hierarchy is built a type system where the dependent pair (e.g. the type {n: nat | even n } is the type of even natural numbers) is restricted. You can build a Prop from other Prop (e.g. forall p:Prop, p -> p lives in Prop). However you need to be careful when Type is involved. For example, (again, please refer to Coq's documentation for the exact statement) forall n:Type_i, Type_j is of type Type_max(i,j).
This restriction is here to avoid inconsistency (like Russel's paradox) in Coq's type system.
In your case, you are trying to inspect (using inversion) a term of sort Prop (Is_dense (S n) s) to build a term of type A, of sort Type. This is forbidden by the type system. To build a term of sort Type, you need to inspect terms of at least the sort Set. In your example, all you have to do is change the definition of Is_dense to land in Type instead of Prop, and you're good to go.
In Coq, I'm having problems with applying the rewrite tactic in the following situation:
Section Test.
Hypothesis s t : nat -> nat.
Hypothesis s_ext_eq_t : forall (x : nat), s x = t x.
Definition dummy_s : nat -> nat :=
fun n => match n with
| O => 42
| S np => s np
end.
Definition dummy_t : nat -> nat :=
fun n => match n with
| O => 42
| S np => t np
end.
Goal forall (n : nat), dummy_s n = dummy_t n.
Proof.
intro n. unfold dummy_s. unfold dummy_t.
At that stage, the local context and current goal look as follows:
1 subgoals, subgoal 1 (ID 6)
s : nat -> nat
t : nat -> nat
s_ext_eq_t : forall x : nat, s x = t x
n : nat
============================
match n with
| 0 => 42
| S np => s np
end = match n with
| 0 => 42
| S np => t np
end
Now it should be possible to apply the rewrite tactic to replace the occurence of s np in the goal by t np, thereby making it possible to solve the goal using reflexivity. However,
rewrite s_ext_eq_t.
gives
Toplevel input, characters 0-18:
Error: Found no subterm matching "s ?190" in the current goal.
What am I doing wrong? One can get into a situation where rewrite is applicable via
destruct n.
(* n = 0 *)
reflexivity.
(* n > 0 *)
rewrite s_ext_eq_t.
reflexivity.
Qed.
but in the actual situation I am facing, several such destructs would be necessary, and I wonder whether rewrite or a variant of it is able to do this automatically.
Addendum The above situation naturally occurs when proving that a function defined via well-founded recursion has the desired fixed point property:
Suppose A: Type and that R: A -> A -> Prop is a well-founded relation, i.e. we have Rwf: well_founded R. Then, given a type family P: A -> Type we may construct a section
Fix : forall (x : A), P a
through recursion over R, with the recursion step given as a function
F : forall x:A, (forall y:A, R y x -> P y) -> P x
See https://coq.inria.fr/library/Coq.Init.Wf.html However, to show that Fix indeed has the fixed point property
forall (x : A), Fix x = F (fun (y:A) _ => Fix y)`
we need to provide a witness
F_ext : forall (x:A) (f g:forall y:A, R y x -> P y),
(forall (y:A) (p:R y x), f y p = g y p) -> F f = F g.
i.e. we have to show that F does not use anything else from the given f: forall y:A, R y x -> P y but its values. Of course, in any concrete situation, this should be trivial to verify, but when one tries to prove it, one runs into a situation a minimal example of which I have presented above: One is facing a huge equality of two copies of the code for the recursion step, one time with f and another time with g. Your assumption tells that f and g are extensionally equal, so one should be able to rewrite them. However, in the code for the recursion step, there might be a large number of pattern matchings and new variables that doesn't make sense in the local context, hence it would be (unnecessarily?) quite tedious to destruct dozens of times before being allowed to apply rewrite.
As mentioned in a comment above, it is not possible to perform the rewrite directly on the branch of the match statement, because np is not in scope in the top-level environment. As far as Coq's theory is concerned, a proof of your statement will have to destruct n at some point.
Although I am not aware of any tactics for automating this kind of problem, it is not too hard to come up with some custom ltac code for solving your problem without too much pain:
Ltac solve_eq :=
try reflexivity;
match goal with
| |- match ?x with _ => _ end
= match ?x with _ => _ end =>
destruct x; auto
end.
Goal forall (n : nat), dummy_s n = dummy_t n.
Proof.
intro n. unfold dummy_s. unfold dummy_t.
solve_eq.
Qed.
If your extensional equality results are hypotheses that appear in your context, then solve_eq should be able to solve many goals of this shape; if not, you might have to add extra lemmas to your hint database.