I have defined a function, which finds the greatest value from the natural number list and move this value to head position of the list. I am sure, all the elements in the list are less or equal to the value at head location. Then I defined index_value function,to find value in the list at any index.For clarification [4,7,11,9,11] list become [11,7,9,11].I have a problem in proving the following lemma. Plz guide me.
` Require Import Coq.Arith.PeanoNat.
Require Import Lia.
Fixpoint index_value (index: nat) (l: list nat) : nat :=
match l with
| nil => 0
| cons h t => match (Nat.eqb index 0) with
| true => h
| false => index_value (index - 1) t
end
end.
Theorem head_value : forall ( n':nat) (l:list nat),
(index_value 0 l)<= n'.
Proof.
Admitted.
Theorem index_value1:forall (n s2:nat) (l:list nat),
index_value (S s2) (n :: l) <=
index_value 0 (n :: l) \/
index_value (S s2) (n :: l) > 0.
Proof.
intros. simpl in *. left . induction s2. simpl.
appply head_value . simpl in *. auto with arith.`
I think your statements do not quite mean what you think they mean. The first one is contradictory, and the second one is trivial: you do not need the definition of index_value at all:
Require Import Coq.Arith.PeanoNat.
Require Import Lia.
Require Import Coq.Lists.List.
Import ListNotations.
Fixpoint index_value (index: nat) (l: list nat) : nat :=
match l with
| nil => 0
| cons h t => match (Nat.eqb index 0) with
| true => h
| false => index_value (index - 1) t
end
end.
Theorem not_head_value :
~ forall ( n':nat) (l:list nat),
(index_value 0 l)<= n'.
Proof.
intros contra.
specialize (contra 0 (1 :: nil)).
simpl in *. lia.
Qed.
Theorem index_value1:forall (n s2:nat) (l:list nat),
index_value (S s2) (n :: l) <=
index_value 0 (n :: l) \/
index_value (S s2) (n :: l) > 0.
Proof. intros n s2 l. lia. Qed.
Related
I am trying to reverse a vector in Coq. My implementation is as follows:
Fixpoint vappend {T : Type} {n m} (v1 : vect T n) (v2 : vect T m)
: vect T (plus n m) :=
match v1 in vect _ n return vect T (plus n m) with
| vnil => v2
| x ::: v1' => x ::: (vappend v1' v2)
end.
Theorem plus_n_S : forall n m, plus n (S m) = S (plus n m).
Proof.
intros. induction n; auto.
- simpl. rewrite <- IHn. auto.
Qed.
Theorem plus_n_O : forall n, plus n O = n.
Proof.
induction n.
- reflexivity.
- simpl. rewrite IHn. reflexivity.
Qed.
Definition vreverse {T : Type} {n} (v : vect T n) : vect T n.
induction v.
- apply [[]].
- rewrite <- plus_n_O. simpl. rewrite <- plus_n_S.
apply (vappend IHv (t ::: [[]])).
Show Proof.
Defined.
The problem is, when I try to compute the function, it produces something like:
match plus_n_O (S (S O)) in (_ = y) return (vect nat y) with
...
and couldn't get further. What's the problem here? How can I fix this?
The problem is that your functions use opaque proofs, plus_n_S and plus_n_O. To compute vreverse, you need to compute these proofs, and if they are opaque, the computation will be blocked.
You can fix this issue by defining the functions transparently. Personally, I prefer not to use proof mode when doing this, since it is easier to see what is going on. (I have used the standard library definition of vectors here.)
Require Import Coq.Vectors.Vector.
Import VectorNotations.
Fixpoint vappend {T : Type} {n m} (v1 : t T n) (v2 : t T m)
: t T (plus n m) :=
match v1 in t _ n return t T (plus n m) with
| [] => v2
| x :: v1' => x :: vappend v1' v2
end.
Fixpoint plus_n_S n m : n + S m = S (n + m) :=
match n with
| 0 => eq_refl
| S n => f_equal S (plus_n_S n m)
end.
Fixpoint plus_n_O n : n + 0 = n :=
match n with
| 0 => eq_refl
| S n => f_equal S (plus_n_O n)
end.
Fixpoint vreverse {T : Type} {n} (v : t T n) : t T n :=
match v in t _ n return t T n with
| [] => []
| x :: v =>
eq_rect _ (t T)
(eq_rect _ (t T) (vappend (vreverse v) [x]) _ (plus_n_S _ 0))
_ (f_equal S ( plus_n_O _))
end.
Compute vreverse (1 :: 2 :: 3 :: []).
I have defined a function,which finds greatest value in the list of natural numbers and head of the list save this value. I want to prove that all the elements in the list are less or equal to natural number present at head of the list.I have problem in proving the lemma. I have written two lemmas,I want to know,which would be helpful in solving the problem. Thanks for help and
support .
Require Import Coq.Arith.Arith.
Require Import Coq.Lists.List.
Import ListNotations.
Definition change_variable (n: nat) (l: list nat) : list nat:=
match l with
| nil => l
| h::t => if n <=? h then l else n::t
end.
Fixpoint largest_value (numbers: nat) (l: list nat) {struct numbers}: nat:=
match l with
| nil => 0
| cons b nil => b
| cons h l => match numbers with
| O => h
| S numbers' => largest_value numbers' (change_variable h l)
end
end.
Theorem all_values_less :forall (n c :nat)(l:list nat),
(largest_value (length (c :: l))
(change_variable n (c :: l)) <= n).
First in this way,
Inductive changing : l -> Prop :=
| change_nil : changing nil
| change_1 n : changing (cons n nil)
| change_head n h l :
n <= h ->
changing (cons h l) ->
changing (cons n l).
Lemma head_is_gt l a:
changing l -> forall n, In n l -> n <= hd a l.
Proof.
induction 1. intros k H'.
now exfalso; apply in_nil in H'.
Admitted.
Secondly ,
Definition head_is_greater (l: list nat): nil <> l -> nat.
intros.
destruct l.
destruct (H (#erefl (list nat) nil)).
apply : (largest_value s l).
Defined.
Theorem values_les_n : forall l (H : [] <> l) n, In n l -> n <=
head_is_greater H.
The theorem does not hold, unfortunately. Here is a counterexample:
Require Import Coq.Arith.Arith.
Require Import Coq.Lists.List.
Require Import Lia.
Import ListNotations.
Definition change_variable (n: nat) (l: list nat) : list nat:=
match l with
| nil => l
| h::t => if n <=? h then l else n::t
end.
Fixpoint largest_value (numbers: nat) (l: list nat) {struct numbers}: nat:=
match l with
| nil => 0
| cons b nil => b
| cons h l => match numbers with
| O => h
| S numbers' => largest_value numbers' (change_variable h l)
end
end.
Hypothesis all_values_less :forall (n c :nat)(l:list nat),
(largest_value (length (c :: l))
(change_variable n (c :: l)) <= n).
Theorem contra : False.
Proof.
pose proof (all_values_less 0 1 []).
simpl in *. lia.
Qed.
You probably need to add more hypothesis to your statement to rule out such cases.
I have function,whose output is some natural number.I have proved a lemma,that output of this function cannot be zero. It means output is equal to some natural number S m.I want to convert the above lemma.
Theorem greater:forall (m :nat)(l:list nat),
m=?0=false ->
0=? (f1 + m)=false->
(f1 + m)= S m.
The statement you entered does not type check. Regardless, I don't see how it could hold -- for instance, if by l you mean f1 : nat, then the statement would imply that 3 = 2.
Require Import Coq.Arith.Arith.
Theorem greater:forall (m :nat)(f1:nat),
m=?0=false ->
0=? (f1 + m)=false->
(f1 + m)= S m.
Admitted.
Lemma contra : False.
Proof.
pose proof (greater 1 2 eq_refl eq_refl).
easy.
Qed.
Proving that something that is not zero is a successor can be done as follows:
Require Import Coq.Arith.Arith.
Lemma not_zero_succ :
forall n, n <> 0 ->
exists m, n = S m.
Proof. destruct n as [|n]; eauto; easy. Qed.
Edit The complete statement you wrote below is also contradictory:
Require Import Coq.Arith.Arith.
Require Import Coq.Lists.List.
Import ListNotations.
Fixpoint lt_numb (n: nat) (l: list nat) : nat :=
match l with
| nil => 0
| h::tl =>
if h <? n then S (lt_numb n tl) else lt_numb n tl
end.
Fixpoint greatest (large: nat) (l: list nat) : nat :=
match large with
| O => 0
| S m' => (lt_numb large l) + (greatest m' l)
end.
Definition change (n: nat) (l: list nat) : list nat :=
match l with
| nil => l
| h::tl => if n <? h then l else n::tl
end.
Fixpoint g_value (elements: nat) (l: list nat) : nat :=
match l with
| nil => 0
| [n] => n
| h :: l =>
match elements with
| O => h
| S elements' => g_value elements' (change h l)
end
end.
Theorem no_elements : forall (m n z :nat)(l:list nat),
m=?0=false -> greatest(g_value (length (n :: l)) (n :: l) + m) (n :: l) = (S z).
Proof. Admitted.
Goal False.
pose proof (no_elements 1 0 1 [] eq_refl).
simpl in H.
discriminate.
Qed.
I am using index function to find the value of element at any location in the list nat. Plz guide me in proving the second part of the lemma, which is illustrated below
Fixpoint index(n: nat) (m: nat) (l: list nat) : nat :=
match l with
| nil => 0
| cons h tl => match (eqb n m) with
| true => h
| false => index (succ n) m tl
end
end.
Theorem a_ref:forall (a:nat),
a <= a.
Proof.
intros. eauto.
Qed.
Theorem n_leq_0 :forall (n:nat),
n <= 0.
Proof.
intros. induction n.
+ simpl. apply a_ref.
+ Admitted.
Theorem n_le_index:forall (n:nat) (l:list nat),
n <= index (succ (succ 0)) 0 l.
Proof.
intros. induction l as [| l'].
+ simpl. apply n_leq_0.
+ simpl in *. inversion IHl.
rewrite <- H.
The theorem you want cannot be proved:
Fixpoint index(n: nat) (m: nat) (l: list nat) : nat :=
match l with
| nil => 0
| cons h tl => match (Nat.eqb n m) with
| true => h
| false => index (Nat.succ n) m tl
end
end.
Theorem n_le_index:forall (n:nat) (l:list nat),
n <= index (Nat.succ (Nat.succ 0)) 0 l.
Admitted.
Require Import Omega.
Goal False.
pose proof (n_le_index 10 nil).
simpl in H.
omega.
Qed.
It looks definitely simple task until I actually try to work on it. My method is to use twin pointers to avoid asking the length of the list ahead of time, but the difficulties come from the implication that I know for sure one list is "no emptier" than another. Specifically, in pseudo-coq:
Definition twin_ptr (heads, tail, rem : list nat) :=
match tail, rem with
| _, [] => (rev heads, tail)
| _, [_] => (rev heads, tail)
| t :: tl, _ :: _ :: rm => twin_ptr (t :: heads) tl rm
end.
Definition split (l : list nat) := twin_ptr [] l l
But definitely it's not going to compile because the match cases are incomplete. However, the missing case by construction doesn't exist.
What's your way of implementing it?
I you are not afraid of dependent types, you can add a proof that rem is shorter than tail as an argument of twin_ptr. Using Program to help manage these dependent types, this could give the following.
Require Import List. Import ListNotations.
Require Import Program.
Require Import Arith.
Require Import Omega.
Program Fixpoint twin_ptr
(heads tail rem : list nat)
(H:List.length rem <= List.length tail) :=
match tail, rem with
| a1, [] => (rev heads, tail)
| a2, [a3] => (rev heads, tail)
| t :: tl, _ :: _ :: rm => twin_ptr (t :: heads) tl rm _
| [], _::_::_ => !
end.
Next Obligation.
simpl in H. omega.
Qed.
Next Obligation.
simpl in H. omega.
Qed.
Definition split (l : list nat) := twin_ptr [] l l (le_n _).
The exclamation mark means that a branch is unreachable.
You can then prove lemmas about twin_ptr and deduce the properties of split from them. For example,
Lemma twin_ptr_correct : forall head tail rem H h t,
twin_ptr head tail rem H = (h, t) ->
h ++ t = rev head ++ tail.
Proof.
Admitted.
Lemma split_correct : forall l h t,
split l = (h, t) ->
h ++ t = l.
Proof.
intros. apply twin_ptr_correct in H. assumption.
Qed.
Personally, I dislike to use dependent types in functions, as resulting objects are more difficult to manipulate. Instead, I prefer defining total functions and give them the right hypotheses in the lemmas.
You do not need to maintain the invariant that the second list is bigger than the third. Here is a possible solution:
Require Import Coq.Arith.PeanoNat.
Require Import Coq.Arith.Div2.
Require Import Coq.Lists.List.
Import ListNotations.
Section Split.
Variable A : Type.
Fixpoint split_aux (hs ts l : list A) {struct l} : list A * list A :=
match l with
| [] => (rev hs, ts)
| [_] => (rev hs, ts)
| _ :: _ :: l' =>
match ts with
| [] => (rev hs, [])
| h :: ts => split_aux (h :: hs) ts l'
end
end.
Lemma split_aux_spec hs ts l n :
n = div2 (length l) ->
split_aux hs ts l = (rev (rev (firstn n ts) ++ hs), skipn n ts).
Proof.
revert hs ts l.
induction n as [|n IH].
- intros hs ts [|x [|y l]]; easy.
- intros hs ts [|x [|y l]]; simpl; try easy.
intros Hn.
destruct ts as [|h ts]; try easy.
rewrite IH; try congruence.
now simpl; rewrite <- app_assoc.
Qed.
Definition split l := split_aux [] l l.
Lemma split_spec l :
split l = (firstn (div2 (length l)) l, skipn (div2 (length l)) l).
Proof.
unfold split.
rewrite (split_aux_spec [] l l (div2 (length l))); trivial.
now rewrite app_nil_r, rev_involutive.
Qed.
End Split.
May I suggest going via a more precise type? The main idea is to define a function splitting a Vector.t whose nat index has the shape m + n into a Vector.t of size m and one of size n.
Require Import Vector.
Definition split_vector : forall a m n,
Vector.t a (m + n) -> (Vector.t a m * Vector.t a n).
Proof.
intros a m n; induction m; intro v.
- firstorder; constructor.
- destruct (IHm (tl v)) as [xs ys].
firstorder; constructor; [exact (hd v)|assumption].
Defined.
Once you have this, you've reduced your problem to defining the floor and ceil of n / 2 and proving that they sum to n.
Fixpoint div2_floor_ceil (n : nat) : (nat * nat) := match n with
| O => (O , O)
| S O => (O , S O)
| S (S n') => let (p , q) := div2_floor_ceil n'
in (S p, S q)
end.
Definition div2_floor (n : nat) := fst (div2_floor_ceil n).
Definition div2_ceil (n : nat) := snd (div2_floor_ceil n).
Lemma plus_div2_floor_ceil : forall n, div2_floor n + div2_ceil n = n.
Proof.
refine
(fix ih n := match n with
| O => _
| S O => _
| S (S n') => _
end); try reflexivity.
unfold div2_floor, div2_ceil in *; simpl.
destruct (div2_floor_ceil n') as [p q] eqn: eq.
simpl.
replace p with (div2_floor n') by (unfold div2_floor ; rewrite eq ; auto).
replace q with (div2_ceil n') by (unfold div2_ceil ; rewrite eq ; auto).
rewrite <- plus_n_Sm; do 2 f_equal.
apply ih.
Qed.
Indeed, you can then convert length xs into ceil (length xs / 2) + floor (length xs / 2) and use split_vector to get each part.
Definition split_list a (xs : list a) : (list a * list a).
Proof.
refine
(let v := of_list xs in
let (p , q) := split_vector a (div2_floor _) (div2_ceil _) _ in
(to_list p, to_list q)).
rewrite plus_div2_floor_ceil; exact v.
Defined.