|
1 %% $Id$ |
|
2 \chapter{Tactics} \label{tactics} |
|
3 \index{tactics|(} |
|
4 Tactics have type \ttindexbold{tactic}. They are essentially |
|
5 functions from theorems to theorem sequences, where the theorems represent |
|
6 states of a backward proof. Tactics seldom need to be coded from scratch, |
|
7 as functions; the basic tactics suffice for most proofs. |
|
8 |
|
9 \section{Resolution and assumption tactics} |
|
10 {\bf Resolution} is Isabelle's basic mechanism for refining a subgoal using |
|
11 a rule. {\bf Elim-resolution} is particularly suited for elimination |
|
12 rules, while {\bf destruct-resolution} is particularly suited for |
|
13 destruction rules. The {\tt r}, {\tt e}, {\tt d} naming convention is |
|
14 maintained for several different kinds of resolution tactics, as well as |
|
15 the shortcuts in the subgoal module. |
|
16 |
|
17 All the tactics in this section act on a subgoal designated by a positive |
|
18 integer~$i$. They fail (by returning the empty sequence) if~$i$ is out of |
|
19 range. |
|
20 |
|
21 \subsection{Resolution tactics} |
|
22 \index{tactics!resolution|bold} |
|
23 \begin{ttbox} |
|
24 resolve_tac : thm list -> int -> tactic |
|
25 eresolve_tac : thm list -> int -> tactic |
|
26 dresolve_tac : thm list -> int -> tactic |
|
27 forward_tac : thm list -> int -> tactic |
|
28 \end{ttbox} |
|
29 These perform resolution on a list of theorems, $thms$, representing a list |
|
30 of object-rules. When generating next states, they take each of the rules |
|
31 in the order given. Each rule may yield several next states, or none: |
|
32 higher-order resolution may yield multiple resolvents. |
|
33 \begin{description} |
|
34 \item[\ttindexbold{resolve_tac} {\it thms} {\it i}] |
|
35 refines the proof state using the object-rules, which should normally be |
|
36 introduction rules. It resolves an object-rule's conclusion with |
|
37 subgoal~$i$ of the proof state. |
|
38 |
|
39 \item[\ttindexbold{eresolve_tac} {\it thms} {\it i}] |
|
40 refines the proof state by elim-resolution with the object-rules, which |
|
41 should normally be elimination rules. It resolves with a rule, solves |
|
42 its first premise by assumption, and finally {\bf deletes} that assumption |
|
43 from any new subgoals. |
|
44 |
|
45 \item[\ttindexbold{dresolve_tac} {\it thms} {\it i}] |
|
46 performs destruct-resolution with the object-rules, which normally should |
|
47 be destruction rules. This replaces an assumption by the result of |
|
48 applying one of the rules. |
|
49 |
|
50 \item[\ttindexbold{forward_tac}] |
|
51 is like \ttindex{dresolve_tac} except that the selected assumption is not |
|
52 deleted. It applies a rule to an assumption, adding the result as a new |
|
53 assumption. |
|
54 \end{description} |
|
55 |
|
56 \subsection{Assumption tactics} |
|
57 \index{tactics!assumption|bold} |
|
58 \begin{ttbox} |
|
59 assume_tac : int -> tactic |
|
60 eq_assume_tac : int -> tactic |
|
61 \end{ttbox} |
|
62 \begin{description} |
|
63 \item[\ttindexbold{assume_tac} {\it i}] |
|
64 attempts to solve subgoal~$i$ by assumption. |
|
65 |
|
66 \item[\ttindexbold{eq_assume_tac}] |
|
67 is like {\tt assume_tac} but does not use unification. It succeeds (with a |
|
68 {\bf unique} next state) if one of the assumptions is identical to the |
|
69 subgoal's conclusion. Since it does not instantiate variables, it cannot |
|
70 make other subgoals unprovable. It is intended to be called from proof |
|
71 strategies, not interactively. |
|
72 \end{description} |
|
73 |
|
74 \subsection{Matching tactics} \label{match_tac} |
|
75 \index{tactics!matching|bold} |
|
76 \begin{ttbox} |
|
77 match_tac : thm list -> int -> tactic |
|
78 ematch_tac : thm list -> int -> tactic |
|
79 dmatch_tac : thm list -> int -> tactic |
|
80 \end{ttbox} |
|
81 These are just like the resolution tactics except that they never |
|
82 instantiate unknowns in the proof state. Flexible subgoals are not updated |
|
83 willy-nilly, but are left alone. Matching --- strictly speaking --- means |
|
84 treating the unknowns in the proof state as constants; these tactics merely |
|
85 discard unifiers that would update the proof state. |
|
86 \begin{description} |
|
87 \item[\ttindexbold{match_tac} {\it thms} {\it i}] |
|
88 refines the proof state using the object-rules, matching an object-rule's |
|
89 conclusion with subgoal~$i$ of the proof state. |
|
90 |
|
91 \item[\ttindexbold{ematch_tac}] |
|
92 is like {\tt match_tac}, but performs elim-resolution. |
|
93 |
|
94 \item[\ttindexbold{dmatch_tac}] |
|
95 is like {\tt match_tac}, but performs destruct-resolution. |
|
96 \end{description} |
|
97 |
|
98 |
|
99 \subsection{Resolution with instantiation} \label{res_inst_tac} |
|
100 \index{tactics!instantiation|bold} |
|
101 \begin{ttbox} |
|
102 res_inst_tac : (string*string)list -> thm -> int -> tactic |
|
103 eres_inst_tac : (string*string)list -> thm -> int -> tactic |
|
104 dres_inst_tac : (string*string)list -> thm -> int -> tactic |
|
105 forw_inst_tac : (string*string)list -> thm -> int -> tactic |
|
106 \end{ttbox} |
|
107 These tactics are designed for applying rules such as substitution and |
|
108 induction, which cause difficulties for higher-order unification. The |
|
109 tactics accept explicit instantiations for schematic variables in the rule |
|
110 --- typically, in the rule's conclusion. Each instantiation is a pair |
|
111 {\tt($v$,$e$)}, where $v$ can be a type variable or ordinary variable: |
|
112 \begin{itemize} |
|
113 \item If $v$ is the {\bf type variable} {\tt'a}, then |
|
114 the rule must contain a schematic type variable \verb$?'a$ of some |
|
115 sort~$s$, and $e$ should be a type of sort $s$. |
|
116 |
|
117 \item If $v$ is the {\bf variable} {\tt P}, then |
|
118 the rule must contain a schematic variable \verb$?P$ of some type~$\tau$, |
|
119 and $e$ should be a term of some type~$\sigma$ such that $\tau$ and |
|
120 $\sigma$ are unifiable. If the unification of $\tau$ and $\sigma$ |
|
121 instantiates any schematic type variables in $\tau$, these instantiations |
|
122 are recorded for application to the rule. |
|
123 \end{itemize} |
|
124 Types are instantiated before terms. Because type instantiations are |
|
125 inferred from term instantiations, explicit type instantiations are seldom |
|
126 necessary --- if \verb$?t$ has type \verb$?'a$, then the instantiation list |
|
127 \verb$[("'a","bool"),("t","True")]$ may be simplified to |
|
128 \verb$[("t","True")]$. Type unknowns in the proof state may cause |
|
129 failure because the tactics cannot instantiate them. |
|
130 |
|
131 The instantiation tactics act on a given subgoal. Terms in the |
|
132 instantiations are type-checked in the context of that subgoal --- in |
|
133 particular, they may refer to that subgoal's parameters. Any unknowns in |
|
134 the terms receive subscripts and are lifted over the parameters; thus, you |
|
135 may not refer to unknowns in the subgoal. |
|
136 |
|
137 \begin{description} |
|
138 \item[\ttindexbold{res_inst_tac} {\it insts} {\it thm} {\it i}] |
|
139 instantiates the rule {\it thm} with the instantiations {\it insts}, as |
|
140 described above, and then performs resolution on subgoal~$i$. Resolution |
|
141 typically causes further instantiations; you need not give explicit |
|
142 instantiations for every variable in the rule. |
|
143 |
|
144 \item[\ttindexbold{eres_inst_tac}] |
|
145 is like {\tt res_inst_tac}, but performs elim-resolution. |
|
146 |
|
147 \item[\ttindexbold{dres_inst_tac}] |
|
148 is like {\tt res_inst_tac}, but performs destruct-resolution. |
|
149 |
|
150 \item[\ttindexbold{forw_inst_tac}] |
|
151 is like {\tt dres_inst_tac} except that the selected assumption is not |
|
152 deleted. It applies the instantiated rule to an assumption, adding the |
|
153 result as a new assumption. |
|
154 \end{description} |
|
155 |
|
156 |
|
157 \section{Other basic tactics} |
|
158 \subsection{Definitions and meta-level rewriting} |
|
159 \index{tactics!meta-rewriting|bold}\index{rewriting!meta-level} |
|
160 Definitions in Isabelle have the form $t\equiv u$, where typically $t$ is a |
|
161 constant or a constant applied to a list of variables, for example $\it |
|
162 sqr(n)\equiv n\times n$. (Conditional definitions, $\phi\Imp t\equiv u$, |
|
163 are not supported.) {\bf Unfolding} the definition $t\equiv u$ means using |
|
164 it as a rewrite rule, replacing~$t$ by~$u$ throughout a theorem. {\bf |
|
165 Folding} $t\equiv u$ means replacing~$u$ by~$t$. Rewriting continues until |
|
166 no rewrites are applicable to any subterm. |
|
167 |
|
168 There are rules for unfolding and folding definitions; Isabelle does not do |
|
169 this automatically. The corresponding tactics rewrite the proof state, |
|
170 yielding a unique result. See also the {\tt goalw} command, which is the |
|
171 easiest way of handling definitions. |
|
172 \begin{ttbox} |
|
173 rewrite_goals_tac : thm list -> tactic |
|
174 rewrite_tac : thm list -> tactic |
|
175 fold_goals_tac : thm list -> tactic |
|
176 fold_tac : thm list -> tactic |
|
177 \end{ttbox} |
|
178 \begin{description} |
|
179 \item[\ttindexbold{rewrite_goals_tac} {\it defs}] |
|
180 unfolds the {\it defs} throughout the subgoals of the proof state, while |
|
181 leaving the main goal unchanged. Use \ttindex{SELECT_GOAL} to restrict it to a |
|
182 particular subgoal. |
|
183 |
|
184 \item[\ttindexbold{rewrite_tac} {\it defs}] |
|
185 unfolds the {\it defs} throughout the proof state, including the main goal |
|
186 --- not normally desirable! |
|
187 |
|
188 \item[\ttindexbold{fold_goals_tac} {\it defs}] |
|
189 folds the {\it defs} throughout the subgoals of the proof state, while |
|
190 leaving the main goal unchanged. |
|
191 |
|
192 \item[\ttindexbold{fold_tac} {\it defs}] |
|
193 folds the {\it defs} throughout the proof state. |
|
194 \end{description} |
|
195 |
|
196 |
|
197 \subsection{Tactic shortcuts} |
|
198 \index{shortcuts!for tactics|bold} |
|
199 \index{tactics!resolution}\index{tactics!assumption} |
|
200 \index{tactics!meta-rewriting} |
|
201 \begin{ttbox} |
|
202 rtac : thm -> int ->tactic |
|
203 etac : thm -> int ->tactic |
|
204 dtac : thm -> int ->tactic |
|
205 atac : int ->tactic |
|
206 ares_tac : thm list -> int -> tactic |
|
207 rewtac : thm -> tactic |
|
208 \end{ttbox} |
|
209 These abbreviate common uses of tactics. |
|
210 \begin{description} |
|
211 \item[\ttindexbold{rtac} {\it thm} {\it i}] |
|
212 abbreviates \hbox{\tt resolve_tac [{\it thm}] {\it i}}, doing resolution. |
|
213 |
|
214 \item[\ttindexbold{etac} {\it thm} {\it i}] |
|
215 abbreviates \hbox{\tt eresolve_tac [{\it thm}] {\it i}}, doing elim-resolution. |
|
216 |
|
217 \item[\ttindexbold{dtac} {\it thm} {\it i}] |
|
218 abbreviates \hbox{\tt dresolve_tac [{\it thm}] {\it i}}, doing |
|
219 destruct-resolution. |
|
220 |
|
221 \item[\ttindexbold{atac} {\it i}] |
|
222 is a synonym for \hbox{\tt assume_tac {\it i}}, doing proof by assumption. |
|
223 |
|
224 \item[\ttindexbold{ares_tac} {\it thms} {\it i}] |
|
225 tries proof by assumption and resolution; it abbreviates |
|
226 \begin{ttbox} |
|
227 assume_tac {\it i} ORELSE resolve_tac {\it thms} {\it i} |
|
228 \end{ttbox} |
|
229 |
|
230 \item[\ttindexbold{rewtac} {\it def}] |
|
231 abbreviates \hbox{\tt rewrite_goals_tac [{\it def}]}, unfolding a definition. |
|
232 \end{description} |
|
233 |
|
234 |
|
235 \subsection{Inserting premises and facts}\label{cut_facts_tac} |
|
236 \index{tactics!for inserting facts|bold} |
|
237 \begin{ttbox} |
|
238 cut_facts_tac : thm list -> int -> tactic |
|
239 subgoal_tac : string -> int -> tactic |
|
240 \end{ttbox} |
|
241 These tactics add assumptions --- which must be proved, sooner or later --- |
|
242 to a given subgoal. |
|
243 \begin{description} |
|
244 \item[\ttindexbold{cut_facts_tac} {\it thms} {\it i}] |
|
245 adds the {\it thms} as new assumptions to subgoal~$i$. Once they have |
|
246 been inserted as assumptions, they become subject to {\tt eresolve_tac} |
|
247 and {\tt rewrite_goals_tac}. Only rules with no premises are inserted: |
|
248 Isabelle cannot use assumptions that contain $\Imp$ or~$\Forall$. Sometimes |
|
249 the theorems are premises of a rule being derived, returned by~{\tt |
|
250 goal}; instead of calling this tactic, you could state the goal with an |
|
251 outermost meta-quantifier. |
|
252 |
|
253 \item[\ttindexbold{subgoal_tac} {\it formula} {\it i}] |
|
254 adds the {\it formula} as a assumption to subgoal~$i$, and inserts the same |
|
255 {\it formula} as a new subgoal, $i+1$. |
|
256 \end{description} |
|
257 |
|
258 |
|
259 \subsection{Theorems useful with tactics} |
|
260 \index{theorems!of pure theory|bold} |
|
261 \begin{ttbox} |
|
262 asm_rl: thm |
|
263 cut_rl: thm |
|
264 \end{ttbox} |
|
265 \begin{description} |
|
266 \item[\ttindexbold{asm_rl}] |
|
267 is $\psi\Imp\psi$. Under elim-resolution it does proof by assumption, and |
|
268 \hbox{\tt eresolve_tac (asm_rl::{\it thms}) {\it i}} is equivalent to |
|
269 \begin{ttbox} |
|
270 assume_tac {\it i} ORELSE eresolve_tac {\it thms} {\it i} |
|
271 \end{ttbox} |
|
272 |
|
273 \item[\ttindexbold{cut_rl}] |
|
274 is $\List{\psi\Imp\theta,\psi}\Imp\theta$. It is useful for inserting |
|
275 assumptions; it underlies \ttindex{forward_tac}, \ttindex{cut_facts_tac} |
|
276 and \ttindex{subgoal_tac}. |
|
277 \end{description} |
|
278 |
|
279 |
|
280 \section{Obscure tactics} |
|
281 \subsection{Tidying the proof state} |
|
282 \index{parameters!removing unused|bold} |
|
283 \index{flex-flex constraints} |
|
284 \begin{ttbox} |
|
285 prune_params_tac : tactic |
|
286 flexflex_tac : tactic |
|
287 \end{ttbox} |
|
288 \begin{description} |
|
289 \item[\ttindexbold{prune_params_tac}] |
|
290 removes unused parameters from all subgoals of the proof state. It works |
|
291 by rewriting with the theorem $(\Forall x. V)\equiv V$. This tactic can |
|
292 make the proof state more readable. It is used with |
|
293 \ttindex{rule_by_tactic} to simplify the resulting theorem. |
|
294 |
|
295 \item[\ttindexbold{flexflex_tac}] |
|
296 removes all flex-flex pairs from the proof state by applying the trivial |
|
297 unifier. This drastic step loses information, and should only be done as |
|
298 the last step of a proof. |
|
299 |
|
300 Flex-flex constraints arise from difficult cases of higher-order |
|
301 unification. To prevent this, use \ttindex{res_inst_tac} to instantiate |
|
302 some variables in a rule~(\S\ref{res_inst_tac}). Normally flex-flex |
|
303 constraints can be ignored; they often disappear as unknowns get |
|
304 instantiated. |
|
305 \end{description} |
|
306 |
|
307 |
|
308 \subsection{Renaming parameters in a goal} \index{parameters!renaming|bold} |
|
309 \begin{ttbox} |
|
310 rename_tac : string -> int -> tactic |
|
311 rename_last_tac : string -> string list -> int -> tactic |
|
312 Logic.set_rename_prefix : string -> unit |
|
313 Logic.auto_rename : bool ref \hfill{\bf initially false} |
|
314 \end{ttbox} |
|
315 When creating a parameter, Isabelle chooses its name by matching variable |
|
316 names via the object-rule. Given the rule $(\forall I)$ formalized as |
|
317 $\left(\Forall x. P(x)\right) \Imp \forall x.P(x)$, Isabelle will note that |
|
318 the $\Forall$-bound variable in the premise has the same name as the |
|
319 $\forall$-bound variable in the conclusion. |
|
320 |
|
321 Sometimes there is insufficient information and Isabelle chooses an |
|
322 arbitrary name. The renaming tactics let you override Isabelle's choice. |
|
323 Because renaming parameters has no logical effect on the proof state, the |
|
324 {\tt by} command prints the needless message {\tt Warning:\ same as previous |
|
325 level}. |
|
326 |
|
327 Alternatively, you can suppress the naming mechanism described above and |
|
328 have Isabelle generate uniform names for parameters. These names have the |
|
329 form $p${\tt a}, $p${\tt b}, $p${\tt c},~\ldots, where $p$ is any desired |
|
330 prefix. They are ugly but predictable. |
|
331 |
|
332 \begin{description} |
|
333 \item[\ttindexbold{rename_tac} {\it str} {\it i}] |
|
334 interprets the string {\it str} as a series of blank-separated variable |
|
335 names, and uses them to rename the parameters of subgoal~$i$. The names |
|
336 must be distinct. If there are fewer names than parameters, then the |
|
337 tactic renames the innermost parameters and may modify the remaining ones |
|
338 to ensure that all the parameters are distinct. |
|
339 |
|
340 \item[\ttindexbold{rename_last_tac} {\it prefix} {\it suffixes} {\it i}] |
|
341 generates a list of names by attaching each of the {\it suffixes\/} to the |
|
342 {\it prefix}. It is intended for coding structural induction tactics, |
|
343 where several of the new parameters should have related names. |
|
344 |
|
345 \item[\ttindexbold{Logic.set_rename_prefix} {\it prefix};] |
|
346 sets the prefix for uniform renaming to~{\it prefix}. The default prefix |
|
347 is {\tt"k"}. |
|
348 |
|
349 \item[\ttindexbold{Logic.auto_rename} \tt:= true;] |
|
350 makes Isabelle generate uniform names for parameters. |
|
351 \end{description} |
|
352 |
|
353 |
|
354 \subsection{Composition: resolution without lifting} |
|
355 \index{tactics!for composition|bold} |
|
356 \begin{ttbox} |
|
357 compose_tac: (bool * thm * int) -> int -> tactic |
|
358 \end{ttbox} |
|
359 {\bf Composing} two rules means to resolve them without prior lifting or |
|
360 renaming of unknowns. This low-level operation, which underlies the |
|
361 resolution tactics, may occasionally be useful for special effects. |
|
362 A typical application is \ttindex{res_inst_tac}, which lifts and instantiates a |
|
363 rule, then passes the result to {\tt compose_tac}. |
|
364 \begin{description} |
|
365 \item[\ttindexbold{compose_tac} ($flag$, $rule$, $m$) $i$] |
|
366 refines subgoal~$i$ using $rule$, without lifting. The $rule$ is taken to |
|
367 have the form $\List{\psi@1; \ldots; \psi@m} \Imp \psi$, where $\psi$ need |
|
368 {\bf not} be atomic; thus $m$ determines the number of new subgoals. If |
|
369 $flag$ is {\tt true} then it performs elim-resolution --- it solves the |
|
370 first premise of~$rule$ by assumption and deletes that assumption. |
|
371 \end{description} |
|
372 |
|
373 |
|
374 \section{Managing lots of rules} |
|
375 These operations are not intended for interactive use. They are concerned |
|
376 with the processing of large numbers of rules in automatic proof |
|
377 strategies. Higher-order resolution involving a long list of rules is |
|
378 slow. Filtering techniques can shorten the list of rules given to |
|
379 resolution, and can also detect whether a given subgoal is too flexible, |
|
380 with too many rules applicable. |
|
381 |
|
382 \subsection{Combined resolution and elim-resolution} \label{biresolve_tac} |
|
383 \index{tactics!resolution} |
|
384 \begin{ttbox} |
|
385 biresolve_tac : (bool*thm)list -> int -> tactic |
|
386 bimatch_tac : (bool*thm)list -> int -> tactic |
|
387 subgoals_of_brl : bool*thm -> int |
|
388 lessb : (bool*thm) * (bool*thm) -> bool |
|
389 \end{ttbox} |
|
390 {\bf Bi-resolution} takes a list of $\it (flag,rule)$ pairs. For each |
|
391 pair, it applies resolution if the flag is~{\tt false} and |
|
392 elim-resolution if the flag is~{\tt true}. A single tactic call handles a |
|
393 mixture of introduction and elimination rules. |
|
394 |
|
395 \begin{description} |
|
396 \item[\ttindexbold{biresolve_tac} {\it brls} {\it i}] |
|
397 refines the proof state by resolution or elim-resolution on each rule, as |
|
398 indicated by its flag. It affects subgoal~$i$ of the proof state. |
|
399 |
|
400 \item[\ttindexbold{bimatch_tac}] |
|
401 is like {\tt biresolve_tac}, but performs matching: unknowns in the |
|
402 proof state are never updated (see~\S\ref{match_tac}). |
|
403 |
|
404 \item[\ttindexbold{subgoals_of_brl}({\it flag},{\it rule})] |
|
405 returns the number of new subgoals that bi-resolution would yield for the |
|
406 pair (if applied to a suitable subgoal). This is $n$ if the flag is |
|
407 {\tt false} and $n-1$ if the flag is {\tt true}, where $n$ is the number |
|
408 of premises of the rule. Elim-resolution yields one fewer subgoal than |
|
409 ordinary resolution because it solves the major premise by assumption. |
|
410 |
|
411 \item[\ttindexbold{lessb} ({\it brl1},{\it brl2})] |
|
412 returns the result of |
|
413 \begin{ttbox} |
|
414 subgoals_of_brl {\it brl1} < subgoals_of_brl {\it brl2} |
|
415 \end{ttbox} |
|
416 Note that \hbox{\tt sort lessb {\it brls}} sorts a list of $\it |
|
417 (flag,rule)$ pairs by the number of new subgoals they will yield. Thus, |
|
418 those that yield the fewest subgoals should be tried first. |
|
419 \end{description} |
|
420 |
|
421 |
|
422 \subsection{Discrimination nets for fast resolution} |
|
423 \index{discrimination nets|bold} |
|
424 \index{tactics!resolution} |
|
425 \begin{ttbox} |
|
426 net_resolve_tac : thm list -> int -> tactic |
|
427 net_match_tac : thm list -> int -> tactic |
|
428 net_biresolve_tac: (bool*thm) list -> int -> tactic |
|
429 net_bimatch_tac : (bool*thm) list -> int -> tactic |
|
430 filt_resolve_tac : thm list -> int -> int -> tactic |
|
431 could_unify : term*term->bool |
|
432 filter_thms : (term*term->bool) -> int*term*thm list -> thm list |
|
433 \end{ttbox} |
|
434 The module \ttindex{Net} implements a discrimination net data structure for |
|
435 fast selection of rules \cite[Chapter 14]{charniak80}. A term is |
|
436 classified by the symbol list obtained by flattening it in preorder. |
|
437 The flattening takes account of function applications, constants, and free |
|
438 and bound variables; it identifies all unknowns and also regards |
|
439 $\lambda$-abstractions as unknowns, since they could $\eta$-contract to |
|
440 anything. |
|
441 |
|
442 A discrimination net serves as a polymorphic dictionary indexed by terms. |
|
443 The module provides various functions for inserting and removing items from |
|
444 nets. It provides functions for returning all items whose term could match |
|
445 or unify with a target term. The matching and unification tests are |
|
446 overly lax (due to the identifications mentioned above) but they serve as |
|
447 useful filters. |
|
448 |
|
449 A net can store introduction rules indexed by their conclusion, and |
|
450 elimination rules indexed by their major premise. Isabelle provides |
|
451 several functions for ``compiling'' long lists of rules into fast |
|
452 resolution tactics. When supplied with a list of theorems, these functions |
|
453 build a discrimination net; the net is used when the tactic is applied to a |
|
454 goal. To avoid repreatedly constructing the nets, use currying: bind the |
|
455 resulting tactics to \ML{} identifiers. |
|
456 |
|
457 \begin{description} |
|
458 \item[\ttindexbold{net_resolve_tac} {\it thms}] |
|
459 builds a discrimination net to obtain the effect of a similar call to {\tt |
|
460 resolve_tac}. |
|
461 |
|
462 \item[\ttindexbold{net_match_tac} {\it thms}] |
|
463 builds a discrimination net to obtain the effect of a similar call to {\tt |
|
464 match_tac}. |
|
465 |
|
466 \item[\ttindexbold{net_biresolve_tac} {\it brls}] |
|
467 builds a discrimination net to obtain the effect of a similar call to {\tt |
|
468 biresolve_tac}. |
|
469 |
|
470 \item[\ttindexbold{net_bimatch_tac} {\it brls}] |
|
471 builds a discrimination net to obtain the effect of a similar call to {\tt |
|
472 bimatch_tac}. |
|
473 |
|
474 \item[\ttindexbold{filt_resolve_tac} {\it thms} {\it maxr} {\it i}] |
|
475 uses discrimination nets to extract the {\it thms} that are applicable to |
|
476 subgoal~$i$. If more than {\it maxr\/} theorems are applicable then the |
|
477 tactic fails. Otherwise it calls {\tt resolve_tac}. |
|
478 |
|
479 This tactic helps avoid runaway instantiation of unknowns, for example in |
|
480 type inference. |
|
481 |
|
482 \item[\ttindexbold{could_unify} ({\it t},{\it u})] |
|
483 returns {\tt false} if~$t$ and~$u$ are ``obviously'' non-unifiable, and |
|
484 otherwise returns~{\tt true}. It assumes all variables are distinct, |
|
485 reporting that {\tt ?a=?a} may unify with {\tt 0=1}. |
|
486 |
|
487 \item[\ttindexbold{filter_thms} $could\; (limit,prem,thms)$] |
|
488 returns the list of potentially resolvable rules (in {\it thms\/}) for the |
|
489 subgoal {\it prem}, using the predicate {\it could\/} to compare the |
|
490 conclusion of the subgoal with the conclusion of each rule. The resulting list |
|
491 is no longer than {\it limit}. |
|
492 \end{description} |
|
493 |
|
494 |
|
495 \section{Programming tools for proof strategies} |
|
496 Do not consider using the primitives discussed in this section unless you |
|
497 really need to code tactics from scratch, |
|
498 |
|
499 \subsection{Operations on type {\tt tactic}} |
|
500 \index{tactics!primitives for coding|bold} |
|
501 A tactic maps theorems to theorem sequences (lazy lists). The type |
|
502 constructor for sequences is called \ttindex{Sequence.seq}. To simplify the |
|
503 types of tactics and tacticals, Isabelle defines a type of tactics: |
|
504 \begin{ttbox} |
|
505 datatype tactic = Tactic of thm -> thm Sequence.seq |
|
506 \end{ttbox} |
|
507 {\tt Tactic} and {\tt tapply} convert between tactics and functions. The |
|
508 other operations provide means for coding tactics in a clean style. |
|
509 \begin{ttbox} |
|
510 tapply : tactic * thm -> thm Sequence.seq |
|
511 Tactic : (thm -> thm Sequence.seq) -> tactic |
|
512 PRIMITIVE : (thm -> thm) -> tactic |
|
513 STATE : (thm -> tactic) -> tactic |
|
514 SUBGOAL : ((term*int) -> tactic) -> int -> tactic |
|
515 \end{ttbox} |
|
516 \begin{description} |
|
517 \item[\ttindexbold{tapply} {\it tac} {\it thm}] |
|
518 returns the result of applying the tactic, as a function, to {\it thm}. |
|
519 |
|
520 \item[\ttindexbold{Tactic} {\it f}] |
|
521 packages {\it f} as a tactic. |
|
522 |
|
523 \item[\ttindexbold{PRIMITIVE} $f$] |
|
524 applies $f$ to the proof state and returns the result as a |
|
525 one-element sequence. This packages the meta-rule~$f$ as a tactic. |
|
526 |
|
527 \item[\ttindexbold{STATE} $f$] |
|
528 applies $f$ to the proof state and then applies the resulting tactic to the |
|
529 same state. It supports the following style, where the tactic body is |
|
530 expressed at a high level, but may peek at the proof state: |
|
531 \begin{ttbox} |
|
532 STATE (fn state => {\it some tactic}) |
|
533 \end{ttbox} |
|
534 |
|
535 \item[\ttindexbold{SUBGOAL} $f$ $i$] |
|
536 extracts subgoal~$i$ from the proof state as a term~$t$, and computes a |
|
537 tactic by calling~$f(t,i)$. It applies the resulting tactic to the same |
|
538 state. The tactic body is expressed at a high level, but may peek at a |
|
539 particular subgoal: |
|
540 \begin{ttbox} |
|
541 SUBGOAL (fn (t,i) => {\it some tactic}) |
|
542 \end{ttbox} |
|
543 \end{description} |
|
544 |
|
545 |
|
546 \subsection{Tracing} |
|
547 \index{tactics!tracing|bold} |
|
548 \index{tracing!of tactics} |
|
549 \begin{ttbox} |
|
550 pause_tac: tactic |
|
551 print_tac: tactic |
|
552 \end{ttbox} |
|
553 These violate the functional behaviour of tactics by printing information |
|
554 when they are applied to a proof state. Their output may be difficult to |
|
555 interpret. Note that certain of the searching tacticals, such as {\tt |
|
556 REPEAT}, have built-in tracing options. |
|
557 \begin{description} |
|
558 \item[\ttindexbold{pause_tac}] |
|
559 prints {\tt** Press RETURN to continue:} and then reads a line from the |
|
560 terminal. If this line is blank then it returns the proof state unchanged; |
|
561 otherwise it fails (which may terminate a repetition). |
|
562 |
|
563 \item[\ttindexbold{print_tac}] |
|
564 returns the proof state unchanged, with the side effect of printing it at |
|
565 the terminal. |
|
566 \end{description} |
|
567 |
|
568 |
|
569 \subsection{Sequences} |
|
570 \index{sequences (lazy lists)|bold} |
|
571 The module \ttindex{Sequence} declares a type of lazy lists. It uses |
|
572 Isabelle's type \ttindexbold{option} to represent the possible presence |
|
573 (\ttindexbold{Some}) or absence (\ttindexbold{None}) of |
|
574 a value: |
|
575 \begin{ttbox} |
|
576 datatype 'a option = None | Some of 'a; |
|
577 \end{ttbox} |
|
578 |
|
579 \subsubsection{Basic operations on sequences} |
|
580 \begin{ttbox} |
|
581 Sequence.null : 'a Sequence.seq |
|
582 Sequence.seqof : (unit -> ('a * 'a Sequence.seq) option) |
|
583 -> 'a Sequence.seq |
|
584 Sequence.single : 'a -> 'a Sequence.seq |
|
585 Sequence.pull : 'a Sequence.seq -> ('a * 'a Sequence.seq) option |
|
586 \end{ttbox} |
|
587 \begin{description} |
|
588 \item[{\tt Sequence.null}] |
|
589 is the empty sequence. |
|
590 |
|
591 \item[\tt Sequence.seqof (fn()=> Some($x$,$s$))] |
|
592 constructs the sequence with head~$x$ and tail~$s$, neither of which is |
|
593 evaluated. |
|
594 |
|
595 \item[{\tt Sequence.single} $x$] |
|
596 constructs the sequence containing the single element~$x$. |
|
597 |
|
598 \item[{\tt Sequence.pull} $s$] |
|
599 returns {\tt None} if the sequence is empty and {\tt Some($x$,$s'$)} if the |
|
600 sequence has head~$x$ and tail~$s'$. Warning: calling \hbox{Sequence.pull |
|
601 $s$} again will {\bf recompute} the value of~$x$; it is not stored! |
|
602 \end{description} |
|
603 |
|
604 |
|
605 \subsubsection{Converting between sequences and lists} |
|
606 \begin{ttbox} |
|
607 Sequence.chop: int * 'a Sequence.seq -> 'a list * 'a Sequence.seq |
|
608 Sequence.list_of_s : 'a Sequence.seq -> 'a list |
|
609 Sequence.s_of_list : 'a list -> 'a Sequence.seq |
|
610 \end{ttbox} |
|
611 \begin{description} |
|
612 \item[{\tt Sequence.chop} ($n$, $s$)] |
|
613 returns the first~$n$ elements of~$s$ as a list, paired with the remaining |
|
614 elements of~$s$. If $s$ has fewer than~$n$ elements, then so will the |
|
615 list. |
|
616 |
|
617 \item[{\tt Sequence.list_of_s} $s$] |
|
618 returns the elements of~$s$, which must be finite, as a list. |
|
619 |
|
620 \item[{\tt Sequence.s_of_list} $l$] |
|
621 creates a sequence containing the elements of~$l$. |
|
622 \end{description} |
|
623 |
|
624 |
|
625 \subsubsection{Combining sequences} |
|
626 \begin{ttbox} |
|
627 Sequence.append: 'a Sequence.seq * 'a Sequence.seq -> 'a Sequence.seq |
|
628 Sequence.interleave : 'a Sequence.seq * 'a Sequence.seq |
|
629 -> 'a Sequence.seq |
|
630 Sequence.flats : 'a Sequence.seq Sequence.seq -> 'a Sequence.seq |
|
631 Sequence.maps : ('a -> 'b) -> 'a Sequence.seq -> 'b Sequence.seq |
|
632 Sequence.filters : ('a -> bool) -> 'a Sequence.seq -> 'a Sequence.seq |
|
633 \end{ttbox} |
|
634 \begin{description} |
|
635 \item[{\tt Sequence.append} ($s@1$, $s@2$)] |
|
636 concatenates $s@1$ to $s@2$. |
|
637 |
|
638 \item[{\tt Sequence.interleave} ($s@1$, $s@2$)] |
|
639 joins $s@1$ with $s@2$ by interleaving their elements. The result contains |
|
640 all the elements of the sequences, even if both are infinite. |
|
641 |
|
642 \item[{\tt Sequence.flats} $ss$] |
|
643 concatenates a sequence of sequences. |
|
644 |
|
645 \item[{\tt Sequence.maps} $f$ $s$] |
|
646 applies $f$ to every element of~$s=x@1,x@2,\ldots$, yielding the sequence |
|
647 $f(x@1),f(x@2),\ldots$. |
|
648 |
|
649 \item[{\tt Sequence.filters} $p$ $s$] |
|
650 returns the sequence consisting of all elements~$x$ of~$s$ such that $p(x)$ |
|
651 is {\tt true}. |
|
652 \end{description} |
|
653 |
|
654 \index{tactics|)} |