How I can convert the relation between two terms in Coq - coq

I have less than relationship between two terms (S i2) < i1. May I write it in the form of less or equal (a1<=a2).

You can Search for relevant lemmas:
Require Import Arith.
Search (_ < _) (_ <= _).
If you wish to preserve the same information, you have two options:
Do a case analysis on i1:
1.1. if it's 0 then you have an impossible statement, since there is no natural number smaller than zero. To look for this fact, Search (_ < 0) provides Nat.nlt_0_r.
1.2. if it's a successor, say S i1', then your statement becomes S i2 < S i1'. From our Search above, we found Nat.lt_succ_r, so we can rewrite our S i2 < S i1' to S i2 <= i1'.
Use Nat.lt_le_pred directly, but this will lead to S i2 <= Nat.pred i1, and the predecessor of i1 may or may not be useful to you.
Alternatively, if you know S i2 < i1 but you only care that S i2 <= i2, ie, you want to weaken your hypothesis, you can use Nat.lt_le_incl.

These terms are not fully equivalent, but the first is stronger than the second, using transitivity with the weakening i2 <= S (S i2) does suffice:
Require Import PArith PeanoNat.
Lemma example a b : S a < b -> a <= b.
Proof.
assert (a <= S (S a)).
now apply Le.le_Sn_le, Le.le_Sn_le.
exact (Nat.le_trans _ _ _ H).
Qed.
Recall that a < b is notation for S a <= b. You can also just weaken directly in backwards-chaining style.
Lemma example2 a b : S a < b -> a <= b.
Proof. now intros hlt; apply Nat.lt_le_incl, Nat.lt_le_incl. Qed.

Except for early stages of learning Coq, I would recommend the lia tactic:
Require Import PArith PeanoNat.
Require Import Lia.
Lemma example a b : S a < b -> a <= b.
Proof.
intros H.
lia.
Qed.

Related

Why unable to perform case analysis in rather simple case

Well, the code
From mathcomp Require Import ssreflect ssrnat ssrbool eqtype.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Inductive nat_rels m n : bool -> bool -> bool -> Set :=
| CompareNatLt of m < n : nat_rels m n true false false
| CompareNatGt of m > n : nat_rels m n false true false
| CompareNatEq of m == n : nat_rels m n false false true.
Lemma natrelP m n : nat_rels m n (m < n) (m > n) (m == n).
Proof.
case (leqP m n); case (leqP n m).
move => H1 H2; move: (conj H1 H2) => {H1} {H2} /andP.
rewrite -eqn_leq => /eqP /ssrfun.esym /eqP H.
by rewrite H; constructor.
move => H. rewrite leq_eqVlt => /orP.
case.
Error is Error: Case analysis on sort Set is not allowed for inductive definition or.
The last goal before the case is
m, n : nat
H : m < n
============================
m == n \/ m < n -> nat_rels m n true false (m == n)
I've already used this construction (rewrite leq_eqVlt => /orP; case) in very similar situation and it just worked:
Lemma succ_max_distr n m : (maxn n m).+1 = maxn (n.+1) (m.+1).
Proof.
wlog : m n / m < n => H; last first.
rewrite max_l /maxn; last by exact: ltnW.
rewrite leqNgt.
have: m.+1 < n.+2 by apply: ltnW.
by move => ->.
case: (leqP n m); last by apply: H.
rewrite leq_eqVlt => /orP. case.
What is the difference between two cases?
and Why "Case analysis on sort Set is not allowed for inductive definition or"?
The difference between the two cases is the sort of the goal (Set vs Prop) when you execute the case command. In the first situation your goal is nat_rels ... and you declared that inductive in Set; in the second situation your goal is an equality that lands in Prop.
The reason why you can't do a case analysis on \/ when the goal is in Set (the first situation) is because \/ has been declared as Prop-valued. The main restriction associated to such a declaration is that you cannot use informative content from a Prop to build something in Set (or more generally Type), so that Prop is compatible with an erasure-semantic at extraction time.
In particular, doing a case analysis on \/ gives away the side of the \/ that is valid, and you can't be allowed to use that information for building some data in Set.
You have at least two solutions at your disposal:
You could move your family nat_rels from Set to Prop if that's compatible with what you want to do later on.
Or you could use the fact that the hypothesis that you want to branch on is decidable and find a way to produce some {m == n} + { m <n } out of m <= n; here the notation { _ } + { _ } is the Set-valued disjunction of proposition.

