How to compare two elements of list - coq

I have a list with all elements equal to zero and the length of the list not equal to zero. I want to prove the following and compare both
(length l=?0)=false->
k < length l ->
(forall k, nth k l 0 = 0)->
1<=count 0 l.
(length l=?0)=false->
(forall k, nth k l 0 = 0) ->
(S n) < length l ->
count (S n) l = 0.
count (S n) l < count 0 l.
Fixpoint count (v:nat) (s:list nat) : nat :=
match s with
| [] => 0
| h :: t => (if beq_nat h v then 1 else 0) + (count v t) end.

Related

How to consider both out puts in list

I have less than relation between two index values and want to esteblish a relation between indexes. Have hypothesis - (nth i2 l d < nth i1 l d). There are two possibilities that (i2 < i1) or (i2> i1). I want to consider both cases. Plz guide me in writing this relation.
Use Nat.lt_gt_cases, which proves n < m \/ n > m given n <> m. In context, that would look like this
Require Import PeanoNat.
Goal forall (d : nat) (l : list nat) (n m : nat), nth n l d < nth m l d -> True.
intros d l n m prf.
assert (ineq : n <> m). (* hypothesis for lt_gt_cases *)
{ intros ->.
now apply Nat.lt_irrefl in prf.
}
destruct (proj1 (Nat.lt_gt_cases n m) ineq) as [ord | ord].
(* two goals left, one with n < m and the other with m > n *)

How to simplify a statement of lemma

