Proving x >= a /\ x <= a -> x = a - coq

How would one go about proving the following
Theorem T: forall x, a: nat, x >= a /\ x <= a -> x = a.
in Coq?

If you don't want to use the full power of omega, I would search the standard library for the antisymmetric property of <= using SearchPattern or SearchAbout (or google) and apply le_antisym.
If you want a proof without using lemmas from the library, go by induction on x and a.

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 does the "intro ->" in Coq work on context?

I am interested in how does dependent-typed theorem provers do substitution on the context. I find a thing called "intro ->" in Coq, as described in:
https://coq.inria.fr/refman/proof-engine/tactics.html#intropattern-rarrow-ex
In the example, it says the goal:
x, y, z : nat
H : x = y
y = z -> x = z
will become
x, z : nat
H : x = z
x = z
after an application of "intros ->".
I am not sure how is the step of substituting H:x = y into H:x = z be done, what is the rule of the logic of Coq is this step according to? It seems like a step of rewriting, and according to my current knowledge most of these rewriting are according to equalities, so the replacement from H:x = y into H:x = z should come from an equality like (H:x = y) = (H:x= z) ($\diamond$), but such an equality is ill-formed because, in principle, we require the LHS and RHS of an equality to have the same type, so the well-formedness of such equality ($\diamond$) depends on the assumption that y = z.
Could someone please help explaining how does "intro ->" work here? Do we need to get "equalities" like ($\diamond$) involved?
In Coq, rewriting on the context is a derived notion. The tactic intros -> in this case is roughly equivalent to the following tactics:
intros H'. rewrite H' in H. clear y H'.
The tactic rewrite H' in H., in turn, is roughly equivalent to
revert H. rewrite H'. intros H.
In words, to rewrite on the context, Coq first transfers all the relevant hypotheses to the goal, rewrites the goal and then brings the hypotheses back to the context.
Rewriting the goal uses the following elimination principle for the equality type:
forall [A : Type] [a : A] (P : A -> Prop), P a -> forall b : A, b = a -> P b
For rewriting H' above, we would have:
A := T
a := z
P := fun c => x = c -> x = z
b := y
so,
P b == x = y -> x = z
P a == x = z -> x = z
Indeed, ignoring the move steps to and from the context, Coq went from P b to P a when you performed the rewrite.

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 does 'elim' in Coq work on existential quantifier?

I'm confused by Coq on its way dealing with existential quantification.
I have a predicate P and an assumption H
P : nat -> Prop
H : exists n, P n
while the current goal is (whatever)
(Some goal)
If I want to instantiate n in H, I will do
elim H.
However after the elimination, the current goal becomes
forall n, P n -> (Some goal)
It looks like Coq converts an existential quantifier into a universal one. I know that (forall a, P a -> Q a) -> ((exists a, P a) -> Q a) out of my limited knowledge on first-order logic. But the reverse proposition seems to be incorrect. If the 'forall' one and 'exists' one are not equivalent, why Coq would do such conversion?
Does 'elim' in Coq replace the goal with a harder to prove one? Or could anyone please show why ((exists a, P a) -> Q a) -> (forall a, P a -> Q a) holds in first-order logic?
Maybe the missing key is that the goal:
forall n, P n -> (Some goal)
is to be read as:
forall n, (P n -> (Some goal))
and not as:
(forall n, P n) -> (Some goal)
That is, the goal you are given just gives you an arbitrary n and a proof P n, which is indeed the proper way to eliminate an existential (you don't get to know the value of the witness since it could be any value that makes P true, you just get to know that there is a n and that P n holds).
On the contrary, the latter would provide you with a function that can build P n for any n you pass it, which is indeed a stronger statement than the one you have.
I realize this question is old but I would like to add the following important clarification:
In Coq, (and more generally, in intuitionistic logic) the existential quantifier is defined (see here) as follows
(exists x, (P x)) := forall (P0 : Prop), ((forall x, (P x -> P0)) -> P0)
Intuitively this can be read as
(exists x, P x) is the smallest proposition which holds whenever P x0 holds for some x0
In fact one can easily prove the following two theorems in Coq:
forall x0, (P x0 -> (exists x, P x)) (* the introduction rule -- proved from ex_intro *)
and (provided A : Prop)
(exists x : A, P x) -> {x : A | P x} (* the elimination rule -- proved from ex_ind *)
So a Coq goal of the form
H1...Hn, w : (exists x, P x) |- G
is transformed (using elim) to a Coq goal of the form
H1...Hn, w : (exists x, P x) |- forall x0, (P x0 -> G)
because whenever h : forall x0, (P x0 -> G), then G is precisely justified by the proof term
(ex_ind A P G h w) : G
which works whenever G : Prop.
Note: the elimination rule above is only valid whenever A : Prop, and cannot be proved whenever A : Type. In Coq, this mean that we do not have the ex_rect eliminator.
From my understanding (see here for more details), this is a design choice to preserve good program extraction properties.

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)