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
...
*)
Related
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'm looking for this lemma about nats. I'm hoping it already exists in one of the Coq libraries so I don't have to prove it.
forall m n : nat, (S m < n)%nat -> (n - (S m) < n)%nat
Please point me to the library if it exists. Thanks!
You are almost looking for Nat.sub_lt. I recommend using the Search command to find lemmas. It's quite powerful.
Require Import Arith.
Goal forall m n, (S m < n)%nat -> (n - (S m) < n)%nat.
intros.
Search (_ - _ < _).
apply Nat.sub_lt.
Search (_ < _ -> _ <= _).
apply Nat.lt_le_incl, H.
Search (0 < S _).
apply Nat.lt_0_succ.
Qed.
or auto using Nat.sub_lt, Nat.lt_le_incl, Nat.lt_0_succ. or auto with arith.
This statement does not hold: substituting m = 0, the conclusion becomes n < n, a clear contradiction.
As far as I know, there is no Coq library to prove your statement. So you can come up with your own proof as:
Require Import PeanoNat List.
Import Nat.
Goal(forall m n : nat, (S m < n)%nat -> (n - (S m) < n)%nat).
Proof.
induction m.
destruct n.
intros.
inversion H.
intros. simpl.
rewrite Nat.sub_0_r.
apply lt_succ_diag_r.
intros.
intuition.
Qed.
I tried to define the reciprocal of a nonzero rational number, imitating the answers in my another question. I tried to delay the proof, but it seems that I misunderstood.
The following is my code:
1) Integers: define z (= a - b) as a pair (a, b) which is in a setoid with the equiv rel (a, b) ~ (c, d) <-> a + d = b + c
Definition Z_eq (z w: integer): Prop :=
match z with
| (z1, z2) =>
match w with
| (w1, w2) => z1 + w2 = z2 + w1
end
end.
Add Parametric Relation:
integer Z_eq
reflexivity proved by Z_refl
symmetry proved by Z_symm
transitivity proved by Z_tran
as Z. (** proved; omitting the proof *)
(** addition, subtraction, negation, multiplication are well-defined as a morphism *)
Add Morphism Z_plus with signature Z_eq ==> Z_eq ==> Z_eq as Z_plus_morph.
(** etc. *)
2) Positive integers: {n : nat | 0 <? n }
(** as in answers of the previous question *)
Local Coercion is_true : bool >-> Sortclass.
Definition Z_pos: Set := {n : nat | 0 <? n }.
Definition Z_pos__N (p: Z_pos): nat := proj1_sig p.
Coercion Z_pos__N : Z_pos >-> nat.
Definition Z_pos__Z (p: Z_pos): integer := (proj1_sig p, 0).
Coercion Z_pos__Z : Z_pos >-> integer.
Definition Z_pos_plus : Z_pos -> Z_pos -> Z_pos.
intros [x xpos%Nat.ltb_lt] [y ypos%Nat.ltb_lt].
refine (exist _ (x + y) _).
now apply Nat.ltb_lt, Nat.add_pos_pos.
Defined.
Definition Z_pos_mult : Z_pos -> Z_pos -> Z_pos.
intros [x xpos%Nat.ltb_lt] [y ypos%Nat.ltb_lt].
refine (exist _ (x * y) _).
now apply Nat.ltb_lt, Nat.mul_pos_pos.
Defined.
Lemma Z_pos_mult_compat: forall p q: Z_pos, Z_pos__N (Z_pos_mult p q) = Z_pos__N p * Z_pos__N q.
Proof. now intros [x xpos] [y ypos]. Qed.
Definition ZP1: Z_pos.
refine (exist _ 1 _). easy.
Defined.
3) Nonzero integers: {z : integer | z <Z> Z0}
(** nonzero integer *)
Definition Z_nonzero: Set := {z : integer | z <Z> Z0}.
(* abs value of a nonzero integer as an obj of type Z_pos *)
Definition Z_nonzero_abs__Z_pos (z: Z_nonzero): Z_pos.
destruct z as [[z1 z2] z3].
exists ((z1 - z2) + (z2 - z1))%nat.
Admitted. (** proof ommited *)
(* multiplication b/w two nonzero integers *)
Definition Z_nonzero_mult (z w: Z_nonzero): Z_nonzero.
exists (proj1_sig z *Z proj1_sig w).
Admitted.
(* sign of n - m *)
Definition N_sgn_diff__Z (n m: nat): integer :=
if n >? m then Z1 else if n =? m then Z0 else -Z Z1.
(* sign of n - m *)
Definition Z_nonzero_sgn__Z (z: Z_nonzero): Z_nonzero.
destruct z as [[z1 z2] z3].
exists (N_sgn_diff__Z z1 z2).
Admitted.
4) Rational numbers: ( a // b ) (a: integer, b: Z_pos)
Inductive rational: Type :=
| prerat : integer -> Z_pos -> rational.
Notation "( x '//' y )" := (prerat x y).
(* equality *)
Definition Q_eq (p q: rational): Prop :=
match p with
| (p1 // p2) =>
match q with
| (q1 // q2) => (Z_mult p1 (Z_pos__Z q2)) =Z= (Z_mult (Z_pos__Z p2) q1)
end
end.
(* numerator of a rational *)
Definition Q_numerator (q: rational) :=
match q with
| (iq // rq) => iq
end.
(* nonzero rationals *)
Definition Q_nonzero: Set := {q : rational | Q_numerator q <Z> Z0}.
(* numerator and denominator *)
Definition Q_nonzero_numerator (q: Q_nonzero): Z_nonzero.
destruct q as [[q1 q2] q3].
exists q1.
simpl in q3. apply q3.
Qed.
Definition Q_nonzero_denominator (q: Q_nonzero): Z_pos.
destruct q as [[q1 q2] q3].
exact q2.
Qed.
Definition Q_recip (q: Q_nonzero): Q_nonzero.
exists ( proj1_sig (Z_nonzero_mult (Z_nonzero_sgn__Z (Q_nonzero_numerator q)) (Z_pos__Z_nonzero (Q_nonzero_denominator q))) // Z_nonzero_abs__Z_pos (Q_nonzero_numerator q) ).
Admitted. (* proved. *)
(* inherited equality *)
Definition Q_nonzero_eq (p q: Q_nonzero): Prop := (proj1_sig p) =Q= (proj1_sig q).
Add Morphism Q_recip with signature Q_nonzero_eq ==> Q_nonzero_eq as Q_recip_morph.
Proof. (* well-definedness of Q_recip *)
destruct x, y.
unfold Q_nonzero_eq. simpl. intros.
unfold Q_recip. (* <----- unfolded result was very long and complex; not simplified after simpl. *)
Abort.
I think this definitions are somewhat complex, but it was my best try...
Now, how can I prove the consistency of the morphism Q_recip?
(View full code)
I think you forgot to add the definition of Q_nonzero in your development, so I cannot run your code. However, I believe that the issue is that you have used Qed instead of Defined in some of your definitions. This question discusses the issue in more detail. (In any case, as Emilio points out, it is usually better to avoid definitions in proof mode, as they tend to be harder to reason about, as you've probably noticed.)
A note on style: your development mimics common definitions of number systems from first principles in set theory, where we often use equivalence classes to define the integers, the rational numbers, etc. Though elegant, this approach is often inconvenient to use in Coq. The main issue is that, because of the lack of proper quotient types, you are forced to use setoids everywhere, which prevents you from using Coq's much more convenient equality operator =. It is simpler to write these definitions as plain datatypes. For instance, you can define the integers as
Inductive int :=
| Posz : nat -> int
| Negz : nat -> int.
where Posz represents the canonical injection from natural numbers into integers, and Negz maps the natural number n to the integer - n - 1. This is the approach followed in the mathematical components library. Of course, the standard library also has its own definition of the integers (here), so you do not need to replicate it. Defining the rationals is more complicated, but it can still be done: in mathematical components, they are defined as pairs of coprime integers (num, den) such that den > 0 and num.
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.
I have a list with a known value and want to induct on it, keeping track of what the original list was, and referring to it by element. That is, I need to refer to it by l[i] with varying i instead of just having (a :: l).
I tried to make an induction principle to allow me to do that. Here is a program with all of the unnecessary Theorems replaced with Admitted, using a simplified example. The objective is to prove allLE_countDown using countDown_nth, and have list_nth_rect in a convenient form. (The theorem is easy to prove directly without any of those.)
Require Import Arith.
Require Import List.
Definition countDown1 := fix f a i := match i with
| 0 => nil
| S i0 => (a + i0) :: f a i0
end.
(* countDown from a number to another, excluding greatest. *)
Definition countDown a b := countDown1 b (a - b).
Theorem countDown_nth a b i d (boundi : i < length (countDown a b))
: nth i (countDown a b) d = a - i - 1.
Admitted.
Definition allLE := fix f l m := match l with
| nil => true
| a :: l0 => if Nat.leb a m then f l0 m else false
end.
Definition drop {A} := fix f (l : list A) n := match n with
| 0 => l
| S a => match l with
| nil => nil
| _ :: l2 => f l2 a
end
end.
Theorem list_nth_rect_aux {A : Type} (P : list A -> list A -> nat -> Type)
(Pnil : forall l, P l nil (length l))
(Pcons : forall i s l d (boundi : i < length l), P l s (S i) -> P l ((nth i l d) :: s) i)
l s i (size : length l = i + length s) (sub : s = drop l i) : P l s i.
Admitted.
Theorem list_nth_rect {A : Type} (P : list A -> list A -> nat -> Type)
(Pnil : forall l, P l nil (length l))
(Pcons : forall i s l d (boundi : i < length l), P l s (S i) -> P l ((nth i l d) :: s) i)
l s (leqs : l = s): P l s 0.
Admitted.
Theorem allLE_countDown a b : allLE (countDown a b) a = true.
remember (countDown a b) as l.
refine (list_nth_rect (fun l s _ => l = countDown a b -> allLE s a = true) _ _ l l eq_refl Heql);
intros; subst; [ apply eq_refl | ].
rewrite countDown_nth; [ | apply boundi ].
pose proof (Nat.le_sub_l a (i + 1)).
rewrite Nat.sub_add_distr in H0.
apply leb_correct in H0.
simpl; rewrite H0; clear H0.
apply (H eq_refl).
Qed.
So, I have list_nth_rect and was able to use it with refine to prove the theorem by referring to the nth element, as desired. However, I had to construct the Proposition P myself. Normally, you'd like to use induction.
This requires distinguishing which elements are the original list l vs. the sublist s that is inducted on. So, I can use remember.
Theorem allLE_countDown a b : allLE (countDown a b) a = true.
remember (countDown a b) as s.
remember s as l.
rewrite Heql.
This puts me at
a, b : nat
s, l : list nat
Heql : l = s
Heqs : l = countDown a b
============================
allLE s a = true
However, I can't seem to pass the equality as I just did above. When I try
induction l, s, Heql using list_nth_rect.
I get the error
Error: Abstracting over the terms "l", "s" and "0" leads to a term
fun (l0 : list ?X133#{__:=a; __:=b; __:=s; __:=l; __:=Heql; __:=Heqs})
(s0 : list ?X133#{__:=a; __:=b; __:=s; __:=l0; __:=Heql; __:=Heqs})
(_ : nat) =>
(fun (l1 l2 : list nat) (_ : l1 = l2) =>
l1 = countDown a b -> allLE l2 a = true) l0 s0 Heql
which is ill-typed.
Reason is: Illegal application:
The term
"fun (l l0 : list nat) (_ : l = l0) =>
l = countDown a b -> allLE l0 a = true" of type
"forall l l0 : list nat, l = l0 -> Prop"
cannot be applied to the terms
"l0" : "list nat"
"s0" : "list nat"
"Heql" : "l = s"
The 3rd term has type "l = s" which should be coercible to
"l0 = s0".
So, how can I change the induction principle
such that it works with the induction tactic?
It looks like it's getting confused between
the outer variables and the ones inside the
function. But, I don't have a way to talk
about the inner variables that aren't in scope.
It's very strange, since invoking it with
refine works without issues.
I know for match, there's as clauses, but
I can't figure out how to apply that here.
Or, is there a way to make list_nth_rect use
P l l 0 and still indicate which variables correspond to l and s?
First, you can prove this result much more easily by reusing more basic ones. Here's a version based on definitions of the ssreflect library:
From mathcomp
Require Import ssreflect ssrfun ssrbool ssrnat eqtype seq.
Definition countDown n m := rev (iota m (n - m)).
Lemma allLE_countDown n m : all (fun k => k <= n) (countDown n m).
Proof.
rewrite /countDown all_rev; apply/allP=> k; rewrite mem_iota.
have [mn|/ltnW] := leqP m n.
by rewrite subnKC //; case/andP => _; apply/leqW.
by rewrite -subn_eq0 => /eqP ->; rewrite addn0 ltnNge andbN.
Qed.
Here, iota n m is the list of m elements that counts starting from n, and all is a generic version of your allLE. Similar functions and results exist in the standard library.
Back to your original question, it is true that sometimes we need to induct on a list while remembering the entire list we started with. I don't know if there is a way to get what you want with the standard induction tactic; I didn't even know that it had a multi-argument variant. When I want to prove P l using this strategy, I usually proceed as follows:
Find a predicate Q : nat -> Prop such that Q (length l) implies P l. Typically, Q n will have the form n <= length l -> R (take n l) (drop n l), where R : list A -> list A -> Prop.
Prove Q n for all n by induction.
I do not know if this answers your question, but induction seems to accept with clauses. Thus, you can write the following.
Theorem allLE_countDown a b : allLE (countDown a b) a = true.
remember (countDown a b) as s.
remember s as l.
rewrite Heql.
induction l, s, Heql using list_nth_rect
with (P:=fun l s _ => l = countDown a b -> allLE s a = true).
But the benefit is quite limited w.r.t. the refine version, since you need to specify manually the predicate.
Now, here is how I would have proved such a result using objects from the standard library.
Require Import List. Import ListNotations.
Require Import Omega.
Definition countDown1 := fix f a i := match i with
| 0 => nil
| S i0 => (a + i0) :: f a i0
end.
(* countDown from a number to another, excluding greatest. *)
Definition countDown a b := countDown1 b (a - b).
Theorem countDown1_nth a i k d (boundi : k < i) :
nth k (countDown1 a i) d = a + i -k - 1.
Proof.
revert k boundi.
induction i; intros.
- inversion boundi.
- simpl. destruct k.
+ omega.
+ rewrite IHi; omega.
Qed.
Lemma countDown1_length a i : length (countDown1 a i) = i.
Proof.
induction i.
- reflexivity.
- simpl. rewrite IHi. reflexivity.
Qed.
Theorem countDown_nth a b i d (boundi : i < length (countDown a b))
: nth i (countDown a b) d = a - i - 1.
Proof.
unfold countDown in *.
rewrite countDown1_length in boundi.
rewrite countDown1_nth.
replace (b+(a-b)) with a by omega. reflexivity. assumption.
Qed.
Theorem allLE_countDown a b : Forall (ge a) (countDown a b).
Proof.
apply Forall_forall. intros.
apply In_nth with (d:=0) in H.
destruct H as (n & H & H0).
rewrite countDown_nth in H0 by assumption. omega.
Qed.
EDIT:
You can state an helper lemma to make an even more concise proof.
Lemma Forall_nth : forall {A} (P:A->Prop) l,
(forall d i, i < length l -> P (nth i l d)) ->
Forall P l.
Proof.
intros. apply Forall_forall.
intros. apply In_nth with (d:=x) in H0.
destruct H0 as (n & H0 & H1).
rewrite <- H1. apply H. assumption.
Qed.
Theorem allLE_countDown a b : Forall (ge a) (countDown a b).
Proof.
apply Forall_nth.
intros. rewrite countDown_nth. omega. assumption.
Qed.
The issue is that, for better or for worse, induction seems to assume that its arguments are independent. The solution, then, is to let induction automatically infer l and s from Heql:
Theorem list_nth_rect {A : Type} {l s : list A} (P : list A -> list A -> nat -> Type)
(Pnil : P l nil (length l))
(Pcons : forall i s d (boundi : i < length l), P l s (S i) -> P l ((nth i l d) :: s) i)
(leqs : l = s): P l s 0.
Admitted.
Theorem allLE_countDown a b : allLE (countDown a b) a = true.
remember (countDown a b) as s.
remember s as l.
rewrite Heql.
induction Heql using list_nth_rect;
intros; subst; [ apply eq_refl | ].
rewrite countDown_nth; [ | apply boundi ].
pose proof (Nat.le_sub_l a (i + 1)).
rewrite Nat.sub_add_distr in H.
apply leb_correct in H.
simpl; rewrite H; clear H.
assumption.
Qed.
I had to change around the type of list_nth_rect a bit; I hope I haven't made it false.