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.
Related
I tried to add a definition of a natural number in CoqIDE.
Inductive nat : Set :=
| O: nat
| S: nat -> nat.
But I couldn't add this as "assumed true":
forall (n m: nat, S n = S m -> n = m).
How do I add this?
I'm not completely clear on what you want to do, but your formula is not syntactically correct. I believe you meant forall (n m: nat), S n = S m -> n = m (note the parenthesis' placement).
Your statement is actually provable, no need to assume it:
Lemma S_inj : forall (n m: nat), S n = S m -> n = m.
Proof. intros n m [=]. assumption. Qed.
The [=] intro pattern expresses the built-in injectivity of the S constructor.
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.
Is there any way to call apply lem in H for every possible H in premises, like rewrite lem in *?
Axiom P Q : nat -> Prop.
Axiom lem : forall (n : nat), P n -> Q n.
Goal P O -> P (S O) -> True.
intros. apply lem in H. apply lem in H0.
I couldn't find anything built in, but it's possible to write such a tactic with Ltac.
First, the special case.
Axiom P Q : nat -> Prop.
Axiom lem : forall (n : nat), P n -> Q n.
Goal P O -> P (S O) -> True.
intros.
repeat match goal with
x : _ |- _ => apply lem in x
end.
Abort.
Now we can generalize this
Ltac apply_in_premises t :=
repeat match goal with
x : _ |- _ => apply t in x
end.
and use it like this:
Goal P O -> P (S O) -> True.
intros.
apply_in_premises lem.
Abort.
Unfortunately, this way of doing it can cause an infinite loop if applying lem produces something else that lem can be applied to.
Axiom P : nat -> Prop.
Axiom lem : forall (n : nat), P n -> P (S n).
Ltac apply_in_premises t :=
repeat match goal with
x : _ |- _ => apply t in x
end.
Goal P O -> P (S O) -> nat -> True.
intros.
apply_in_premises lem. (* infinite loop *)
Abort.
If this is a concern for you, you can use a variant suggested by Yves in the comments. Simply changing apply t in x to apply t in x; revert x will ensure that that hypothesis won't be matched again. However, the end result will have all the hypotheses in the goal, like P -> G, instead of p: P as a premise and G as the goal.
To automatically reintroduce these hypotheses, we can keep track of how many times a hypothesis was reverted, then introduce them again.
Ltac intro_n n :=
match n with
| 0 => idtac
| S ?n' => intro; intro_n n'
end.
Ltac apply_in_premises_n t n :=
match goal with
| x : _ |- _ => apply t in x; revert x;
apply_in_premises_n t (S n)
| _ => intro_n n (* now intro all the premises that were reverted *)
end.
Tactic Notation "apply_in_premises" uconstr(t) := apply_in_premises_n t 0.
Axiom P : nat -> Prop.
Axiom lem : forall (n : nat), P n -> P (S n).
Goal P O -> P (S O) -> nat -> True.
intros.
apply_in_premises lem. (* only applies `lem` once in each of the premises *)
Abort.
Here, the tactic intro_n n applies intro n times.
I haven't tested this in general, but it works well in the case above. It might fail if a hypothesis can't be reverted (for example, if some other hypothesis depends on it). It also may reorder the hypotheses, since when a reverted hypothesis is reintroduced, it's put on the end of the hypothesis list.
Here are the inductive & computational definitions of evenness of natural numbers.
Inductive ev : nat -> Prop :=
| ev_0 : ev O
| ev_SS : forall n:nat, ev n -> ev (S (S n)).
Definition even (n:nat) : Prop :=
evenb n = true.
And the proof that one implies the other.
Theorem ev__even : forall n,
ev n -> even n.
intros n E.
induction E as [ | n' E' ].
reflexivity. apply IHE'. Qed.
I didn't think much of this proof at first, but on a closer look I find something troubling. The problem is that after the reflexivity step, I expect to see the context
1 subgoal
n' : nat
E : ev (S (S n'))
E' : ev n'
IHE' : ev n' -> even n'
====================================================================== (1/1)
even (S (S n'))
But what I actually get instead is
1 subgoal
n' : nat
E' : ev n'
IHE' : even n'
====================================================================== (1/1)
even (S (S n'))
Although the theorem is still provable as is, it is disturbing to see hypotheses mysteriously disappear. I'd like to know how to get the context I initially expected. From web searches I understand that this is a general problem with induction over constructed terms in Coq. One proposed solution on SO suggests using the remember tactic on hypotheses to be kept. But when I try that in this proof,
Theorem ev__even : forall n,
ev n -> even n.
intros n E.
remember E.
induction E as [ | n' E' ].
I get the following error message at the induction step.
Error: Abstracting over the term "n" leads to a term
"fun n : nat => forall e : ev n, e = E -> even n" which is ill-typed.
Which I do not really understand. I think the problem is that E has a free variable, but in that case I would be stuck, since there is no way to introduce E without also introducing n. (generalize dependent n would generalize E with it)
Is there any way to obtain the initially expected context?
To be useful, the induction tactic tries to generalize over all variables that depend on the thing you are doing induction on, and things that depend on the indices of its type. In your case, this implies generalizing over n, the newly generated proof e : ev n, and the equality e = E. However, it does not generalize over E itself, because the induction principles that are automatically generated for propositions ignore the proof argument. Unfortunately, this means that that generalization will be ill-typed, and your intuition is correct: because E was not generalized with n, its type will mention a different number, which will make the equality e = E ill-typed.
I don't understand what the induction tactic is doing here.
Whenever I don't understand what a tactic is doing, I try to just write the proof term myself.
If you invoke the induction principle by hand, you can keep the original hypothesis:
Theorem ev__even : forall n, ev n -> even n.
intros n E.
refine (ev_ind even _ _ n E).
- reflexivity.
- intros n' E' IH.
apply IH.
Qed.
This is what the context looks like in the second case of the induction:
n : nat
E : ev n
n' : nat
E' : ev n'
IH : even n'
============================
even (S (S n'))
Assuming
Fixpoint evenb (n:nat) : bool :=
match n with
| O => true
| S O => false
| S (S n') => evenb n'
end.
I am trying to write an induction hypothesis specifically for proving properties of even numbers. I formulated and proved the following:
Theorem ind_hyp_on_evens:
forall (p : nat -> Prop),
(p 0 -> (forall n, p n -> p (S (S n))) ->
forall n, p (n + n)).
Proof.
intros p P0 P1.
intro n.
assert(p (n + n) /\ p (S (S (n + n)))).
induction n as [| n'].
split. unfold plus. assumption.
unfold plus.
apply (P1 0).
assumption.
destruct IHn' as [A B].
split.
rewrite <- plus_Snm_nSm.
rewrite -> ? plus_Sn_m.
assumption.
rewrite <- plus_Snm_nSm.
rewrite -> ? plus_Sn_m.
apply (P1 (S (S (n' + n')))).
assumption.
destruct H as [H1 H2].
assumption. Qed.
Despite the fact that it's proved, any attempt to use it results in the error message: "Error: Not the right number of induction arguments."
Can someone please tell me what is the problem with the induction hypothesis, or otherwise, how to apply it??
Thanks,
Mayer
I believe induction assumes that any induction principle that will be used has the
fixed form
forall ... (P : SomeType -> Type) ..., (* or ->Set or ->Prop *)
... ->
forall (v : SomeType), P v
Your ind_hyp_on_evens matches only P (plus n n) which seems to confuse induction.
If you have a suitable goal, say forall n, is_even (n+n), you can manually do the
steps that induction normally does and extend that to handle the special form.
intro n0; (* temp. var *)
pattern (n0 + n0); (* restructure as (fun x => (is_even x)) (n0+n0) *)
refine (ind_hyp_on_evens _ _ _ n0); (* apply ind. scheme *)
clear n0; [| intros n IHn ]. (* clear temp., do one 'intros' per branch *)
I don't know if it's possible to pack that up as a general helper tactic for any induction scheme, packing these steps up as a per-scheme Ltac tactic should work however.
You could consider writing an inductive predicate that describes even numbers (code not tested):
Inductive even : nat -> Prop :=
| evenO : even O
| evenSSn : forall n, even n -> even (S (S n))
.
Coq will generate the induction principle automatically.
You would have to prove that even n holds before being able to perform induction on the "evenness" of n.