Coq - Proving condition about elements of sequence in Ssreflect - coq

I have a goal that looks like this:
x \in [seq (f v j) | j <- enum 'I_m & P v j] -> 0 < x
In the above, f is a definition generating a solution of an inequality depending on v, j and P v j is a predicate restricting j to indices which satisfy another inequality.
I have already proven that Goal : P v j -> (f v j > 0), but how can I use this to prove that it holds for any x in the sequence? I have found just a few relevant lemmas like nthP which introduce sequence manipulation, which I'm very unfamiliar with.
Thanks in advance!

You need to use the mapP lemma (that characterizes membership wrt map):
Lemma U m (P : rel 'I_m) f v x (hp : forall j, P v j -> f v j > 0) :
x \in [seq f v j | j <- enum 'I_m & P v j] -> 0 < x.
Proof. by case/mapP=> [y]; rewrite mem_filter; case/andP=> /hp ? _ ->. Qed.

Related

COQ: How to use "<=" for Z and R in the same lemma?

Suppose I already defined floor (from R to Z). Now I want to prove that n <= x implies n <= floor(x), where n : Z, x : R.
I tried:
Lemma l: forall (n:Z) (x:R), (IZR n) <= x -> n <= (floor x).
but I'm getting the error The term n has type Z while it is expected to have type R.
How should I write this? Is there a way that I can use <= for Z and R simultaneously?
In order to override the default interpretation of a notation, you can open a notation scope locally using %key:
Lemma l : forall n x, (IZR n <= x)%R -> (n <= floor x)%Z.

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 do I describe a multiplication of vectorized matrices?

I want to calculate a product of huge (specific) matrices. From a point complexity of view, the product should be taken the form of an elementwise expression.
I tried to "vectorize" the matrices with mxvec / vec_mx and calculate the product via one dimensional streams. But indices access was blocked by the term of enum ('I_p * 'I_q).
I want to know a nth value of enum ('I_p * 'I_q) because I want to decscribe a multiplication of matrices in the form of a primitive expression in an underlying field.
How do I do this? In particular, how do I prove this statement?
From mathcomp Require Import all_ssreflect.
Lemma nth_enum_prod p q (a : 'I_q) :
val a = index (ord0, a) (enum (prod_finType (ordinal_finType p.+1) (ordinal_finType q))).
I'm surprised you need to vectorize the matrices if your definition is point-wise, usually you should be able to define your result as \matrix_(i, j) op, for example the standard definition of matrix multiplication is:
\matrix_(i, k) \sum_j (A i j * B j k).
By the way, a quick "dirty" proof of your lemma is:
Lemma nth_enum_prod p q (a : 'I_q) : val a = index (#ord0 p, a) (enum predT).
Proof.
have /(_ _ 'I_q) pair_snd_inj: injective [eta pair ord0] by move => n T i j [].
have Hfst : (ord0, a) \in [seq (ord0, x2) | x2 <- enum 'I_q].
by move=> n; rewrite mem_map /= ?mem_enum.
rewrite enumT !unlock /= /prod_enum enum_ordS /= index_cat {}Hfst.
by rewrite index_map /= ?index_enum_ord.
Qed.
but indeed if you find yourself using this it means you are into a different kind of problem. I just posted it as an illustration on how to manipulate this kind of expressions.
edit: based on your comment, a more principled way to manipulate the above is to define a lemma about index and products; I've left the full proof as an exercise, but the outline is:
Lemma index_allpairs (T U : eqType) (x : T) (y : U) r s :
(* TODO: Some conditions are missing here *)
index (x,y) [seq (x,y) | x <- r , y <- s] =
size s * (index x r) + index y s.
Proof.
Admitted.
Lemma index_ord_allpairs p q (x : 'I_p) (y : 'I_q) :
index (x,y) [seq (x,y) | x <- enum 'I_p , y <- enum 'I_q] = q * x + y.
Proof. by rewrite index_allpairs ?mem_enum ?size_enum_ord ?index_enum_ord. Qed.
Lemma nth_enum_prod p q (a : 'I_q) : val a = index (#ord0 p, a) (enum predT).
Proof. by rewrite enumT unlock index_ord_allpairs muln0. Qed.

Equality of proof-carrying dependent functions in Coq

Suppose we have:
Require Import ZArith Program Omega.
Open Scope Z_scope.
Definition Z_to_nat (z : Z) (p : 0 <= z) : nat.
Proof.
dependent destruction z.
- exact (0%nat).
- exact (Pos.to_nat p).
- assert (Z.neg p < 0) by apply Zlt_neg_0.
contradiction.
Qed.
Now I would like to formulate something like this:
Lemma Z_to_nat_pred : forall x y p p', (Z_to_nat x p <= Z_to_nat y p')%nat <-> x <= y.
This doesn't seem quite right to me, because in x <= y, I can have negative x, y, and then I won't have proofs about their positivity. All in all, the dependent Z_to_nat seems extremely difficult to use. How does one formulate that it suffices to show x <= y to conclude (Z_to_nat x p <= Z_to_nat y p')%nat and the other way around?
I've given it a bash to inspect the way I could formulate the proof (although I am fairly sure it can't be proven with this formulation).
I've tried:
Lemma Z_to_nat_pred : forall x y p p',
(Z_to_nat x p <= Z_to_nat y p')%nat <-> x <= y.
Proof.
intros.
split; intros.
- dependent destruction x;
dependent destruction y; try easy; try omega.
Which leads me to the following goal:
p : positive
p0 : 0 <= Z.pos p
p' : 0 <= 0
H : (Z_to_nat (Z.pos p) p0 <= Z_to_nat 0 p')%nat
______________________________________(1/1)
Z.pos p <= 0
Could I here, for example, solve the goal by deriving contradiction from H, as Z.pos p cannot be <= 0? I can't really do much with the Z_to_nat definition.
here are several remarks that are related to your question:
In Coq when one defines functions using tactics and especially when we want to compute with, it is preferable to end the corresponding proof script with Defined., not Qed. (the notion at stake is "transparent definition" vs. "opaque definition", cf. the Coq ref man)
so if you replace Qed with Defined, the tactic simpl in H. will be applicable in your proof of Z_to_nat_pred
EDIT: another tactic that would have been useful in your goal is exfalso.
your function Z_to_nat is a partial function that takes a proof as argument. But in many practical cases, it is simpler to avoid dependent types, and just use a default value (making thus the function "total")
this latter strategy is already that of the two functions below that are available in the the standard library (that you have already imported with Require Import ZArith). These two functions can be viewed as two ways to define your function Z_to_nat in a non-dependently-typed way:
Print Z.abs_nat.
Z.abs_nat =
fun z : Z => match z with
| 0 => 0%nat
| Z.pos p => Pos.to_nat p
| Z.neg p => Pos.to_nat p
end
: Z -> nat
Print Z.to_nat.
Z.to_nat =
fun z : Z => match z with
| 0 => 0%nat
| Z.pos p => Pos.to_nat p
| Z.neg _ => 0%nat
end
: Z -> nat
Finally it appears that for each of these two functions, lemmas similar to yours are available in ZArith:
SearchAbout Z.abs_nat Z.le iff.
Zabs2Nat.inj_le: forall n m : Z, 0 <= n -> 0 <= m -> n <= m <-> (Z.abs_nat n <= Z.abs_nat m)%nat
Zabs2Nat.inj_lt: forall n m : Z, 0 <= n -> 0 <= m -> n < m <-> (Z.abs_nat n < Z.abs_nat m)%nat
SearchAbout Z.to_nat Z.le iff.
Z2Nat.inj_iff: forall n m : Z, 0 <= n -> 0 <= m -> Z.to_nat n = Z.to_nat m <-> n = m
Z2Nat.inj_le: forall n m : Z, 0 <= n -> 0 <= m -> n <= m <-> (Z.to_nat n <= Z.to_nat m)%nat
Z2Nat.inj_lt: forall n m : Z, 0 <= n -> 0 <= m -> n < m <-> (Z.to_nat n < Z.to_nat m)%nat
Best regards

How can I break `forall i: nat i < S k -> H` in Coq into `i < k and i=k`?

I have to prove:
i < Datatypes.length (l0 ++ f :: nil) -> H
I have a separate hypothesis for i < Datatypes.length l0 and i = Datatypes.length l0.
Require Import Arith.
SearchAbout lt le.
gives me (among other things):
le_lt_or_eq: forall n m : nat, n <= m -> n < m \/ n = m
Now. You have i < S k which is equivalent to S i <= S k and you want i <= k. So you need to peel-off S on each side.
SearchAbout le S.
gives me (among other things):
le_S_n: forall n m : nat, S n <= S m -> n <= m
By combining the two, you should be able to prove your goal:
Goal forall i k, i < S k -> i < k \/ i = k.
intros i k iltSk.
apply le_lt_or_eq.
apply le_S_n.
assumption.
Qed.