How to prove a goal from contradictory hypotheses? - coq

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.

Related

Proof with multiple cases theorem

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.

How I can convert the relation between two terms in Coq

I have less than relationship between two terms (S i2) < i1. May I write it in the form of less or equal (a1<=a2).
You can Search for relevant lemmas:
Require Import Arith.
Search (_ < _) (_ <= _).
If you wish to preserve the same information, you have two options:
Do a case analysis on i1:
1.1. if it's 0 then you have an impossible statement, since there is no natural number smaller than zero. To look for this fact, Search (_ < 0) provides Nat.nlt_0_r.
1.2. if it's a successor, say S i1', then your statement becomes S i2 < S i1'. From our Search above, we found Nat.lt_succ_r, so we can rewrite our S i2 < S i1' to S i2 <= i1'.
Use Nat.lt_le_pred directly, but this will lead to S i2 <= Nat.pred i1, and the predecessor of i1 may or may not be useful to you.
Alternatively, if you know S i2 < i1 but you only care that S i2 <= i2, ie, you want to weaken your hypothesis, you can use Nat.lt_le_incl.
These terms are not fully equivalent, but the first is stronger than the second, using transitivity with the weakening i2 <= S (S i2) does suffice:
Require Import PArith PeanoNat.
Lemma example a b : S a < b -> a <= b.
Proof.
assert (a <= S (S a)).
now apply Le.le_Sn_le, Le.le_Sn_le.
exact (Nat.le_trans _ _ _ H).
Qed.
Recall that a < b is notation for S a <= b. You can also just weaken directly in backwards-chaining style.
Lemma example2 a b : S a < b -> a <= b.
Proof. now intros hlt; apply Nat.lt_le_incl, Nat.lt_le_incl. Qed.
Except for early stages of learning Coq, I would recommend the lia tactic:
Require Import PArith PeanoNat.
Require Import Lia.
Lemma example a b : S a < b -> a <= b.
Proof.
intros H.
lia.
Qed.

Apply partially instantiated lemma

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.

Stuck in the construction of a very simple function

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.

coq change premise 'negation of not equal' to 'equal'

Suppose I have a premise like this:
H2: ~ a b c <> a b c
And I wish to change it to:
a b c = a b c
Where
a is Term -> Term -> Term
b and c are both Term
How can I do it? Thanks!
If you unfold the definitions of ~ and <>, you hypothesis has the following type:
H2: (a b c = a b c -> False) -> False
Therefore, what you wish to achieve is what logicians usually call "double negation elimination". It is not an intuitionistically-provable theorem, and is therefore defined in the Classical module of Coq (see http://coq.inria.fr/distrib/V8.4/stdlib/Coq.Logic.Classical_Prop.html for details):
Classical.NNPP : forall (p : Prop), ~ ~ p -> p
I assume your actual problem is more involved than a b c = a b c, but for the sake of mentioning it, if you really care about obtaining that particular hypothesis, you can safely prove it without even looking at H2:
assert (abc_refl : a b c = a b c) by reflexivity.
If your actual example is not immediately reflexive and the equality is actually false, maybe you want to turn your goal into showing that H2 is absurd. You can do so by eliminating H2 (elim H2., which is basically doing a cut on the False type), and you will end up in the context:
H2 : ~ a b c <> a b c
EQ : a b c = a b c
=====================
False
I'm not sure whether all of this helps, but you might have oversimplified your problem so that I cannot provide more insight on what your real problem is.
Just a little thought to add to Ptival's answer - if your desired goal was not trivially solved by reflexivity, you could still make progress provided you had decidable equality on your Term, for example by applying this little lemma:
Section S.
Parameter T : Type.
Parameter T_eq_dec : forall (x y : T), {x = y} + {x <> y}.
Lemma not_ne : forall (x y : T), ~ (x <> y) -> x = y.
Proof.
intros.
destruct (T_eq_dec x y); auto.
unfold not in *.
assert False.
apply (H n).
contradiction.
Qed.
End S.