Equality of proof-carrying dependent functions in Coq - 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

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.

Case splitting on if-then-else condition

This is a silly beginner question, but how do I prove this theorem?
Open Scope Z.
Theorem test : forall x y:Z, (x > 0 -> y = 1) \/ (x <= 0 -> y = 2) -> y >= 1.
Proof.
intros.
destruct x.
destruct H.
(* stuck *)
Qed.
What I'm really trying to do is model an if-then-else statement as a Prop and case split on the condition to prove it. I get stuck with the context like this:
y: nat
H: 0 > 0 -> y = 1
-----------------
(1/3)
y >= 1
(2/3)
y >= 1
(3/3)
y >= 1
I sort of understand that to get rid of impossible cases, I need to find a contradiction in the hypothesis, but how do I do that here?
Advice on how this could be done better is welcome, e.g. is this the best way to model if-then-else?
how do I prove this theorem?
Theorem test : forall x y:Z, (x > 0 -> y = 1) \/ (x <= 0 -> y = 2) -> y >= 1.
Your theorem is not true.
Suppose H: x > 0 -> y = 1 but x is actully 0, then you have no way of proving y >= 1 as you know nothing about y.
Perhaps you meant to use and (/\) instead of or? Then here's one proof that uses lia to do the tedious Z arithmetic.
Require Import ZArith Lia. Open Scope Z.
Theorem test : forall x y:Z, (x > 0 -> y = 1) /\ (x <= 0 -> y = 2) -> y >= 1.
Proof. intros x y [H1 H2]. enough (x>0 \/ x<=0) as [H|H]; lia. Qed.
I think what you are looking for is the lemma
Z_lt_le_dec : forall x y : Z, {x < y} + {y <= x}
of the library. What { … } + { … } means is similar to \/, i.e. it is a kind of disjuction, but here this disjuction constructs a type in Set rather than Prop. This means that while you cannot use a \/ disjuction to build a function returning a nat (because of Coq’s enforcement that propositions should be irrelevant) you can use a { … } + { … } one. You can write
Definition test (x : Z) := if (Z_lt_le_dec 0 x) then 1 else 2.
which is syntactic sugar for a pattern matching like this one
Definition test (x : Z) := match (Z_lt_le_dec 0 x) with
| left _ => 1
| right _ => 2
end.
where left and right are the two constructors of { … } + { … }.
To check that this test does what it should, you can now try to go and prove
Lemma test_ge1 (x : Z) : 1 <= test x.

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.

Coq - Proving condition about elements of sequence in Ssreflect

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.

How to "flip" an equality proposition in Coq?

If I'm in Coq and I find myself in a situation with a goal like so:
==================
x = y -> y = x
Is there a tactic that can can take care of this in one swoop? As it is, I'm writing
intros H. rewrite -> H. reflexivity.
But it's a bit clunky.
To "flip" an equality H: x = y you can use symmetry in H. If you want to flip the goal, simply use symmetry.
If you're looking for a single tactic, then the easy tactic handles this one immediately:
Coq < Parameter x y : nat.
x is assumed
y is assumed
Coq < Lemma sym : x = y -> y = x.
1 subgoal
============================
x = y -> y = x
sym < easy.
No more subgoals.
If you take a look at the proof that the easy tactic found, the key part is an application of eq_sym:
sym < Show Proof.
(fun H : x = y => eq_sym H)
The heavier-weight auto tactic will also handle this goal in a single step. For a slightly lower-level proof that produces exactly the same proof term, you can use the symmetry tactic (which also automatically does the necessary intro for you):
sym < Restart.
1 subgoal
============================
x = y -> y = x
sym < symmetry.
1 subgoal
H : x = y
============================
x = y
sym < assumption.
No more subgoals.
sym < Show Proof.
(fun H : x = y => eq_sym H)