In Coq, how do I introduce a variable from an hypothesis into the environment? - coq

Let's say I have made an Hypothesis about the existance of a value. How do I name that variable in the environment?
Example:
Require Import ZArith.
Open Scope Z.
Hint Resolve Zred_factor0 Zmult_assoc_reverse Z.mul_comm Z.mul_add_distr_l
Z.mul_1_l Z.mul_0_r Z.mul_0_l Z.abs_nonneg.
Definition divides d n := exists c, d*c = n.
Section divisor.
Variables (d n a:Z).
Hypothesis H: divides d n.
Now I want to introduce c and the fact that d*c = n into the environment, so I don't have to start my proof by destructing H every time, like this:
Lemma div4: divides (a*d) (a*n).
destruct H as [c H']. (*** Here I would like to already have c and H' *)
subst; exists c; auto.
Qed.
End divisor.

There is no way of doing what you want, as far as I know. I think it would be a bit complicated to implement because of the restrictions governing Prop elimination.
In this particular case, one thing you could do would be to name n / d as c in your context, and then prove an auxiliary lemma, using your hypothesis, saying that n = c * d. Then you would still have your hypothesis in the statement of your lemmas, but wouldn't have to destruct it all the time.

Related

Use of contradiction statement

I have two natural numbers a & b. Relation between these numbers exist in the form of hypothesis (H1 H2 H3). I want to extract contradiction from these hypothesis on the basis of which I can close any sub goal.
H1: a<=b
H2: a>=b
H3: a=b.
Your hypothesis are not contradicting: a=b is an obvious solution. Assuming your hypothesis are contradicting, the lia tactic does the job. It can solve any goal on linear integer arithmetic in Z and nat. If you have hypothesis which contradict based on linear integer arithmetic, lia will solve any goal, as in:
Require Import Lia.
Goal forall a b : nat, a<=b -> a>=b -> a<>b -> False.
lia.

How to make algebraic manipulations in Coq easier?

