I'm learning coq and can't figure out why a rewrite doesn't work.
My code looks like this:
Inductive nat : Type :=
| zero
| succ (n : nat)
.
Fixpoint add (a b : nat) : nat :=
match b with
| zero => a
| succ b' => add (succ a) b'
end.
Theorem add_succ : forall a b : nat,
add a (succ b) = succ (add a b).
Proof.
induction b as [ | b' IHb ].
- simpl.
reflexivity.
-
My current proof state is this:
- a, b' : nat
- IHb : add a (succ b') = succ (add a b')
============================
add a (succ (succ b')) = succ (add a (succ b'))
My expectation is that if I run
rewrite -> IHb.
then, coq will rewrite the left-hand side of my goal to
succ (add a (succ b')
My reason for thinking this is that (succ b') is of type nat and b' is of type nat with no other restriction. So I expect coq to notice that the pattern in IHb is matched by the left-hand side of the goal. But that does not happen.
What am I doing wrong?
Your hypothesis IHb only allows to rewrite the exact term add a (succ b'), because a and b' are variables in your context. You could do the rewrite step you indicate if your hypothesis IHb was quantifying universally over b', e.g. IHb : forall x, add a (succ x) = succ (add a x). Maybe you can modify your proof to obtain a stronger induction hypothesis at that point (relevant tactics to do that might be revert and generalize).
It's very simple:
Theorem add_succ : forall a b : nat,
add a (succ b) = succ (add a b).
Proof.
intros *. revert a. induction b as [|b' IHb].
- simpl. reflexivity.
- simpl. intro a'. rewrite <- IHb with (succ a'). reflexivity.
Qed.
Related
I try to solve this proof but I don't find how to it.
I have two subgoals but I don't even know if it's correct.
Here the lemma that I trid to solve with this but I'm stuck :
2 subgoals
a, b : Nat
H : Equal (leB a b) True
______________________________________(1/2)
Equal match b with
| Z => False
| S m' => leB a m'
end (leB a b) / Equal (leB b (S a)) (leB a b)
______________________________________(2/2)
Equal (leB (S a) b) True / Equal (leB b (S a)) True
Inductive Bool : Type :=
True : Bool | False : Bool.
Definition Not(b : Bool) : Bool :=
Bool_rect (fun a => Bool)
False
True
b.
Lemma classic : forall b : Bool, Equal b (Not (Not b)).
Proof.
intro.
induction b.
simpl.
apply refl.
simpl.
apply refl.
Qed.
Definition Equal(T : Type)(x y : T) : Prop :=
forall P : T -> Prop, (P x) -> (P y).
Arguments Equal[T].
(* Avec certaines versions Arguments Equal[T] *)
Lemma refl : forall T : Type, forall x : T, Equal x x.
Proof.
intros.
unfold Equal.
intros.
assumption.
Qed.
Fixpoint leB n m : Bool :=
match n, m with
| Z, _ => True
| _, Z => False
| S n', S m' => leB n' m'
end.
First, don't introduce all variables in the beginning with intros. You will get a too weak induction hypothesis. Just introduce a.
Then in each branch, consider the different cases of b with the destruct tactic. It will simplify your goal and you can see if it is the left or the right side of goal that is true, and use your refl lemma to finish the goal.
The last case require that you use your induction hypothesis, and it is here that it is important that it holds for all b, not just one specific b.
Also, you didn't provide a definition for you Nat type, I guess it is something like this:
Inductive Nat := Z | S (n:Nat).
Here is a proof.
Lemma Linear : forall a b, (Equal (leB a b) True) \/ (Equal (leB b a) True).
Proof.
induction a.
- intros b. destruct b; simpl.
+ left. apply refl.
+ left. apply refl.
- intros b. destruct b; simpl.
+ right. apply refl.
+ destruct (IHa b) as [Hleft | Hright].
++ left. apply Hleft.
++ right. apply Hright.
Qed.
While it may not be as insightful, you can also use tactics that try these steps to get a shorter proof.
induction a; destruct b; firstorder.
will also prove your lemma.
I'm trying to proof that my function nonzeros' distribute over concat of list.
I wrote nonzeros' with a filter in this way:
Definition nonzeros' (l : list nat) : list nat := filter (fun x => match x with | O => false | _ => true end) l.
I've already proofed this 2 lemmas:
Lemma nonzeros'_remove_0 :
forall (a b: list nat),
nonzeros' (0 :: b) = nonzeros' b.
Proof.
intros a b.
unfold nonzeros'.
simpl.
reflexivity.
Qed.
Lemma nonzeros'_not_remove_Sn :
forall (a b: list nat) (n : nat),
nonzeros' (S n :: b) = S n :: nonzeros' b.
Proof.
intros a b n.
unfold nonzeros'.
simpl.
reflexivity.
Qed.
Now I have to proof the distribution over concat:
Lemma nonzero'_distribution_over_concat :
forall (a b : list nat),
nonzeros' (concat a b) = concat (nonzeros' a) (nonzeros' b).
In order to proof it I do the following:
Proof.
intros a b.
induction a as [| h t IHa].
-
simpl.
reflexivity.
-
simpl.
destruct h.
+ rewrite nonzeros'_remove_0. rewrite nonzeros'_remove_0. rewrite IHa. reflexivity.
The problem is that after the tactics
rewrite nonzeros'_remove_0.
Coq create 2 subgoal:
______________________________________(1/2)
nonzeros' (concat t b) = concat (nonzeros' (0 :: t)) (nonzeros' b)
______________________________________(2/2)
list nat
The second subgoal is unexpected. Why does it appear?
The lemma has an unused parameter a : list nat:
Lemma nonzeros'_remove_0 :
forall (a b: list nat),
nonzeros' (0 :: b) = nonzeros' b.
so to apply that lemma you need to provide such a list, and there is no way to tell which list it should be, other than by asking you via an extra goal. One could also develop automation to make an arbitrary choice here, but a better fix is to remove that unused parameter from the lemma in the first place.
Lemma nonzeros'_remove_0 :
forall (b: list nat),
nonzeros' (0 :: b) = nonzeros' b.
I am completely new to coq programming and unable to prove below theorem. I need help on steps how to solve below construct?
Theorem PeirceContra: forall (p q:Prop), ~p->~((p ->q) ->p).
I tried the proof below way.
Given axiom as Axiom classic : forall P:Prop, P \/ ~ P.
Theorem PeirceContra: forall (p q:Prop), ~ p -> ~((p -> q) -> p).
Proof.
unfold not.
intros.
apply H.
destruct (classic p) as [ p_true | p_not_true].
- apply p_true.
- elimtype False. apply H.
Qed.
Getting subgoal after using elimtype and apply H as
1 subgoal
p, q : Prop
H : p -> False
H0 : (p -> q) -> p
p_not_true : ~ p
______________________________________(1/1)
p
But now I am stuck here because I am unable to prove P using p_not_true construct of given axiom......Please suggest some help......
I am not clear how to use the given axiom to prove logic................
This lemma can be proved constructively. If you think about what can be done at each step to make progress the lemma proves itself:
Lemma PeirceContra :
forall P Q, ~P -> ~((P -> Q) -> P).
Proof.
intros P Q np.
unfold "~".
intros pq_p.
apply np. (* this is pretty much the only thing we can do at this point *)
apply pq_p. (* this is almost inevitable too *)
(* the rest should be easy *)
(* Qed. *)
I am experimenting with Coq Coinductive types. I use the lazy list type form the Coq'Art book (sect. 13.1.4):
Set Implicit Arguments.
CoInductive LList (A:Set) : Set :=
| LNil : LList A
| LCons : A -> LList A -> LList A.
Implicit Arguments LNil [A].
CoFixpoint LAppend (A:Set) (u v:LList A) : LList A :=
match u with
| LNil => v
| LCons a u' => LCons a (LAppend u' v)
end.
In order to match the guard condition I also use the following decomposition functions form this book:
Definition LList_decomp (A:Set) (l:LList A) : LList A :=
match l with
| LNil => LNil
| LCons a l' => LCons a l'
end.
Lemma LList_decompose : forall (A:Set) (l:LList A), l = LList_decomp l.
Proof.
intros.
case l.
simpl.
reflexivity.
intros.
simpl.
reflexivity.
Qed.
The Lemma that LNil is left-neutral is easy to prove:
Lemma LAppend_LNil : forall (A:Set) (v:LList A), LAppend LNil v = v.
Proof.
intros A v.
rewrite LList_decompose with (l:= LAppend LNil v).
case v.
simpl.
reflexivity.
intros.
simpl.
reflexivity.
Qed.
But I got stuck by proving that LNil is also right-neutral:
Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), LAppend v LNil = v.
After Arthur's answer, I tried with the new equality:
Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), LListEq (LAppend v LNil) v.
Proof.
intros.
cofix.
destruct v.
rewrite LAppend_LNil.
apply LNilEq.
Here I'm stuck. Coq's answer is:
1 subgoal
A : Set
a : A
v : LList A
LAppend_v_LNil : LListEq (LAppend (LCons a v) LNil) (LCons a v)
______________________________________(1/1)
LListEq (LAppend (LCons a v) LNil) (LCons a v)
After Eponier's answer I want to give it the final touch by introducing an Extensionality Axiom:
Axiom LList_ext: forall (A:Set)(l1 l2: LList A), (LListEq l1 l2 ) -> l1 = l2.
With that axiom I get the final cut of the Lemma:
Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), (LAppend v LNil) = v.
Proof.
intros.
apply LList_ext.
revert v.
cofix.
intros.
destruct v. Guarded. (* now we can safely destruct v *)
- rewrite LAppend_LNil.
constructor.
- rewrite (LList_decompose (LAppend _ _)).
simpl. constructor. apply LAppend_v_LNil.
Qed.
Now, here are my final questions for this thread:
Does such an axiom already exist in some Coq library?
Is that axiom consistent with Coq?
With what standard axioms of Coq (e.g. classic, UIP, fun ext, Streicher K) is that axiom inconsistent?
You guessed it right: just like for functions, Coq's generic notion of equality is too weak to be useful for most coinductive types. If you want to prove your result, you need to replace eq by a coinductive notion of equality for lists; for instance:
CoInductive LListEq (A:Set) : LList A -> LList A -> Prop :=
| LNilEq : LListEq A LNil LNil
| LConsEq x lst1 lst2 : LListEq A lst1 lst2 ->
LListEq A (LCons x lst1) (LCons x lst2).
Manipulating infinite objects is a vast topic in Coq. If you want to learn more, Adam Chlipala's CPDT has an entire chapter on coinduction.
A simple rule is to use cofix as soon as possible in your proofs.
Actually, in your proof of LAppend_v_LNil, the guarded condition is already violated at destruct v. You can check this fact using the command Guarded, which helps testing before the end of the proof if all the uses of coinduction hypotheses are legit.
Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), LListEq (LAppend v LNil) v.
intros.
cofix.
destruct v. Fail Guarded.
Abort.
You should actually swap intros and cofix. From there, the proof is not difficult.
EDIT: here is the complete solution.
Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), LListEq (LAppend v LNil) v.
cofix.
intros.
destruct v. Guarded. (* now we can safely destruct v *)
- rewrite LAppend_LNil.
constructor.
- rewrite (LList_decompose (LAppend _ _)).
simpl. constructor. apply LAppend_v_LNil.
Qed.
I have the defined inductive types:
Inductive InL (A:Type) (y:A) : list A -> Prop :=
| InHead : forall xs:list A, InL y (cons y xs)
| InTail : forall (x:A) (xs:list A), InL y xs -> InL y (cons x xs).
Inductive SubSeq (A:Type) : list A -> list A -> Prop :=
| SubNil : forall l:list A, SubSeq nil l
| SubCons1 : forall (x:A) (l1 l2:list A), SubSeq l1 l2 -> SubSeq l1 (x::l2)
| SubCons2 : forall (x:A) (l1 l2:list A), SubSeq l1 l2 -> SubSeq (x::l1) (x::l2).
Now I have to prove a series of properties of that inductive type, but I keep getting stuck.
Lemma proof1: forall (A:Type) (x:A) (l1 l2:list A), SubSeq l1 l2 -> InL x l1 -> InL x l2.
Proof.
intros.
induction l1.
induction l2.
exact H0.
Qed.
Can some one help me advance.
In fact, it is easier to do an induction on the SubSet judgment directly.
However, you need to be as general as possible, so here is my advice:
Lemma proof1: forall (A:Type) (x:A) (l1 l2:list A),
SubSeq l1 l2 -> InL x l1 -> InL x l2.
(* first introduce your hypothesis, but put back x and In foo
inside the goal, so that your induction hypothesis are correct*)
intros.
revert x H0. induction H; intros.
(* x In [] is not possible, so inversion will kill the subgoal *)
inversion H0.
(* here it is straitforward: just combine the correct hypothesis *)
apply InTail; apply IHSubSeq; trivial.
(* x0 in x::l1 has to possible sources: x0 == x or x0 in l1 *)
inversion H0; subst; clear H0.
apply InHead.
apply InTail; apply IHSubSeq; trivial.
Qed.
"inversion" is a tactic that checks an inductive term and gives you all the possible way to build such a term !!without any induction hypothesis!!
It only gives you the constructive premices.
You could have done it directly by induction on l1 then l2, but you would have to construct by hand the correct instance of inversion because your induction hypothesis would have been really weak.
Hope it helps,
V.