how to simplify basic arithmetic in more complex goals

Here's a minimal example of my problem
Lemma arith: forall T (G: seq T), (size G + 1 + 1).+1 = (size G + 3).
I would like to be able to reduce this to
forall T (G: seq T), (size G + 2).+1 = (size G + 3).
by the simplest possible means. Trying simpl or auto immediately does nothing.
If I rewrite with associativity first, that is,
intros. rewrite - addnA. simpl. auto.,
simpl and auto still do nothing. I am left with a goal of
(size G + (1 + 1)).+1 = size G + 3
I guess the .+1 is "in the way" of simpl and auto working on the (1+1) somehow. It seems like I must first remove the .+1 before I can simplify the 1+1.
However, in my actual proof, there is a lot more stuff than the .+1 "in the way" and I would really like to simplify my copious amount of +1s first. As a hack, I'm using 'replace' on individual occurrences but this feels very clumsy (and there are a lot of different arithmetic expressions to replace). Is there any better way to do this?
I am using the ssrnat library.
Thanks.
Coq has a ring and ring_simplify tactic for this kind of work. Sorry for my ssreflect ignorant intros, but this works:
From mathcomp Require Import all_ssreflect.
Lemma arith: forall T (G: seq T), (size G + 1 + 1).+1 = (size G + 3).
Proof.
intros.
ring.
Qed.
There is also a field and field_simplify. For inequalities there are lia and lra, but I am not sure if these work in mathcomp - for lia you might need this (https://github.com/math-comp/mczify) but it might be integrated meanwhile.
There are many lemmas in ssrnat to reason about addition. One possible solution to your problem is the following:
From mathcomp Require Import all_ssreflect.
Lemma arith: forall T (G: seq T), (size G + 1 + 1).+1 = (size G + 3).
Proof. by move=> T G; rewrite !addn1 addn3. Qed.
where
addn1 : forall n, n + 1 = n.+1
addn3 : forall n, n + 3 = n.+3 (* := n.+1.+1.+1 *)
You can use the Search command to look for lemmas related to certain term patterns. For instance, Search (_ + 1) returns, among other things, addn1.

What's the difference between logical (Leibniz) equality and local definition in Coq?

I am having trouble understanding the difference between an equality and a local definition. For example, when reading the documentation about the set tactic:
remember term as ident
This behaves as set ( ident := term ) in * and
using a logical (Leibniz’s) equality instead of a local definition
Indeed,
set (ca := c + a) in *. e.g. generates ca := c + a : Z in the context, while
remember (c + a ) as ca. generates Heqca : ca = c + a in the context.
In case 2. I can make use of the generated hypothesis like rewrite Heqca., while in case 1., I cannot use rewrite ca.
What's the purpose of case 1. and how is it different from case 2. in terms of practical usage?
Also, if the difference between the two is fundamental, why is remember described as a variant of set in the documentation (8.5p1)?
You could think of set a := b + b in H as rewriting H to be:
(fun a => H[b+b/a]) (b+b)
or
let a := b + b in
H[b+b/a]
That is, it replaces all matched patterns b+b by a fresh variable a, which is then instantiated to the value of the pattern. In this regard, both H and the rewrited hypotheses remain equal by "conversion".
Indeed, remember is in a sense a variant of set, however its implications are very different. In this case, remember will introduce a new proof of equality eq_refl: b + b = b + b, then it will abstract away the left part. This is convenient for having enough freedom in pattern matching etc... This is remember in terms of more atomic tactics:
Lemma U b c : b + b = c + c.
Proof.
assert (b + b = b + b). reflexivity.
revert H.
generalize (b+b) at 1 3.
intros n H.
In addition to #ejgallego's answer.
Yes, you cannot rewrite a (local) definition, but you can unfold it:
set (ca := c + a) in *.
unfold ca.
As for the differences in their practical use -- they are quite different. For example, see this answer by #eponier. It relies on the remember tactic so that induction works as we'd like to. But, if we replace remember with set it fails:
Inductive good : nat -> Prop :=
| g1 : good 1
| g3 : forall n, good n -> good (n * 3)
| g5 : forall n, good n -> good (n + 5).
Require Import Omega.
The variant with remember works:
Goal ~ good 0.
remember 0 as n.
intro contra. induction contra; try omega.
apply IHcontra; omega.
Qed.
and the variant with set doesn't (because we didn't introduce any free variables to work with):
Goal ~ good 0.
set (n := 0). intro contra.
induction contra; try omega.
Fail apply IHcontra; omega.
Abort.

