I have a hypothesis of the form
H := check_smaller_thm 1 2 : {2 <= 1} + {2 > 1}
I also have a sub goal
If check_smaller_thm 1 2 then some stuff else some other stuff
I am stuck at this point because I do not see what tactic to use in order to modify H such that I keep the correct Hypothesis (here, {2 > 1}). Then I would like to use it in my sub goal to keep the correct part of the if.
Is there a way to achieve this ?
EDIT
It seems that
If check_smaller_thm 1 2 then some stuff else some other stuff
always applies some stuff instead of other stuff. Is that possible ?
I think you need destruct (check_smaller_thm 1 2) eqn:Hd- see the reference manual here (https://coq.inria.fr/refman/proofs/writing-proofs/reasoning-inductives.html#coq:tacv.destruct-…-eqn:).
If your theorem check_smaller_thm 1 2 has type {2 <= 1} + {2 > 1}, when
you type the tactic destruct (check_smaller_thm 1 2), it creates two goals.
One of these goals contains the hypothesis 2 <= 1. This goal says, if 2 was smaller than or equal to 1, then the result would be some_stuff.
So it does look like the if expression returns some_stuff, but it is under a false hypothesis. You can get rid of this goal by showing that this hypothesis is inconsistent.
Here is an example. Notice that we spend some time working on the hypothesis named c2le1. Here I use elementary tactics to solve the problem, but lia would take care of the problem right away.
Require Import Arith Lia.
Lemma tutu (A : Type) (some_stuff : A) (some_other_stuff : A)
(check_smaller_thm : forall n m, {m <= n}+{m > n}) :
(if check_smaller_thm 1 2 then some_stuff else some_other_stuff) = some_other_stuff.
Proof.
destruct check_smaller_thm as [c2le1 | c1lt2].
apply le_S_n in c2le1; inversion c2le1.
reflexivity.
Qed.
Related
I am having trouble understanding the difference between an equality and a local definition. For example, when reading the documentation about the set tactic:
remember term as ident
This behaves as set ( ident := term ) in * and
using a logical (Leibniz’s) equality instead of a local definition
Indeed,
set (ca := c + a) in *. e.g. generates ca := c + a : Z in the context, while
remember (c + a ) as ca. generates Heqca : ca = c + a in the context.
In case 2. I can make use of the generated hypothesis like rewrite Heqca., while in case 1., I cannot use rewrite ca.
What's the purpose of case 1. and how is it different from case 2. in terms of practical usage?
Also, if the difference between the two is fundamental, why is remember described as a variant of set in the documentation (8.5p1)?
You could think of set a := b + b in H as rewriting H to be:
(fun a => H[b+b/a]) (b+b)
or
let a := b + b in
H[b+b/a]
That is, it replaces all matched patterns b+b by a fresh variable a, which is then instantiated to the value of the pattern. In this regard, both H and the rewrited hypotheses remain equal by "conversion".
Indeed, remember is in a sense a variant of set, however its implications are very different. In this case, remember will introduce a new proof of equality eq_refl: b + b = b + b, then it will abstract away the left part. This is convenient for having enough freedom in pattern matching etc... This is remember in terms of more atomic tactics:
Lemma U b c : b + b = c + c.
Proof.
assert (b + b = b + b). reflexivity.
revert H.
generalize (b+b) at 1 3.
intros n H.
In addition to #ejgallego's answer.
Yes, you cannot rewrite a (local) definition, but you can unfold it:
set (ca := c + a) in *.
unfold ca.
As for the differences in their practical use -- they are quite different. For example, see this answer by #eponier. It relies on the remember tactic so that induction works as we'd like to. But, if we replace remember with set it fails:
Inductive good : nat -> Prop :=
| g1 : good 1
| g3 : forall n, good n -> good (n * 3)
| g5 : forall n, good n -> good (n + 5).
Require Import Omega.
The variant with remember works:
Goal ~ good 0.
remember 0 as n.
intro contra. induction contra; try omega.
apply IHcontra; omega.
Qed.
and the variant with set doesn't (because we didn't introduce any free variables to work with):
Goal ~ good 0.
set (n := 0). intro contra.
induction contra; try omega.
Fail apply IHcontra; omega.
Abort.
I was following (incomplete) examples in Coq 8.5p1 's reference manual in chapter 11 about the mathematical/declarative proof language. In the example below for iterated equalities (~= and =~), I got a warning Insufficient Justification for rewriting 4 into 2+2, and eventually got an error saying:
No more subgoals, but there are non-instantiated existential
variables:
?Goal : [x : R H : x = 2 _eq0 : 4 = x * x
|- 2 + 2 = 4]
You can use Grab Existential Variables.
Example:
Goal forall x, x = 2 -> x + x = x * x.
Proof.
proof. Show.
let x:R.
assume H: (x = 2). Show.
have ( 4 = 4). Show.
~= (2*2). Show.
~= (x*x) by H. Show.
=~ (2+2). Show. (*Problem Here: Insufficient Justification*)
=~ H':(x + x) by H.
thus thesis by H'.
end proof.
Fail Qed.
I'm not familiar with the mathematical proof language in Coq and couldn't understand why this happens. Can someone help explain how to fix the error?
--EDIT--
#Vinz
I had these random imports before the example:
Require Import Reals.
Require Import Fourier.
Your proof would work for nat or Z, but it fails in case of R.
From the Coq Reference Manual (v8.5):
The purpose of a declarative proof language is to take the opposite approach where intermediate states are always given by the user, but the transitions of the system are automated as much as possible.
It looks like the automation fails for 4 = 2 + 2. I don't know what kind of automation uses the declarative proof engine, but, for instance, the auto tactic is not able to prove almost all simple equalities, like this one:
Open Scope R_scope.
Goal 2 + 2 = 4. auto. Fail Qed.
And as #ejgallego points out we can prove 2 * 2 = 4 using auto only by chance:
Open Scope R_scope.
Goal 2 * 2 = 4. auto. Qed.
(* `reflexivity.` would do here *)
However, the field tactic works like a charm. So one approach would be to suggest the declarative proof engine using the field tactic:
Require Import Coq.Reals.Reals.
Open Scope R_scope.
Unset Printing Notations. (* to better understand what we prove *)
Goal forall x, x = 2 -> x + x = x * x.
Proof.
proof.
let x : R.
assume H: (x = 2).
have (4 = 4).
~= (x*x) by H.
=~ (2+2) using field. (* we're using the `field` tactic here *)
=~ H':(x + x) by H.
thus thesis by H'.
end proof.
Qed.
The problem here is that Coq's standard reals are defined in an axiomatic way.
Thus, + : R -> R -> R and *, etc... are abstract operations, and will never compute. What does this mean? It means that Coq doesn't have a rule on what to do with +, contrary for instance to the nat case, where Coq knows that:
0 + n ~> 0
S n + m ~> S (n + m)
Thus, the only way to manipulate + for the real numbers it to manually apply the corresponding axioms that characterize the operator, see:
https://coq.inria.fr/library/Coq.Reals.Rdefinitions.html
https://coq.inria.fr/library/Coq.Reals.Raxioms.html
This is what field, omega, etc... do. Even 0 + 1 = 1 is not probable by computation.
Anton's example 2 + 2 = 4 works by chance. Actually, Coq has to parse the numeral 4 to a suitable representation using the real axioms, and it turns out that 4 is parsed as Rmult (Rplus R1 R1) (Rplus R1 R1) (to be more efficient), which is the same than the left side of the previous equality.
Let us assume that we want to prove the following (totally contrived) lemma.
Lemma lem : (forall n0 : nat, 0 <= n0 -> 0 <= S n0) -> forall n, le 0 n.
We want to apply nat_ind to prove it. Here is a possible proof:
Proof.
intros H n. apply nat_ind. constructor. exact H.
Qed.
But why not directly using H in the apply tactic, using something like apply (nat_ind _ _ H) or eapply (nat_ind _ _ H) ? But the first one fails, and the second one hides the remaining goal in an existential variable.
Is it possible in apply or its derivatives to skip hypotheses in order to specify the other arguments while keeping them as classic goals in the remainder of the proof ?
If you do
intros. refine (nat_ind _ _ H _).
then you only have
0 <= 0
left. Is that useful in your case?
Another approach (more universal than in my other answer) would be using the apply ... with ... construct, like this:
intros H n.
apply nat_ind with (2 := H).
Here, 2 is referring to the inductive step parameter of nat_ind (see the Coq v8.5 reference manual, 8.1.3):
In a bindings list of the form (ref_1 := term_1) ... (ref_n := term_n), ref is either an ident or a num. ... If ref_i is some number n, this number denotes the n-th non dependent premise of the term, as determined by the type of term.
This partial proof
intros H n.
apply nat_ind, H.
will give you 0 <= 0 as the only subgoal left.
This approach uses the apply tactic, but does not answer the question in its generality, since it will work only if you want to instantiate the last parameter (which is the case for the example in the question).
Here is quote from the Coq reference manual:
apply term_1 , ... , term_n
This is a shortcut for apply term_1 ; [ .. | ... ; [ .. | apply term_n ]... ], i.e. for the successive applications of term_(i+1) on the last subgoal generated by apply term_i, starting from the application of term_1.
Also, since it's just syntactic sugar, the solution may be considered cheating (and, I guess, abuse of the original intent of the Coq tactics developers) in the context of the question.
I am learning Coq. I am stuck on a quite silly problem (which has no motivation, it is really silly). I want to build a function from ]2,+oo] to the set of integers mapping x to x-3. That should be simple... In any language I know, it is simple. But not in Coq. First, I write (I explain with a lot of details so that someone can explain what I don't understand in the behaviour of Coq)
Definition f : forall n : nat, n > 2 -> nat.
I get a subgoal
============================
forall n : nat, n > 2 -> nat
which means that Coq wants a map from a proof of n>2 to the set of integers. Fine. So I want to tell it that n = 3 + p for some integer p, and then return the integer p. I write :
intros n H.
And I get the context/subgoal
n : nat
H : n > 2
============================
nat
Then i suppose that I have proved n = 3 + p for some integer p by
cut(exists p, 3 + p = n).
I get the context/subgoal
n : nat
H : n > 2
============================
(exists p : nat, 3 + p = n) -> nat
subgoal 2 (ID 6) is:
exists p : nat, 3 + p = n
I move the hypothesis in the context by
intro K.
I obtain:
n : nat
H : n > 2
K : exists p : nat, 3 + p = n
============================
nat
subgoal 2 (ID 6) is:
exists p : nat, 3 + p = n
I will prove the existence of p later. Now I want to finish the proof by exact p. So i need first to do a
destruct K as (p,K).
and I obtain the error message
Error: Case analysis on sort Set is not allowed for inductive
definition ex.
And I am stuck.
You are absolutely right! Writing this function should be easy in any reasonable programming language, and, fortunately, Coq is no exception.
In your case, it is much easier to define your function by simply ignoring the proof argument you are supplying:
Definition f (n : nat) : nat := n - 3.
You may then wonder "but wait a second, the natural numbers aren't closed under subtraction, so how can this make sense?". Well, in Coq, subtraction on the natural numbers isn't really subtraction: it is actually truncated. If you try to subtract, say, 3 from 2, you get 0 as an answer:
Goal 2 - 3 = 0. reflexivity. Qed.
What this means in practice is that you are always allowed to "subtract" two natural numbers and get a natural number back, but in order for this subtraction make sense, the first argument needs to be greater than the second. We then get lemmas such as the following (available in the standard library):
le_plus_minus_r : forall n m, n <= m -> n + (m - n) = m
In most cases, working with a function that is partially correct, such as this definition of subtraction, is good enough. If you want, however, you can restrict the domain of f to make its properties more pleasant. I've taken the liberty of doing the following script with the ssreflect library, which makes writing this kind of function easier:
Require Import Ssreflect.ssreflect Ssreflect.ssrfun Ssreflect.ssrbool.
Require Import Ssreflect.ssrnat Ssreflect.eqtype.
Definition f (n : {n | 2 < n}) : nat :=
val n - 3.
Definition finv (m : nat) : {n | 2 < n} :=
Sub (3 + m) erefl.
Lemma fK : cancel f finv.
Proof.
move=> [n Pn] /=; apply/val_inj=> /=.
by rewrite /f /= addnC subnK.
Qed.
Lemma finvK : cancel finv f.
Proof.
by move=> n; rewrite /finv /f /= addnC addnK.
Qed.
Now, f takes as an argument a natural number n that is greater than 2 (the {x : T | P x} form is syntax sugar for the sig type from the standard library, which is used for forming types that work like subsets). By restricting the argument type, we can write an inverse function finv that takes an arbitrary nat and returns another number that is greater than 2. Then, we can prove lemmas fK and finvK, which assert that fK and finvK are inverses of each other.
On the definition of f, we use val, which is ssreflect's idiom for extracting the element out of a member of a type such as {n | 2 < n}. The Sub function on finv does the opposite, packaging a natural number n with a proof that 2 < n and returning an element of {n | 2 < n}. Here, we rely crucially on the fact that the < is expressed in ssreflect as a boolean computation, so that Coq can use its computation rules to check that erefl, a proof of true = true, is also a valid proof of 2 < 3 + m.
To conclude, the mysterious error message you got in the end has to do with Coq's rules governing computational types, with live in Type, and propositional types, which live in Prop. Coq's rules forbid you from using proofs of propositions to build elements that have computational content (such as natural numbers), except in very particular cases. If you wanted, you could still finish your definition by using {p | 3 + p = n} instead of exists p, 3 + p = n -- both mean the same thing, except the former lives in Type while the latter lives in Prop.
I have hypotheses i <= 0 and i >= 2 in my context. How can I prove my goal? are there tactics for this?
You can solve this automatically with Omega tactic.
Require Import Omega.
Open Scope Z_scope.
Lemma xxx : forall i : Z, i <= 0 -> i >= 2 -> False.
Proof.
intros.
omega.
Qed.
If you are interested in the content of a proof, rather than just "is it true or false", here is a script "by hand" which details one way to prove this proposition. By the way, since the OP didn't give the type of i, I first assume it is a natural number.
Lemma xxx : forall i : nat, i <= 0 -> i >= 2 -> False.
Proof.
intros i h_i_O h_2_i.
assert (h_2_O: 2 <= 0).
- apply le_trans with i.
+ exact h_2_i. (* i >= 2 is just a notation for 2 <= i *)
+ exact h_i_O.
- apply le_Sn_O in h_2_O.
contradiction.
Qed.
The idea is to say: if 2 <= i <= 0 then 2 <= 0 and it is impossible that any number of the shape S n is less or equal than 0.
If you need the same result on Z:
Lemma yyy : forall i : Z, i <= 0 -> i >= 2 -> False.
Proof.
intros i h_i_O h_2_i.
assert (h_2_O: 2 <= 0).
- apply Zle_trans with i.
+ apply Z.ge_le; exact h_2_i. (* here we first need to switch the direction of <= by hand *)
+ exact h_i_O.
- vm_compute in h_2_O.
apply h_2_O; reflexivity.
Qed.
The main difference is how both <= operators le and Z.le are defined. Z.le is build on top of a decidable function Z.compare (a.k.a. ?=) (basically, Z.le a b means Z.compare a b <> Gt) so the vm_compute invocation asks Z.compare to compute the result of 2 ?= 0, which is Gt (2 is greater than 0), so you end up having the hypothesis Gt = Gt -> False which is used to close the goal.
There are other ways to prove it, you should have a look at the libraries about nat and Z. You can also compare these script with the one generated by Omega by printing (Print xxx) the content of the proof after the Qed.
Best,
V.