Addition of natural numbers in Coq - coq

Coq's standard libraries give the Peano natural numbers and addition:
Inductive nat : Set :=
| O : nat
| S : nat -> nat.
Fixpoint add n m :=
match n with
| 0 => m
| S p => S (add p m)
end.
I am curious if I change the fix_definition of addition like
Fixpoint add n m :=
match n with
| 0 => m
| S p => add p (S m)
end.
Is the new addition equivalent to the old one? I tried to prove their equivalence by proving forall n m, add (S n) m = S (add n m) but failed.

In order to proof your helper lemma, you need to be careful what to introduce. If you don't introduce m, you get a more general induction hypothesis as in:
Require Import Nat.
Print add.
Fixpoint my_add n m :=
match n with
| 0 => m
| S p => my_add p (S m)
end.
Lemma my_add_S_r: forall n m, my_add n (S m) = S (my_add n m).
Proof.
(* Note: don't introduce m here - you get a more general induction hypothesis this way *)
intros n.
induction n.
- intros; reflexivity.
- intros; cbn. rewrite IHn. reflexivity.
Qed.
Lemma my_add_equiv: forall n m, add n m = my_add n m.
intros.
induction n.
- reflexivity.
- cbn. rewrite my_add_S_r. rewrite IHn. reflexivity.
Qed.

Yes both additions are equivalent, you can prove it using the lemma plus_n_Sm : forall n m : nat, S (n + m) = n + S m from the standard library (found using Search "+" (S _).) and an adequate induction hypothesis (for instance P(n) := forall m, n + m = add n m).

Related

Proving S (n + m) = n + (S m), how to rewrite n+1 = S(n)?

Theorem add_0_r : forall n:nat, n + 0 = n.
Proof.
intros n. induction n as [| n' IHn'].
- (* n = 0 *) reflexivity.
- (* n = S n' *) simpl. rewrite -> IHn'. reflexivity. Qed.
Theorem plus_n_Sm : forall n m : nat,
S (n + m) = n + (S m).
Proof.
intros n m. induction m as [| m' IHn']. rewrite -> add_0_r. rewrite <- sum.
The last tactic rewirte <- sum does not work. This is the goal:
n: ℕ
-------------
S(n) = n + 1
I don't know how to rewrite n+1 as S(n). I think that n+1 is just a notation for S(n), right?
If you look at the definition of + as follows, you can see that it is defined by induction on its first argument:
Locate "+". (* to obtain the name Nat.add *)
Print Nat.add.
(*
Nat.add =
fix add (n m : nat) {struct n} : nat :=
match n with
| 0 => m
| S p => S (add p m)
end
: nat -> nat -> nat
*)
As a result 1 + n is indeed convertible to S n (you can see that using Eval cbn in 1 + ?[n].) but not n + 1 (if you unfold Nat.add. you will obtain a pattern match stuck on the variable n).
For your proof, that specific definition of + means that you might reconsider your approach and try to do your proof by induction on n rather than m (paying attention to have the right induction hypothesis).
If you are using the nat type from the standard library, then n+1 is not a notation for S n, but a notation for the function Nat.add. In that case n+1 is not apparently equal to S n. You need to prove it by an induction on n.
By the way, if you are using Nat.nat, you need to use induction on n rather than m. Because Nat.add is defined by a match on the first argument. In this case, your first subgoal of the induction can be proved simply by reflexivity. (Coq is able to simplify S (0 + m) and 0 + S m, but not S (n + 0) and n + 1).
Was able to prove with the following:
Theorem plus_n_Sm : forall n m : nat,
S (n + m) = n + (S m).
Proof.
intros n m. induction n as [| n' IHn'].
- simpl. reflexivity.
- simpl. rewrite -> IHn'. reflexivity.
Qed.

Induction on evidence for the "less than" relation in coq

I am working on the proof of the following theorem Sn_le_Sm__n_le_m in IndProp.v of Software Foundations (Vol 1: Logical Foundations).
Theorem Sn_le_Sm__n_le_m : ∀n m,
S n ≤ S m → n ≤ m.
Proof.
intros n m HS.
induction HS as [ | m' Hm' IHm'].
- (* le_n *) (* Failed Here *)
- (* le_S *) apply IHSm'.
Admitted.
where, the definition of le (i.e., ≤) is:
Inductive le : nat → nat → Prop :=
| le_n n : le n n
| le_S n m (H : le n m) : le n (S m).
Notation "m ≤ n" := (le m n).
Before induction HS, the context as well as the goal is as follows:
n, m : nat
HS : S n <= S m
______________________________________(1/1)
n <= m
At the point of the first bullet -, the context as well as the goal is:
n, m : nat
______________________________________(1/1)
n <= m
where we have to prove n <= m without any context, which is obviously impossible.
Why does it not generate S n = S m (and then n = m) for the le_n case in induction HS?
The main problem here -I think- is it is impossible to prove the Theorem using induction on HS as there is no way to say something about n with only hypothesis about S n because non of the constructors of le do not change the value of n. But anyway the reason that after first bullet - there is no assumption is because calling induction has the effect of replacing all occurrences of the property argument by the values that correspond to each constructor and it doesn't help in this case since the term that gets replaced S n is not mentioned anywhere. There are some tricks to avoid this. for example you can replace n with pred(S n) as follows.
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
Proof.
intros n m HS.
assert(Hn: n=pred (S n)). reflexivity. rewrite Hn.
assert(Hm: m=pred (S m)). reflexivity. rewrite Hm.
induction HS.
- (* le_n *) apply le_n.
- (* le_S *) (* Stucks! *) Abort.
But as I mentioned above it is impossible to go further. Another way is to use inversion which is smarter but in some cases it may not help since induction hypothesis would be necessary. But it worth to know about it.
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
Proof.
intros n m HS.
inversion HS.
- (* le_n *) apply le_n.
- (* le_S *) (* Stucks! *) Abort.
Best way to solve the problem is use of remember tactic as follows.
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
Proof.
intros n m HS.
remember (S n) as Sn.
remember (S m) as Sm.
induction HS as [ n' | n' m' H IH].
- (* le_n *)
rewrite HeqSn in HeqSm. injection HeqSm as Heq.
rewrite <- Heq. apply le_n.
- (* le_S *) (* Stucks! *) Abort.
According to Software Foundations (Vol 1: Logical Foundations)
The tactic remember e as x causes Coq to (1) replace all occurrences
of the expression e by the variable x, and (2) add an equation x = e
to the context.
Anyway, although it is impossible to prove the fact using induction on HS -imo-, performing an induction on m will solve the case. (Note the use of inversion.)
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
Proof.
intros n.
induction m as [|m' IHm'].
- intros H. inversion H as [Hn | n' contra Hn'].
+ apply le_n.
+ inversion contra.
- intros H. inversion H as [HnSm' | n' HSnSm' Heq].
+ apply le_n.
+ apply le_S. apply IHm'. apply HSnSm'.
Qed.
Just more examples of Kamyar's answer.
Well, let's take a look of le induction scheme :
Compute le_ind.
forall (n : nat) (P : nat -> Prop),
P n ->
(forall m : nat, n <= m -> P m -> P (S m)) ->
forall n0 : nat, n <= n0 -> P n0
P is some proposition that holds one natural number, which means in the case of le_n, our preposition n <= m will be reduced to forall n, n <= m. Indeed, it's the same lemma that we want to prove, however unprovable because there is no premise.
An easy to solve this is doing induction where le_ind doesn't do.
For example :
Theorem Sn_le_Sm__n_le_m' : forall m n,
S n <= S m -> n <= m.
elim.
by intros; apply : Gt.gt_S_le .
intros; inversion H0.
by subst.
by subst; apply : le_Sn_le.
Qed.
Notice that we doing induction by m, and using inversion to generates the two possible construction of le ({x = y} + {x < y}). Optionally, you can use le decidability.
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
intros.
generalize dependent n.
elim.
auto with arith.
intros.
have : n <= m.
by apply : H; apply : le_Sn_le.
move => H'.
destruct m.
auto with arith.
destruct (le_lt_eq_dec _ _ H').
assumption.
subst.
(* just prove that there is no S m <= m *)
Qed.
For the sake of your time, coq has the tactic dependent induction that easily solves your goal :
Theorem Sn_le_Sm__n_le_m'' : forall n m,
S n <= S m -> n <= m.
intros.
dependent induction H.
auto.
by apply : (le_Sn_le _ _ H).
Qed.

Proving increasing iota in Coq

I am stuck on a goal.
Assume we have the following definition:
Fixpoint iota (n : nat) : list nat :=
match n with
| 0 => []
| S k => iota k ++ [k]
end.
And we want to prove:
Theorem t1 : forall n, In n (iota n) -> False.
So far, I have managed to the following:
Theorem t1 : forall n, In n (iota n) -> False.
Proof.
intros.
induction n.
- cbn in H. contradiction.
- cbn in H. apply app_split in H.
Focus 2. unfold not. intros.
unfold In in H0. destruct H0. assert (~(n = S n)) by now apply s_inj.
contradiction.
apply H0.
apply IHn.
I used these two lemmas, proofs omitted:
Axiom app_split : forall A x (l l2 : list A), In x (l ++ l2) -> not (In x l2) -> In x l.
Axiom s_inj : forall n, ~(n = S n).
However, I am completely stuck, I need to somehow show that: In n (iota n) assuming In (S n) (iota n).
As you've observed the fact that the n in In n and the one in iota n are in lockstep in your statement makes the induction hypothesis hard to invoke (if not completely useless).
The trick here is to prove a more general statement than the one you are actually interested in which breaks this dependency between the two ns. I would suggest:
Theorem t : forall n k, n <= k -> In k (iota n) -> False.
from which you can derive t1 as a corollary:
Corollary t1 : forall n, In n (iota n) -> False.
intro n; apply (t n n); reflexivity.
Qed.
If you want to peek at the proof of t, you can have a look at this self-contained gist

Inductive Predicate for Addition in Coq

I'm new to inductive predicates in Coq. I have learned how to define simple inductive predicates such as "even" (as in adam.chlipala.net/cpdt/html/Predicates.html) or "last" (as in http://www.cse.chalmers.se/research/group/logic/TypesSS05/resources/coq/CoqArt/inductive-prop-chap/SRC/last.v).
Now I wanted to try something slightly more complicated: to define addition as an inductive predicate, but I got stuck. I did the following:
Inductive N : Type :=
| z : N (* zero *)
| s : N -> N. (* successor *)
Inductive Add: N -> N -> N -> Prop :=
| add_z: forall n, (Add n z n)
| add_s: forall m n r, (Add m n r) -> (Add m (s n) (s r)).
Fixpoint plus (x y : N) :=
match y with
| z => x
| (s n) => (s (plus x n))
end.
And I would like to prove a simple theorem (analogously to what has been done for last and last_fun in www.cse.chalmers.se/research/group/logic/TypesSS05/resources/coq/CoqArt/inductive-prop-chap/SRC/last.v):
Theorem T1: forall x y r, (plus x y) = r -> (Add x y r).
Proof.
intros x y r. induction y.
simpl. intro H. rewrite H. apply add_z.
case r.
simpl. intro H. discriminate H.
???
But then I get stuck. The induction hypothesis seems strange. I don't know if I defined Add wrongly, or if I am just using wrong tactics. Could you please help me, by either correcting my inductive Add or telling me how to complete this proof?
You introduced r before using induction on y. In general you'll want to use induction before introducing anything so the induction hypothesis is as general as possible.
Conjecture injectivity : forall n m, s n = s m -> n = m.
Theorem T1: forall x y r, (plus x y) = r -> (Add x y r).
Proof.
intros x y. induction y.
simpl. intros r H. rewrite H. apply add_z.
intro r. case r.
simpl. intro H. discriminate H.
simpl. intros n H. apply add_s. apply IHy. apply injectivity. apply H.
Qed.

Proving commutativity of max in coq

I have a function max:
Fixpoint max (n : nat) (m : nat) : nat :=
match n, m with
| O, O => O
| O, S x => S x
| S x, O => S x
| S x, S y => S (max x y)
end.
and a proof of the commutativity of max as follows:
Theorem max_comm :
forall n m : nat, max n m = max m n.
Proof.
intros n m.
induction n as [|n'];
induction m as [|m'];
simpl; trivial.
(* Qed. *)
This leaves off at S (max n' m') = S (max m' n'), which seems correct, and given the base case has already been proven, seems like one should be able to tell coq "just use the recursion!". However, I cannot figure out how to do it. Any help?
The problem is you introduce variable m before doing induction on variable n, and that makes the induction hypothesis less general. Try this instead.
intro n; induction n as [| n' IHn'];
intro m; destruct m as [| m'];
simpl; try (rewrite IHn'); trivial.