First question post! Sorry for any inappropriate format in advance.
Trying to prove two versions of functions are the equivalent, I can't proceed after reaching this step. How can I solve this?
1 subgoal
a' : nat
Ha' : forall b : nat, version1 a' b 0 = version2 a' b 0
b' : nat
Hb' : version1 a' b' b' = version2 a' b' b'
______________________________________(1/1)
version1 a' (S b') (S b') = version2 a' (S b') (S b')
As currently stated, this goal is incomplete, because we do not know what version1 and version2 are. One may be tempted to think the statement should be true for any choices of version1 and version2, but for some choices of these functions, the opposite is provable:
Definition v1 (a b c : nat) :=
Nat.leb c 1.
Definition v2 (a b c : nat) :=
Nat.ltb c 1.
Lemma counterexample :
~ (forall (version1 version2 : nat -> nat -> nat -> bool),
forall a' : nat,
forall Ha' : (forall b : nat, version1 a' b 0 = version2 a' b 0),
forall b' : nat,
forall Hb': (version1 a' b' b' = version2 a' b' b'),
version1 a' (S b') (S b') = version2 a' (S b') (S b')).
Proof.
intros abs.
assert (v1 0 1 1 = v2 0 1 1).
apply abs.
auto.
auto.
discriminate.
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 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.
I'm trying to reason on a TRS, and I have ran into the following proof obligation:
infinite_sequence : forall t' : Term,
transitive_closure R t t' ->
exists t'' : Term, R t' t''
============================
exists f : nat -> Term, forall n : nat, R (f n) (f (n + 1))
With transitive_closure defined as follows:
Definition transitive_closure (trs : TRS) (x y : Term) :=
exists f: nat -> Term,
f 0 = x
/\
exists l: nat,
f l = y
/\
forall n: nat,
n < l
->
trs (f n) (f (n + 1))
.
So when I unfold:
infinite_sequence : forall t' : Term,
(exists f : nat -> Term,
f 0 = t /\
(exists l : nat,
f l = t' /\
(forall n : nat, n < l -> R (f n) (f (n + 1))))) ->
exists t'' : Term, R t' t''
============================
exists f : nat -> Term, forall n : nat, R (f n) (f (n + 1))
Is this proof obligation possible to fulfill? I am not married this exact definition of transitive_closure, so if it becomes much easier by choosing a different definition for that, I'm open to that.
Since your goal starts with exists f : nat -> Term, you have to explicitly build such a function. The easiest way to do so is to first build a function with a slightly richer return type ({ u: Term | transitive_closure R t u } instead of Term) and then to project pointwise its first component to finish the proof. This would give the following script:
simple refine (let f : nat -> { u: Term | transitive_closure R t u } := _ in _).
- fix f 1.
intros [|n].
{ exists t. exists (fun _ => t). admit. }
destruct (f n) as [t' H].
destruct (infinite_sequence t' H) as [t'' H']. (* ISSUE *)
exists t''.
destruct H as [f' [H1 [l [H2 H3]]]].
exists (fun m => if Nat.ltb m l then f' m else t'').
admit.
- exists (fun n => proj1_sig (f n)).
intros n.
rewrite Nat.add_1_r.
simpl.
destruct (f n) as [fn Hn].
now destruct infinite_sequence as [t'' H'].
The two admit are just there to keep the code simple; there is nothing difficult about them. The real issue comes from the line destruct (infinite_sequence t' H), since Coq will complain that "Case analysis on sort Set is not allowed for inductive definition ex." Indeed, infinite_sequence states that there exists t'' such that R t' t'', but it does so in a non-informative way (i.e., in Prop), while you need it to build a function that lives in the concrete world (i.e., in Set).
There are only two axiom-free solutions, but both might be incompatible with the remaining of your development. The easiest one is to put infinite_sequence in Set, which means its type is changed to forall t', transitive_closure R t t' -> { t'' | R t' t'' }.
The second solution requires R to be a decidable relation and Term to be an enumerable set. That way, you can still build a concrete t'' by enumerating all the terms until you find one that satisfies R t' t''. In that case, infinite_sequence is only used to prove that this process terminates, so it can be non-informative.
Rel chapter from Logical foundations. I was given a solution to the excersize that I'm trying to comprehend:
Definition antisymmetric {X: Type} (R: relation X) :=
forall a b : X, (R a b) -> (R b a) -> a = b.
Theorem le_antisymmetric :
antisymmetric le.
Proof.
unfold antisymmetric. intros a b [| b' H1] H2.
- reflexivity.
- absurd (S b' <= b').
+ apply le_Sn_n.
+ etransitivity ; eassumption.
I don't understand, how does intro pattern [| b' H1] work? After intros it shows:
2 subgoals (ID 43)
a, b : nat
H2 : a <= a
============================
a = a
subgoal 2 (ID 46) is:
a = S b'
2-nd subgoal:
a, b, b' : nat
H1 : a <= b'
H2 : S b' <= a
============================
a = S b'
I understand that it is equivalent to destruct, but what sort of destruct? It's definitely not a simple destruct b.
Also I'm trying to understand the logics behind using absurd (S b' <= b') tactics. Does it mean that if we prove that a = S b' in this context, it would imply that after we rewrite a to S b' in H1, we get: S b' <= b', which is a universally false statement (absurd)?
intros a b [| b' H1] H2 is equivalent to
intros a b H H2.
destruct H as [| b' H1].
destruct patterns generally follow the rules that if an inductive type has a single constructor (e.g. products) then for x in that inductive type, destruct x as [a b c...] does (non-recursive) induction and renames the new variables to a, b, c, etc. When the inductive type has more than one constructor, there are multiple cases. For that, you use destruct x as [a b c ... | d e f ... | ...]. These destruction patterns can be nested if needed, e.g. destruct x as [[a b] | [c [d | e]]]. Note that if a constructor takes no arguments, there is nothing to rename, so you can leave the pattern empty.
In particular, something like a natural number can be destructed with destruct n as [ | n']. This divides into the cases where n is zero (and the constructor has no arguments, so there's nothing to the left of the |) or n is the successor of n'. Similarly, a list could be destructed as destruct li as [ | a li'] to divide into the cases where the list is nil and where it is cons a li'. The space to the left of the | is unnecessary, so you could do destruct li as [| a li'].
What's happening in your case specifically is that le is defined as an inductive type something along the lines of
Inductive le (n : nat) : nat -> Prop :=
| le_n : le n n
| le_S : forall m : nat, le n m -> le n (S m).
So there are two cases: one with no arguments, and the successor case where the arguments are m: nat and H: le n m. Hence, the destruct pattern is [| m H].
To answer your second question, absurd (S b' <= b'). means that (we think) we're able to prove S b' <= b' in the current context. We can also prove (in the same context) that S b' <= b' is absurd, i.e. leads to a witness of False (more precisely, S b' <= b' -> False). Using the induction principle for False, this allows us to generate a witness for any type, and in particular for a = S b'.
You can see what kind of proof term absurd produces with a minimal experiment.
Goal forall A B: Type, A.
Proof.
intros A B.
absurd B.
Show Proof.
This should print (fun A B : Type => False_rect A (?Goal ?Goal0)). The first goal (?Goal) has type ~B (i.e. B -> False). The second goal (?Goal0) has type B. If we can provide both, then ?Goal ?Goal0 has type False, so False_rect A (?Goal ?Goal0) produces a witness of type A.
In an attempt to get a grasp what Coq is about, I ended up in a situation where I essentially need to prove that a=b -> nat_compare a b = Eq.
I can get a handy start by doing:
Coq < Theorem foo: forall (a:nat) (b:nat), a=b->nat_compare a b=Eq.
1 subgoal
============================
forall a b : nat, a = b -> nat_compare a b = Eq
foo < intros. rewrite H. destruct b.
which gives me:
2 subgoals
a : nat
H : a = 0
============================
nat_compare 0 0 = Eq
subgoal 2 is:
nat_compare (S b) (S b) = Eq
The first is trivial:
foo < simpl. reflexivity.
But the next goal stumps me:
1 subgoal
a : nat
b : nat
H : a = S b
============================
nat_compare (S b) (S b) = Eq
I can do
foo < rewrite <- H.
which gives:
1 subgoal
a : nat
b : nat
H : a = S b
============================
nat_compare a a = Eq
(I can also arrive to this exact point by simpl, which seems to make more sense.)
Now, with pen an paper, I'd just claim that here is my proof by induction..
Am I approaching this at all in a correct way? Where can I best learn how to do this properly?
I was able to prove this with
Theorem triv : forall a b, a = b -> nat_compare a b = Eq.
intros; subst; induction b; auto.
Qed.
The trick here is to leave the inductive hypothesis lying around. destruct is a weaker form of induction that doesn't give you an inductive hypothesis which you need for this proof.