Proving theorem in Coq, the number of occurances in a list is <= the lenght of this list - coq

Fixpoint num_occ (x : nat)(xs : list nat) : nat :=
match xs with
| [] => 0
| (y :: ys) => if eq_dec x y
then 1 + num_occ x ys
else num_occ x ys
end.
Theorem exercise2
: forall x xs, num_occ x xs <= length xs.
Proof.
I tried, but i have no idea of how can i prove that, i am iniciating in this language....
i tried this:
intros x xs.
induction xs.
simpl.
reflexivity.
case 1.
simpl.
destruct x.
simpl.
and show this:
2 goals
x, n : nat
______________________________________(1/2)
0 = n
______________________________________(2/2)
num_occ x (n0 :: l) = n

I think case 1 is not necessary. Try this:
Theorem exercise2
: forall x xs, num_occ x xs <= length xs.
Proof.
intros x xs. induction xs; simpl.
- reflexivity.
- destruct (eq_dec x a).
+ apply le_n_S. assumption.
+ apply le_le_succ_r. assumption.
Qed.

Related

Prove that the number of occurences of x in a list that has n position with valor x = n

Fixpoint n_copies (n x : nat) : list nat :=
match n with
| 0 => []
| S n' => x :: n_copies n' x
end.
Theorem exercise3
: forall x n, num_occ x (n_copies n x) = n.
Proof.
I tried:
intros x n. induction n. simpl.
- congruence.
- destruct (eq_dec x n).
+ induction e.
+
but i cant think a solution for another "+", and i have this notice:
1 goal
x : nat
IHn : num_occ x (n_copies x x) = x
______________________________________(1/1)
num_occ x (n_copies (S x) x) = S x
I think that i have to take of the S of both sides, but i don't know how.
It's strange that you had to compare x and n.
In general, they don't live in the same type:
From Coq Require Import List.
Section A_dec.
Variables (A:Type)(A_eq_dec : forall a b:A, {a = b}+{a <> b}).
Goal forall x n, count_occ A_eq_dec (repeat x n) x = n.
induction n.
(* ... *)
But you didn't share your function num_occ..., perhaps it's buggy ?
You should compare it with stdlib's count_occ.
Please note also that stdlib’s repeat and your n_copies don’t have the same order of arguments.
Here's is a solution (with Aas the type of elements of the list):
Require Import List Arith.
Import ListNotations.
Section A_decl.
Variables (A: Type)(eqdec: forall a b:A, {a = b}+{a <> b}).
Fixpoint n_copies (x:A) (n:nat) : list A :=
match n with
| 0 => []
| S n' => x :: n_copies x n'
end.
Fixpoint num_occ (x : A)(xs : list A) : nat :=
match xs with
| [] => 0
| (y :: ys) => if eqdec x y
then 1 + num_occ x ys
else num_occ x ys
end.
Theorem exercise3
: forall x n, num_occ x (n_copies x n) = n.
Proof.
induction n; simpl.
- reflexivity.
- destruct (eqdec x x) as [e | n0].
+ rewrite IHn; trivial.
+ now destruct n0.
Qed.
End A_decl.

I want to prove some properties about list, but am stuck at induction

