Can't automate a lemma that works manually in Coq - coq

(It seems that my previous question had too much irrelevant information, so I tried to abstract away the details. I'm not sure it's still the same problem, but I'll delete the other question if the same solution works for both.)
I'm trying to reason about some custom-defined lists and predicates :
Inductive alphabet := A.
Definition sentence : Type := list alphabet.
Variable pred1 : sentence -> Prop.
Variable pred2 : sentence -> Prop.
Variable conclusion : Prop.
Now, with the following hypotheses,
Hypothesis H1 : forall (X : sentence),
pred1 X -> pred2 (X ++ X).
Hypothesis H2 : forall X,
pred2 X -> conclusion.
I want to prove
Example manual : pred1 [A] -> conclusion.
Which is obviously true, since conclusion follows whenever some sentence has pred2, and pred1 for any sentence implies that the repetition of that sentence has pred2. A hand-written proof would be
intro. eapply H2. apply H1. exact H. Qed.
Notice that the proof uses nothing but intro, apply, eapply, and exact. This means that the proof should allow a straightforward automation, as long as H1 and H2 are available in the context. For instance, a semi-automatic version
Example semiauto : pred1 [A] -> conclusion.
pose proof H1. pose proof H2. eauto. Qed.
works exactly as you would expect. Now, let's try a fully automated version with hints :
Hint Resolve H1 H2.
Example auto : pred1 [A] -> conclusion.
eauto.
intro.
eauto.
eapply H2.
eauto.
apply H1.
eauto. Qed.
This is strange. eauto fails not only in the beginning, but for every step except the last. Why does this happen?
Some guesses : the consequent of H1 includes the form X ++ X, which might be causing problems with unification. Perhaps Coq performs some implicit cleanup with H1 when it is explicitly introduced to context, but not when it's just in hint DB.
Any ideas?

The issue is transparency of sentence.
Building on Anton Trunov's answer, if you look very closely, you'll notice that a difference between Print HintDb core and Create HintDb foo. Print HintDb foo. is that Print HintDb core says
Unfoldable variable definitions: none
Unfoldable constant definitions: none
while Create HintDb foo. Print HintDb foo. says
Unfoldable variable definitions: all
Unfoldable constant definitions: all
I constructed the following simplified version of your example:
Require Import Coq.Lists.List.
Import ListNotations.
Definition sentence := list nat.
Variable pred1 : sentence -> Prop.
Variable pred2 : sentence -> Prop.
Hypothesis H1 : forall (X : sentence),
pred1 X -> pred2 (X ++ X).
Create HintDb foo.
Hint Resolve H1 : foo.
Hint Resolve H1 : bar.
Hint Resolve H1.
Example ex1 : pred1 [0] -> exists X, pred2 X.
eexists.
debug eauto.
Here, we have that eauto and eauto with bar (and eauto with bar nocore, which removes the core database from eauto's consideration) both fail, but eauto with foo (and eauto with foo nocore) succeeds. This suggests that the issue is transparency. A bit of playing around resulted in me discovering that eauto will work if we write
Hint Transparent sentence.
Additionally, even without this, eauto works fine if we explicitly give the X variable the unfolded type:
Example ex2 : pred1 [0] -> exists X : list nat, pred2 X.
I am not entirely sure why Coq behaves this way... perhaps it is refusing to unify evars with terms which are of different types (if ?X has type sentence when X ++ X has type list), or perhaps it is a holdover of meta-based unification... I've opened an issue on the bugtracker about this lack of documentation / bad behavior.

A possible workaround here is to add the hints to a new user-defined database:
Create HintDb my_hints.
Hint Resolve H1 H2 : my_hints.
Now we can finish the proof:
Example auto : pred1 [A] -> conclusion.
eauto with my_hints. Qed.
One more thing: Coq's reference manual tells (ยง8.9.1) us that
One can optionally declare a hint database using the command Create HintDb. If a hint is added to an unknown database, it will be automatically created.
But if we omit the Create HintDb my_hints. part, the eauto tactic won't work. It looks like the same thing is going on when the hints are being added to the default core hint database.

Related

Remove useless hypothesis from context

Sometimes I have a hypothesis in my proof context that I've used already, and now I know I won't need it anymore. In order to keep my context tidy while I work on the proof, I'd like to remove this hypothesis. Is there a tactic to do that?
If you use the SSReflect proof language, you can clear an hypothesis H by using the {H} notation. This can be done inline after many tactics such as move or rewrite, as in:
rewrite foo bar => {H}
Use the clear tactic:
Before:
1 goal
stuff ...
H : T
============================
goal
clear H.
After:
1 goal
stuff ...
============================
goal

Can any additional axiom make Coq Turing complete?

Here I mean axiom as what we can define with the Axiom keyword in Coq Gallina, not with such command-line argument passing to Coq.
I know some axioms make Coq inconsistent. However, AFAIK they don't make Coq Turing complete. In my rough understanding, it's because they don't offer any additional computational behavior.
Is there one that makes Coq turning complete? If not, could you give a more concrete explanation of why it's impossible?
The answer to your question largely depends on where you want your functions defined in Coq to compute. In general, there is no problem to encode arbitrary partial functions in Coq using for instance step-indexing, see Mc Bride's "Turing completeness, totally free" for more details.
But you will only be able to evaluate these functions up to a specified finite bound in Coq.
If the goal is to write formally verified programs that could use arbitrary recursion and run them outside of Coq, then you don't need axioms, you can use the Extraction mechanism and its proof-erasure semantics as shown by the following example of an unbounded while loop:
Inductive Loop : Prop := Wrap : Loop -> Loop.
Notation next := (fun l => match l with Wrap l' => l' end).
Definition while {A : Type} (f : A -> A * bool) : Loop -> A -> A :=
fix aux (l : Loop) (a : A) {struct l} :=
let '(x, b) := f a in
if b then aux (next l) x else x.
Require Extraction.
Recursive Extraction while.
with extraction result:
type bool =
| True
| False
type ('a, 'b) prod =
| Pair of 'a * 'b
(** val while0 : ('a1 -> ('a1, bool) prod) -> 'a1 -> 'a1 **)
let rec while0 f x =
let Pair (x0, b) = f x in (match b with
| True -> while0 f x0
| False -> x0)
Note that the function while requires a proof of termination in Coq that is erased once it is turned to ocaml.
Finally, as you explain, you would need to extend Coq's computational reduction machinery if you wanted evaluation of partial functions to stay inside Coq. There is no general mechanism providing this feature at the moment (even though there is a coq enhancement proposal to add rewriting rules). It might be possible to abuse definitional UIP to evaluate partial functions. In all cases, adding the possibility to evaluate partial functions inside Coq, making it part of the conversion, automatically entails that the theory itself because undecidable (the proof assistant may fail to return a typechecking result).

Classical axioms implies every proposition is decidable?

In the Lean manual 'Theorem proving in Lean' I read:
"With the classical axioms, we can prove that every proposition is decidable".
I would like to seek clarification about this statement and I am asking a Coq forum, as the question applies as much to Coq as it does to Lean (but feeling I am more likely to get an answer here).
When reading "With the classical axioms", I understand that we have something equivalent to the law of excluded middle:
Axiom LEM : forall (p:Prop), p \/ ~p.
When reading "every proposition is decidable", I understand that we can define a function (or at least we can prove the existence of such a function):
Definition decide (p:Prop) : Dec p.
where Dec is the inductive type family:
Inductive Dec (p:Prop) : Type :=
| isFalse : ~p -> Dec p
| isTrue : p -> Dec p
.
Yet, with what I know of Coq, I cannot implement decide as I cannot destruct (LEM p) (of sort Prop) to return something other than a Prop.
So my question is: assuming there is no mistake and the statement "With the classical axioms, we can prove that every proposition is decidable" is justified, I would like to know how I should understand it so I get out of the paradox I have highlighted. Is it maybe that we can prove the existence of the function decide (using LEM) but cannot actually provide a witness of this existence?
In the calculus of constructions without any axioms, there is meta-theoretical property that every proof of A \/ B is necessarily a proof that A holds (packaged using the constructor or_introl) or a proof that B holds (using the other constructor). So a proof of A \/ ~ A is either a proof that A holds or a proof that ~ A holds.
Following this meta-theoretical property, in Coq without any axioms, all proofs of propositions of the form forall x, P x \/ ~P x actually are proofs that P is decidable. In this paragraph, the meaning of decidable is the commonly accepted meaning, as used by computability books.
Some users started using the word decidable for any predicate P so that there exists a proof of forall x, P x \/ ~ P x. But they are actually talking about a different thing. To make it clearer, I will call this notion abuse-of-terminology-decidable.
Now, if you add an axiom like LEM in Coq, you basically state that every predicate P becomes abuse-of-terminology-decidable. Of course, you cannot change the meaning of conventionally-decidable by just adding an axiom in you Coq development, so there is no inclusion anymore.
I have been fighting against this abuse of terminology for years, but without success.
To be more precise, in Coq terminology, the term decidable is not used for propositions or predicates that enjoy LEM, but for propositions or predicates that enjoy the stronger following statement:
forall x, {P x}+{~P x}
Proofs of such propositions are often named with _dec suffix, where _dec directly refers to decidable. This abuse is less strong, but it is still an abuse of terminology.

apply rewrite tactic to sub-expression

How can I apply rewrite -> targetting only a sub-expression? For example, consider this theorem:
Parameter add : nat -> nat -> nat.
Axiom comm : forall a b, add a b = add b a.
Theorem t1 : forall a b : nat,
(add (add a b) (add a (add a b))) =
(add (add a b) (add a (add b a))).
Intuitively, it requires commuting only one (add a b) sub-expression, but if I do rewrite -> (comm a b), it rewrites all the occurrences. How can I target a particular sub-expression?
This is a case where the ssreflect matching facilities will usually be more convenient than "at" [I'd dare to say sub-term rewrites are often a cause of people switching to ssreflect's rewrite]. In particular:
rewrite {pos}[pat]lemma will select occurrences pos of pattern pat to rewrite,
pat can be a contextual pattern that may allow you improve the robustness of your scripts.
You can target a specific occurrence with the rewrite tactic using the suffix at N. Occurrences are numbered from 1 in left-to-right order. You can rewrite multiple occurrencess by separating their indices with spaces. You need Require Import Setoid. The at suffix is also available with some other tactics that target occurrences of a term, including many tactics that perform conversions (change, unfold, fold, etc.), set, destruct, etc.
intros.
rewrite -> (comm a b) at 2.
rewrite -> (comm _ _).
reflexivity.
There are other possible approaches, especially if all you need is to apply equalities. The congruence tactic can find what to rewrite and apply symmetry and transitivity on its own, but you need to prime it by adding all equivalences to the context (in the form of universally-quantified equalities), it won't query hint databases.
assert (Comm := comm).
congruence.
To get more automation, Hint Rewrite creates a database of theorems which the tactic autorewrite will try applying. For more advanced automation, look up generalized rewriting with setoids, which I'm not sufficiently familiar with to expound on.

Can you find function by type signature in Coq?

I'm looking for utility similar to one of Hoogle for Haskell. For the sake of example, let's say I need a function of signature forall n m:nat, n <> m -> m <> n.
When my Google searches don't yield any results, I write Definition foo: forall n m:nat, n <> m -> m <> n. and write intros; auto with arith. to prove it. But is there any way to not pollute my workspace with these temporary results and search for them based on their type? I'm sure I've seen this symmetry stated somewhere in standard library.
There's a Search command that's somewhat similar to Hoogle, but a bit more precise. Here are some searches you might use for symmetry of not. In practice I would use the first and fall back to the second if there were a lot of results.
Search (_ <> _). (* everything related to not equal *)
Search (?a <> ?b -> ?b <> ?a). (* exactly what you want -
note that unlike Hoogle, you need to use ?a for a pattern variable *)
Search (?R ?a ?b -> ?R ?b ?a). (* this searches for any symmetry theorem;
not terribly useful for it's cool that it works *)
Search not "_sym". (* if you know some of the theorem name you can use that, too *)