Programmable proof search¶
Tactics¶
- Tactic auto nat_or_var? auto_using? hintbases?¶
- auto_using
::=
using one_term+,hintbases
::=
with *|
with ident+Implements a Prolog-like resolution procedure to solve the current goal. It first tries to solve the goal using the
assumption
tactic, then it reduces the goal to an atomic one usingintros
and introduces the newly generated hypotheses as hints. Then it looks at the list of tactics associated with the head symbol of the goal and tries to apply one of them. This process is recursively applied to the generated subgoals.Within each hintbase, lower cost tactics are tried before higher-cost tactics. When multiple hintbases are specified, all hints in the first database are tried before any in the second database (and so forth) regardless of their cost (unlike
eauto
andtypeclasses eauto
).nat_or_var
Specifies the maximum search depth. The default is 5.
using one_term+,
Uses lemmas
one_term+,
in addition to hints. Ifone_term
is an inductive type, the collection of its constructors are added as hints.Note that hints passed through the
using
clause are used in the same way as if they were passed through a hint database. Consequently, they use a weaker version ofapply
andauto using one_term
may fail whereapply one_term
succeeds.with *
Use all existing hint databases. Using this variant is highly discouraged in finished scripts since it is both slower and less robust than explicitly selecting the required databases.
with ident+
Use the hint databases
ident+
in addition to the databasecore
. Use the fake databasenocore
to omitcore
.
If no
with
clause is given,auto
only uses the hypotheses of the current goal and the hints of the database namedcore
.auto
generally either completely solves the goal or leaves it unchanged. Usesolve
[ auto ]
if you want a failure when they don't solve the goal.auto
will fail iffail
orgfail
are invoked directly or indirectly, in which case setting theLtac Debug
may help you debug the failure.Warning
auto
uses a weaker version ofapply
that is closer tosimple apply
so it is expected that sometimesauto
will fail even if applying manually one of the hints would succeed.See also
Hint databases for the list of pre-defined databases and the way to create or extend a database.
- Tactic info_auto nat_or_var? auto_using? hintbases?¶
Behaves like
auto
but shows the tactics it uses to solve the goal. This variant is very useful for getting a better understanding of automation, or to know what lemmas/assumptions were used.
- Tactic debug auto nat_or_var? auto_using? hintbases?¶
Behaves like
auto
but shows the tactics it tries to solve the goal, including failing paths.
- Tactic trivial auto_using? hintbases?¶
- Tactic debug trivial auto_using? hintbases?¶
- Tactic info_trivial auto_using? hintbases?¶
Like
auto
, but is not recursive and only tries hints with zero cost. Typically used to solve goals for which a lemma is already available in the specifiedhintbases
.
- Flag Info Auto¶
- Flag Debug Auto¶
- Flag Info Trivial¶
- Flag Debug Trivial¶
These flags enable printing of informative or debug information for the
auto
andtrivial
tactics.
- Tactic eauto nat_or_var? auto_using? hintbases?¶
Generalizes
auto
. Whileauto
does not try resolution hints which would leave existential variables in the goal,eauto
will try them. Also,eauto
internally useseassumption
instead ofassumption
and a tactic similar tosimple eapply
instead of a tactic similar tosimple apply
. As a consequence,eauto
can solve goals such as:Example
- Hint Resolve ex_intro : core.
- The hint ex_intro will only be used by eauto, because applying ex_intro would leave variable x as unresolved existential variable.
- Goal forall P:nat -> Prop, P 0 -> exists n, P n.
- 1 goal ============================ forall P : nat -> Prop, P 0 -> exists n : nat, P n
- eauto.
- No more goals.
ex_intro
is declared as a hint so the proof succeeds.See also
- Tactic info_eauto nat_or_var? auto_using? hintbases?¶
The various options for
info_eauto
are the same as forinfo_auto
.
eauto
uses the following flags:- Tactic debug eauto nat_or_var? auto_using? hintbases?¶
Behaves like
eauto
but shows the tactics it tries to solve the goal, including failing paths.
- Tactic autounfold hintbases? simple_occurrences?¶
Unfolds constants that were declared through a
Hint Unfold
in the given databases.simple_occurrences
Performs the unfolding in the specified occurrences.
- Tactic autorewrite *? with ident+ occurrences? using ltac_expr?¶
*
If present, rewrite all occurrences whose side conditions are solved.
with ident+
Specifies the rewriting rule bases to use.
occurrences
Performs rewriting in the specified occurrences. Note: the
at
clause is currently not supported.- Error The "at" syntax isn't available yet for the autorewrite tactic.¶
Appears when there is an
at
clause on the conclusion.
using ltac_expr
ltac_expr
is applied to the main subgoal after each rewriting step.
Applies rewritings according to the rewriting rule bases
ident+
.For each rule base, applies each rewriting to the main subgoal until it fails. Once all the rules have been processed, if the main subgoal has changed then the rules of this base are processed again. If the main subgoal has not changed then the next base is processed. For the bases, the behavior is very similar to the processing of the rewriting rules.
The rewriting rule bases are built with the
Hint Rewrite
command.
Warning
This tactic may loop if you build non-terminating rewriting systems.
See also
Hint Rewrite
for feeding the database of lemmas used by
autorewrite
and autorewrite
for examples showing the use of this tactic.
Also see Strategies for rewriting.
Here are two examples of autorewrite
use. The first one ( Ackermann
function) shows actually a quite basic use where there is no
conditional rewriting. The second one ( Mac Carthy function)
involves conditional rewritings and shows how to deal with them using
the optional tactic of the Hint Rewrite
command.
Example: Ackermann function
- Require Import Arith.
- [Loading ML file coq-core.plugins.ring ... done]
- Parameter Ack : nat -> nat -> nat.
- Ack is declared
- Axiom Ack0 : forall m:nat, Ack 0 m = S m.
- Ack0 is declared
- Axiom Ack1 : forall n:nat, Ack (S n) 0 = Ack n 1.
- Ack1 is declared
- Axiom Ack2 : forall n m:nat, Ack (S n) (S m) = Ack n (Ack (S n) m).
- Ack2 is declared
- Global Hint Rewrite Ack0 Ack1 Ack2 : base0.
- Lemma ResAck0 : Ack 3 2 = 29.
- 1 goal ============================ Ack 3 2 = 29
- autorewrite with base0 using try reflexivity.
- No more goals.
Example: MacCarthy function
- Require Import Lia.
- [Loading ML file coq-core.plugins.zify ... done] [Loading ML file coq-core.plugins.micromega_core ... done] [Loading ML file coq-core.plugins.micromega ... done]
- Parameter g : nat -> nat -> nat.
- g is declared
- Axiom g0 : forall m:nat, g 0 m = m.
- g0 is declared
- Axiom g1 : forall n m:nat, (n > 0) -> (m > 100) -> g n m = g (pred n) (m - 10).
- g1 is declared
- Axiom g2 : forall n m:nat, (n > 0) -> (m <= 100) -> g n m = g (S n) (m + 11).
- g2 is declared
- Global Hint Rewrite g0 g1 g2 using lia : base1.
- Lemma Resg0 : g 1 110 = 100.
- 1 goal ============================ g 1 110 = 100
- Show.
- 1 goal ============================ g 1 110 = 100
- autorewrite with base1 using reflexivity || simpl.
- No more goals.
- Qed.
- Lemma Resg1 : g 1 95 = 91.
- 1 goal ============================ g 1 95 = 91
- autorewrite with base1 using reflexivity || simpl.
- No more goals.
- Qed.
- Tactic easy¶
This tactic tries to solve the current goal by a number of standard closing steps. In particular, it tries to close the current goal using the closing tactics
trivial
,reflexivity
,symmetry
,contradiction
andinversion
of hypothesis. If this fails, it tries introducing variables and splitting and-hypotheses, using the closing tactics afterwards, and splitting the goal usingsplit
and recursing.This tactic solves goals that belong to many common classes; in particular, many cases of unsatisfiable hypotheses, and simple equality goals are usually solved by this tactic.
Hint databases¶
Hints used by auto
, eauto
and other tactics are stored in hint
databases. Each database maps head symbols to a list of hints. Use the
Print Hint
command to view a database.
Each hint has a cost and an optional pattern. Hints with lower
cost are tried first. (Cost is not used to limit the scope of searches.)
auto
tries a hint when the conclusion of the current goal matches its
pattern or when the hint has no pattern.
Creating hint databases¶
Hint databases can be created with the Create HintDb
command or implicitly
by adding a hint to an unknown database. We recommend you always use Create HintDb
and then imediately use Hint Constants
and Hint Variables
to make
those settings explicit.
Note that the default transparency
settings differ between these two methods of creation. Databases created with
Create HintDb
have the default setting Transparent
for both Variables
and Constants
, while implicitly created databases have the Opaque
setting.
- Command Create HintDb ident discriminated?¶
Creates a new hint database named
ident
. The database is implemented by a Discrimination Tree (DT) that serves as a filter to select the lemmas that will be applied. When discriminated, the DT uses transparency information to decide if a constant should considered rigid for filtering, making the retrieval more efficient. By contrast, undiscriminated databases treat all constants as transparent, resulting in a larger number of selected lemmas to be applied, and thus putting more pressure on unification.By default, hint databases are undiscriminated.
Hint databases defined in the Rocq standard library¶
Several hint databases are defined in the Rocq standard library. The database contains all hints declared to belong to it in the currently loaded modules. In particular, requiring new modules may extend the database. At Rocq startup, only the core database is nonempty and ready to be used immediately.
- core
This special database is automatically used by
auto
, except when pseudo-databasenocore
is given toauto
. The core database contains only basic lemmas about negation, conjunction, and so on. Most of the hints in this database come from the Init and Logic directories.- arith
all lemmas about Peano’s arithmetic proved in the directories Init and Arith.
- zarith
lemmas about binary signed integers from the directories theories/ZArith. The database also contains high-cost hints that call
lia
on equations and inequalities innat
orZ
.- bool
lemmas about booleans, mostly from directory theories/Bool.
- datatypes
lemmas about lists, streams and so on that are mainly proved in the Lists subdirectory.
- sets
lemmas about sets and relations from the directories Sets and Relations.
- typeclass_instances
special database containing all typeclass instances declared in the environment, including those used for
setoid_rewrite
, from the Classes directory.- fset
internal database for the implementation of the
FSets
library.- ordered_type
lemmas about ordered types (as defined in the legacy
OrderedType
module), mainly used in theFSets
andFMaps
libraries.
You are advised not to put your own hints in the core database, but use one or more databases specific to your development.
Creating Hints¶
The various
Hint
commands share these elements:
: ident+?
specifies the hint database(s) to add to. (Deprecated since version 8.10: If noident
s are given, the hint is added to thecore
database.)Hints in hint databases are ordered, which is the order in which they're tried, as shown by the
Print HintDb
command. Hints with lower costs are tried first. Hints with the same cost are tried in reverse of their order of definition, i.e., last to first.Outside of sections, these commands support the
local
,export
andglobal
attributes.export
is the default.Inside sections, some commands only support the
local
attribute. These areHint Immediate
,Hint Resolve
,Hint Constructors
,Hint Unfold
,Hint Extern
andHint Rewrite
.local
is the default for all hint commands inside sections.
local
hints are never visible from other modules, even if theyImport
orRequire
the current module.
export
hints are visible from other modules when theyImport
the current module, but not when they onlyRequire
it.
global
hints are visible from other modules when theyImport
orRequire
the current module.Changed in version 8.18: The default value for hint locality outside sections is now
export
. It used to beglobal
.The
Hint
commands are:
- Command Hint Resolve qualidone_term+ hint_info? : ident+?¶
- Command Hint Resolve -><- qualid+ natural? : ident+?¶
- hint_info
::=
| natural? one_pattern?one_pattern
::=
one_termThe first form adds each
qualid
as a hint with the head symbol of the type ofqualid
to the specified hint databases (ident
s). The cost of the hint is the number of subgoals generated bysimple apply
qualid
or, if specified,natural
. The associated pattern is inferred from the conclusion of the type ofqualid
or, if specified, the givenone_pattern
.If the inferred type of
qualid
does not start with a product,exact
qualid
is added to the hint list. If the type can be reduced to a type starting with a product,simple apply
qualid
is also added to the hints list.If the inferred type of
qualid
contains a dependent quantification on a variable which occurs only in the premises of the type and not in its conclusion, no instance could be inferred for the variable by unification with the goal. In this case, the hint is only used byeauto
/typeclasses eauto
, but not byauto
. A typical hint that would only be used byeauto
is a transitivity lemma.
-><-
The second form adds the left-to-right (
->
) or right-ot-left implication (<-
) of an equivalence as a hint (informally the hint will be used as, respectively,apply
-> qualid
orapply
<- qualid
, although as mentioned before, the tactic actually used is a restricted version ofapply
).one_term
Permits declaring a hint without declaring a new constant first. This is deprecated.
- Warning Declaring arbitrary terms as hints is fragile and deprecated; it is recommended to declare a toplevel constant instead¶
- Command Hint Immediate qualidone_term+ : ident+?¶
For each specified
qualid
, adds the tacticsimple apply
qualid;
solve
[
trivial
]
to the hint list associated with the head symbol of the type ofqualid
. This tactic will fail if all the subgoals generated bysimple apply
qualid
are not solved immediately by thetrivial
tactic (which only tries tactics with cost 0). This command is useful for theorems such as the symmetry of equality orn+1=m+1 -> n=m
that we may want to introduce with limited use in order to avoid useless proof search. The cost of this tactic (which never generates subgoals) is always 1, so that it is not used bytrivial
itself.
- Command Hint Constructors qualid+ : ident+?¶
For each
qualid
that is an inductive type, adds all its constructors as hints of typeResolve
. Then, when the conclusion of current goal has the form(qualid ...)
,auto
will try to apply each constructor.
- Command Hint Unfold qualid+ : ident+?¶
For each
qualid
, adds the tacticunfold
qualid
to the hint list that will only be used when the head constant of the goal isqualid
. Its cost is 4.
- Command Hint TransparentOpaque qualid+ : ident+?¶
Adds transparency hints to the database, making each
qualid
a transparent or opaque constant during resolution. This information is used during unification of the goal with any lemma in the database and inside the discrimination network to relax or constrain it in the case of discriminated databases.
- Command Hint ConstantsProjectionsVariables TransparentOpaque : ident+?¶
Sets the transparency flag for constants, projections or variables for the specified hint databases. These flags affect the unification of hints in the database. We advise using this just after a
Create HintDb
command.
- Command Hint Extern natural one_pattern? => ltac_expr : ident+?¶
Extends
auto
with tactics other thanapply
andunfold
.natural
is the cost,one_pattern
is the pattern to match andltac_expr
is the action to apply.Usage tip: tactics that can succeed even if they don't change the context, such as most of the conversion tactics, should be prefaced with
progress
to avoid needless repetition of the tactic.Usage tip: Use a
Hint Extern
with no pattern to do pattern matching on hypotheses usingmatch goal with
inside the tactic.Example
- Hint Extern 4 (~(_ = _)) => discriminate : core.
Now, when the head of the goal is a disequality,
auto
will try discriminate if it does not manage to solve the goal with hints with a cost less than 4.One can even use some sub-patterns of the pattern in the tactic script. A sub-pattern is a question mark followed by an identifier, like
?X1
or?X2
. Here is an example:Example
- Require Import List.
- Hint Extern 5 ({?X1 = ?X2} + {?X1 <> ?X2}) => generalize X1, X2; decide equality : eqdec.
- Goal forall a b:list (nat * nat), {a = b} + {a <> b}.
- 1 goal ============================ forall a b : list (nat * nat), {a = b} + {a <> b}
- info_auto.
- (* info auto: *) idtac.
- Command Hint Cut [ hints_regexp ] : ident+?¶
- hints_regexp
::=
qualid+(hint or instance identifier)
|
_(any hint)
|
hints_regexp | hints_regexp(disjunction)
|
hints_regexp hints_regexp(sequence)
|
hints_regexp *(Kleene star)
|
emp(empty)
|
eps(epsilon)
|
( hints_regexp )Used to cut the proof search tree according to a regular expression that matches the paths to be cut.
During proof search, the path of successive successful hints on a search branch is recorded as a list of identifiers for the hints (note that
Hint Extern
s do not have an associated identifier). For each hintqualid
in the hint database, the current pathp
extended withqualid
is matched against the current cut expressionc
associated with the hint database. If the match succeeds the hint is not applied.
Hint Cut hints_regexp
sets the cut expression toc | hints_regexp
. The initial cut expression isemp
.The output of
Print HintDb
shows the cut expression.Warning
The regexp matches the entire path. Most hints will start with a leading
( _* )
to match the tail of the path. (Note that(_*)
misparses since*)
would end a comment.)Warning
There is no operator precedence during parsing, one can check with
Print HintDb
to verify the current cut expression.Warning
These hints currently only apply to typeclass proof search and the
typeclasses eauto
tactic.
- Command Hint Mode qualid +!-+ : ident+?¶
Sets an optional mode of resolution for the identifier
qualid
. When proof search has a goal that ends in an application ofqualid
to argumentsarg ... arg
, the mode tells if the hints associated withqualid
can be applied or not, depending on a criterion on the arguments. A mode specification is a list of+
,!
or-
items that specify if an argument of the identifier is to be treated as an input (+
), if its head only is an input (!
) or an output (-
) of the identifier. Mode-
matches any term, mode+
matches a term if and only if it does not contain existential variables, while mode!
matches a term if and only if the head of the term is not an existential variable. The head of a term is understood here as the applicative head, recursively, ignoring casts. For a mode declaration to match a list of arguments, each argument should match its corresponding mode.
Hint Mode
is especially useful for typeclasses, when one does not want to support default instances and wants to avoid ambiguity in general. Setting a parameter of a class as an input forces proof search to be driven by that index of the class, with!
allowing existentials to appear in the index but not at its head.Note
Multiple modes can be declared for a single identifier. In that case only one mode needs to match the arguments for the hints to be applied.
If you want to add hints such as
Hint Transparent
,Hint Cut
, orHint Mode
, for typeclass resolution, do not forget to put them in thetypeclass_instances
hint database.
- Warning This hint is not local but depends on a section variable. It will disappear when the section is closed.¶
A hint with a non-local attribute was added inside a section, but it refers to a local variable that will go out of scope when closing the section. As a result the hint will not survive either.
Example: Logic programming with addition on natural numbers
This example illustrates the use of modes to control how resolutions can be triggered during proof search.
- Parameter plus : nat -> nat -> nat -> Prop.
- plus is declared
- Hint Mode plus ! - - : plus.
- Hint Mode plus - ! - : plus.
- Axiom plus0l : forall m : nat, plus 0 m m.
- plus0l is declared
- Axiom plus0r : forall n : nat, plus n 0 n.
- plus0r is declared
- Axiom plusSl : forall n m r : nat, plus n m r -> plus (S n) m (S r).
- plusSl is declared
- Axiom plusSr : forall n m r : nat, plus n m r -> plus m (S m) (S r).
- plusSr is declared
- Hint Resolve plus0l plus0r plusSl plusSr : plus.
- The hint plusSr will only be used by eauto, because applying plusSr would leave variable n as unresolved existential variable.
The previous commands define the addition predicate and set its mode so it can resolve goals if and only if one of the first two arguments is headed by a constructor or constant. The last argument of the predicate will be the inferred result.
- Goal exists x y, plus x y 12.
- 1 goal ============================ exists x y : nat, plus x y 12
- Proof. eexists ?[x], ?[y].
- 1 focused goal (shelved: 2) ============================ plus ?x ?y 12
- Fail typeclasses eauto with plus.
- The command has indeed failed with message: Tactic failure: Proof search failed.
- instantiate (y := 1).
- 1 focused goal (shelved: 1) ============================ plus ?x 1 12
- typeclasses eauto with plus.
- No more goals.
- Defined.
In the proof script, the first call to
typeclasses eauto
fails as the two arguments are headed by an existential variable, while when we instantiate the second argument with1
, typeclass resolution succeeds as the second declared mode is matched, and instantiatesx
with11
.
- Command Hint Rewrite -><-? one_term+ using ltac_expr? : ident+?¶
using ltac_expr?
If specified,
ltac_expr
is applied to the generated subgoals, except for the main subgoal.-><-
Arrows specify the orientation; left to right (
->
) or right to left (<-
). If no arrow is given, the default orientation is left to right (->
).
Adds the terms
one_term+
(their types must be equalities) to the rewriting basesident*
. Note that the rewriting bases are distinct from theauto
hint bases and thatauto
does not take them into account.
- Command Remove Hints qualid+ : ident+?¶
Removes the hints associated with the
qualid+
in databasesident+
. Note: hints created withHint Extern
currently can't be removed. The best workaround for this is to make the hints non-global and carefully select which modules you import.
- Command Print Hint *reference?¶
-
Displays tactics from the hints list. The default is to show hints that apply to the conclusion of the current goal. The other forms with
*
andreference
can be used even if no proof is open.Each hint has a cost that is a nonnegative integer and an optional pattern. The hints with lower cost are tried first.
- Command Print HintDb ident¶
This command displays all hints from database
ident
. Hints in each group ("For ... ->") are shown in the order in which they will be tried (first to last). The groups are shown ordered alphabetically on the last component of the symbol name. Note that hints with the same cost are tried in reverse of the order they're defined in, i.e., last to first.
Hint locality¶
As explained at the beginning of Creating Hints, hints outside sections have three
possible localities: local
, export
, and global
,
with export
now being the default. The default used to
be global
, so old code bases may still use it. The following
option may be useful to help transition hints from the global
to the export
locality, as it can provide an over-approximation
of where these hints are used:
- Option Loose Hint Behavior "Lax""Warn""Strict"¶
This option accepts three values:
"Lax": no scope errors or warnings are generated for hints. This is the default.
"Warn": outputs a warning when a non-imported hint is used. Note that this is an over-approximation, because a hint may be triggered by a run that will eventually fail and backtrack, resulting in the hint not being actually useful for the proof.
"Strict": fails when a non-imported hint is used, with the same caveats as "Warn".