How can I rewrite "+ 1" (plus one) to "S" (succ) in Coq? - coq

I have the following Lemma with an incomplete proof:
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros.
reflexivity.
Qed.
This proof fails with
Unable to unify "n + 1" with "S n".
It seems like eq_S would be the way to prove this, but I can't apply it (it doesn't recognize n + 1 as S n: Error: Unable to find an instance for the variable y.). I've also tried ring, but it can't find a relation. When I use rewrite, it just reduces to the same final goal.
How can I finish this proof?

This is related to the way (+) is defined. You can access (+)'s underlying definition by turning notations off (in CoqIDE that's in View > Display notations), seeing that the notation (+) corresponds to the function Nat.add and then calling Print Nat.add which gives you:
Nat.add =
fix add (n m : nat) {struct n} : nat :=
match n with
| O => m
| S p => S (add p m)
end
You can see that (+) is defined by matching on its first argument which in n + 1 is the variable n. Because n does not start with either O or S (it's not "constructor-headed"), the match cannot reduce. Which means you won't be able to prove the equality just by saying that the two things compute to the same normal form (which is what reflexivity claims).
Instead you need to explain to coq why it is the case that for any n the equality will hold true. A classic move in the case of a recursive function like Nat.add is to proceed with a proof by induction. And it does indeed do the job here:
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros. induction n.
- reflexivity.
- simpl. rewrite <- IHn. reflexivity.
Qed.
Another thing you can do is notice that 1 on the other hand is constructor-headed which means that the match would fire if only you had 1 + n rather than n + 1. Well, we're in luck because in the standard library someone already has proven that Nat.add is commutative so we can just use that:
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros.
rewrite (Nat.add_comm n 1).
reflexivity.
Qed.
A last alternative: using SearchAbout (?n + 1), we can find all the theorems talking about the pattern ?n + 1 for some variable ?n (the question mark is important here). The first result is the really relevant lemma:
Nat.add_1_r: forall n : nat, n + 1 = S n

Related

Prove equality on list constructed with a map

I have two lists, one constructed directly by recursion and the other constructed using a map operation. I'm trying to show they are equal, and surprisingly I got stuck.
Require Import Coq.Lists.List.
Import ListNotations.
Fixpoint ls_zeroes n :=
match n with
| 0 => nil
| S n' => 0 :: ls_zeroes n'
end.
Fixpoint ls_ones n := map S (ls_zeroes n).
Fixpoint ls_ones' n :=
match n with
| 0 => nil
| S n' => 1 :: ls_ones' n'
end.
Goal forall n, ls_ones n = ls_ones' n.
Proof.
intros.
induction n.
- reflexivity.
- simpl. f_equal. (* ??? *)
Abort.
This is what the context looks like:
1 subgoal
n : nat
IHn : ls_ones n = ls_ones' n
______________________________________(1/1)
map S (ls_zeroes n) = ls_ones' n
I thought fold ls_ones would map S (ls_zeroes n) into ls_ones n since that's literally the definition of ls_ones but it does nothing. If I try to unfold ls_ones in IHn I get a nasty recursive expression instead of the verbatim definition of ls_ones.
What is the cleanest way to complete this proof?
Notice that when you define ls_one and unfold the definition you gets :
(fix ls_ones (n0 : nat) : list nat := map S (ls_zeroes n0)) n = ls_ones' n
The problem is that ls_one isn't a fixpoint. Indeed, it's doesn't make a recursion. Once coq automatically defines the point {struct n0} (in that case the n argument), your proof gets stuck because n is never destructed in P k -> P (k + 1), 'cause k is not destructed.
Using :
Definition ls_ones n := map S (ls_zeroes n).
The proof becomes trivial :
Goal forall n, ls_ones n = ls_ones' n.
Proof.
intros.
induction n.
trivial.
unfold ls_ones in *.
simpl.
rewrite IHn.
trivial.
Qed.
I thought fold ls_ones would map S (ls_zeroes n) into ls_ones n since that's literally the definition of ls_ones
Is it? You said Fixpoint ls_ones, not Definition. Just like any Fixpoint, this means that the given definition of ls_ones is transformed into a fix. There's no recursive structure in the definition given, so this is pointless, but you said to do it, so Coq does it. Issue Print ls_ones. to see the actual definition. The true solution is to make ls_ones a Definition.
If you don't fix that, Coq will only reduce a Fixpoint if the recursive argument(s) start with constructors. Then, in order to complete this proof, you need to destruct n to show those constructors:
Goal forall n, ls_ones n = ls_ones' n.
Proof.
intros.
induction n.
- reflexivity.
- simpl. f_equal. destruct n; assumption.
Qed.
Unfortunately, due to the value being fixed in your definitions you must use induction to do the proof:
From mathcomp Require Import all_ssreflect.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Fixpoint seq0 n :=
match n with
| 0 => nil
| S n' => 0 :: seq0 n'
end.
Fixpoint seq1 n :=
match n with
| 0 => nil
| S n' => 1 :: seq1 n'
end.
Lemma eq_F n : seq1 n = [seq n.+1 | n <- seq0 n].
Proof. by elim: n => //= n ->. Qed.
There is not a lot to proof tho. I'd recommend tho using the more general nseq count elem function instead of definition your own duplicate structures, then the proof follows pretty quickly from the general lemma about map:
Lemma eq_G n : nseq n 1 = [seq n.+1 | n <- nseq n 0].
Proof. by rewrite map_nseq. Qed.

What should be done when simpl does not reduce all the necessary steps?

The following example is from chapter Poly of the Software Foundations book.
Definition fold_length {X : Type} (l : list X) : nat :=
fold (fun _ n => S n) l 0.
Theorem fold_length_correct : forall X (l : list X),
fold_length l = length l.
Proof.
intros.
induction l.
- simpl. reflexivity.
- simpl.
1 subgoal
X : Type
x : X
l : list X
IHl : fold_length l = length l
______________________________________(1/1)
fold_length (x :: l) = S (length l)
I expected it to simplify a step here on the left side. It certainly should be able to.
Theorem fold_length_correct : forall X (l : list X),
fold_length l = length l.
Proof.
intros.
induction l.
- simpl. reflexivity.
- simpl. rewrite <- IHl. simpl.
1 subgoal
X : Type
x : X
l : list X
IHl : fold_length l = length l
______________________________________(1/1)
fold_length (x :: l) = S (fold_length l)
During the running of the tests I had an issue where simpl would refuse to dive in, but reflexivity did the trick, so I tried the same thing here and the proof succeeded.
Note that one would not expect reflexivity to pass given the state of the goal, but it does. In this example it worked, but it did force me to do the rewrite in the opposite direction of what I intended originally.
Is it possible to have more control over simpl so that it does the desired reductions?
For the purposes of this answer, I'll assume the definition of fold is something along the lines of
Fixpoint fold {A B: Type} (f: A -> B -> B) (u: list A) (b: B): B :=
match u with
| [] => b
| x :: v => f x (fold f v b)
end.
(basically fold_right from the standard library). If your definition is substantially different, the tactics I recommend might not work.
The issue here is the behavior of simpl with constants that have to be unfolded before they can be simplified. From the documentation:
Notice that only transparent constants whose name can be reused in the recursive calls are possibly unfolded by simpl. For instance a constant defined by plus' := plus is possibly unfolded and reused in the recursive calls, but a constant such as succ := plus (S O) is never unfolded.
This is a bit hard to understand, so let's use an example.
Definition add_5 (n: nat) := n + 5.
Goal forall n: nat, add_5 (S n) = S (add_5 n).
Proof.
intro n.
simpl.
unfold add_5; simpl.
exact eq_refl.
Qed.
You'll see that the first call to simpl didn't do anything, even though add_5 (S n) could be simplified to S (n + 5). However, if I unfold add_5 first, it works perfectly. I think the issue is that plus_5 is not directly a Fixpoint. While plus_5 (S n) is equivalent to S (plus_5 n), that isn't actually the definition of it. So Coq doesn't recognize that its "name can be reused in the recursive calls". Nat.add (that is, "+") is defined directly as a recursive Fixpoint, so simpl does simplify it.
The behavior of simpl can be changed a little bit (see the documentation again). As Anton mentions in the comments, you can use the Arguments vernacular command to change when simpl tries to simplify. Arguments fold_length _ _ /. tells Coq that fold_length should be unfolded if at least two arguments are provided (the slash separates between the required arguments on the left and the unnecessary arguments on the right).[sup]1[\sup]
A simpler tactic to use if you don't want to deal with that is cbn which works here by default and works better in general. Quoting from the documentation:
The cbn tactic is claimed to be a more principled, faster and more predictable replacement for simpl.
Neither simpl with Arguments and a slash nor cbn reduce the goal to quite what you want in your case, since it'll unfold fold_length but not refold it. You could recognize that the call to fold is just fold_length l and refold it with fold (fold_length l).
Another possibility in your case is to use the change tactic. It seemed like you knew already that fold_length (a :: l) was supposed to simplify to S (fold_length l). If that's the case, you could use change (fold_length (a :: l)) with (S (fold_length l)). and Coq will try to convert one into the other (using only the basic conversion rules, not equalities like rewrite does).
After you've gotten the goal to S (fold_length l) = S (length l) using either of the above tactics, you can use rewrite -> IHl. like you wanted to.
I thought the slashes only made simpl unfold things less, which is why I didn't mention it before. I'm not sure what the default actually is, since putting the slash anywhere seems to make simpl unfold fold_length.

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.

prove that a list returned from a recursively defined function is fixed length in Coq

How do I prove a lemma like the following:
Require Import Coq.Lists.List.
Lemma len_seq_n : forall start n, length (seq start n)=n.
I tried
Proof.
induction n.
simpl. auto. simpl.
and at this point Coq gives me
1 subgoal
start, n : nat
IHn : length (seq start n) = n
______________________________________(1/1)
S (length (seq (S start) n)) = S n
I'm not sure how to proceed from there.
The problem is that your induction hypothesis is not general enough. You need the following statement instead:
IHn : forall start', length (seq start' n) = n
To obtain this hypothesis, simply generalize over start before doing induction on n with the revert tactic.
Proof.
intros start n.
revert start.
induction n.
(* Continue as previously *)
(Next time, please provide a complete example so that we can help you better. Your question was missing the definition of seq.)

