Coq: viewing proof term during proof script writing - coq

So, I've got a proof that looks like this:
induction t; intros; inversion H ; crush.
It solves all my goals, but when I do Qed, I get the following error:
Cannot guess decreasing argument of fix.
So somewhere in the generated proof term, there's non-well-founded recursion. The problem is, I have no idea where.
Is there a way to debug this kind of error, or to see the (possibly non halting) proof term that the tactics script generates?

You can use Show Proof. to view the proof term so far.
Another command that can help with seeing where the recursion went wrong is Guarded., which runs the termination checker on the proof term so far. You'll need to break apart the tactic script into independent sentences to use it, though. Here's an example:
Fixpoint f (n:nat) : nat.
Proof.
apply plus.
exact (f n).
Guarded.
(* fails with:
Error:
Recursive definition of f is ill-formed.
...
*)
Defined.

You can use the Show Proof. command inside proof mode to print the proof term produced so far.

In addition to the other excellent answers, I also want to point out that using induction inside an interactive-mode Fixpoint is usually a mistake, because you're recursing twice. Writing fixpoints in interactive mode is often tricky because most automation tools will happily make a recursive call at every possible opportunity, even when it would be ill-founded.
I would advise to use Definition instead of Fixpoint and use induction in the proof script. This invokes the explicit recursor, which allows for much better control of automation. The disadvantage is decreased flexibility since fixpoints have fewer restrictions than recursors - but as we've seen, that is both a blessing and a curse.

Related

Why does Coquelicot mess with my bullets?

