proving two fixpoint functions by induction - coq

I am struggling with seemingly simple lemma which involves 2 fixpoint definitions. The following two are axially definitions from CoLoR library:
From Coq Require Import Vector Program.
Import VectorNotations.
Program Fixpoint Vnth {A:Type} {n} (v : t A n) : forall i, i < n -> A :=
match v with
| nil _ => fun i ip => !
| cons _ x _ v' => fun i =>
match i with
| 0 => fun _ => x
| S j => fun H => Vnth v' j _
end
end.
Admit Obligations.
Fixpoint Vmap {A B : Type} (f: A -> B) n (v : t A n) : t B n :=
match v with
| nil _ => nil _
| cons _ a _ v' => cons _ (f a) _ (Vmap f _ v')
end.
The actual problem:
Fixpoint Ind (n:nat) {A:Type} (f:A -> A -> A)
(initial: A) (v: A) {struct n} : t A n
:=
match n with
| O => []
| S p => cons _ initial _ (Vmap (fun x => f x v) _ (Ind p f initial v))
end.
Lemma Foo {A: Type} (n : nat) (f : A -> A -> A) (initial v : A)
(b : nat) (bc : S b < n) (bc1 : b < n)
: Vnth (Ind n f initial v) _ bc = f (Vnth (Ind n f initial v) _ bc1) v.
Proof.
Qed.
Normally I would proceed by induction on n here but this does not gets me much further. I feel like I am missing something here. I also tried program induction here.

You need simplification of Vnth_vmap and a generalized induction to achieve this:
From Coq Require Import Vector Program.
Import VectorNotations.
Program Fixpoint Vnth {A:Type} {n} (v : t A n) : forall i, i < n -> A :=
match v with
| nil _ => fun i ip => !
| cons _ x _ v' => fun i =>
match i with
| 0 => fun _ => x
| S j => fun H => Vnth v' j _
end
end.
Admit Obligations.
Fixpoint Vmap {A B : Type} (f: A -> B) n (v : t A n) : t B n :=
match v with
| nil _ => nil _
| cons _ a _ v' => cons _ (f a) _ (Vmap f _ v')
end.
Lemma Vnth_vmap {A B i n p} (v : t A n) f : Vnth (Vmap (B:=B) f n v) i p = f (Vnth v i p).
Proof.
induction i in n, p, v |- *. destruct v. inversion p.
simpl. reflexivity.
destruct v. simpl. bang.
simpl.
rewrite IHi. f_equal. f_equal.
(* Applies proof-irrelevance, might also be directly provable when giving the proofs in Vnth *) pi.
Qed.
Fixpoint Ind (n:nat) {A:Type} (f:A -> A -> A)
(initial: A) (v: A) {struct n} : t A n
:=
match n with
| O => []
| S p => cons _ initial _ (Vmap (fun x => f x v) _ (Ind p f initial v))
end.
Lemma Foo {A: Type} (n : nat) (f : A -> A -> A) (initial v : A)
(b : nat) (bc : S b < n) (bc1 : b < n)
: Vnth (Ind n f initial v) _ bc = f (Vnth (Ind n f initial v) _ bc1) v.
Proof.
induction n in b, bc, bc1 |- *; simpl.
- bang.
- rewrite Vnth_vmap. f_equal.
destruct b.
+ destruct n. simpl. bang. simpl. reflexivity.
+ rewrite Vnth_vmap. apply IHn.
Qed.

Related

Reversing a vector in Coq

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 :: []).

Transform the lemma leaving previous state on Coq