How to apply theorems for definitions with restrictions in coq

I found a number of examples of definitions with restrictions in coq. Here is for example a variation of the pred function:
Lemma Lemma_NotZeroIsNotEqualToZero : ~ 0 <> 0.
Proof.
omega.
Qed.
Definition pred (s : { n : nat | n <> 0 }) : nat :=
match s with
| exist 0 pf => match (Lemma_NotZeroIsNotEqualToZero pf) with end
| exist (S n') _ => n'
end.
But I don't actually understand how to use this definition. Suppose I want to use pred for some natural number and I proved that this number is not zero. Like, for instance, suppose I proved the following lemma:
Lemma Lemma_TenIsNotEqualToZero : 10 <> 0.
Proof.
omega.
Qed.
Now, I want to compute what in essence is "pred 10" using Lemma_TenIsNotEqualToZero:
Eval compute in (pred ??).
How to do it?
pred is a function taking a sig type (try to Print sig.). Simply put, it's an inductive type with one constructor stating that "there exists an x of type A such that P x is true".
If you want to create a term of type {n : nat | n <> 0}, you will have to build it using constructors, like any other inductive type. In your case:
Eval compute in (pred (exist 10 Lemma_TenIsNotEqualToZero)).
It is the exact same syntax you used to pattern match on the s argument of pred.
Hope it helps,
V
PS: using omega for both your proofs is really overkill...
Lemma Lemma_NotZeroIsNotEqualToZero : ~ 0 <> 0.
Proof.
intro h.
apply h; reflexivity.
Qed.
Lemma Lemma_TenIsNotEqualToZero : 10 <> 0.
Proof.
intro h.
discriminate h.
Qed.
Edit: exists takes 3 arguments in practice (use Print to get a clear idea what are they used for). Depending on the status of implicit types, you should write
exists _ 10 Lemma_TenIsNotEqualToZero
with the additional _.