I tried following proof,
Require Import List Omega.
Import ListNotations.
Variable X : Type.
Lemma length_n_nth_app_error_same : forall (n:nat) (x:X) (l:list X),
n <= length l -> 0 < n -> nth_error l n = nth_error (l ++ [x]) n .
Proof.
intros.
induction l eqn:eqHl.
- unfold length in H. omega.
-
but I'm stuck, as what I have is only
1 subgoal
n : nat
x : X
l : list X
a : X
l0 : list X
eqHl : l = a :: l0
H : n <= length (a :: l0)
H0 : 0 < n
IHl0 : l = l0 ->
n <= length l0 ->
nth_error l0 n = nth_error (l0 ++ [x]) n
______________________________________(1/1)
nth_error (a :: l0) n = nth_error ((a :: l0) ++ [x]) n
I've met some similar cases also for other proofs on lists.
I don't know if the usual induction would be useful here.
How should I prove this?
Should I use generalize?
Your theorem is wrong. Maybe your understanding of nth_error is incorrect.
Specifically, when n = length l, nth_error l n returns None while nth_error (l ++ [x]) n returns Some x.
Require Import List Omega.
Import ListNotations.
Lemma length_n_nth_app_error_not_always_same :
(forall (n:nat) (X:Type) (x:X) (l:list X),
n <= length l -> 0 < n -> nth_error l n = nth_error (l ++ [x]) n)
-> False.
Proof.
intros.
assert (1 <= 1) by omega. assert (0 < 1) by omega.
specialize (H 1 nat 2 [1] H0 H1). simpl in H. inversion H. Qed.
On the other hand, proving a similar theorem with fixed inequality is easy:
Lemma length_n_nth_app_error_same : forall (n:nat) (X:Type) (x:X) (l:list X),
n < length l -> nth_error l n = nth_error (l ++ [x]) n .
Proof.
induction n; intros.
- simpl. destruct l; simpl in *.
+ omega.
+ reflexivity.
- simpl. destruct l; simpl in *.
+ omega.
+ apply IHn. omega. Qed.
Note that I used induction n instead of induction l. It is mainly because nth_error does recursive calls on decreasing n.
Also, if you felt like an induction hypothesis is not general enough, it is probably because your order of intros and induction was wrong. The rule of thumb is to start the proof by induction, and then intros the variables. If it is still not enough, you can revert dependent all the variables other than the one to do induction, and then induction x; intros.

Minimum in non-empty, finite set

