forall equality in Coq - 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.

Related

coq program module throws out my hypotheses

EDIT: I fixed the issue by using subtypes, ie changing
forall(i: nat) to
forall(i: {n: nat | n <? length})
but I would still like to know why the program module behaves like this and if there's anything I could have done about it. The two programs are logically equivalent, so it would be silly for one to type-check but the other not to.
I am trying to write this function
Program Fixpoint indomain_arr (m: mem) (a: array) :=
match a with Array _ length => forall(i: nat), (i< length -> indomain m (inr(El a i))) end.
Obligation 1.
The specifics are not too important, I don't think, except for the fact that I have (i < length) as a hypothesis. When I proceed to obligation 1, the proof state is
m : mem
wildcard' : string
length, i : nat
============================
i <? length
which is annoying, as it doesn't include the hypothesis I put in the output proposition specifically so that I could solve this obligation. What is the fix for this? How can I bring that hypothesis back into my context?
Thanks.
I tried this code with coq 8.11.1.
Require Import Program.
Require Import Arith.
Inductive P (n : nat) : (n =? 0 = true) -> Prop :=
| P_intro : forall p, P n p.
Program Definition f (n : nat) : Prop :=
forall (i : nat), i < n -> P i _.
Next Obligation.
This results in the proof state
n, i : nat
============================
(i =? 0) = true
which doesn't have i < n as an assumption.
I tried another definition of f.
Program Definition f (n : nat) : Prop :=
forall (i : nat) (Hsmall : i < n), P i _.
Next Obligation.
(note that the hypothesis i < n is explicitly named as Hsmall)
Now I have the hypothesis in my proof state.
n, i : nat
Hsmall : i < n
============================
(i =? 0) = true

Using well founded induction to define factorial

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

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 do I prove 'S x > 0' from scratch in 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

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