I have a proof that states the following:
forall n:nat, 0 <= n -> My_Property.
If I want to prove it let's say for n=2. Is there a way to tell Coq that because 2 is of type nat greater than 0, that 2 -> My_Property and that I can prove it for this particular case ?
If your proof has a name, for example:
Lemma My_PropertyP : forall (n : nat), 0 <= n -> My_Property n.
you can refer to the case n = 2 with My_PropertyP 2:
Check (My_PropertyP 2).
(*
My_PropertyP 2
: 0 <= 2 -> My_Property 2
*)
And since indeed we can prove 0 <= 2,
Lemma leq_0_2 : 0 <= 2. Proof. auto. Qed.
we can even instantiate this proof to obtain My_Property 2:
Check (My_PropertyP 2 leq_0_2).
(*
My_PropertyP 2 leq_0_2
: My_Property 2
*)
The above illustrates that you can think of lemmas as functions. name : forall (n : nat), P n represents a function called name that receives an element n of type nat and outputs an element of type P n. If P n has type Prop we usually say that name is a "lemma" instead of a "function" and that name n is a "proof of P n" instead of an "element of type P n", but ultimately they are just different names for the same thing. This is related to the Curry-Howard Isomorphism.
P.S. 0 <= n holds for every natural number, so it is spurious in this particular example.
If your goal is to prove that for every n something holds, then showing the particular case n = 2 won't solve the goal.
If you want to give a different proof for n = 2 than for every other n, you have two options:
Case analysis on n.
intro n.
case n.
- admit. (* 0 *)
- intro n'; case n'.
+ admit. (* 1 *)
+ intro n''; case n''.
* admit. (* 2 *)
* admit. (* 3 <= n *)
Case analysis on whether n equals 2.
Require Import Arith.
(*...*)
intro n.
case (Nat.eq_dec n 2).
- (* n = 2 -> ... *)
admit.
- (* n <> 2 -> ... *)
admit.
Related
I'm trying to prove that n <= 2^n in Coq, and I'm missing a simple lemma that must exist somewhere:
a <= b /\ c <= d -> a+c <= b+d
Even more generally, how can I search Coq libraries for lemmas like this one?
Here is my code for completeness:
(***********)
(* imports *)
(***********)
Require Import Nat.
Require Import Init.Nat.
Require Import Coq.Arith.PeanoNat.
(************************)
(* exponential function *)
(************************)
Definition f (a : nat) : nat := 2^a.
(**********************)
(* inequality theorem *)
(**********************)
Theorem a_leq_pow_2_a: forall a, a <= f(a).
Proof.
induction a as[|a' IHa].
- apply le_0_n.
- unfold f.
rewrite Nat.pow_succ_r.
* rewrite Nat.mul_comm.
rewrite Nat.mul_succ_r.
rewrite Nat.mul_1_r.
unfold f in IHa.
(* stuck here *)
Qed.
The command for searching lemmas is called Search. (For older Coq versions, it was split into SearchAbout, SearchPattern, etc.) See the documentation for all the possible variants.
In your case, you are looking for a lemma with a consequent of the form _+_ <= _+_. So, you can type the following, which will give six results, including the one you are looking for:
Search (_ + _ <= _ + _).
(*
Nat.add_le_mono_r: forall n m p : nat, n <= m <-> n + p <= m + p
Nat.add_le_mono: forall n m p q : nat, n <= m -> p <= q -> n + p <= m + q
...
*)
I have spent a lot of time on the notion of well founded induction and thought it was time to apply it to a simple case. So I wanted to use it do define the factorial function and came up with:
Definition fac : nat -> nat := Fix LtWellFounded (fun _ => nat) (* 'LtWellFounded' is some proof *)
(fun (n:nat) =>
match n as n' return (forall (m:nat), m < n' -> nat) -> nat with
| 0 => fun _ => 1
| S m => fun (g : forall (k:nat), k < S m -> nat) => S m * g m (le_n (S m))
end).
but then of course immediately arises the question of correctness. And when attempting to
prove that my function coincided everywhere with a usual implementation of fac, I realized things were far from trivial. In fact simply showing that fac 0 = 1:
Lemma fac0 : fac 0 = 1.
Proof.
unfold fac, Fix, Fix_F.
Show.
appears to be difficult. I am left with a goal:
1 subgoal
============================
(fix Fix_F (x : nat) (a : Acc lt x) {struct a} : nat :=
match x as n' return ((forall m : nat, m < n' -> nat) -> nat) with
| 0 => fun _ : forall m : nat, m < 0 -> nat => 1
| S m =>
fun g : forall k : nat, k < S m -> nat => S m * g m (le_n (S m))
end (fun (y : nat) (h : y < x) => Fix_F y (Acc_inv a h))) 0
(LtWellFounded' 0) = 1
and I cannot see how to reduce it further. Can anyone suggest a way foward ?
An application of a fixpoint only reduces when the argument it's recursing on has a constructor at its head. destruct (LtWellFounded' 0) to reveal the constructor, and then this will reduce to 1 = 1. Or, better, make sure LtWellFounded' is transparent (its proof should end with Defined., not Qed.), and then this entire proof is just reflexivity..
Some of the types that you give can actually be inferred by Coq, so you can also write
your fib in a slightly more readable form. Use dec to not forget which if branch your are in, and make the recursive function take a recursor fac as argument. It can be called with smaller arguments. By using refine, you can put in holes (a bit like in Agda), and get a proof obligation later.
Require Import Wf_nat PeanoNat Psatz. (* for lt_wf, =? and lia *)
Definition dec b: {b=true}+{b=false}.
now destruct b; auto.
Defined.
Definition fac : nat -> nat.
refine (Fix lt_wf _
(fun n fac =>
if dec (n =? 0)
then 1
else n * (fac (n - 1) _))).
clear fac. (* otherwise proving fac_S becomes impossible *)
destruct n; [ inversion e | lia].
Defined.
Lemma fac_S n: fac (S n) = (S n) * fac n.
unfold fac at 1; rewrite Fix_eq; fold fac.
now replace (S n - 1) with n by lia.
now intros x f g H; case dec; intros; rewrite ?H.
Defined.
Compute fac 8.
gives
Compute fac 8.
= 40320
: nat
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.
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
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