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.
Related
The definition of int comes from compcert,
Record int: Type := mkint { intval: Z; intrange: -1 < intval < modulus }.
I wanna prove foo, suppose that the induction strategy needs to be used, because there is a recursive relationship in P1 and P2, and i is positive in P1 and P2 actually.
From compcert Require Import Integers.
Parameter P1 : int -> Prop.
Parameter P2 : int -> Prop.
Theorem foo:
forall i: int,
(P1 i) -> (P2 i).
Proof.
destruct i. induction intval.
admit.
induction p.
Abort.
If induction p, I need to prove two cases, BinNums.Zpos (BinNums.xI p) and BinNums.Zpos (BinNums.xO p). it is hard to prove, I would like to be able to use int like nat, that is something to prove P1 (i + 1) -> P2 (i + 1) by (P1 i) -> (P2 i)
Any hints? thank you very much!
The fact that you are using int numbers from CompCert makes everything more complicated, because there is too little arithmetic available for this datatype.
If you were using just plain integers of type Z, you would be able to perform the proof you require by using well_founded_induction and Zwf.Zwf_well_founded. Here is an example.
Theorem foo:
forall i: Z, (0 <= i)%Z -> P i.
intros i.
induction i using
(well_founded_ind (Zwf.Zwf_well_founded 0)).
Print Zwf.
intros ige0.
assert (cases : (i = 0 \/ 0 < i)%Z) by lia.
destruct cases as [case0 | casegt0].
rewrite case0.
now apply base_case.
assert (dec : i = ((i - 1) + 1)%Z) by lia.
rewrite dec.
apply rec_case.
apply H.
unfold Zwf.
lia.
lia.
Qed.
Now, if we want to make a similar proof using numbers of type int, life is more complicated because these numbers are in a record, and this record contains a field that is a proof. Usually, the value of the proof is irrelevant, only its existence matters, in in this case we would rather have the intval projection be injective. To make it short, I simply place myself in a theoretical setting where this is granted, this well known and acceptable in most use cases. Here is the full example:
Require Import ZArith Zwf.
Require Import Wellfounded.
Require Import Lia.
Require Import ProofIrrelevance.
Open Scope Z_scope.
Parameter modulus : Z.
Hypothesis modulus_gt_0 : 0 < modulus.
Record int : Type := mkint {intval : Z; intrange: -1 < intval < modulus}.
Lemma intval_inj : forall x y : int, intval x = intval y -> x = y.
Proof.
intros [x xp] [y yp]; simpl.
intros xy; revert xp; rewrite xy; intros xp.
now rewrite (proof_irrelevance _ xp yp).
Qed.
Definition int0 := mkint 0 (conj eq_refl modulus_gt_0).
Parameter P : int -> Prop.
Axiom base_case : P int0.
Lemma modulo_Z_bound (z : Z) : -1 < z mod modulus < modulus.
Proof.
assert (tmp := Z.mod_pos_bound z modulus modulus_gt_0).
lia.
Qed.
Axiom rec_case : forall x, P x -> P (mkint _ (modulo_Z_bound (intval x + 1))).
Theorem foo: forall i, P i.
intros i; destruct i as [z zbounds].
revert zbounds.
induction z as [z Ih] using (well_founded_ind (Zwf_well_founded 0)).
intros zbounds.
assert (cases : z = 0 \/ 0 < z) by lia.
destruct cases as [case0 | casegt0].
revert zbounds; rewrite case0.
intros zbounds; assert (isint0 : {|intval := 0; intrange := zbounds|} = int0).
now apply intval_inj; simpl.
now rewrite isint0; apply base_case.
assert (zm1_bounds : -1 < z - 1 < modulus) by lia.
assert (dec : {| intval := z; intrange := zbounds|} =
mkint _ (modulo_Z_bound (intval (mkint _ zm1_bounds) + 1))).
apply intval_inj; simpl.
replace (z - 1 + 1) with z by ring.
symmetry; apply Z.mod_small; lia.
rewrite dec.
apply rec_case.
apply Ih.
unfold Zwf.
lia.
Qed.
Note that mkint _ (modulo_Z_bound (intval x + 1)) is just a way to write x + 1 when x has type int (with the convention that
the successor of the largest number is 0).
There is a way to avoid using the proof_irrelevance axiom, but this would make this answer even longer.
Here is the definition for the Count predicate. It uses 2 indices to denote starting and ending elements, "check" predicate to count/skip the "current" element and the last argument "sum" to keep track the number of elements that satisfy check predicate between these boundary indices.
Require Import ZArith.
Open Scope Z_scope.
Inductive Count : Z -> Z -> (Z -> Prop) -> Z -> Prop :=
| Q_Nil:
forall (m n : Z),
forall (check : Z -> Prop),
(n <= m) ->
(Count m n check 0)
| Q_Hit:
forall (m n sum : Z),
forall (check : Z -> Prop),
let x := (n - 1) in
(m < n) ->
(check x) ->
(Count m x check sum) ->
(Count m n check (1 + sum))
| Q_Miss:
forall (m n sum : Z),
forall (check : Z -> Prop),
let x := (n - 1) in
(m < n) ->
~(check x) ->
(Count m x check sum) ->
(Count m n check sum).
It is required to prove that the number of counted elements "sum" is non-negative.
Goal
forall (m n sum : Z),
forall (check : Z -> Prop),
(Count m n check sum) -> (0 <= sum).
Proof.
Obviously, the induction could be applied here. However, schemes like natlike_rec3 are not applicable because of the Q_Hit|Q_Miss difference in sum element (i.e. +1 in Q_Hit).
Here is my proof attempt till the step where an induction should be applied.
Proof.
Require Import Psatz.
intros m n sum check.
assert (X: n <= m \/ n > m) by lia.
destruct X as [le|gt].
+ intro.
inversion H; subst; intuition.
+ pose (p := (n - m)).
assert (PZ: p > 0). { subst p. auto with zarith. }
replace n with (m + p) in * by (subst p; auto with zarith).
1 subgoal
m, n, sum : Z
check : Z -> Prop
p := n - m : Z
gt : m + p > m
PZ : p > 0
______________________________________(1/1)
Count m (m + p) check sum -> 0 <= sum
I think that maybe well_founded_induction_type_2 could be used further with relation on sum and p: sum <= p.
You can use induction on the Count hypothesis (in a way, that's the main point of Inductive types).
Proof.
intros.
induction H.
all: omega.
(* or, as a single sequence: intros; induction H; omega. *)
(* lia also works instead of omega, and should probably be preferred nowadays (Require Import Lia.) *)
Qed.
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
Often in Coq I find myself doing the following: I have the proof goal, for example:
some_constructor a c d = some_constructor b c d
And I really only need to prove a = b because everything else is identical anyway, so I do:
assert (a = b).
Then prove that subgoal, then
rewrite H.
reflexivity.
finishes the proof.
But it seems to just be unnecessary clutter to have those hanging around at the bottom of my proof.
Is there a general strategy in Coq for taking an equality of constructors and splitting it up into an equality of constructor parameters, kinda like a split but for equalities rather than conjunctions.
You can use Coq's searching capabilities:
Search (?X _ = ?X _).
Search (_ _ = _ _).
Among some noise it reveals a lemma
f_equal: forall (A B : Type) (f : A -> B) (x y : A), x = y -> f x = f y
And its siblings for multi-argument equalities: f_equal2 ... f_equal5 (as of Coq version 8.4).
Here is an example:
Inductive silly : Set :=
| some_constructor : nat -> nat -> nat -> silly
| another_constructor : nat -> nat -> silly.
Goal forall x y,
x = 42 ->
y = 6 * 7 ->
some_constructor x 0 1 = some_constructor y 0 1.
intros x y Hx Hy.
apply f_equal3; try reflexivity.
At this point all you need to prove is x = y.
In particular, standard Coq provides the f_equal tactic.
Inductive u : Type := U : nat -> nat -> nat -> u.
Lemma U1 x y z1 z2 : U x y z1 = U x y z2.
f_equal
Also, ssreflect provides a general-purpose congruence tactic congr.
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)