`No more subgoals, but there are non-instantiated existential variables` in Coq proof language? - coq

I was following (incomplete) examples in Coq 8.5p1 's reference manual in chapter 11 about the mathematical/declarative proof language. In the example below for iterated equalities (~= and =~), I got a warning Insufficient Justification for rewriting 4 into 2+2, and eventually got an error saying:
No more subgoals, but there are non-instantiated existential
variables:
?Goal : [x : R H : x = 2 _eq0 : 4 = x * x
|- 2 + 2 = 4]
You can use Grab Existential Variables.
Example:
Goal forall x, x = 2 -> x + x = x * x.
Proof.
proof. Show.
let x:R.
assume H: (x = 2). Show.
have ( 4 = 4). Show.
~= (2*2). Show.
~= (x*x) by H. Show.
=~ (2+2). Show. (*Problem Here: Insufficient Justification*)
=~ H':(x + x) by H.
thus thesis by H'.
end proof.
Fail Qed.
I'm not familiar with the mathematical proof language in Coq and couldn't understand why this happens. Can someone help explain how to fix the error?
--EDIT--
#Vinz
I had these random imports before the example:
Require Import Reals.
Require Import Fourier.

Your proof would work for nat or Z, but it fails in case of R.
From the Coq Reference Manual (v8.5):
The purpose of a declarative proof language is to take the opposite approach where intermediate states are always given by the user, but the transitions of the system are automated as much as possible.
It looks like the automation fails for 4 = 2 + 2. I don't know what kind of automation uses the declarative proof engine, but, for instance, the auto tactic is not able to prove almost all simple equalities, like this one:
Open Scope R_scope.
Goal 2 + 2 = 4. auto. Fail Qed.
And as #ejgallego points out we can prove 2 * 2 = 4 using auto only by chance:
Open Scope R_scope.
Goal 2 * 2 = 4. auto. Qed.
(* `reflexivity.` would do here *)
However, the field tactic works like a charm. So one approach would be to suggest the declarative proof engine using the field tactic:
Require Import Coq.Reals.Reals.
Open Scope R_scope.
Unset Printing Notations. (* to better understand what we prove *)
Goal forall x, x = 2 -> x + x = x * x.
Proof.
proof.
let x : R.
assume H: (x = 2).
have (4 = 4).
~= (x*x) by H.
=~ (2+2) using field. (* we're using the `field` tactic here *)
=~ H':(x + x) by H.
thus thesis by H'.
end proof.
Qed.

The problem here is that Coq's standard reals are defined in an axiomatic way.
Thus, + : R -> R -> R and *, etc... are abstract operations, and will never compute. What does this mean? It means that Coq doesn't have a rule on what to do with +, contrary for instance to the nat case, where Coq knows that:
0 + n ~> 0
S n + m ~> S (n + m)
Thus, the only way to manipulate + for the real numbers it to manually apply the corresponding axioms that characterize the operator, see:
https://coq.inria.fr/library/Coq.Reals.Rdefinitions.html
https://coq.inria.fr/library/Coq.Reals.Raxioms.html
This is what field, omega, etc... do. Even 0 + 1 = 1 is not probable by computation.
Anton's example 2 + 2 = 4 works by chance. Actually, Coq has to parse the numeral 4 to a suitable representation using the real axioms, and it turns out that 4 is parsed as Rmult (Rplus R1 R1) (Rplus R1 R1) (to be more efficient), which is the same than the left side of the previous equality.

Related

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.

How to prove the arithmetic equality `3 * S (i + j) + 1 = S (3 * i + 1) + S (3 * j + 1)` in Coq?

How to prove the equality
3 * S (i + j) + 1 = S (3 * i + 1) + S (3 * j + 1)`
in Coq?
Trying to prove my induction hypothesis in Coq, I need to prove that these sides are equal (which they obviously are).
However, if I remove S on ,e.g., the left-hand side, then I get the natural number 3. But, I don't know how to decompose this into 1 + 1 + 1.
Also, sitting and fidling with Nat.add_assoc and Nat.add_comm is very time consuming and makes me crazy.
There must be some "straightforward" way for a beginner how to prove this using "basic" tactics?
Let's do some automatic proofs first. To compare them with the (much) longer manual proof I came up with.
Require Import
Arith (* `ring` tactic on `nat` and lemmas *)
Omega (* `omega` tactic *)
Psatz. (* `lia`, `nia` tactics *)
Goal forall i j,
3 * S (i + j) + 1 = S (3 * i + 1) + S (3 * j + 1).
Proof.
The ring tactic
The Coq Reference Manual, §8.16.3:
The ring tactic solves equations upon polynomial expressions of a ring (or semi-ring) structure. It proceeds by normalizing both hand sides of the equation (w.r.t. associativity, commutativity and distributivity, constant propagation) and comparing syntactically the results.
intros; ring.
Undo.
The omega tactic
The Coq Reference Manual, §8.16.2:
The tactic omega, due to Pierre Crégut, is an automatic decision procedure for Presburger arithmetic. It solves quantifier-free formulas built with ~, \/, /\, -> on top of equalities, inequalities and disequalities on both the type nat of natural numbers and Z of binary integers. This tactic must be loaded by the command Require Import Omega. See the additional documentation about omega (see Chapter 21).
intros; omega.
Undo.
The lia tactic
The Coq Reference Manual, §22.5:
The tactic lia offers an alternative to the omega and romega tactic (see Chapter 21). Roughly speaking, the deductive power of lia is the combined deductive power of ring_simplify and omega. However, it solves linear goals that omega and romega do not solve, such as the following so-called omega nightmare [130].
intros; lia.
Undo.
The nia tactic
The Coq Reference Manual, §22.6:
The nia tactic is an experimental proof procedure for non-linear integer arithmetic. The tactic performs a limited amount of non-linear reasoning before running the linear prover of lia...
intros; nia.
Undo.
A manual proof
All the above tactics automatically solve the goal. Undo is a Vernacular command that "un-does" a step, it allows us to restart the proof from the beginning, the same effect in this case could've been achieved using the Restart command.
Now, let's do a manual proof. I didn't delete the Search commands I used to find the necessary lemmas for didactic reasons. Frankly, I don't use them too often and do not remember their names -- it much easier to use the automatic tactics.
One of the main difficulties (at least for me) is to "focus" on the subexpression of the goal I want to make a rewrite in.
For that purpose we can use the replace ... with ... tactic (see an example below) and symmetry (to some extent). symmetry turns a goal of the form a = b into b = a -- it allows you to rewrite in b rather than in a.
Also, rewrite !<lemma> helps a lot too -- the exclamation point means "do rewrites as many times as possible".
intros.
Search (S (?n + ?m) = ?n + S ?m).
rewrite !plus_n_Sm.
rewrite <- Nat.add_assoc.
Search (?n + (?m + ?p) = ?m + (?n + ?p)).
rewrite Nat.add_shuffle3.
symmetry.
rewrite Nat.add_comm.
rewrite Nat.add_assoc.
Search (?k * ?x + ?k * ?y).
rewrite <- Nat.mul_add_distr_l.
replace (S j) with (j + 1) by now rewrite Nat.add_comm.
rewrite Nat.add_assoc.
symmetry.
rewrite Nat.mul_add_distr_l.
rewrite <- !Nat.add_assoc.
reflexivity.
Qed.
The above manual proof can be compressed into this equivalent form:
intros.
rewrite !plus_n_Sm, <- Nat.add_assoc, Nat.add_shuffle3.
symmetry.
rewrite Nat.add_comm, Nat.add_assoc, <- Nat.mul_add_distr_l.
replace (S j) with (j + 1) by now rewrite Nat.add_comm.
rewrite Nat.add_assoc. symmetry.
now rewrite Nat.mul_add_distr_l, <- !Nat.add_assoc.
You can use one of the automatic tactics for arithmetic:
Require Import Coq.omega.Omega.
Lemma U i j : 3 * S (i + j) + 1 = S (3 * i + 1) + S (3 * j + 1).
now omega.
Qed.
Indeed some of these proofs are very time consuming, see the Coq manual for more details about the existing tactics. If you want to do the proof manually, I'd proceed as:
simpl; rewrite !add_0_r, !add_1_r, !add_succ_r, !add_assoc; simpl.
and add to my auxiliary library a few interchange lemmas.

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.

rewrite works for integer but not for rationals for Coq aac_tactics

I was testing Coq rewrite tactics modulo associativity and commutativity (aac_tactics). The following example works for integer (Z), but generates an error when integers are replaced by rationals (Q).
Require Import ZArith.
Import Instances.Z.
Goal (forall x:Z, x + (-x) = 0)
-> forall a b c:Z, a + b + c + (-(c+a)) = b.
intros H ? ? ?.
aac_rewrite H.
When replacing Require Import ZArith. with Require Import QArith. etc., there is an error:
Error: Tactic failure: No matching occurence modulo AC found.
at aac_rewrite H.
There was a similar inconsistency issue between Z and Q, which turned out to be related to whether the Z/Q scope is open.
But I don't understand why aac rewrite didn't work here. What's the cause of the inconsistency, and how can one make it behave the same for Z and Q?
The AAC_tactics library needs theorems which express associativity, commutativity and so forth. Let's take Qplus_assoc which expresses the associativity law for the rational numbers.
Qplus_assoc
: forall x y z : Q, x + (y + z) == x + y + z
As you can see Qplus_assoc doesn't use =, it uses == to express the connection between the left-hand side and the right-hand side. Rationals are defined in the standard library as pairs of integers and positive numbers:
Record Q : Set := Qmake {Qnum : Z; Qden : positive}.
Since, e.g. 1/2 = 2/4, we need some other way of comparing the rationals for equality (other than = which is the notation for eq). For this reason the stdlib defines Qeq:
Definition Qeq (p q : Q) := (Qnum p * QDen q)%Z = (Qnum q * QDen p)%Z.
with notation
Infix "==" := Qeq (at level 70, no associativity) : Q_scope.
So, in case of rational numbers you might want to rewrite your example to something like this:
Require Import Coq.QArith.QArith.
Require Import AAC_tactics.AAC.
Require AAC_tactics.Instances.
Import AAC_tactics.Instances.Q.
Open Scope Q_scope.
Goal (forall x, x + (-x) == 0) ->
forall a b c, a + b + c + (-(c+a)) == b.
intros H ? ? ?.
aac_rewrite H.
Search (0 + ?x == ?x).
apply Qplus_0_l.
Qed.

Stuck in the construction of a very simple function

I am learning Coq. I am stuck on a quite silly problem (which has no motivation, it is really silly). I want to build a function from ]2,+oo] to the set of integers mapping x to x-3. That should be simple... In any language I know, it is simple. But not in Coq. First, I write (I explain with a lot of details so that someone can explain what I don't understand in the behaviour of Coq)
Definition f : forall n : nat, n > 2 -> nat.
I get a subgoal
============================
forall n : nat, n > 2 -> nat
which means that Coq wants a map from a proof of n>2 to the set of integers. Fine. So I want to tell it that n = 3 + p for some integer p, and then return the integer p. I write :
intros n H.
And I get the context/subgoal
n : nat
H : n > 2
============================
nat
Then i suppose that I have proved n = 3 + p for some integer p by
cut(exists p, 3 + p = n).
I get the context/subgoal
n : nat
H : n > 2
============================
(exists p : nat, 3 + p = n) -> nat
subgoal 2 (ID 6) is:
exists p : nat, 3 + p = n
I move the hypothesis in the context by
intro K.
I obtain:
n : nat
H : n > 2
K : exists p : nat, 3 + p = n
============================
nat
subgoal 2 (ID 6) is:
exists p : nat, 3 + p = n
I will prove the existence of p later. Now I want to finish the proof by exact p. So i need first to do a
destruct K as (p,K).
and I obtain the error message
Error: Case analysis on sort Set is not allowed for inductive
definition ex.
And I am stuck.
You are absolutely right! Writing this function should be easy in any reasonable programming language, and, fortunately, Coq is no exception.
In your case, it is much easier to define your function by simply ignoring the proof argument you are supplying:
Definition f (n : nat) : nat := n - 3.
You may then wonder "but wait a second, the natural numbers aren't closed under subtraction, so how can this make sense?". Well, in Coq, subtraction on the natural numbers isn't really subtraction: it is actually truncated. If you try to subtract, say, 3 from 2, you get 0 as an answer:
Goal 2 - 3 = 0. reflexivity. Qed.
What this means in practice is that you are always allowed to "subtract" two natural numbers and get a natural number back, but in order for this subtraction make sense, the first argument needs to be greater than the second. We then get lemmas such as the following (available in the standard library):
le_plus_minus_r : forall n m, n <= m -> n + (m - n) = m
In most cases, working with a function that is partially correct, such as this definition of subtraction, is good enough. If you want, however, you can restrict the domain of f to make its properties more pleasant. I've taken the liberty of doing the following script with the ssreflect library, which makes writing this kind of function easier:
Require Import Ssreflect.ssreflect Ssreflect.ssrfun Ssreflect.ssrbool.
Require Import Ssreflect.ssrnat Ssreflect.eqtype.
Definition f (n : {n | 2 < n}) : nat :=
val n - 3.
Definition finv (m : nat) : {n | 2 < n} :=
Sub (3 + m) erefl.
Lemma fK : cancel f finv.
Proof.
move=> [n Pn] /=; apply/val_inj=> /=.
by rewrite /f /= addnC subnK.
Qed.
Lemma finvK : cancel finv f.
Proof.
by move=> n; rewrite /finv /f /= addnC addnK.
Qed.
Now, f takes as an argument a natural number n that is greater than 2 (the {x : T | P x} form is syntax sugar for the sig type from the standard library, which is used for forming types that work like subsets). By restricting the argument type, we can write an inverse function finv that takes an arbitrary nat and returns another number that is greater than 2. Then, we can prove lemmas fK and finvK, which assert that fK and finvK are inverses of each other.
On the definition of f, we use val, which is ssreflect's idiom for extracting the element out of a member of a type such as {n | 2 < n}. The Sub function on finv does the opposite, packaging a natural number n with a proof that 2 < n and returning an element of {n | 2 < n}. Here, we rely crucially on the fact that the < is expressed in ssreflect as a boolean computation, so that Coq can use its computation rules to check that erefl, a proof of true = true, is also a valid proof of 2 < 3 + m.
To conclude, the mysterious error message you got in the end has to do with Coq's rules governing computational types, with live in Type, and propositional types, which live in Prop. Coq's rules forbid you from using proofs of propositions to build elements that have computational content (such as natural numbers), except in very particular cases. If you wanted, you could still finish your definition by using {p | 3 + p = n} instead of exists p, 3 + p = n -- both mean the same thing, except the former lives in Type while the latter lives in Prop.