How do I prove 'S x > 0' from scratch in Coq? - coq

How do I prove the simple fact
forall x:nat, S x > 0.
?
My logic is that
For any nat n, either n > 0 or n = 0.
S x = 0 leads to a contradiction.
My main problem is that I can't memorize all these trivial theorems/lemma about nat, and I don't know the Search commands well enough.
I've tried to 'destruct gt' or the '>' constructor, or do some inversion on 'gt'. But I couldn't figure out the syntax or whether this is even the right direction.
Any help (except heavy things like omega) is highly appreciated.

Here is another approach (based on your observation about the natural numbers).
First of all, we need to import a module which contains many facts about natural numbers (without this import Search won't find what we are going to look for):
Require Import Coq.Arith.Arith.
Now, let's look for the lemma, which states that any nat is either 0 or greater than 0:
Search ({_ = 0} + {_}).
This search results in
zerop: forall n : nat, {n = 0} + {0 < n},
which is Coq's parlance for the previously observed fact.
Using that zerop lemma we can finally prove our goal:
Goal forall x:nat, S x > 0.
intros x.
destruct (zerop (S x)).
(* subcase S x = 0 *)
discriminate. (* deals with the contradiction *)
(* subcase S x > 0 *)
assumption.
Qed.
By the way, there is a lemma in the standard library (as of Coq v8.5), which states exactly the same thing, as your lemma:
Search (S _ > 0).
This results in gt_Sn_O: forall n : nat, S n > 0, and you can just look at the implementation of this lemma in the standard library (which in its turn uses a couple of lemmas).

Here a few commands that may help you:
Unset Printing Notations. in order to be able to see what symbols correspond to
Print ID. to see what the identifier ID is
unfold ID. to replace ID by its definition
SearchAbout (ID (CON ?m) ?n) to look for results involving ID apply to CON of a subterm and any other subterm (if you reuse the same ?m placeholder, the search will only return results where the corresponding subterms match).
In your case for instance, this could lead to this interactive session:
Unset Printing Notations.
Goal forall x:nat, S x > 0.
intro x.
Print gt.
unfold gt.
Print lt.
unfold lt.
Print le.
SearchAbout (le (S ?m) (S ?n)).
apply le_n_S.
SearchAbout (le 0 ?m).
apply le_0_n.
Qed.

I propose an alternative solution based on a computational encoding of the < operator:
From mathcomp
Require Import ssreflect ssrbool ssrfun eqtype ssrnat.
Lemma test n : 0 < n.+1.
Proof. by []. Qed.
How does this work? Indeed, this works because we define the < operation as a function:
(m < n) = (m.+1 <= n) = (m.+1 - n == 0)
when applied to your lemma, it becomes:
(0 < n.+1) = (0.+1 <= n.+1) = (1 - n.+1 == 0) = (0 - n == 0) = (0 == 0) = true

Related

Checking the successor of natural number

I want to prove a goal and I have two hypothesis.
Could you help me in proving the goal? Thank you very much for your help.
Goal : (S m <? S m - (S m - 1)) = true with two hypothesis
m : nat
H : 1 < 1
H0 : (S m =? 0) = false
1 is not, in fact, less than 1. Therefore, we can prove absurdity. Good thing, too, since the goal itself is otherwise impossible.
Require Import PeanoNat.
contradict H. (* now proving ~(1 < 1) *)
(* Well, < is irreflexive: forall x, ~(x < x). *)
apply Nat.le_irrefl.

How to prove a theorem on natural numbers using Coq list

I'm new in Coq. To do practice on list and list of pairs, I used Coq list library to prove a simple theorem of natural numbers. I try to prove the simple property of natural numbers:
forall n, multiplier, a0....an, d1...dn:
((a0*multiplier)=d1)+((a1*multiplier)=d2)+((a2*multiplier)=d3)+...+((an*multiplier)=dn) = result
-> (a0+a1+a2+...+an) * multiplier = d1+d2+...+dn = result
((3*2)=6)+((5*2)=10)+((9*2)=18) = 34 -> (3+5+9)*2 = 6+10+18 = 34 can be an example of this property(i.e. n=3 and multiplier = 2).
I use list of pairs (storing a's in one list and d's in another list) to code this property in Coq as:
Require Import List.
Fixpoint addnumbers (L : list nat) : nat :=
match L with
| nil => 0
| H::tail => H + addnumbers tail
end.
Theorem resultAreEqual : forall (natListofpair :list (nat * nat))
(multiplier : nat) (result : nat),
Forall (fun '(a,d) => a * multiplier = d ) natListofpair ->
addnumbers(List.map (#fst nat nat) natListofpair) * multiplier = result ->
addnumbers (List.map (#snd nat nat) natListofpair) = result.
Proof.
intros.
destruct natListofpair.
subst. simpl. reflexivity.
rewrite <- H0.
inversion H.
destruct p. simpl.
But I don't know how I should continue this prove. I'm stuck in this proving for one week. I'd be thankful for your help.
One reason you are having difficulty is that you have stated your lemma in an indirect way. When proving something in Coq, it is very important that you state it as simple as possible, as this often leads to easier proofs. In this case, the statement can become much simpler by using higher-order functions on lists.
Require Import Coq.Arith.PeanoNat.
Require Import Coq.Lists.List.
Definition sum (l : list nat) := fold_right Nat.add 0 l.
Lemma my_lemma l m : sum (map (Nat.mul m) l) = m * sum l.
The sum function is the equivalent of your addnumbers. The lemma says "the result of multiplying all numbers in l by m and adding them is the same as the result of adding them up first and multiplying by m later".
To prove this result, we need a crucial ingredient that your proof was missing: induction. This is often needed in Coq when we want to reason about objects of unbounded size, such as lists. Here is one possible proof.
Proof.
unfold sum.
induction l as [|x l IH]; simpl.
- (* Nil case *)
now rewrite Nat.mul_0_r.
- (* Cons case *)
now rewrite IH, Nat.mul_add_distr_l.
Qed.

forall equality in Coq

I am trying to prove the following equality:
Lemma Foo (A : Type) (n : nat) (gen : forall p : nat, p < S n -> A)
(ic0 : 0 < S n) (ic1 : 0 mod S n < S n):
gen (n - n) ic1 = gen 0 ic0.
The n-n is 0 by Nat.sub_diag and 0 mod S n is also 0 by Nat.mod_0_l. However I could not easily apply these lemmas to types. I tried usual trick of remember/rewrite/subst but subst part fails:
remember (gen (n-n)) as Q.
remember (n-n) as Q1.
rewrite Nat.sub_diag in HeqQ1.
subst.
P.S. This question may use a better title. Please suggest.
The subst tactic fails because remember is buggy; I have reported this bug here. (As a sanity, check, finishing a goal with abstract admit, where admit comes from Coq.Compat.AdmitAxiom, should never fail with a type error. If it does, that means there's a bug in Coq (or a plugin you're using).)
Here is a working proof (tested in 8.6.1 and 8.7+beta2):
Require Import Coq.Arith.Arith.
Lemma Foo (A : Type) (n : nat) (gen : forall p : nat, p < S n -> A)
(ic0 : 0 < S n) (ic1 : 0 mod S n < S n):
gen (n - n) ic1 = gen 0 ic0.
Proof.
revert ic0 ic1; simpl; rewrite Nat.sub_diag; intros ic0 ic1.
apply f_equal, le_unique.
Qed.
Note that you got lucky, in some sense, that n - n and 0 mod S n are judgmentally equal. Using simpl exposes this fact, and allows rewrite to work.

What prevents Coq from performing a trivial rewrite?

After clearing all superfluous hypotheses, I have the following goal in Coq:
1 focused subgoals (unfocused: 1-1-1-0-0)
, subgoal 1 (ID 14043)
in_contents : list byte
H0 : Zlength in_contents = 1
============================
0 <= 0 < Zlength in_contents
And, for context:
Print byte.
byte = {b : Z | 0 <= b < 256}
: Set
However, rewrite H0 gives:
Error: Found no subterm matching "Zlength in_contents" in the current
goal.
However, I can do this ridiculous proof:
split; try omega.
change ((1-1) < Zlength in_contents); rewrite <- H0; omega.
I'm sure that I must be missing something fundamental here.
(Even more oddly, this works fine:)
Example what : forall (in_contents:list byte), Zlength in_contents = 1 -> 0 <= 0 < Zlength in_contents.
Proof.
intros in_contents H0.
rewrite H0.
omega.
Qed.
as others have mentioned, it is likely that the rewrite is obstructed by some hidden terms in your goal or hypotheses. There are two common sources for this kind of problems:
Coercions:
Coercions (automatic type castings) are hidden by default by the Coq pretty printer. An example illustrating the issue is:
Section CRew.
Variable (A B : Type) (f : A -> B).
Coercion f : A >-> B.
Variable (x y : A).
Hypothesis H : #eq B x y.
Print H.
Lemma L1 : x = y.
(* rewrite H. fail *) Abort.
Set Printing Coercions.
Print H. (* H : f x = f y *)
End CRew.
In this case, H is really specifying an equality between f x and f
y but it is shown as x = y.
Implicit Arguments
Another common source of confusion is the implicit arguments feature. Again, have a look at this code.
Section IARew.
Definition U := fun (_ : nat) => nat.
Variable (f : forall x, U x -> B).
Arguments f [x] y.
Hypothesis H : eq (#f 1 2) (#f 2 3).
Print H.
Lemma L2 : (#f 2 2) = (#f 2 3).
(* rewrite H. Fail. *) Abort.
Set Printing Implicit.
Print H.
End IARew.
Here, #f 1 2 and #f 2 2 are shown as f 2, leading to a confusion.
I hope it helps, you can run the examples at:
https://x80.org/collacoq/eqosecuzar.coq

How to do case analysis on the length of a list in Coq?

I am in a situation during a proof where I need to do case analysis on the length of a list l.
When the length l < 2 it's one case (in which a binary operation like + does not apply)
When the length l >= 2 it's the other case (in which the binary operation applies)
How do I use destruct or some other tactic(s) to do this, and obtain two cases, i.e. True and False?
I tried:
destruct (length l < 2).
destruct (lt (length l) 2).
remember (length l < 2).
destruct HeqP.
But none worked.
You need a "constructive" version of <, because the standard one is in Prop, so you can't perform case analysis on it.
You can either use compare, le_lt_dec or a boolean version of < (search through the doc for all the options, the easiest one should be this one).
If you really need to test the length against 2, you could also destruct length n 3 times and handle by hand the 3 first cases.
Vinz answer is the right one. When you need to consider two cases that you "know are distinct", it's usually because they are decidable, so look for lemmas that end with _dec. In this case lt_dec is defined in Compare_dec, and you get it when you import Arith. So:
Require Import Arith.
Goal forall (l:list nat), True.
intro. destruct (lt_dec (length l) 2).
Now the first goal is
l : list nat
l0 : length l < 2
============================
True
and the second goal is
l : list nat
n : ~ length l < 2
============================
True