I have a Contradictory statements in hypothesis. Want to convert it into true=false. Thanks for guidence in advance. Here is code
n < current_value 0 (n :: l)
current_value 0 (n :: l)<= n.
The question could be a lot more complete. What is the type of n? I'll assume that it is nat.
Starting like this:
Lemma manual:
forall current_value n l P,
n < current_value 0 (n :: l) ->
current_value 0 (n :: l) <= n ->
P.
Proof.
intros.
We arrive at a state that looks like this (omitting things we don't need):
H : n < current_value 0 (n :: l)
H0 : current_value 0 (n :: l) ≤ n
-----
P
The strategy will be to prove that H and H0 together lead to a contradiction from which we can prove any statement P.
We know that n < m (if m stands for the expression current_value 0 (n :: l)) and also m <= n. What can we prove from this? You can search for relevant lemmas using the Search command with a pattern that summarizes what you know:
Search (?n < ?m -> ?m <= ?p -> _).
This query means "given that I know that n < m and also m <= p for the same m, what can I deduce?". The named variables in the query need the ? prefix, they can stand for any expressions. They are not related to any variables you might have in the current environment.
One of the search hits is this (in PeanoNat, which you will have to import):
Nat.lt_le_trans:
forall n m p : nat, n < m -> m <= p -> n < p
So given this lemma we should be able to prove n < n and see if we can make progress from there.
{
apply Nat.lt_le_trans with (m := current_value 0 (n :: l)).
auto.
auto.
}
Now we have:
H1 : n < n
-----
P
So now we have a more "obvious" contradiction in an assumption. Do we have a lemma for proving that this is indeed false?
Search (~ ?n < ?n).
This gives:
Nat.lt_irrefl: forall x : nat, ~ x < x
So then:
apply Nat.lt_irrefl in H1.
We arrive at:
H1 : False
-----
P
This is a tautology that we can prove with tauto:
tauto.
Qed.
Doing such simple arithmetic manually can get very tedious, so there is a lot of automation for doing it. Here's a simpler method using the lia tactic:
Require Import Lia.
Lemma automatic:
forall current_value n l P,
n < current_value 0 (n :: l) ->
current_value 0 (n :: l) <= n ->
P.
Proof.
intros.
lia.
Qed.
Internally this will do some sort of similar reasoning, proving a contradiction in the assumptions.

How to use coercion with sig in coq

I have a code like
Definition even := {n : nat | exists k, n = k + k}.
Definition even_to_nat (e : even) : nat.
Admitted.
Coercion even_to_nat : even >-> nat.
Example Ex : forall n : even, exists k, k + k = n.
Admitted.
Example Ex2 : forall k, exists n : even, k + k = n.
Admitted.
How should I remove Admitted in this case?
Also, why does
Example Ex' : forall n : even, exists k, n = k + k
not work even with coercion? Is there a nice way to remove such errors?
This is a definition for the even_to_nat function written in Gallina:
Definition even := {n : nat | exists k, n = k + k}.
Definition even_to_nat (e : even) : nat :=
match e with
| exist _ n _ => n
end.
Coercion even_to_nat : even >-> nat.
It pattern matches on e to retrieve the wrapped natural number n.
This is an equivalent implementation using tactics:
Definition even_to_nat_tac (e : even) : nat.
destruct e.
auto.
Defined.
The destruct tactic essentially pattern matches on e. Then, auto automatically uses the natural number inside to finish the definition.
Here is a Gallina implementation of your first example:
Example Ex : forall n : even, exists k, k + k = n :=
fun n => match n with
| exist _ n (ex_intro _ k eq) => ex_intro (fun k => k + k = n) k (eq_sym eq)
end.
Essentially, it pattern matches on n, retrieves the k and the proof that n = k + k, then uses eq_sym to flip the equality.
Here is an implementation for Ex2:
Example Ex2 : forall k, exists n : even, k + k = n :=
fun k =>
let n := k + k in
let exists_k := ex_intro (fun k => n = k + k) k eq_refl in
let even_nat := exist (fun n => exists k, n = k + k) n exists_k in
ex_intro (fun n => k + k = even_to_nat n) even_nat eq_refl.
exists_k is the proof contained inside an even number stating exists k, n + n = k. even_nat is an even number fulfilling the condition exists n, k + k = n, where n is obviously k + k. Finally, I inhabit the desired type. It seems that I can't use coercions here, so I explicitly use even_to_nat.
Alternatively, the coercion works if I add a type annotation:
Example Ex2 : forall k, exists n : even, k + k = n :=
fun k =>
let n := k + k in
let exists_k := ex_intro (fun k => n = k + k) k eq_refl in
let even_nat := exist (fun n => exists k, n = k + k) n exists_k in
ex_intro (fun (n : even) => k + k = n) even_nat eq_refl.
For your Ex' example, see the warning in this example from the coercion documentation. Given the coercion Coercion bool_in_nat : bool >-> nat.:
Note that Check (true = O) would fail. This is "normal" behavior of coercions. To validate true=O, the coercion is searched from nat to bool. There is none.
You can only coerce on the right side of the equality type, not the left.

Well-founded induction for a counting predicate

Here is the definition for the Count predicate. It uses 2 indices to denote starting and ending elements, "check" predicate to count/skip the "current" element and the last argument "sum" to keep track the number of elements that satisfy check predicate between these boundary indices.
Require Import ZArith.
Open Scope Z_scope.
Inductive Count : Z -> Z -> (Z -> Prop) -> Z -> Prop :=
| Q_Nil:
forall (m n : Z),
forall (check : Z -> Prop),
(n <= m) ->
(Count m n check 0)
| Q_Hit:
forall (m n sum : Z),
forall (check : Z -> Prop),
let x := (n - 1) in
(m < n) ->
(check x) ->
(Count m x check sum) ->
(Count m n check (1 + sum))
| Q_Miss:
forall (m n sum : Z),
forall (check : Z -> Prop),
let x := (n - 1) in
(m < n) ->
~(check x) ->
(Count m x check sum) ->
(Count m n check sum).
It is required to prove that the number of counted elements "sum" is non-negative.
Goal
forall (m n sum : Z),
forall (check : Z -> Prop),
(Count m n check sum) -> (0 <= sum).
Proof.
Obviously, the induction could be applied here. However, schemes like natlike_rec3 are not applicable because of the Q_Hit|Q_Miss difference in sum element (i.e. +1 in Q_Hit).
Here is my proof attempt till the step where an induction should be applied.
Proof.
Require Import Psatz.
intros m n sum check.
assert (X: n <= m \/ n > m) by lia.
destruct X as [le|gt].
+ intro.
inversion H; subst; intuition.
+ pose (p := (n - m)).
assert (PZ: p > 0). { subst p. auto with zarith. }
replace n with (m + p) in * by (subst p; auto with zarith).
1 subgoal
m, n, sum : Z
check : Z -> Prop
p := n - m : Z
gt : m + p > m
PZ : p > 0
______________________________________(1/1)
Count m (m + p) check sum -> 0 <= sum
I think that maybe well_founded_induction_type_2 could be used further with relation on sum and p: sum <= p.
You can use induction on the Count hypothesis (in a way, that's the main point of Inductive types).
Proof.
intros.
induction H.
all: omega.
(* or, as a single sequence: intros; induction H; omega. *)
(* lia also works instead of omega, and should probably be preferred nowadays (Require Import Lia.) *)
Qed.

Proving a theorem about ordered lists

This should be a straight forward thing to prove, but I keep getting stuck. Would be grateful for help...
Require Import Arith.
Fixpoint At n (l:list nat) :=
match n with
| 0 => match l with nil => None | cons x _ => Some x end
| S n' => match l with nil => None | cons _ l' => At n' l' end
end.
Definition ordered l :=
forall i j, i < j -> j < length l ->
exists x y, At i l = Some x /\ At j l = Some y /\ x <= y.
Lemma ordered_cons:
forall l a b, ordered (cons b l) -> a <= b -> ordered (cons a (cons b l)).
intros l a b H H0 i j Hij Hj.
destruct i,j;
(* solve three of the four cases, and leave one untouched *)
try (inversion Hij; fail);
try (apply H; simpl in *; omega).
EDIT: Here is the solution to finish the proof. I need to consider the two next cases for j.
destruct j;
try (exists a,b; auto; fail).
destruct (H 0 (S j)) as [x [y [Ha [Hb Hc]]]]; auto with arith;
simpl in *; inversion Ha; exists a, y;
repeat split; try tauto; omega.
Qed.