You need to disentangle your statement. In its current form, the number n
and the vector v
are used in too many places for different purposes. This makes a proof by induction very difficult.
If you look at the recursive call in Sumation
, you see that the second explicit argument (the one locally named v
) does not change during recursive call, while the main recursive argument k
decreases. So you have to have a statement where the second explicit argument does not have to have size S n
. It suffices that the size of v
is larger than or equal to S n
.
Similarly, the uses of kLess _ _
are blocking your abilities to think and Coq's ability to rewrite. What really matters, is that we are accessing inside v
and inside the result of the Sumation _ _
call using arguments that are smaller than the size, so you should generalize about this.
The proof below exploits these guidelines.
Require Import Coq.Vectors.Vector.
Require Import Psatz.
Require Import ssreflect.
Require Import Arith.
Definition kLess : forall (k P:nat), (P - k) < (S P).
intros. lia.
Defined.
Definition Sum {A}(v:t nat A) :nat:= Vector.fold_right Nat.add v 0.
Fixpoint Sumation {A} (k:nat)(v:t nat (S A)):t nat (S k):=
match k in nat return t nat (S k) with
|0 => cons _ ((nth_order v (kLess k A)) + (Sum v)) _ (nil nat)
|S k' => cons _ ((nth_order v (kLess k A)) + (Sum v)) _ (Sumation k' v)
end.
Definition v := cons nat 0 1 (cons nat 1 0 (nil nat)).
Compute Sumation 0 v.
Compute nth_order (Sumation 0 v) (kLess 0 _).
Compute nth_order v (kLess 0 _) + Sum v.
Lemma aaa {n}(k:nat)(v:t nat (S n)): nth_order (Sumation n v) (kLess k n) =
(nth_order v (kLess k n)) + (Sum v).
Proof.
move: n k v.
suff main : (forall (n m k : nat) (v : t nat (S m)) (h1 : m - k < S m)
(h2 : n - k < S n),
k <= n <= m->
nth_order (Sumation n v) h2 = nth_order v h1
+ Sum v).
move=> n k v.
have [klen | ngtk] := (Compare_dec.le_lt_dec k n).
rewrite (main n n k v); intuition.
by congr (nth _ _ + _); apply: Fin.of_nat_ext.
rewrite /nth_order /=.
rewrite (_ : Fin.of_nat_lt (kLess k n) = Fin.F1).
by move: (kLess k n); rewrite [n - k](_ : _ = 0) //; lia.
case: n v {ngtk} => //=.
move=> n v; rewrite /nth_order (_ : Fin.of_nat_lt _ = Fin.F1) //.
by move: (kLess (S n) (S n)); rewrite /= (Nat.sub_diag n).
elim => [ | n Ih] m k v h1 h2 [kle nle].
rewrite /= /nth_order /=.
congr (nth _ _ + _).
have k0 : k = 0 by lia.
move: (kLess 0 m) h1; rewrite k0 Nat.sub_0_r.
by apply: Fin.of_nat_ext.
rewrite /=.
have [nltSm | neqSm] := Compare_dec.le_lt_eq_dec _ _ kle.
rewrite /nth_order.
have [k' k'P] : exists k', S n - k = S k'.
exists (n - k); lia.
have h' : S k' < S (S n).
by lia.
have -> /= : Fin.of_nat_lt h2 = Fin.of_nat_lt h'.
move: h'; rewrite -k'P => h'.
by apply Fin.of_nat_ext.
move: (Lt.lt_S_n k' _ _) => {h'}h2.
have k'P2 : n - k = k' by lia.
rewrite -[LHS]/(nth_order (Sumation n v) h2).
move: h2; rewrite -k'P2=> h2.
rewrite Ih; first by lia.
by [].
rewrite /nth_order.
have -> /= : Fin.of_nat_lt h2 =
Fin.of_nat_lt (Nat.lt_0_succ (S n)).
move: h2; rewrite neqSm Nat.sub_diag; apply: Fin.of_nat_ext.
lia.
congr (nth _ _ + _).
by move: h1; rewrite neqSm; apply: Fin.of_nat_ext.
Qed.