Suppose I write the following lemma and proof in Coq:
Lemma foo : forall A, A -> A.
Proof.
- simpl.
- auto.
Qed.
The simpl here doesn't do anything, and this is a bad use of bullet points (-). When I try to compile this with coqc, I get the following complaint:
Error: [Focus] Wrong bullet -: Current bullet - is not finished.
It's clear to me why this error happens. When I open the second bullet point for auto, it complains that I didn't finish the first bullet point. However, what doesn't make sense to me is that this code compiles fine:
From Coquelicot Require Import Complex.
Lemma foo : forall A, A -> A.
Proof.
- simpl.
- auto.
Qed.
It seems that the act of importing from Coquelicot makes it so that bullet points are completely ignored. A couple questions:
Why does this happen? Is this some sort of bug?
Is there a way to disable this behavior? I would like to use Coquelicot and still have proper bullet point usage be checked.
I'm currently using Coq 8.13.2 compiled with OCaml 4.10.2, and Coquelicot 3.2.0.
Coquelicot depends on MathComp and MathComp disables the conventional meaning of bullets (because they use them differently). However, instead of doing this locally to the MathComp project, they set an option globally, and that's why you get this behavior.
To retrieve the expected behavior, you need to reset the option to the default value like this:
Set Bullet Behavior "Strict Subproofs".
(cf. https://coq.inria.fr/refman/proofs/writing-proofs/proof-mode.html#coq:opt.Bullet-Behavior)

Trivial lemma on real numbers on Coq

I want to prove following lemma.
Require Import Reals.Reals.
Open Scope R_scope.
Lemma trivial_lemma (r1 r2:R) : r1 - (r1 - r2) = r2.
Proof.
rewrite <- Ropp_minus_distr.
rewrite Ropp_plus_distr.
rewrite Ropp_involutive.
rewrite Ropp_minus_distr'.
Abort.
I know Rplus_opp_l, but I cannot apply it to my goal because of r2.
Please tell me your solution.
First you should know that the automatic tactic ring solves this kind of goals autommatically. In the long run, you should rely on this tactic often if you wish to be productive.
Second, it appears (through Search) that the library does not contain many lemmas about subtraction. In this case, you may have to unfold this operator to end up with a goal that has the more primitive addition and opposite operations. Here is a sequence of rewrites that does your work.
unfold Rminus.
rewrite Ropp_plus_distr.
rewrite Ropp_involutive.
rewrite <- Rplus_assoc.
rewrite Rplus_opp_r.
rewrite Rplus_0_l.
easy.
The fact that the library does not contain basic lemmas like this is an indication that the library designers intend users to rely more on the ring tactic.

Show theorem definition in Coq

I'd like to view the definition of a Standard Library theorem which I found through Search. I think seeing the definition will help me complete a similar theorem.
Doing Print Rdiv_lt_0_compat. yields:
Rdiv_lt_0_compat =
fun (a b : R) (H : (0 < a)%R) (H0 : (0 < b)%R) =>
Rmult_lt_0_compat a (/ b) H (Rinv_0_lt_compat b H0)
: forall a b : R, (0 < a)%R -> (0 < b)%R -> (0 < a / b)%R
Argument scopes are [R_scope R_scope _ _]
Setting Set Printing All. doesn't help. There's nothing extra available in the docs page.
The whole Coq system is based on the idea Proofs are programs, logical formulas are types. When you consider a theorem, it is a proof (a program) and its statement is a logical formula (the type of a program). In the very
first years of Coq, there was no tactic language, every proof was defined using the same keywords as when defining a program.
After a few years, it was recognized that writing the programs entirely by hand was long and tiresome, so a tactic language was invented to explain how to construct the proof-programs in a shorter and less difficult way. But what is recorded and eventually checked are still the programs that you see using Print.
When building a proof-program, the tactic intros constructs anonymous function expressions (also known as lambdas, usually written with the keyword fun, and apply constructs an application of a function to a certain number arguments, which apply infers or leaves to the user as goals. The tactics induction and rewrite are similar, but they apply theorems that are not
given by the user. The tactic destruct essentially produces a piece of programs that is a pattern-matching construct.
With Rdiv_lt_0_compat, you are lucky that the proof built by the tactic is quite short. Often, proofs written using tactics produce programs that are much longer.
If instead of the program, you want to see the sequence of tactics that generated it, you need to find it in the sources of the system, because this
is not kept in the memory of the proof assistant. Here are the clues.
Require Import Reals.
Locate Rdiv_lt_0_compat.
the answer is Constant Coq.Reals.RIneq.Rdiv_lt_0_compat
This sequence of names indicates the hierarchy of modules in which the theorem is kept. The first name Coq expresses that this theorem is in the Coq sources, essentially in directory ...theories/, the second name Reals, indicates that you should look in tge sub directory ...theories/Reals.
The fourth name should not be used as a directory name, but as file name. So you should look in the file RIneq.v
So go an look in https://github.com/coq/coq/tree/v8.12/theories/Reals/RIneq.v and you will probably find the script fragment that was used to generate your theorem (for the 8.12 version of Coq). I just checked, the theorem appears at line https://github.com/coq/coq/blob/c95bd4cf015a3084a8bddf6d3640458c9c25b455/theories/Reals/RIneq.v#L2106
The sequence of names provided by Locate is not a sure way to find the file where the script for a theorem is stored. The correspondence between the long name and the file path is broken when the theorem is defined using modules and functor instantiation. In that case, you have to rely on stronger knowledge of how the Coq system works.

interactive theorem proving with no specified goal

What's the best approach to do interactive theorem proving in Coq without specifying a Theorem definition first? I'd like to state some initial assumptions and definitions, and then interactively explore transformations to see if I can prove any interesting theorems without knowing them ahead of time. I'd like Coq to help me keep track of the transformed assumptions and check that my rewrites are valid, like when proving explicit theorems in interactive mode. Does Coq have support for this use case?
One convenient method is to use the Variable/Hypothesis commands (they do the same thing) to add assumptions and introduce example objects (eg, Variable n:nat. introduces a nat you can now work with). Then to get into theorem proving mode what I do occasionally is Goal False. to start proving False, just to make sure I don't accidentally prove the theorem. You can also assert and admit things to get additional assumptions without restarting the proof.

when is the `:` (colon) in necessary in ssreflect/Coq?

I am trying to understand the exact meaning of the : (colon) in Coq/ssreflect proofs in terms of non-ssreflect Coq.
I read that it has something to do with moving things to the goal (like generalize??) and is the opposite of =>, which move things to the hypotheses. However, I often find it confusing because proofs work either way with or without the :. Below is an example from a tutorial:
Lemma tmirror_leaf2 t : tmirror (tmirror t) = Leaf -> t = Leaf.
Proof.
move=> e.
by apply: (tmirror_leaf (tmirror_leaf e)).
Qed.
where,
tmirror_leaf
: forall t, tmirror t = Leaf -> t = Leaf
is a lemma that says if the mirror of a tree is a leaf, then the tree is a leaf.
I don't understand why we need the : here and not merely do the Coq apply. In fact, if I remove the :, it works just fine. Why does it make a difference?
Indeed, apply: H1 ... Hn is to all effects equivalent to move: H1 .. Hn; apply. A more interesting use of apply is apply/H and its variations, which can interpret views.
I think I found the answer while reading the SSReflect documentation. Essentially, ssr has redefined tactics like apply such that it operates on the first variable of the goal instead of something in the context. That's why the : is used in apply: XX. in the ssr way (which is equivalent to move: XX; apply.), and it also works if : is omitted as that is the traditional Coq way.
Quoting the documentation:
Furthermore, SSReflect redefines the basic Coq tactics case, elim, and
apply so that they can take better advantage of ':' and '=>'. These
Coq tactics require an argument from the context but operate on the
goal. Their SSReflect counterparts use the first variable or constant
of the goal instead, so they are "purely deductive":
they do not use or change the proof context. There is no loss since
`:' can readily be used to supply the required variable.