Apply partially instantiated lemma

Let us assume that we want to prove the following (totally contrived) lemma.
Lemma lem : (forall n0 : nat, 0 <= n0 -> 0 <= S n0) -> forall n, le 0 n.
We want to apply nat_ind to prove it. Here is a possible proof:
Proof.
intros H n. apply nat_ind. constructor. exact H.
Qed.
But why not directly using H in the apply tactic, using something like apply (nat_ind _ _ H) or eapply (nat_ind _ _ H) ? But the first one fails, and the second one hides the remaining goal in an existential variable.
Is it possible in apply or its derivatives to skip hypotheses in order to specify the other arguments while keeping them as classic goals in the remainder of the proof ?
If you do
intros. refine (nat_ind _ _ H _).
then you only have
0 <= 0
left. Is that useful in your case?
Another approach (more universal than in my other answer) would be using the apply ... with ... construct, like this:
intros H n.
apply nat_ind with (2 := H).
Here, 2 is referring to the inductive step parameter of nat_ind (see the Coq v8.5 reference manual, 8.1.3):
In a bindings list of the form (ref_1 := term_1) ... (ref_n := term_n), ref is either an ident or a num. ... If ref_i is some number n, this number denotes the n-th non dependent premise of the term, as determined by the type of term.
This partial proof
intros H n.
apply nat_ind, H.
will give you 0 <= 0 as the only subgoal left.
This approach uses the apply tactic, but does not answer the question in its generality, since it will work only if you want to instantiate the last parameter (which is the case for the example in the question).
Here is quote from the Coq reference manual:
apply term_1 , ... , term_n
This is a shortcut for apply term_1 ; [ .. | ... ; [ .. | apply term_n ]... ], i.e. for the successive applications of term_(i+1) on the last subgoal generated by apply term_i, starting from the application of term_1.
Also, since it's just syntactic sugar, the solution may be considered cheating (and, I guess, abuse of the original intent of the Coq tactics developers) in the context of the question.

How to prove a goal from contradictory hypotheses?

I have hypotheses i <= 0 and i >= 2 in my context. How can I prove my goal? are there tactics for this?
You can solve this automatically with Omega tactic.
Require Import Omega.
Open Scope Z_scope.
Lemma xxx : forall i : Z, i <= 0 -> i >= 2 -> False.
Proof.
intros.
omega.
Qed.
If you are interested in the content of a proof, rather than just "is it true or false", here is a script "by hand" which details one way to prove this proposition. By the way, since the OP didn't give the type of i, I first assume it is a natural number.
Lemma xxx : forall i : nat, i <= 0 -> i >= 2 -> False.
Proof.
intros i h_i_O h_2_i.
assert (h_2_O: 2 <= 0).
- apply le_trans with i.
+ exact h_2_i. (* i >= 2 is just a notation for 2 <= i *)
+ exact h_i_O.
- apply le_Sn_O in h_2_O.
contradiction.
Qed.
The idea is to say: if 2 <= i <= 0 then 2 <= 0 and it is impossible that any number of the shape S n is less or equal than 0.
If you need the same result on Z:
Lemma yyy : forall i : Z, i <= 0 -> i >= 2 -> False.
Proof.
intros i h_i_O h_2_i.
assert (h_2_O: 2 <= 0).
- apply Zle_trans with i.
+ apply Z.ge_le; exact h_2_i. (* here we first need to switch the direction of <= by hand *)
+ exact h_i_O.
- vm_compute in h_2_O.
apply h_2_O; reflexivity.
Qed.
The main difference is how both <= operators le and Z.le are defined. Z.le is build on top of a decidable function Z.compare (a.k.a. ?=) (basically, Z.le a b means Z.compare a b <> Gt) so the vm_compute invocation asks Z.compare to compute the result of 2 ?= 0, which is Gt (2 is greater than 0), so you end up having the hypothesis Gt = Gt -> False which is used to close the goal.
There are other ways to prove it, you should have a look at the libraries about nat and Z. You can also compare these script with the one generated by Omega by printing (Print xxx) the content of the proof after the Qed.
Best,
V.