I want to partially derive functions whose input is a dependent list.
I tried to define deriveP with proving.
Derive is a function in Coquelicot.Derive.
Definition deriveP {P A B}(k:nat)(I:Euc (S P) -> Euc A -> Euc B)
(input:Euc A)(train:Euc B)(p :Euc (S P))
:(lt k (S P)) -> (lt ((S P)-(k+1)) (S P)) -> R.
intros.
pose fk := firstk k (S P) p H.
pose lk := lastk ((S P)-(k+1)) (S P) p H0.
pose pk := EucNth k p.
apply arith_basic in H.
exact ( Derive (fun PK => EucSum (QuadraticError (I (fk +++ (PK ::: lk)) input) train )) pk ).
I can not apply arith_basic poposed by Tiago because H is used in fk.
I can apply arith_basic to H before I make fk, but then I can not make fk because There is not k < P.+1.
I want to apply arith_basic to H while leaving k < P.+1.
Please help me.
(***********************************************************)
This is dependent list of R.
Require Import Coq.Reals.Reals.
Require Import Coquelicot.Coquelicot.
Inductive Euc:nat -> Type:=
|RO : Euc 0
|Rn : forall {n:nat}, R -> Euc n -> Euc (S n).
Notation "[ ]" := RO.
Notation "[ r1 , .. , r2 ]" := (Rn r1 .. ( Rn r2 RO ) .. ).
Infix ":::" := Rn (at level 60, right associativity).
Basic list operation.
Definition head {n} (v : Euc (S n)) : R :=
match v with
| x ::: _ => x
end.
Definition tail {n} (v : Euc (S n)) : Euc n :=
match v with
| _ ::: v => v
end.
(* extract the last element *)
Fixpoint last {n} : Euc (S n) -> R :=
match n with
| 0%nat => fun v => head v
| S n => fun v => last (tail v)
end.
(* eliminate last element from list *)
Fixpoint but_last {n} : Euc (S n) -> Euc n :=
match n with
| 0%nat => fun _ => []
| S n => fun v => head v ::: but_last (tail v)
end.
(* do the opposite of cons *)
Fixpoint snoc {n} (v : Euc n) (x : R) : Euc (S n) :=
match v with
| [] => [x]
| y ::: v => y ::: snoc v x
end.
(* extract last k elements *)
Fixpoint lastk k n : Euc n -> (lt k n) -> Euc k :=
match n with
|0%nat => fun _ (H : lt k 0) => False_rect _ (Lt.lt_n_O _ H)
|S n => match k with
|S m => fun v H => snoc (lastk m n (but_last v) (le_S_n _ _ H)) (last v)
|0%nat => fun _ H => []
end
end.
(* extract first k elements *)
Fixpoint firstk k n : Euc n -> (lt k n) -> Euc k :=
match n with
|0%nat => fun _ (H :lt k 0) => False_rect _ (Lt.lt_n_O _ H)
|S n => match k with
|S m => fun v H => (head v) ::: firstk m n (tail v) (le_S_n _ _ H)
|0%nat => fun _ _ => []
end
end.
(* extract nth element *)
(* 0 origine *)
Fixpoint EucNth (k:nat) :forall {n}, Euc (S n) -> R:=
match k with
| 0%nat => fun _ e => head e
| S k' => fun n =>
match n return Euc (S n) -> R with
| 0%nat => fun e => head e
| S n' => fun v => EucNth k' (tail v)
end
end.
Fixpoint EucAppend {n m} (e:Euc n) (f:Euc m) :Euc (n+m):=
match e with
|[] => f
|e' ::: es => e' ::: (EucAppend es f)
end.
Infix "+++" := EucAppend (at level 60, right associativity).
Fixpoint QuadraticError {n : nat} (b : Euc n) : Euc n -> Euc n.
refine (match b in Euc n return Euc n -> Euc n with
|#Rn m x xs => _
|#RO => fun H => []
end).
remember (S m).
intro H; destruct H as [| k y ys].
inversion Heqn0.
inversion Heqn0.
subst; exact ((x - y)^2 ::: QuadraticError _ xs ys).
Defined.
Fixpoint EucSum {A}(e:Euc A) :R:=
match e with
| [] => 0%R
| e' ::: es => e' + (EucSum es)
end.
Your lemma k + S (P - (k + 1)) = P can be solved just with basic algebraic operations.
Particularly you just need two lemmas to make this easier:
Theorem minus_assoc : forall y z, z < y -> z + (y - z) = y.
intro y.
induction y.
intros;inversion H.
intros.
destruct z.
trivial.
rewrite PeanoNat.Nat.sub_succ.
rewrite <- (IHy _ (le_S_n _ _ H)) at 2; trivial.
Qed.
Theorem minus_S : forall x y, y < x -> S (x - (S y)) = x - y.
intro.
induction x.
intros.
inversion H.
intros.
destruct y.
simpl.
rewrite PeanoNat.Nat.sub_0_r; trivial.
rewrite PeanoNat.Nat.sub_succ.
apply IHx.
exact (le_S_n _ _ H).
Qed.
Now you just have to rewrite your goal to a trivial preposition :
Theorem arith_basic : forall k P, k < P -> k + S (P - (k + 1)) = P.
intros.
rewrite PeanoNat.Nat.add_1_r.
rewrite minus_S.
auto.
rewrite minus_assoc.
assumption.
trivial.
Qed.
Most of these kinds of goals can solve by lia tactic which automatically solves arithmetics goals of Z, nat, positive, and N.
Theorem arith_basic : forall k P, k < P -> k + S (P - (k + 1)) = P.
intros;lia.
Qed
Even though I recommend automation, proving by hands can help understand your main goal which may be not able to be solved by only automation.
I have solved on my own.
We can duplicate lemma in the sub-goal with generalize tactic.
Definition deriveP {P A B}(k:nat)(I:Euc (S P) -> Euc A -> Euc B)
(input:Euc A)(train:Euc B)(p :Euc (S P))
:(lt k (S P)) -> (lt ((S P)-(k+1)) (S P)) -> R.
intros.
generalize H.
intro H1.
apply arith_basic in H1.
pose lk := lastk ((S P)-(k+1)) (S P) p H0.
pose fk := firstk k (S P) p H.
pose pk := EucNth k p.
rewrite (_: (P.+1)%nat = (k + (P.+1 - (k + 1)%coq_nat)%coq_nat.+1)%coq_nat) in I.
exact ( Derive (fun PK => EucSum (QuadraticError (I (fk +++ (PK ::: lk)) input) train )) pk ).
apply H1.
Defined.