With the following definitions I want to prove lemma without_P
Variable n : nat.
Definition mnnat := {m : nat | m < n}.
Variable f : mnnat -> nat.
Lemma without_P : (exists x : mnnat, True) -> (exists x, forall y, f x <= f y).
Lemma without_P means: if you know (the finite) set mnnat is not empty, then there must exist an element in mnnat, that is the smallest of them all, after mapping f onto mnnat.
We know mnnat is finite, as there are n-1 numbers in it and in the context of the proof of without_P we also know mnnat is not empty, because of the premise (exists x : mnnat, True).
Now mnnat being non-empty and finite "naturally/intuitively" has some smallest element (after applying f on all its elements).
At the moment I am stuck at the point below, where I thought to proceed by induction over n, which is not allowed.
1 subgoal
n : nat
f : mnnat -> nat
x : nat
H' : x < n
______________________________________(1/1)
exists (y : nat) (H0 : y < n),
forall (y0 : nat) (H1 : y0 < n),
f (exist (fun m : nat => m < n) y H0) <= f (exist (fun m : nat => m < n) y0 H1)
My only idea here is to assert the existance of a function f' : nat -> nat like this: exists (f' : nat -> nat), forall (x : nat) (H0: x < n), f' (exist (fun m : nat => m < n) x H0) = f x, after solving this assertion I have proven the lemma by induction over n. How can I prove this assertion?
Is there a way to prove "non-empty, finite sets (after applying f to each element) have a minimum" more directly? My current path seems too hard for my Coq-skills.
Require Import Psatz Arith. (* use lia to solve the linear integer arithmetic. *)
Variable f : nat -> nat.
This below is essentially your goal, modulo packing of the statement into some dependent type. (It doesn't say that mi < n, but you can extend the proof statement to also contain that.)
Goal forall n, exists mi, forall i, i < n -> f mi <= f i.
induction n; intros.
- now exists 0; inversion 1. (* n cant be zero *)
- destruct IHn as [mi IHn]. (* get the smallest pos mi, which is < n *)
(* Is f mi still smallest, or is f n the smallest? *)
(* If f mi < f n then mi is the position of the
smallest value, otherwise n is that position,
so consider those two cases. *)
destruct (lt_dec (f mi) (f n));
[ exists mi | exists n];
intros.
+ destruct (eq_nat_dec i n).
subst; lia.
apply IHn; lia.
+ destruct (eq_nat_dec i n).
subst; lia.
apply le_trans with(f mi).
lia.
apply IHn.
lia.
Qed.
Your problem is an specific instance of a more general result which is proven for example in math-comp. There, you even have a notation for denoting "the minimal x such that it meets P", where P must be a decidable predicate.
Without tweaking your statement too much, we get:
From mathcomp Require Import all_ssreflect.
Variable n : nat.
Variable f : 'I_n.+1 -> nat.
Lemma without_P : exists x, forall y, f x <= f y.
Proof.
have/(_ ord0)[] := arg_minP (P:=xpredT) f erefl => i _ P.
by exists i => ?; apply/P.
Qed.
I found a proof to my assertion (exists (f' : nat -> nat), forall (x : nat) (H0: x < n), f (exist (fun m : nat => m < n) x H0) = f' x). by proving the similar assertion (exists (f' : nat -> nat), forall x : mnnat, f x = f' (proj1_sig x)). with Lemma f'exists. The first assertion then follows almost trivially.
After I proved this assertion I can do a similar proof to user larsr, to prove Lemma without_P.
I used the mod-Function to convert any nat to a nat smaller then n, apart from the base case of n = 0.
Lemma mod_mnnat : forall m,
n > 0 -> m mod n < n.
Proof.
intros.
apply PeanoNat.Nat.mod_upper_bound.
intuition.
Qed.
Lemma mod_mnnat' : forall m,
m < n -> m mod n = m.
Proof.
intros.
apply PeanoNat.Nat.mod_small.
auto.
Qed.
Lemma f_proj1_sig : forall x y,
proj1_sig x = proj1_sig y -> f x = f y.
Proof.
intros.
rewrite (sig_eta x).
rewrite (sig_eta y).
destruct x. destruct y as [y H0].
simpl in *.
subst.
assert (l = H0).
apply proof_irrelevance. (* This was tricky to find.
It means two proofs of the same thing are equal themselves.
This makes (exist a b c) (exist a b d) equal,
if c and d prove the same thing. *)
subst.
intuition.
Qed.
(* Main Lemma *)
Lemma f'exists :
exists (ff : nat -> nat), forall x : mnnat, f x = ff (proj1_sig x).
Proof.
assert (n = 0 \/ n > 0).
induction n.
auto.
intuition.
destruct H.
exists (fun m : nat => m).
intuition. destruct x. assert (l' := l). rewrite H in l'. inversion l'.
unfold mnnat in *.
(* I am using the mod-function to map (m : nat) -> {m | m < n} *)
exists (fun m : nat => f (exist (ltn n) (m mod n) (mod_mnnat m H))).
intros.
destruct x.
simpl.
unfold ltn.
assert (l' := l).
apply mod_mnnat' in l'.
assert (proj1_sig (exist (fun m : nat => m < n) x l) = proj1_sig (exist (fun m : nat => m < n) (x mod n) (mod_mnnat x H))).
simpl. rewrite l'.
auto.
apply f_proj1_sig in H0.
auto.
Qed.

How to deal with a function with an exists on the right side?

I am not sure whether I am using the right words in the question title, so here is the code:
Lemma In_map_iff :
forall (A B : Type) (f : A -> B) (l : list A) (y : B),
In y (map f l) <->
exists x, f x = y /\ In x l.
Proof.
intros A B f l y.
split.
- intros.
induction l.
+ intros. inversion H.
+ exists x.
simpl.
simpl in H.
destruct H.
* split.
{ apply H. }
{ left. reflexivity. }
* split.
A : Type
B : Type
f : A -> B
x : A
l : list A
y : B
H : In y (map f l)
IHl : In y (map f l) -> exists x : A, f x = y /\ In x l
============================
f x = y
Basically, there is not much to go on with this proof, I can only really use induction on l and after substituting for x in the goal I get the above form. If IHl had a forall instead of exists maybe I could substitute something there, but I am not sure at all what to do here.
I've been stuck on this one for a while now, but unlike the other problems where that has happened, I could not find the solution online for this one. This is a problem as I am going through the book on my own, so have nobody to ask except in places like SO.
I'd appreciate a few hints. Thank you.
Lemma In_map_iff :
forall (A B : Type) (f : A -> B) (l : list A) (y : B),
In y (map f l) <->
exists x, f x = y /\ In x l.
Proof.
intros A B f l y.
split.
- intros.
induction l.
+ intros. inversion H.
+ simpl.
simpl in H.
destruct H.
* exists x.
split.
{ apply H. }
{ left. reflexivity. }
* destruct IHl.
-- apply H.
-- exists x0.
destruct H0.
++ split.
** apply H0.
** right. apply H1.
- intros.
inversion H.
induction l.
+ intros.
inversion H.
inversion H1.
inversion H3.
+ simpl.
right.
apply IHl.
* inversion H.
inversion H0.
inversion H2.
exists x.
split.
-- reflexivity.
-- destruct H3.
A : Type
B : Type
f : A -> B
x0 : A
l : list A
y : B
H : exists x : A, f x = y /\ In x (x0 :: l)
x : A
H0 : f x = y /\ In x (x0 :: l)
IHl : (exists x : A, f x = y /\ In x l) ->
f x = y /\ In x l -> In y (map f l)
x1 : A
H1 : f x1 = y /\ In x1 (x0 :: l)
H2 : f x = y
H3 : x0 = x
H4 : f x = y
============================
In x l
I managed to do one case, but am now stuck in the other. To be honest, since I've already spent 5 hours on a problem that should need like 15 minutes, I am starting to think that maybe I should consider genetic programming at this point.
H can be true on two different ways, try destruct H. From that, the proof follows easily I think, but be careful on the order you destruct H and instantiate the existential thou.
Here is a proof that has the same structure as would have a pen-and-paper proof (at least the first -> part). When you see <tactic>... it means ; intuition (because of Proof with intuition. declaration), i.e. apply the intuition tactic to all the subgoals generated by <tactic>. intuition enables us not to do tedious logical deductions and can be replaced by a sequence of apply and rewrite tactics, utilizing some logical lemmas.
As #ejgallego pointed out the key here is that while proving you can destruct existential hypotheses and get inhabitants of some types out of them. Which is crucial when trying to prove existential goals.
Require Import Coq.Lists.List.
Lemma some_SF_lemma :
forall (A B : Type) (f : A -> B) (l : list A) (y : B),
In y (map f l) <->
exists x, f x = y /\ In x l.
Proof with intuition.
intros A B f l y. split; intro H.
- (* -> *)
induction l as [ | h l'].
+ (* l = [] *)
contradiction.
+ (* l = h :: l' *)
destruct H.
* exists h...
* destruct (IHl' H) as [x H'].
exists x...
- (* <- *)
admit.
Admitted.

Coq: Problems with List In inductive

I'm new to Coq, but with some effort I was able to prove various inductive lemmas. However I get stuck on all exercises that uses the following inductive definition:
Inductive In (A:Type) (y:A) : list A -> Prop :=
| InHead : forall xs:list A, In y (cons y xs)
| InTail : forall (x:A) (xs:list A), In y xs -> In y (cons x xs).
The furthest i got was with the following lemma:
Lemma my_In_rev : forall (A:Type) (x:A) (l:list A), In x l -> In x (rev l).
Proof.
induction l.
simpl.
trivial.
simpl.
intros.
The following two lemmas I cant get past the first steps, because I get stuck on the exists goal right after using intros.
Lemma my_In_map : forall (A B:Type) (y:B) (f:A->B) (l:list A), In y (map f l) -> exists x : A, In x l /\ y = f x.
Lemma my_In_split : forall (A:Type) (x:A) (l : list A), In x l -> exists l1, exists l2, l = l1 ++ (x::l2).
Proof.
Any help would be appreciated!
For your first lemma, I added two simple sublemmas (that you can find in the list library).
The two others are more straightforward.
Require Import List.
Lemma In_concat_l: forall (A: Type) (l1 l2: list A) (x:A),
In x l1 -> In x (l1 ++ l2).
Proof.
intros A.
induction l1 as [ | hd tl hi ]; intros l2 x hIn; simpl in *.
- contradiction.
- destruct hIn.
+ left; assumption.
+ right; now apply hi.
Qed.
Lemma In_concat_r: forall (A: Type) (l1 l2: list A) (x:A),
In x l2 -> In x (l1 ++ l2).
intros A.
induction l1 as [ | hd tl hi ]; intros l2 x hIn; simpl in *.
- assumption.
- right; now apply hi.
Qed.
Lemma my_In_rev : forall (A:Type) (x:A) (l:list A), In x l -> In x (rev l).
Proof.
intros A x l.
induction l as [ | hd tl hi ]; intros hIn; simpl in *.
- contradiction.
- destruct hIn.
+ apply In_concat_r.
rewrite H.
now constructor.
+ apply In_concat_l.
now apply hi.
Qed.
Lemma my_In_map : forall (A B:Type) (y:B) (f:A->B) (l:list A), In y (map f l) -> exists x : A, In x l /\ y = f x.
Proof.
intros A B y f l.
induction l as [ | hd tl hi]; intros hIn; simpl in *.
- contradiction.
- destruct hIn.
+ exists hd; split.
left; reflexivity.
symmetry; assumption.
+ destruct (hi H) as [x0 [ h1 h2]].
exists x0; split.
right; assumption.
assumption.
Qed.
Lemma my_In_split : forall (A:Type) (x:A) (l : list A), In x l -> exists l1, exists l2, l = l1 ++ (x::l2).
Proof.
intros A x l.
induction l as [ | hd tl hi]; intros hIn; simpl in *.
- contradiction.
- destruct hIn.
rewrite H.
exists nil; exists tl; simpl; reflexivity.
destruct (hi H) as [ l1 [ l2 h ]].
exists (hd :: l1); exists l2.
rewrite <- app_comm_cons; rewrite h.
reflexivity.
Qed.
I won't say it's less complex than Rui's answer, but I find this solution a little bit easier to understand. But in the end, they are relatively close.
Cheers,
V.
When the goal is existentially quantified, you have to give a concrete example of an object with the stated property, and when a hypothesis is existentially quantified, you're allowed to assume one such object exists and introduce it. See FAQs 47, 53, and 54. By the way, an In predicate is already defined in Coq.Lists.List. Check it out here. A reference for Coq tactics is here.
A proof of the first lemma:
Require Import Coq.Lists.List.
Require Import Coq.Setoids.Setoid.
Inductive In {A : Type} (y : A) : list A -> Prop :=
| InHead : forall xs : list A, In y (cons y xs)
| InTail : forall (x : A) (xs : list A), In y xs -> In y (cons x xs).
Lemma L1 : forall (t1 : Type) (l1 : list t1) (o1 o2 : t1),
In o1 (o2 :: l1) <-> o1 = o2 \/ In o1 l1.
Proof.
intros t1 l1 o1 o2. split.
intros H1. inversion H1 as [l2 [H3 H4] | o3 l2 H2 [H3 H4]].
left. reflexivity.
right. apply H2.
intros H1. inversion H1 as [H2 | H2].
rewrite H2. apply InHead.
apply InTail. apply H2.
Qed.
Lemma my_In_map : forall (A B : Type) (l : list A) (y : B) (f : A -> B),
In y (map f l) -> exists x : A, In x l /\ y = f x.
Proof.
intros A B. induction l as [| z l H1].
intros y f H2. simpl in *. inversion H2.
intros y f H2. simpl in *. rewrite L1 in H2. inversion H2 as [H3 | H3].
exists z. split.
apply InHead.
apply H3.
assert (H4 := H1 _ _ H3). inversion H4 as [x [H5 H6]]. exists x. split.
rewrite L1. right. apply H5.
apply H6.
Qed.