Each list of hint clauses must start with clauses(hints). and end with end_of_list. Any clause is acceptable as a hint. For example (the labels attributes are optional),
clauses(hints). x ' * (x * y) = y # label(6). x * (x * y) = y # label(7). x * (y * (x * y)) = e # label(8). x ' ' * e = x # label(9). x ' * e = x # label(10). x ' = x # label(11). x * e = x # label(12). x * (y * x) = y # label(13). x * y = y * x # label(14). end_of_list.
Hints are used when selecting given clauses. The mechanism for doing this is that when a derived clause matches a hint, its weight is adjusted so that it is selected sooner (or maybe later, if the hint is for avoiding paths) as the given clause.
A derived clause matches a hint if it subsumes the hint. If a clause matches more than one hint, the first matching hint is used.
In Otter, "matching a hint" can mean (depending on the parameter settings) subsumes, subsumed by, or equivalent to. These other types of matching may be added to Prover9 if there is any demand for them.
Bob Veroff developed the concept, installing code for hints in an early version of Otter, to experiment with his method of proof sketches [Veroff-hints, Veroff-sketches]. In the proof sketches method, a difficult conjecture is attacked by first proving several (or many) weakened variants of the conjecture, and using those proofs as hints to guide searches for a proof of the original conjecture.
The program Prooftrans, which is distributed along with Prover9, can be used to extract proofs from a Prover9 output file and transform the proofs to lists of hints suitable for input to subsequent Prover9 jobs.
prover9 -f easy.in > easy.out
prooftrans hints -f easy.out > easy.hints
prover9 -f hard.in easy.hints > hard.out
assign(bsub_hint_wt, n). % default n=INT_MAX, range [INT_MIN .. INT_MAX]
If the clause being weighed matches a hint and n != INT_MAX, the clause receives n as its weight.
assign(bsub_hint_add_wt, n). % default n=-1000, range [INT_MIN .. INT_MAX]
First the clause is weighed with the weighting rules. Then, if the clause matches a hint and n != INT_MAX, the value n added to the weight of the clause. The typical use of this parameter is to subtract weight from the clause (to make it more preferable); that is, n is negative.
The preceding two parameters can be overridden for specific hints by including attributes on those hints. The attribute names correspond to the two parameter names. For example, consider the following hints.
clauses(hints). x ' * (x * y) = y # label(6) # bsub_hint_wt(-50). x * (x * y) = y # label(7) # bsub_hint_add_wt(-500). x * (y * (x * y)) = e # label(8). x ' ' * e = x # label(9). x ' * e = x # label(10). end_of_list.If a clause matches either of the first two hints, the attributes are used to adjust the weight of the clause. If a clause matches any of the other hints, the ordinary parameters are used.
set(degrade_hints). % default set clear(degrade_hints).
If this flag is set, then every time a hint matches a clause, the value of its bsub_hint_add_wt is cut in half. This parameter applies regardless of whether the bsub_hint_add_wt is determined by the ordinary parameter of by an attribute on the clause.
The following flag addresses the situation in which the input contains
sets of equivalent hints. (This situation frequently occurs when the
hints contain many proofs of similar theorems.)
If this flag is clear, when a clause matches a set of equivalent hints,
it receives the label (if any) from the first copy only.
set(collect_hint_labels).
clear(collect_hint_labels). % default clear
If this flag is set, and the hints list contains a set of equivalent hints,
only the first copy of the hint is retained. However, the labels from
all of the other equivalent hints are collected and put on the retained
copy. When a clause matches the retained hint, it gets copies of all of the
labels from the equivalent hints.