I have two natural numbers a & b. Third number is c which is greater or equal to b (c>=b). Now have following conditions for a & b and want to prove
c greater than a.
a < b->
c >= a->
c > a.
If you know c >= b and b > a then it's only logical that c > a. This kind of reasoning is easily taken care of by the lia tactic, which automates reasoning about linear integer arithmetic.
From Coq Require Import Lia.
Goal forall a b c : nat, a < b -> b <= c -> a <= c.
Proof.
intros.
lia.
Qed.
Related
I have the last subgoal to prove a theorem.
and it's:
1 subgoal
b, d : nat
H : 0 <= b
H0 : 0 <= d
m : nat
H1 : 0 <= m
H2 : S m = d
______________________________________(1/1)
b <= b + S m
I think I need an assumption like n <= n + Sm for this.
Anyone can help me out?? Thanks a lot!
The lia tactic, which stands for "Linear Integer Arithmetic", can solve this and many similar goals. E.g.:
Require Import Lia.
Goal forall b m, b <= b + S m.
Proof. intros. lia. Qed.
This is lemma le_plus_l of the standard library.
It might be a good time for you to get familiar with the Search command. It is very useful to find theorems, and quite powerful once you get the hand of it. Here for instance I simply used Search (?x <= ?x + _) and got exactly the thing you were looking for.
I have simplified my situation to the following piece of code, hopefully this makes it easier to understand.
I would like to prove the following Lemma:
Require Import Arith.
Lemma example: forall a b,
if a<=?b then a<=b else a > b.
Doing the following step in the proof
Proof.
intros.
Gives me the result
1 subgoal
a, b : nat
______________________________________(1/1)
if a <=? b then a <= b else a > b
It seems trivial that either a is smaller than or equal to b, in which case I could prove a<=b. In the other case that b is larger than a I could prove that a>b.
I've tried to prove this with induction(a<=?b) or case (a<=?b) but both give me the following result.
2 subgoals
a, b : nat
______________________________________(1/2)
a <= b
______________________________________(2/2)
a > b
Now I have no way to prove these goals. I expected to gain an hypothesis such as H: a <= b and H: a > b in the second case. This way, I would be able to prove my goals.
Could anybody tell me how I could this issue of the non-appearing hypothesis?
Edit:
The whole lemma can be proven as follows:
Require Import Arith.
Lemma example: forall a b,
if a<=?b then a<=b else a > b.
Proof.
intros.
Check Nat.leb_spec.
case (Nat.leb_spec a b);intuition.
What's happening is that <=? is function returning a boolean, either true or false. When you ask Coq to do an induction or a case analysis on the expression a <=? b, it does exactly that and reduces the proof to two cases: one where a <=? b is substituted by true and another where it is substituted by false. If you want to keep track of the destructed value, you should ask explicitly for it using destruct (a <=? b) eqn:H. (see the documentation).
To do the case distinction that you are looking for you can use
Nat.leb_spec : forall x y : nat, BoolSpec (x <= y) (y < x) (x <=? y)
The type BoolSpec embodies exactly what you are trying to do: if (x <=? y) is the boolean true, then the proposition x <= y is true, and if (x <=? y is false then y < x is true. Thus, Nat.leb_spec embodies the specification of the function x <=? y, as its name suggests.
Now using case (Nat.leb_spec a b) does exactly what you were trying to do with case (a <=? b): it gives you two subgoals, one where x <=? y is replaced by true and you have x <= y as an extra hypothesis, and the other where x <=? y is replaced by false and you have y < x as an hypothesis instead. The fact that you case distinction was on a term of type BoolSpec rather than simply bool did the trick.
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 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.
I have the following goal:
∀x ∈ {0,1,2,3,4,5}. P x
I want to break this goal down into the six subgoals P 0, P 1, P 2, P 3, P 4 and P 5. This is easily done by apply auto. But what is the relevant rule that auto is using to do this? I ask because my actual goal looks more like this:
∀x ∈ {0..<6}. P x
and apply auto doesn't break that goal down in the same way (it gives me
⋀x. 0 ≤ x ⟹ x < 6 ⟹ P x
instead).
The rule that auto is using is ballI (bounded all introduction). This transforms ∀x ∈ S. P x into x ∈ S ==> P x.
The issue of transforming x ∈ {0,1,2,3,4,5} into 6 separate subgoals is a separate one. Basically, auto transforms the explicit enumeration into a disjunction and then splits that.
You could use a lemma such as the following to split out a single goal:
lemma expand_ballI: "⟦ (n :: nat) > 0; ∀x ∈ {0..< (n - 1)}. P x; P (n - 1) ⟧ ⟹ ∀x ∈ {0..< n}. P x"
by (induct n, auto simp: less_Suc_eq)
which could then be repeatedly applied to your rule as follows:
lemma "∀x ∈ {0..< 6 :: nat}. P x"
apply (rule expand_ballI, fastforce)+
apply simp_all
resulting in the goals split out as follows:
goal (6 subgoals):
1. P 0
2. P (Suc 0)
3. P 2
4. P 3
5. P 4
6. P 5
Using a [simp] lemma to transform sets into more convenient versions of the set is very convenient. E.g. {0..<6} = {0,1,2,3,4,5}