I'm experimenting with Coq's standard libraries for integers and rationals. So far my proofs are very time-consuming and look terrible.
I guess I miss some important proof techniques. Such simple lemmas shouldn't be so long to prove. Any hints?
Here is an example:
Require Import ZArith.
Require Import QArith.
Open Scope Q_scope.
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof. intros. destruct H as [Hl Hr]. rewrite (Zle_Qle x y) in Hr.
rewrite <- (Qmult_le_l (inject_Z x) (inject_Z y) (/ inject_Z (Zpos z))) in Hr. simpl in Hr.
- rewrite Qmult_comm in Hr. rewrite Qmult_comm with (x := / inject_Z (Z.pos z)) in Hr.
unfold inject_Z in Hr. unfold Qinv in Hr. destruct (Qnum (Z.pos z # 1)) eqn:ZV.
+ simpl in ZV. discriminate.
+ simpl in Hr. simpl in ZV. injection ZV. intro ZP. unfold Qmult in Hr. simpl in Hr.
rewrite <- ZP in Hr. rewrite Z.mul_1_r in Hr. rewrite Z.mul_1_r in Hr. exact Hr.
+ simpl in ZV. discriminate.
- unfold Qinv. simpl. apply Z.lt_0_1.
Qed.
I did not have the courage to analyze your lengthy proof, but I see you choose to use a forward proof style. The telltale sign is the fact that you have several rewrite ... in ... in your script. Most libraries of theorems are designed to work in backward proof style.
Contrast this with my proposal for the same proof:
Theorem q_less: forall x y z, (0 <= x <= y)%Z -> x # z <= y # z.
Proof.
intros x y z cmp; rewrite !Qmake_Qdiv.
apply Qmult_le_compat_r.
rewrite <- Zle_Qle; tauto.
apply Qinv_le_0_compat; replace 0 with (inject_Z 0) by easy.
now rewrite <- Zle_Qle; apply Zle_0_pos.
Qed.
Here is how I proceed. First, x # z is a notation for a very specific form of division: the one that appears in a basic fraction. There are many chances that this specific form of division is less well covered by theorems in the library, so I choose to replace it by a regular division between rational numbers. To find the theorem, I just use the Search query with the patterns (_ # _) (_ / _). This gives me Qmake_Qdiv.
Then I simply expect that there is a theorem expressing a <= b -> a / c <= b / c under suitable conditions. I use Search (_ / _ <= _ / _). to find such a theorem. Alas, none is found. So I remember that division is often described as multiplication by the inverse so I search for the other possibility Search (_ * _ <= _ * _). This gives me Qmult_le_compat_r. I try applying it and it works.
Here is what I mean by working in a backward proof style: I look at the conclusion and I think what theorem could help me obtain this conclusion? I will then try to fulfill its conditions.
There are two conditions. The first one is (inject_Z x <= inject_Z y). So now I need a theorem relating comparison in Z and comparison in Q through function inject_Z. To find it I type Search inject_Z (_ <= _). This gives me Qmult_le_compat_r. Please note that your hypothesis is too strong: you don't need x to be positive. The automatic tactic tauto obtains the right condition from your hypothesis (which I named cmp).
The last condition is (0 <= inject_Z (Z.pos z)). I can re-use the same theorem as above, because surely 0 must be the same thing as inject_Z 0.
All this being said, I do not recommend using QArith for mathematical reasoning (the kind of algebraic reasoning that you show here), because it is less well populated than other libraries. If you want to work with numbers and reason on them, you should use math-comp or Reals: you will find more theorems that are already proved for you.

Prove something is less or equal to other thing using induction in COQ

I need to prove that the height of a formula's tree is always less than the number of nodes of the same tree, but I got stuck after the assumption and don't know how to proceed. Can somebody help me fill the "admit." spaces?
Require Import String.
Require Import Init.Nat.
Require Import PeanoNat.
Require Import Plus.
Require Import Le.
Theorem le_plus_trans2 : forall n m p, (n <= m) -> (n <= p + m).
Proof.
intros n m p.
intros x.
apply le_trans with (m:= m).
assumption.
admit.
Qed.
If you Require Import Coq.omega.Omega, you can replace all of your admits with omega.
Alternatively, if you want a less hammer-ful solution, you can replace your admits with
etransitivity; [ eassumption | apply le_plus_l || apply le_plus_r ].
That is, you can use the fact that x <= x + y and that y <= x + y, for x : nat and y : nat.
Edit (after your update of the question). Your question now contains a completely different goal, but this goal can still be solved by the standard arithmetic hammer. If you Require Import Coq.omega.Omega, your entire theorem is proven by intros; omega.
Try using Plus.le_plus_trans and PeanoNat.Nat.add_comm.

Is it possible to jointly recurse on a pair of variables in Coq?

Let's say that I'm trying to prove the following:
Theorem le_s_n : forall n m, S n <= S m -> n <= m.
I feel like it might be productive to perform induction on the pair (n, m). The cases would be something like (0, 0), (0, S m'), (S n', 0), and (S n', S m'). Is this at all possible?
You could have a look at this answer to have a glimpse on lexicographic ordering, but I suggest to read #ejgallego comments, that I totally agree with.

is there a `eapply`-like tactic that works on `exists` goals in Coq?

I have the following during a proof where the goal is an existential, and the target property is one of the assumptions.
H : x ==> y
...
______________________________________(1/2)
exists t : tm, x ==> t
I know I can do exists y. apply H. to prove the current goal, but I am wondering if there is a more intelligent tactic that can use the assumption directly to prove the existential goal here, like eapply H?
Since this is one unification away, it would be nice not having to write the X part in exists X..
If such a tactic does not exist, how do I write one?
There exists such a tactic and it is called eexists.
It does exactly what you seem to expect.
https://coq.inria.fr/distrib/current/refman/Reference-Manual010.html#hevea_tactic23
Example use:
Variable T : Type.
Variable R : T -> T -> Prop.
Theorem test : forall x y, R x y -> exists t, R x t.
Proof.
intros. eexists. apply H.
Qed.