Can we ban arguments that don't meet conditions?

I want to partially derive functions whose input is a dependent list.
deriveP has an error because EucAppend fk (pk ::: lk) of length is not always n, but I always expects a list whose length is P.
This is due to the definition of lastk and firstk.
To solve this problem, lastk and firstk must return only Euc k, not Euc n.
I want to ban arguments that n and k don't meet k <= n in lastk and firstk.
I don't know how to do it. Please tell me.
This is dependent list of R.
Require Import Coq.Reals.Reals.
Require Import Coquelicot.Coquelicot.
Inductive Euc:nat -> Type:=
|RO : Euc 0
|Rn : forall {n:nat}, R -> Euc n -> Euc (S n).
Notation "[ ]" := RO.
Notation "[ r1 , .. , r2 ]" := (Rn r1 .. ( Rn r2 RO ) .. ).
Infix ":::" := Rn (at level 60, right associativity).
Basic list operation.
Definition head {n} (v : Euc (S n)) : R :=
match v with
| x ::: _ => x
end.
Definition tail {n} (v : Euc (S n)) : Euc n :=
match v with
| _ ::: v => v
end.
(* extract the last element *)
Fixpoint last {n} : Euc (S n) -> R :=
match n with
| 0%nat => fun v => head v
| S n => fun v => last (tail v)
end.
(* eliminate last element from list *)
Fixpoint but_last {n} : Euc (S n) -> Euc n :=
match n with
| 0%nat => fun _ => []
| S n => fun v => head v ::: but_last (tail v)
end.
(* do the opposite of cons *)
Fixpoint snoc {n} (v : Euc n) (x : R) : Euc (S n) :=
match v with
| [] => [x]
| y ::: v => y ::: snoc v x
end.
(* extract last k elements *)
Fixpoint lastk k : forall n, Euc n -> Euc (Nat.min k n) :=
match k with
| 0%nat => fun _ _ => []
| S k' => fun n =>
match n return Euc n -> Euc (Nat.min (S k') n) with
| 0%nat => fun _ => []
| S n' => fun v =>
snoc (lastk k' _ (but_last v)) (last v)
end
end.
(* extract first k elements *)
Fixpoint firstk k :forall n, Euc n -> Euc (Nat.min k n) :=
match k with
| 0%nat => fun _ _ => []
| S k' => fun n =>
match n return Euc n -> Euc (Nat.min (S k') n) with
| 0%nat => fun _ => []
| S n' => fun v => (head v) ::: firstk k' _ (tail v)
end
end.
(* extract nth element *)
(* 0 origine *)
Fixpoint EucNth (k:nat) :forall n, Euc (S n) -> R:=
match k with
| 0%nat => fun _ e => head e
| S k' => fun n =>
match n return Euc (S n) -> R with
| 0%nat => fun e => head e
| S n' => fun v => EucNth k' n' (tail v)
end
end.
Fixpoint EucAppend {n m} (e:Euc n) (f:Euc m) :Euc (n+m):=
match e with
|[] => f
|e' ::: es => e' ::: (EucAppend es f)
end.
deriveP partially derive fnctions. I (EucAppend fk (pk ::: lk)) is where the error is.
Definition deriveP {n A} (k:nat) (I:Euc n -> Euc A) (p :Euc n) :=
let fk := firstk k P p in
let lk := lastk (P-(k+1)) P p in
(Derive (fun pk => I (EucAppend fk (pk ::: lk)) )) (EucNth k (P-1) p).
You can work with an order relation as you mentioned. My recommendation is to avoid proofs inside your definition (which makes proving after more complex), example :
Fixpoint lastk k n : Euc n -> k < n -> Euc k :=
match n with
|0 => fun _ (H : k < 0) => False_rect _ (Lt.lt_n_O _ H)
|S n => match k with
|S m => fun v H => snoc (lastk (but_last v) (le_S_n _ _ H)) (last v)
|0 => fun _ H => []
end
end.
Fixpoint firstk k n : Euc n -> k < n -> Euc k :=
match n with
|0 => fun _ (H : k < 0) => False_rect _ (Lt.lt_n_O _ H)
|S n => match k with
|S m => fun v H => (head v) ::: firstk (tail v) (le_S_n _ _ H)
|0 => fun _ H => []
end
end.
This definition is transparent which makes it easy to prove after using k n as inductions points.
The vectodef library works with Fin types(finite sequences). You can do a workaround to make it comfortable to extract the definition :
Fixpoint of_nat {n} (x : t n) : nat :=
match x with
|#F1 _ => 0
|#FS _ y => S (of_nat y)
end.
Fixpoint lastk n (H : t n) (v : Euc n) : Euc (of_nat H) :=
match H as t in (t n0) return (Euc n0 -> Euc (of_nat t)) with
| #F1 n0 => fun=> [ ]
| #FS n0 H1 =>
fun H2 : Euc (S n0) => snoc (lastk H1 (but_last H2)) (last H2)
end v.
Theorem of_nat_eq : forall y k (H : k < y), of_nat (of_nat_lt H) = k.
intros y k.
elim/#nat_double_ind : y/k.
intros;inversion H.
intros; auto.
intros; simply.
by rewrite -> (H (Lt.lt_S_n _ _ H0)).
Qed.
Definition last_leb n k (v : Euc n) : k < n -> Euc k.
intros.
rewrite <- (of_nat_eq H).
exact (#lastk _ (of_nat_lt H) v).
Show Proof.
Defined.
But..., as I mentioned this has proofs in the terms.
I think you probably will need another proof for deriveP, but I don't know the definition of Derive, please consider to specify at least the type definition.

Vector error : The type of this term is a product

I want last k elements of vector. I wrote this code with reference to Coq.Vectors.VectorDef.
Require Import Coq.Reals.Reals.
(* vector of R *)
Inductive Euc:nat -> Type:=
|RO : Euc 0
|Rn : forall {n:nat}, R -> Euc n -> Euc (S n).
Notation "[ ]" := RO.
Notation "[ r1 , .. , r2 ]" := (Rn r1 .. ( Rn r2 RO ) .. ).
Infix ":::" := Rn (at level 60, right associativity).
(* return length of vector *)
Definition EucLength {n}(e:Euc n) :nat:= n.
Definition rectEuc (P:forall {n}, Euc (S n) -> Type)
(bas: forall a:R, P [a])
(rect: forall {n} a (v: Euc (S n)), P v -> P (a ::: v)) :=
fix rectEuc_fix {n} (v: Euc (S n)) : P v :=
match v with
|#Rn 0 a v' =>
match v' with
|RO => bas a
|_ => fun devil => False_ind (#IDProp) devil
end
|#Rn (S nn') a v' => rect a v' (rectEuc_fix v')
|_ => fun devil => False_ind (#IDProp) devil
end.
(* eliminate last element from vector *)
Definition EucElimLast := #rectEuc (fun n _ => Euc n) (fun a => []) (fun _ a _ H => a ::: H).
(* this function has an error *)
Definition rectEucLastN (P:forall {n}, nat -> Euc n -> Type)
(bas: forall {n} k (e:Euc n), P k e)
(rect: forall {n} k a (e:Euc (S n)), P k e -> P (S k) (a ::: e)) :=
fix rectEuc_fix {n} (k:nat) (e:Euc n): P k e :=
match k,e with
|S k', e' ::: es => rect k' e' (rectEuc_fix k' (EucElimLast ((EucLength e)-1) e))
|0%nat, e' ::: es => bas k e
|_, _ => fun devil => False_ind (#IDProp) devil
end.
rectEucLastN says The type of this term is a product while it is expected to be (P ?n#{n1:=0%nat} ?n0#{k1:=0%nat} ?e#{n1:=0%nat; e1:=[]}).
The problem is the second line from the bottom of the code.
Why does last pattern have an error?
The function term that you see on the branch of rectEuc is how you tell Coq that a pattern-match branch is contradictory. In your first recursive function, for instance, you use it to say that the first v' cannot be a cons because its length is zero. The reason you are getting the error in the last branch is because that case is not contradictory: nothing in the type of your function prevents the case k = 0 and n = 0.
To write dependently typed programs over indexed families, you often need to use the convoy pattern: to refine the type of an argument x after branching on some expression, your match needs to return a function that abstracts over x. For instance, this function computes the last element of a vector by recursion over its length. In the S branch, we need to know that the length of v is connected to n somehow.
Definition head n (v : Euc (S n)) : R :=
match v with
| x ::: _ => x
end.
Definition tail n (v : Euc (S n)) : Euc n :=
match v with
| _ ::: v => v
end.
Fixpoint last n : Euc (S n) -> R :=
match n with
| 0 => fun v => head 0 v
| S n => fun v => last n (tail _ v)
end.
Here is the code for extracting the last k elements. Note that its type uses the Nat.min function to specify the length of the result: the result cannot be larger than the original vector!
Fixpoint but_last n : Euc (S n) -> Euc n :=
match n with
| 0 => fun _ => []
| S n => fun v => head _ v ::: but_last n (tail _ v)
end.
Fixpoint snoc n (v : Euc n) (x : R) : Euc (S n) :=
match v with
| [] => [x]
| y ::: v => y ::: snoc _ v x
end.
Fixpoint lastk k : forall n, Euc n -> Euc (Nat.min k n) :=
match k with
| 0 => fun _ _ => []
| S k => fun n =>
match n return Euc n -> Euc (Nat.min (S k) n) with
| 0 => fun _ => []
| S n => fun v =>
snoc _ (lastk k _ (but_last _ v)) (last _ v)
end
end.
Personally, I would advise you against programming in this style in Coq, since it makes it difficult to write programs and understand them later. It is usually better to write a program without dependent types and prove after the fact that it has some property that you care about. (E.g. try to show that reversing a list twice yields the same list using vectors!) Of course, there are cases where dependent types are useful, but most of the time they are not needed.

Pattern match with two list whose type is dependent type on Coq

I defined this function.
Inductive Euc:nat -> Type:=
|RO : Euc 0
|Rn : forall {n:nat}, R -> Euc n -> Euc (S n).
Notation "[ ]" := RO.
Infix ":::" := Rn (at level 60, right associativity).
Fixpoint QE {A}(b c:Euc A) :=
match b,c with
|b':::bs, c'::: cs => (b'+c') ::: QE bs cs
|_, _ => []
end.
I have encountered the error "The term "[]" has type "Euc 0" while it is expected to have type "Euc A" ".
How do I teach Coq that Euc 0 is Euc A?
Coq doesn't know that the only pattern left is the "RO" constructor, therefore you're not able to return an empty Euc.
To fix that just remove the _ and specialize the case :
Fixpoint QE {A}(b c:Euc A) : Euc A.
refine (match b,c with
|RO, RO => _
|H => ????
end).
That forces coq to understand that you're dealing with a specific constructor.
Also, Coq always will instantiate new variables (Types not) of elimination, thus coq may complain that bs and cs have different indexes.
The coq vectordef library has several examples of how to manage this.
A first approach and more mature it is to use elimination schemes, notice you can destruct a non-zero vector using the head and last.
For example :
Definition rect_euc {n : nat} (v : Euc (S n)) :
forall (P : Euc (S n) -> Type) (H : forall ys a, P (a ::: ys)), P v.
refine (match v with
|#Rn _ _ _ => _
|R0 => _
end).
apply idProp.
intros; apply H.
Defined.
Now, you just have to use the scheme to destruct both vectors preserving the length of both :
Fixpoint QE (n : nat) {struct n} : Euc n -> Euc n -> Euc n :=
match n as c return Euc c -> Euc c -> Euc c with
| S m => fun a =>
(#rect_euc _ a _ (fun xs x b =>
(#rect_euc _ b _ (fun ys y => (x + y) ::: #QE m xs ys))))
| 0 => fun xs ys => []
end.
Alternatively you can use the coq tactics to remember that two indexes are equal :
Fixpoint QE' (n : nat) (b : Euc n) : Euc n -> Euc n.
refine (match b in Euc n return Euc n -> Euc n with
|#Rn m x xs => _
|#RO => fun H => []
end).
remember (S m).
intro H; destruct H as [| k y ys].
inversion Heqn0.
inversion Heqn0.
subst; exact ((x + y) ::: QE' _ xs ys).
Defined.