3 begin |
3 begin |
4 |
4 |
5 chapter \<open>Tactical reasoning\<close> |
5 chapter \<open>Tactical reasoning\<close> |
6 |
6 |
7 text \<open>Tactical reasoning works by refining an initial claim in a |
7 text \<open>Tactical reasoning works by refining an initial claim in a |
8 backwards fashion, until a solved form is reached. A @{text "goal"} |
8 backwards fashion, until a solved form is reached. A \<open>goal\<close> |
9 consists of several subgoals that need to be solved in order to |
9 consists of several subgoals that need to be solved in order to |
10 achieve the main statement; zero subgoals means that the proof may |
10 achieve the main statement; zero subgoals means that the proof may |
11 be finished. A @{text "tactic"} is a refinement operation that maps |
11 be finished. A \<open>tactic\<close> is a refinement operation that maps |
12 a goal to a lazy sequence of potential successors. A @{text |
12 a goal to a lazy sequence of potential successors. A \<open>tactical\<close> is a combinator for composing tactics.\<close> |
13 "tactical"} is a combinator for composing tactics.\<close> |
|
14 |
13 |
15 |
14 |
16 section \<open>Goals \label{sec:tactical-goals}\<close> |
15 section \<open>Goals \label{sec:tactical-goals}\<close> |
17 |
16 |
18 text \<open> |
17 text \<open> |
19 Isabelle/Pure represents a goal as a theorem stating that the |
18 Isabelle/Pure represents a goal as a theorem stating that the |
20 subgoals imply the main goal: @{text "A\<^sub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^sub>n \<Longrightarrow> |
19 subgoals imply the main goal: \<open>A\<^sub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^sub>n \<Longrightarrow> |
21 C"}. The outermost goal structure is that of a Horn Clause: i.e.\ |
20 C\<close>. The outermost goal structure is that of a Horn Clause: i.e.\ |
22 an iterated implication without any quantifiers\footnote{Recall that |
21 an iterated implication without any quantifiers\footnote{Recall that |
23 outermost @{text "\<And>x. \<phi>[x]"} is always represented via schematic |
22 outermost \<open>\<And>x. \<phi>[x]\<close> is always represented via schematic |
24 variables in the body: @{text "\<phi>[?x]"}. These variables may get |
23 variables in the body: \<open>\<phi>[?x]\<close>. These variables may get |
25 instantiated during the course of reasoning.}. For @{text "n = 0"} |
24 instantiated during the course of reasoning.}. For \<open>n = 0\<close> |
26 a goal is called ``solved''. |
25 a goal is called ``solved''. |
27 |
26 |
28 The structure of each subgoal @{text "A\<^sub>i"} is that of a |
27 The structure of each subgoal \<open>A\<^sub>i\<close> is that of a |
29 general Hereditary Harrop Formula @{text "\<And>x\<^sub>1 \<dots> |
28 general Hereditary Harrop Formula \<open>\<And>x\<^sub>1 \<dots> |
30 \<And>x\<^sub>k. H\<^sub>1 \<Longrightarrow> \<dots> \<Longrightarrow> H\<^sub>m \<Longrightarrow> B"}. Here @{text |
29 \<And>x\<^sub>k. H\<^sub>1 \<Longrightarrow> \<dots> \<Longrightarrow> H\<^sub>m \<Longrightarrow> B\<close>. Here \<open>x\<^sub>1, \<dots>, x\<^sub>k\<close> are goal parameters, i.e.\ |
31 "x\<^sub>1, \<dots>, x\<^sub>k"} are goal parameters, i.e.\ |
30 arbitrary-but-fixed entities of certain types, and \<open>H\<^sub>1, \<dots>, H\<^sub>m\<close> are goal hypotheses, i.e.\ facts that may |
32 arbitrary-but-fixed entities of certain types, and @{text |
|
33 "H\<^sub>1, \<dots>, H\<^sub>m"} are goal hypotheses, i.e.\ facts that may |
|
34 be assumed locally. Together, this forms the goal context of the |
31 be assumed locally. Together, this forms the goal context of the |
35 conclusion @{text B} to be established. The goal hypotheses may be |
32 conclusion \<open>B\<close> to be established. The goal hypotheses may be |
36 again arbitrary Hereditary Harrop Formulas, although the level of |
33 again arbitrary Hereditary Harrop Formulas, although the level of |
37 nesting rarely exceeds 1--2 in practice. |
34 nesting rarely exceeds 1--2 in practice. |
38 |
35 |
39 The main conclusion @{text C} is internally marked as a protected |
36 The main conclusion \<open>C\<close> is internally marked as a protected |
40 proposition, which is represented explicitly by the notation @{text |
37 proposition, which is represented explicitly by the notation \<open>#C\<close> here. This ensures that the decomposition into subgoals and |
41 "#C"} here. This ensures that the decomposition into subgoals and |
|
42 main conclusion is well-defined for arbitrarily structured claims. |
38 main conclusion is well-defined for arbitrarily structured claims. |
43 |
39 |
44 \<^medskip> |
40 \<^medskip> |
45 Basic goal management is performed via the following |
41 Basic goal management is performed via the following |
46 Isabelle/Pure rules: |
42 Isabelle/Pure rules: |
47 |
43 |
48 \[ |
44 \[ |
49 \infer[@{text "(init)"}]{@{text "C \<Longrightarrow> #C"}}{} \qquad |
45 \infer[\<open>(init)\<close>]{\<open>C \<Longrightarrow> #C\<close>}{} \qquad |
50 \infer[@{text "(finish)"}]{@{text "C"}}{@{text "#C"}} |
46 \infer[\<open>(finish)\<close>]{\<open>C\<close>}{\<open>#C\<close>} |
51 \] |
47 \] |
52 |
48 |
53 \<^medskip> |
49 \<^medskip> |
54 The following low-level variants admit general reasoning |
50 The following low-level variants admit general reasoning |
55 with protected propositions: |
51 with protected propositions: |
56 |
52 |
57 \[ |
53 \[ |
58 \infer[@{text "(protect n)"}]{@{text "A\<^sub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^sub>n \<Longrightarrow> #C"}}{@{text "A\<^sub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^sub>n \<Longrightarrow> C"}} |
54 \infer[\<open>(protect n)\<close>]{\<open>A\<^sub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^sub>n \<Longrightarrow> #C\<close>}{\<open>A\<^sub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^sub>n \<Longrightarrow> C\<close>} |
59 \] |
55 \] |
60 \[ |
56 \[ |
61 \infer[@{text "(conclude)"}]{@{text "A \<Longrightarrow> \<dots> \<Longrightarrow> C"}}{@{text "A \<Longrightarrow> \<dots> \<Longrightarrow> #C"}} |
57 \infer[\<open>(conclude)\<close>]{\<open>A \<Longrightarrow> \<dots> \<Longrightarrow> C\<close>}{\<open>A \<Longrightarrow> \<dots> \<Longrightarrow> #C\<close>} |
62 \] |
58 \] |
63 \<close> |
59 \<close> |
64 |
60 |
65 text %mlref \<open> |
61 text %mlref \<open> |
66 \begin{mldecls} |
62 \begin{mldecls} |
68 @{index_ML Goal.finish: "Proof.context -> thm -> thm"} \\ |
64 @{index_ML Goal.finish: "Proof.context -> thm -> thm"} \\ |
69 @{index_ML Goal.protect: "int -> thm -> thm"} \\ |
65 @{index_ML Goal.protect: "int -> thm -> thm"} \\ |
70 @{index_ML Goal.conclude: "thm -> thm"} \\ |
66 @{index_ML Goal.conclude: "thm -> thm"} \\ |
71 \end{mldecls} |
67 \end{mldecls} |
72 |
68 |
73 \<^descr> @{ML "Goal.init"}~@{text C} initializes a tactical goal from |
69 \<^descr> @{ML "Goal.init"}~\<open>C\<close> initializes a tactical goal from |
74 the well-formed proposition @{text C}. |
70 the well-formed proposition \<open>C\<close>. |
75 |
71 |
76 \<^descr> @{ML "Goal.finish"}~@{text "ctxt thm"} checks whether theorem |
72 \<^descr> @{ML "Goal.finish"}~\<open>ctxt thm\<close> checks whether theorem |
77 @{text "thm"} is a solved goal (no subgoals), and concludes the |
73 \<open>thm\<close> is a solved goal (no subgoals), and concludes the |
78 result by removing the goal protection. The context is only |
74 result by removing the goal protection. The context is only |
79 required for printing error messages. |
75 required for printing error messages. |
80 |
76 |
81 \<^descr> @{ML "Goal.protect"}~@{text "n thm"} protects the statement |
77 \<^descr> @{ML "Goal.protect"}~\<open>n thm\<close> protects the statement |
82 of theorem @{text "thm"}. The parameter @{text n} indicates the |
78 of theorem \<open>thm\<close>. The parameter \<open>n\<close> indicates the |
83 number of premises to be retained. |
79 number of premises to be retained. |
84 |
80 |
85 \<^descr> @{ML "Goal.conclude"}~@{text "thm"} removes the goal |
81 \<^descr> @{ML "Goal.conclude"}~\<open>thm\<close> removes the goal |
86 protection, even if there are pending subgoals. |
82 protection, even if there are pending subgoals. |
87 \<close> |
83 \<close> |
88 |
84 |
89 |
85 |
90 section \<open>Tactics\label{sec:tactics}\<close> |
86 section \<open>Tactics\label{sec:tactics}\<close> |
91 |
87 |
92 text \<open>A @{text "tactic"} is a function @{text "goal \<rightarrow> goal\<^sup>*\<^sup>*"} that |
88 text \<open>A \<open>tactic\<close> is a function \<open>goal \<rightarrow> goal\<^sup>*\<^sup>*\<close> that |
93 maps a given goal state (represented as a theorem, cf.\ |
89 maps a given goal state (represented as a theorem, cf.\ |
94 \secref{sec:tactical-goals}) to a lazy sequence of potential |
90 \secref{sec:tactical-goals}) to a lazy sequence of potential |
95 successor states. The underlying sequence implementation is lazy |
91 successor states. The underlying sequence implementation is lazy |
96 both in head and tail, and is purely functional in \<^emph>\<open>not\<close> |
92 both in head and tail, and is purely functional in \<^emph>\<open>not\<close> |
97 supporting memoing.\footnote{The lack of memoing and the strict |
93 supporting memoing.\footnote{The lack of memoing and the strict |
119 operate on all subgoals or on a particularly specified subgoal, but |
115 operate on all subgoals or on a particularly specified subgoal, but |
120 must not change the main conclusion (apart from instantiating |
116 must not change the main conclusion (apart from instantiating |
121 schematic goal variables). |
117 schematic goal variables). |
122 |
118 |
123 Tactics with explicit \<^emph>\<open>subgoal addressing\<close> are of the form |
119 Tactics with explicit \<^emph>\<open>subgoal addressing\<close> are of the form |
124 @{text "int \<rightarrow> tactic"} and may be applied to a particular subgoal |
120 \<open>int \<rightarrow> tactic\<close> and may be applied to a particular subgoal |
125 (counting from 1). If the subgoal number is out of range, the |
121 (counting from 1). If the subgoal number is out of range, the |
126 tactic should fail with an empty result sequence, but must not raise |
122 tactic should fail with an empty result sequence, but must not raise |
127 an exception! |
123 an exception! |
128 |
124 |
129 Operating on a particular subgoal means to replace it by an interval |
125 Operating on a particular subgoal means to replace it by an interval |
193 empty sequence. |
189 empty sequence. |
194 |
190 |
195 \<^descr> @{ML all_tac} is a tactic that always succeeds, returning a |
191 \<^descr> @{ML all_tac} is a tactic that always succeeds, returning a |
196 singleton sequence with unchanged goal state. |
192 singleton sequence with unchanged goal state. |
197 |
193 |
198 \<^descr> @{ML print_tac}~@{text "ctxt message"} is like @{ML all_tac}, but |
194 \<^descr> @{ML print_tac}~\<open>ctxt message\<close> is like @{ML all_tac}, but |
199 prints a message together with the goal state on the tracing |
195 prints a message together with the goal state on the tracing |
200 channel. |
196 channel. |
201 |
197 |
202 \<^descr> @{ML PRIMITIVE}~@{text rule} turns a primitive inference rule |
198 \<^descr> @{ML PRIMITIVE}~\<open>rule\<close> turns a primitive inference rule |
203 into a tactic with unique result. Exception @{ML THM} is considered |
199 into a tactic with unique result. Exception @{ML THM} is considered |
204 a regular tactic failure and produces an empty result; other |
200 a regular tactic failure and produces an empty result; other |
205 exceptions are passed through. |
201 exceptions are passed through. |
206 |
202 |
207 \<^descr> @{ML SUBGOAL}~@{text "(fn (subgoal, i) => tactic)"} is the |
203 \<^descr> @{ML SUBGOAL}~\<open>(fn (subgoal, i) => tactic)\<close> is the |
208 most basic form to produce a tactic with subgoal addressing. The |
204 most basic form to produce a tactic with subgoal addressing. The |
209 given abstraction over the subgoal term and subgoal number allows to |
205 given abstraction over the subgoal term and subgoal number allows to |
210 peek at the relevant information of the full goal state. The |
206 peek at the relevant information of the full goal state. The |
211 subgoal range is checked as required above. |
207 subgoal range is checked as required above. |
212 |
208 |
213 \<^descr> @{ML CSUBGOAL} is similar to @{ML SUBGOAL}, but passes the |
209 \<^descr> @{ML CSUBGOAL} is similar to @{ML SUBGOAL}, but passes the |
214 subgoal as @{ML_type cterm} instead of raw @{ML_type term}. This |
210 subgoal as @{ML_type cterm} instead of raw @{ML_type term}. This |
215 avoids expensive re-certification in situations where the subgoal is |
211 avoids expensive re-certification in situations where the subgoal is |
216 used directly for primitive inferences. |
212 used directly for primitive inferences. |
217 |
213 |
218 \<^descr> @{ML SELECT_GOAL}~@{text "tac i"} confines a tactic to the |
214 \<^descr> @{ML SELECT_GOAL}~\<open>tac i\<close> confines a tactic to the |
219 specified subgoal @{text "i"}. This rearranges subgoals and the |
215 specified subgoal \<open>i\<close>. This rearranges subgoals and the |
220 main goal protection (\secref{sec:tactical-goals}), while retaining |
216 main goal protection (\secref{sec:tactical-goals}), while retaining |
221 the syntactic context of the overall goal state (concerning |
217 the syntactic context of the overall goal state (concerning |
222 schematic variables etc.). |
218 schematic variables etc.). |
223 |
219 |
224 \<^descr> @{ML PREFER_GOAL}~@{text "tac i"} rearranges subgoals to put |
220 \<^descr> @{ML PREFER_GOAL}~\<open>tac i\<close> rearranges subgoals to put |
225 @{text "i"} in front. This is similar to @{ML SELECT_GOAL}, but |
221 \<open>i\<close> in front. This is similar to @{ML SELECT_GOAL}, but |
226 without changing the main goal protection. |
222 without changing the main goal protection. |
227 \<close> |
223 \<close> |
228 |
224 |
229 |
225 |
230 subsection \<open>Resolution and assumption tactics \label{sec:resolve-assume-tac}\<close> |
226 subsection \<open>Resolution and assumption tactics \label{sec:resolve-assume-tac}\<close> |
235 it resolves with a rule, proves its first premise by assumption, and |
231 it resolves with a rule, proves its first premise by assumption, and |
236 finally deletes that assumption from any new subgoals. |
232 finally deletes that assumption from any new subgoals. |
237 \<^emph>\<open>Destruct-resolution\<close> is like elim-resolution, but the given |
233 \<^emph>\<open>Destruct-resolution\<close> is like elim-resolution, but the given |
238 destruction rules are first turned into canonical elimination |
234 destruction rules are first turned into canonical elimination |
239 format. \<^emph>\<open>Forward-resolution\<close> is like destruct-resolution, but |
235 format. \<^emph>\<open>Forward-resolution\<close> is like destruct-resolution, but |
240 without deleting the selected assumption. The @{text "r/e/d/f"} |
236 without deleting the selected assumption. The \<open>r/e/d/f\<close> |
241 naming convention is maintained for several different kinds of |
237 naming convention is maintained for several different kinds of |
242 resolution rules and tactics. |
238 resolution rules and tactics. |
243 |
239 |
244 Assumption tactics close a subgoal by unifying some of its premises |
240 Assumption tactics close a subgoal by unifying some of its premises |
245 against its conclusion. |
241 against its conclusion. |
279 @{index_ML ematch_tac: "Proof.context -> thm list -> int -> tactic"} \\ |
275 @{index_ML ematch_tac: "Proof.context -> thm list -> int -> tactic"} \\ |
280 @{index_ML dmatch_tac: "Proof.context -> thm list -> int -> tactic"} \\ |
276 @{index_ML dmatch_tac: "Proof.context -> thm list -> int -> tactic"} \\ |
281 @{index_ML bimatch_tac: "Proof.context -> (bool * thm) list -> int -> tactic"} \\ |
277 @{index_ML bimatch_tac: "Proof.context -> (bool * thm) list -> int -> tactic"} \\ |
282 \end{mldecls} |
278 \end{mldecls} |
283 |
279 |
284 \<^descr> @{ML resolve_tac}~@{text "ctxt thms i"} refines the goal state |
280 \<^descr> @{ML resolve_tac}~\<open>ctxt thms i\<close> refines the goal state |
285 using the given theorems, which should normally be introduction |
281 using the given theorems, which should normally be introduction |
286 rules. The tactic resolves a rule's conclusion with subgoal @{text |
282 rules. The tactic resolves a rule's conclusion with subgoal \<open>i\<close>, replacing it by the corresponding versions of the rule's |
287 i}, replacing it by the corresponding versions of the rule's |
|
288 premises. |
283 premises. |
289 |
284 |
290 \<^descr> @{ML eresolve_tac}~@{text "ctxt thms i"} performs elim-resolution |
285 \<^descr> @{ML eresolve_tac}~\<open>ctxt thms i\<close> performs elim-resolution |
291 with the given theorems, which are normally be elimination rules. |
286 with the given theorems, which are normally be elimination rules. |
292 |
287 |
293 Note that @{ML_text "eresolve_tac ctxt [asm_rl]"} is equivalent to @{ML_text |
288 Note that @{ML_text "eresolve_tac ctxt [asm_rl]"} is equivalent to @{ML_text |
294 "assume_tac ctxt"}, which facilitates mixing of assumption steps with |
289 "assume_tac ctxt"}, which facilitates mixing of assumption steps with |
295 genuine eliminations. |
290 genuine eliminations. |
296 |
291 |
297 \<^descr> @{ML dresolve_tac}~@{text "ctxt thms i"} performs |
292 \<^descr> @{ML dresolve_tac}~\<open>ctxt thms i\<close> performs |
298 destruct-resolution with the given theorems, which should normally |
293 destruct-resolution with the given theorems, which should normally |
299 be destruction rules. This replaces an assumption by the result of |
294 be destruction rules. This replaces an assumption by the result of |
300 applying one of the rules. |
295 applying one of the rules. |
301 |
296 |
302 \<^descr> @{ML forward_tac} is like @{ML dresolve_tac} except that the |
297 \<^descr> @{ML forward_tac} is like @{ML dresolve_tac} except that the |
303 selected assumption is not deleted. It applies a rule to an |
298 selected assumption is not deleted. It applies a rule to an |
304 assumption, adding the result as a new assumption. |
299 assumption, adding the result as a new assumption. |
305 |
300 |
306 \<^descr> @{ML biresolve_tac}~@{text "ctxt brls i"} refines the proof state |
301 \<^descr> @{ML biresolve_tac}~\<open>ctxt brls i\<close> refines the proof state |
307 by resolution or elim-resolution on each rule, as indicated by its |
302 by resolution or elim-resolution on each rule, as indicated by its |
308 flag. It affects subgoal @{text "i"} of the proof state. |
303 flag. It affects subgoal \<open>i\<close> of the proof state. |
309 |
304 |
310 For each pair @{text "(flag, rule)"}, it applies resolution if the |
305 For each pair \<open>(flag, rule)\<close>, it applies resolution if the |
311 flag is @{text "false"} and elim-resolution if the flag is @{text |
306 flag is \<open>false\<close> and elim-resolution if the flag is \<open>true\<close>. A single tactic call handles a mixture of introduction and |
312 "true"}. A single tactic call handles a mixture of introduction and |
|
313 elimination rules, which is useful to organize the search process |
307 elimination rules, which is useful to organize the search process |
314 systematically in proof tools. |
308 systematically in proof tools. |
315 |
309 |
316 \<^descr> @{ML assume_tac}~@{text "ctxt i"} attempts to solve subgoal @{text i} |
310 \<^descr> @{ML assume_tac}~\<open>ctxt i\<close> attempts to solve subgoal \<open>i\<close> |
317 by assumption (modulo higher-order unification). |
311 by assumption (modulo higher-order unification). |
318 |
312 |
319 \<^descr> @{ML eq_assume_tac} is similar to @{ML assume_tac}, but checks |
313 \<^descr> @{ML eq_assume_tac} is similar to @{ML assume_tac}, but checks |
320 only for immediate @{text "\<alpha>"}-convertibility instead of using |
314 only for immediate \<open>\<alpha>\<close>-convertibility instead of using |
321 unification. It succeeds (with a unique next state) if one of the |
315 unification. It succeeds (with a unique next state) if one of the |
322 assumptions is equal to the subgoal's conclusion. Since it does not |
316 assumptions is equal to the subgoal's conclusion. Since it does not |
323 instantiate variables, it cannot make other subgoals unprovable. |
317 instantiate variables, it cannot make other subgoals unprovable. |
324 |
318 |
325 \<^descr> @{ML match_tac}, @{ML ematch_tac}, @{ML dmatch_tac}, and @{ML |
319 \<^descr> @{ML match_tac}, @{ML ematch_tac}, @{ML dmatch_tac}, and @{ML |
344 situations despite its daunting theoretical properties. |
338 situations despite its daunting theoretical properties. |
345 Nonetheless, there are important problem classes where unguided |
339 Nonetheless, there are important problem classes where unguided |
346 higher-order unification is not so useful. This typically involves |
340 higher-order unification is not so useful. This typically involves |
347 rules like universal elimination, existential introduction, or |
341 rules like universal elimination, existential introduction, or |
348 equational substitution. Here the unification problem involves |
342 equational substitution. Here the unification problem involves |
349 fully flexible @{text "?P ?x"} schemes, which are hard to manage |
343 fully flexible \<open>?P ?x\<close> schemes, which are hard to manage |
350 without further hints. |
344 without further hints. |
351 |
345 |
352 By providing a (small) rigid term for @{text "?x"} explicitly, the |
346 By providing a (small) rigid term for \<open>?x\<close> explicitly, the |
353 remaining unification problem is to assign a (large) term to @{text |
347 remaining unification problem is to assign a (large) term to \<open>?P\<close>, according to the shape of the given subgoal. This is |
354 "?P"}, according to the shape of the given subgoal. This is |
|
355 sufficiently well-behaved in most practical situations. |
348 sufficiently well-behaved in most practical situations. |
356 |
349 |
357 \<^medskip> |
350 \<^medskip> |
358 Isabelle provides separate versions of the standard @{text |
351 Isabelle provides separate versions of the standard \<open>r/e/d/f\<close> resolution tactics that allow to provide explicit |
359 "r/e/d/f"} resolution tactics that allow to provide explicit |
|
360 instantiations of unknowns of the given rule, wrt.\ terms that refer |
352 instantiations of unknowns of the given rule, wrt.\ terms that refer |
361 to the implicit context of the selected subgoal. |
353 to the implicit context of the selected subgoal. |
362 |
354 |
363 An instantiation consists of a list of pairs of the form @{text |
355 An instantiation consists of a list of pairs of the form \<open>(?x, t)\<close>, where \<open>?x\<close> is a schematic variable occurring in |
364 "(?x, t)"}, where @{text ?x} is a schematic variable occurring in |
356 the given rule, and \<open>t\<close> is a term from the current proof |
365 the given rule, and @{text t} is a term from the current proof |
|
366 context, augmented by the local goal parameters of the selected |
357 context, augmented by the local goal parameters of the selected |
367 subgoal; cf.\ the @{text "focus"} operation described in |
358 subgoal; cf.\ the \<open>focus\<close> operation described in |
368 \secref{sec:variables}. |
359 \secref{sec:variables}. |
369 |
360 |
370 Entering the syntactic context of a subgoal is a brittle operation, |
361 Entering the syntactic context of a subgoal is a brittle operation, |
371 because its exact form is somewhat accidental, and the choice of |
362 because its exact form is somewhat accidental, and the choice of |
372 bound variable names depends on the presence of other local and |
363 bound variable names depends on the presence of other local and |
373 global names. Explicit renaming of subgoal parameters prior to |
364 global names. Explicit renaming of subgoal parameters prior to |
374 explicit instantiation might help to achieve a bit more robustness. |
365 explicit instantiation might help to achieve a bit more robustness. |
375 |
366 |
376 Type instantiations may be given as well, via pairs like @{text |
367 Type instantiations may be given as well, via pairs like \<open>(?'a, \<tau>)\<close>. Type instantiations are distinguished from term |
377 "(?'a, \<tau>)"}. Type instantiations are distinguished from term |
|
378 instantiations by the syntactic form of the schematic variable. |
368 instantiations by the syntactic form of the schematic variable. |
379 Types are instantiated before terms are. Since term instantiation |
369 Types are instantiated before terms are. Since term instantiation |
380 already performs simple type-inference, so explicit type |
370 already performs simple type-inference, so explicit type |
381 instantiations are seldom necessary. |
371 instantiations are seldom necessary. |
382 \<close> |
372 \<close> |
400 @{index_ML Rule_Insts.thin_tac: "Proof.context -> string -> |
390 @{index_ML Rule_Insts.thin_tac: "Proof.context -> string -> |
401 (binding * string option * mixfix) list -> int -> tactic"} \\ |
391 (binding * string option * mixfix) list -> int -> tactic"} \\ |
402 @{index_ML rename_tac: "string list -> int -> tactic"} \\ |
392 @{index_ML rename_tac: "string list -> int -> tactic"} \\ |
403 \end{mldecls} |
393 \end{mldecls} |
404 |
394 |
405 \<^descr> @{ML Rule_Insts.res_inst_tac}~@{text "ctxt insts thm i"} instantiates the |
395 \<^descr> @{ML Rule_Insts.res_inst_tac}~\<open>ctxt insts thm i\<close> instantiates the |
406 rule @{text thm} with the instantiations @{text insts}, as described |
396 rule \<open>thm\<close> with the instantiations \<open>insts\<close>, as described |
407 above, and then performs resolution on subgoal @{text i}. |
397 above, and then performs resolution on subgoal \<open>i\<close>. |
408 |
398 |
409 \<^descr> @{ML Rule_Insts.eres_inst_tac} is like @{ML Rule_Insts.res_inst_tac}, |
399 \<^descr> @{ML Rule_Insts.eres_inst_tac} is like @{ML Rule_Insts.res_inst_tac}, |
410 but performs elim-resolution. |
400 but performs elim-resolution. |
411 |
401 |
412 \<^descr> @{ML Rule_Insts.dres_inst_tac} is like @{ML Rule_Insts.res_inst_tac}, |
402 \<^descr> @{ML Rule_Insts.dres_inst_tac} is like @{ML Rule_Insts.res_inst_tac}, |
413 but performs destruct-resolution. |
403 but performs destruct-resolution. |
414 |
404 |
415 \<^descr> @{ML Rule_Insts.forw_inst_tac} is like @{ML Rule_Insts.dres_inst_tac} |
405 \<^descr> @{ML Rule_Insts.forw_inst_tac} is like @{ML Rule_Insts.dres_inst_tac} |
416 except that the selected assumption is not deleted. |
406 except that the selected assumption is not deleted. |
417 |
407 |
418 \<^descr> @{ML Rule_Insts.subgoal_tac}~@{text "ctxt \<phi> i"} adds the proposition |
408 \<^descr> @{ML Rule_Insts.subgoal_tac}~\<open>ctxt \<phi> i\<close> adds the proposition |
419 @{text "\<phi>"} as local premise to subgoal @{text "i"}, and poses the |
409 \<open>\<phi>\<close> as local premise to subgoal \<open>i\<close>, and poses the |
420 same as a new subgoal @{text "i + 1"} (in the original context). |
410 same as a new subgoal \<open>i + 1\<close> (in the original context). |
421 |
411 |
422 \<^descr> @{ML Rule_Insts.thin_tac}~@{text "ctxt \<phi> i"} deletes the specified |
412 \<^descr> @{ML Rule_Insts.thin_tac}~\<open>ctxt \<phi> i\<close> deletes the specified |
423 premise from subgoal @{text i}. Note that @{text \<phi>} may contain |
413 premise from subgoal \<open>i\<close>. Note that \<open>\<phi>\<close> may contain |
424 schematic variables, to abbreviate the intended proposition; the |
414 schematic variables, to abbreviate the intended proposition; the |
425 first matching subgoal premise will be deleted. Removing useless |
415 first matching subgoal premise will be deleted. Removing useless |
426 premises from a subgoal increases its readability and can make |
416 premises from a subgoal increases its readability and can make |
427 search tactics run faster. |
417 search tactics run faster. |
428 |
418 |
429 \<^descr> @{ML rename_tac}~@{text "names i"} renames the innermost |
419 \<^descr> @{ML rename_tac}~\<open>names i\<close> renames the innermost |
430 parameters of subgoal @{text i} according to the provided @{text |
420 parameters of subgoal \<open>i\<close> according to the provided \<open>names\<close> (which need to be distinct identifiers). |
431 names} (which need to be distinct identifiers). |
|
432 |
421 |
433 |
422 |
434 For historical reasons, the above instantiation tactics take |
423 For historical reasons, the above instantiation tactics take |
435 unparsed string arguments, which makes them hard to use in general |
424 unparsed string arguments, which makes them hard to use in general |
436 ML code. The slightly more advanced @{ML Subgoal.FOCUS} combinator |
425 ML code. The slightly more advanced @{ML Subgoal.FOCUS} combinator |
451 @{index_ML rotate_tac: "int -> int -> tactic"} \\ |
440 @{index_ML rotate_tac: "int -> int -> tactic"} \\ |
452 @{index_ML distinct_subgoals_tac: tactic} \\ |
441 @{index_ML distinct_subgoals_tac: tactic} \\ |
453 @{index_ML flexflex_tac: "Proof.context -> tactic"} \\ |
442 @{index_ML flexflex_tac: "Proof.context -> tactic"} \\ |
454 \end{mldecls} |
443 \end{mldecls} |
455 |
444 |
456 \<^descr> @{ML rotate_tac}~@{text "n i"} rotates the premises of subgoal |
445 \<^descr> @{ML rotate_tac}~\<open>n i\<close> rotates the premises of subgoal |
457 @{text i} by @{text n} positions: from right to left if @{text n} is |
446 \<open>i\<close> by \<open>n\<close> positions: from right to left if \<open>n\<close> is |
458 positive, and from left to right if @{text n} is negative. |
447 positive, and from left to right if \<open>n\<close> is negative. |
459 |
448 |
460 \<^descr> @{ML distinct_subgoals_tac} removes duplicate subgoals from a |
449 \<^descr> @{ML distinct_subgoals_tac} removes duplicate subgoals from a |
461 proof state. This is potentially inefficient. |
450 proof state. This is potentially inefficient. |
462 |
451 |
463 \<^descr> @{ML flexflex_tac} removes all flex-flex pairs from the proof |
452 \<^descr> @{ML flexflex_tac} removes all flex-flex pairs from the proof |
487 @{index_ML compose_tac: "Proof.context -> (bool * thm * int) -> int -> tactic"} \\ |
476 @{index_ML compose_tac: "Proof.context -> (bool * thm * int) -> int -> tactic"} \\ |
488 @{index_ML Drule.compose: "thm * int * thm -> thm"} \\ |
477 @{index_ML Drule.compose: "thm * int * thm -> thm"} \\ |
489 @{index_ML_op COMP: "thm * thm -> thm"} \\ |
478 @{index_ML_op COMP: "thm * thm -> thm"} \\ |
490 \end{mldecls} |
479 \end{mldecls} |
491 |
480 |
492 \<^descr> @{ML compose_tac}~@{text "ctxt (flag, rule, m) i"} refines subgoal |
481 \<^descr> @{ML compose_tac}~\<open>ctxt (flag, rule, m) i\<close> refines subgoal |
493 @{text "i"} using @{text "rule"}, without lifting. The @{text |
482 \<open>i\<close> using \<open>rule\<close>, without lifting. The \<open>rule\<close> is taken to have the form \<open>\<psi>\<^sub>1 \<Longrightarrow> \<dots> \<psi>\<^sub>m \<Longrightarrow> \<psi>\<close>, where |
494 "rule"} is taken to have the form @{text "\<psi>\<^sub>1 \<Longrightarrow> \<dots> \<psi>\<^sub>m \<Longrightarrow> \<psi>"}, where |
483 \<open>\<psi>\<close> need not be atomic; thus \<open>m\<close> determines the |
495 @{text "\<psi>"} need not be atomic; thus @{text "m"} determines the |
484 number of new subgoals. If \<open>flag\<close> is \<open>true\<close> then it |
496 number of new subgoals. If @{text "flag"} is @{text "true"} then it |
485 performs elim-resolution --- it solves the first premise of \<open>rule\<close> by assumption and deletes that assumption. |
497 performs elim-resolution --- it solves the first premise of @{text |
486 |
498 "rule"} by assumption and deletes that assumption. |
487 \<^descr> @{ML Drule.compose}~\<open>(thm\<^sub>1, i, thm\<^sub>2)\<close> uses \<open>thm\<^sub>1\<close>, |
499 |
488 regarded as an atomic formula, to solve premise \<open>i\<close> of |
500 \<^descr> @{ML Drule.compose}~@{text "(thm\<^sub>1, i, thm\<^sub>2)"} uses @{text "thm\<^sub>1"}, |
489 \<open>thm\<^sub>2\<close>. Let \<open>thm\<^sub>1\<close> and \<open>thm\<^sub>2\<close> be \<open>\<psi>\<close> and \<open>\<phi>\<^sub>1 \<Longrightarrow> \<dots> \<phi>\<^sub>n \<Longrightarrow> \<phi>\<close>. The unique \<open>s\<close> that |
501 regarded as an atomic formula, to solve premise @{text "i"} of |
490 unifies \<open>\<psi>\<close> and \<open>\<phi>\<^sub>i\<close> yields the theorem \<open>(\<phi>\<^sub>1 \<Longrightarrow> |
502 @{text "thm\<^sub>2"}. Let @{text "thm\<^sub>1"} and @{text "thm\<^sub>2"} be @{text |
491 \<dots> \<phi>\<^sub>i\<^sub>-\<^sub>1 \<Longrightarrow> \<phi>\<^sub>i\<^sub>+\<^sub>1 \<Longrightarrow> \<dots> \<phi>\<^sub>n \<Longrightarrow> \<phi>)s\<close>. Multiple results are considered as |
503 "\<psi>"} and @{text "\<phi>\<^sub>1 \<Longrightarrow> \<dots> \<phi>\<^sub>n \<Longrightarrow> \<phi>"}. The unique @{text "s"} that |
|
504 unifies @{text "\<psi>"} and @{text "\<phi>\<^sub>i"} yields the theorem @{text "(\<phi>\<^sub>1 \<Longrightarrow> |
|
505 \<dots> \<phi>\<^sub>i\<^sub>-\<^sub>1 \<Longrightarrow> \<phi>\<^sub>i\<^sub>+\<^sub>1 \<Longrightarrow> \<dots> \<phi>\<^sub>n \<Longrightarrow> \<phi>)s"}. Multiple results are considered as |
|
506 error (exception @{ML THM}). |
492 error (exception @{ML THM}). |
507 |
493 |
508 \<^descr> @{text "thm\<^sub>1 COMP thm\<^sub>2"} is the same as @{text "Drule.compose |
494 \<^descr> \<open>thm\<^sub>1 COMP thm\<^sub>2\<close> is the same as \<open>Drule.compose |
509 (thm\<^sub>1, 1, thm\<^sub>2)"}. |
495 (thm\<^sub>1, 1, thm\<^sub>2)\<close>. |
510 |
496 |
511 |
497 |
512 \begin{warn} |
498 \begin{warn} |
513 These low-level operations are stepping outside the structure |
499 These low-level operations are stepping outside the structure |
514 imposed by regular rule resolution. Used without understanding of |
500 imposed by regular rule resolution. Used without understanding of |
552 @{index_ML_op "APPEND'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\ |
538 @{index_ML_op "APPEND'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\ |
553 @{index_ML "EVERY'": "('a -> tactic) list -> 'a -> tactic"} \\ |
539 @{index_ML "EVERY'": "('a -> tactic) list -> 'a -> tactic"} \\ |
554 @{index_ML "FIRST'": "('a -> tactic) list -> 'a -> tactic"} \\ |
540 @{index_ML "FIRST'": "('a -> tactic) list -> 'a -> tactic"} \\ |
555 \end{mldecls} |
541 \end{mldecls} |
556 |
542 |
557 \<^descr> @{text "tac\<^sub>1"}~@{ML_op THEN}~@{text "tac\<^sub>2"} is the sequential |
543 \<^descr> \<open>tac\<^sub>1\<close>~@{ML_op THEN}~\<open>tac\<^sub>2\<close> is the sequential |
558 composition of @{text "tac\<^sub>1"} and @{text "tac\<^sub>2"}. Applied to a goal |
544 composition of \<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close>. Applied to a goal |
559 state, it returns all states reachable in two steps by applying |
545 state, it returns all states reachable in two steps by applying |
560 @{text "tac\<^sub>1"} followed by @{text "tac\<^sub>2"}. First, it applies @{text |
546 \<open>tac\<^sub>1\<close> followed by \<open>tac\<^sub>2\<close>. First, it applies \<open>tac\<^sub>1\<close> to the goal state, getting a sequence of possible next |
561 "tac\<^sub>1"} to the goal state, getting a sequence of possible next |
547 states; then, it applies \<open>tac\<^sub>2\<close> to each of these and |
562 states; then, it applies @{text "tac\<^sub>2"} to each of these and |
|
563 concatenates the results to produce again one flat sequence of |
548 concatenates the results to produce again one flat sequence of |
564 states. |
549 states. |
565 |
550 |
566 \<^descr> @{text "tac\<^sub>1"}~@{ML_op ORELSE}~@{text "tac\<^sub>2"} makes a choice |
551 \<^descr> \<open>tac\<^sub>1\<close>~@{ML_op ORELSE}~\<open>tac\<^sub>2\<close> makes a choice |
567 between @{text "tac\<^sub>1"} and @{text "tac\<^sub>2"}. Applied to a state, it |
552 between \<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close>. Applied to a state, it |
568 tries @{text "tac\<^sub>1"} and returns the result if non-empty; if @{text |
553 tries \<open>tac\<^sub>1\<close> and returns the result if non-empty; if \<open>tac\<^sub>1\<close> fails then it uses \<open>tac\<^sub>2\<close>. This is a deterministic |
569 "tac\<^sub>1"} fails then it uses @{text "tac\<^sub>2"}. This is a deterministic |
554 choice: if \<open>tac\<^sub>1\<close> succeeds then \<open>tac\<^sub>2\<close> is excluded |
570 choice: if @{text "tac\<^sub>1"} succeeds then @{text "tac\<^sub>2"} is excluded |
|
571 from the result. |
555 from the result. |
572 |
556 |
573 \<^descr> @{text "tac\<^sub>1"}~@{ML_op APPEND}~@{text "tac\<^sub>2"} concatenates the |
557 \<^descr> \<open>tac\<^sub>1\<close>~@{ML_op APPEND}~\<open>tac\<^sub>2\<close> concatenates the |
574 possible results of @{text "tac\<^sub>1"} and @{text "tac\<^sub>2"}. Unlike |
558 possible results of \<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close>. Unlike |
575 @{ML_op "ORELSE"} there is \<^emph>\<open>no commitment\<close> to either tactic, so |
559 @{ML_op "ORELSE"} there is \<^emph>\<open>no commitment\<close> to either tactic, so |
576 @{ML_op "APPEND"} helps to avoid incompleteness during search, at |
560 @{ML_op "APPEND"} helps to avoid incompleteness during search, at |
577 the cost of potential inefficiencies. |
561 the cost of potential inefficiencies. |
578 |
562 |
579 \<^descr> @{ML EVERY}~@{text "[tac\<^sub>1, \<dots>, tac\<^sub>n]"} abbreviates @{text |
563 \<^descr> @{ML EVERY}~\<open>[tac\<^sub>1, \<dots>, tac\<^sub>n]\<close> abbreviates \<open>tac\<^sub>1\<close>~@{ML_op THEN}~\<open>\<dots>\<close>~@{ML_op THEN}~\<open>tac\<^sub>n\<close>. |
580 "tac\<^sub>1"}~@{ML_op THEN}~@{text "\<dots>"}~@{ML_op THEN}~@{text "tac\<^sub>n"}. |
|
581 Note that @{ML "EVERY []"} is the same as @{ML all_tac}: it always |
564 Note that @{ML "EVERY []"} is the same as @{ML all_tac}: it always |
582 succeeds. |
565 succeeds. |
583 |
566 |
584 \<^descr> @{ML FIRST}~@{text "[tac\<^sub>1, \<dots>, tac\<^sub>n]"} abbreviates @{text |
567 \<^descr> @{ML FIRST}~\<open>[tac\<^sub>1, \<dots>, tac\<^sub>n]\<close> abbreviates \<open>tac\<^sub>1\<close>~@{ML_op ORELSE}~\<open>\<dots>\<close>~@{ML_op "ORELSE"}~\<open>tac\<^sub>n\<close>. Note that @{ML "FIRST []"} is the same as @{ML no_tac}: it |
585 "tac\<^sub>1"}~@{ML_op ORELSE}~@{text "\<dots>"}~@{ML_op "ORELSE"}~@{text |
|
586 "tac\<^sub>n"}. Note that @{ML "FIRST []"} is the same as @{ML no_tac}: it |
|
587 always fails. |
568 always fails. |
588 |
569 |
589 \<^descr> @{ML_op "THEN'"} is the lifted version of @{ML_op "THEN"}, for |
570 \<^descr> @{ML_op "THEN'"} is the lifted version of @{ML_op "THEN"}, for |
590 tactics with explicit subgoal addressing. So @{text |
571 tactics with explicit subgoal addressing. So \<open>(tac\<^sub>1\<close>~@{ML_op THEN'}~\<open>tac\<^sub>2) i\<close> is the same as \<open>(tac\<^sub>1 i\<close>~@{ML_op THEN}~\<open>tac\<^sub>2 i)\<close>. |
591 "(tac\<^sub>1"}~@{ML_op THEN'}~@{text "tac\<^sub>2) i"} is the same as @{text |
|
592 "(tac\<^sub>1 i"}~@{ML_op THEN}~@{text "tac\<^sub>2 i)"}. |
|
593 |
572 |
594 The other primed tacticals work analogously. |
573 The other primed tacticals work analogously. |
595 \<close> |
574 \<close> |
596 |
575 |
597 |
576 |
608 @{index_ML "REPEAT1": "tactic -> tactic"} \\ |
587 @{index_ML "REPEAT1": "tactic -> tactic"} \\ |
609 @{index_ML "REPEAT_DETERM": "tactic -> tactic"} \\ |
588 @{index_ML "REPEAT_DETERM": "tactic -> tactic"} \\ |
610 @{index_ML "REPEAT_DETERM_N": "int -> tactic -> tactic"} \\ |
589 @{index_ML "REPEAT_DETERM_N": "int -> tactic -> tactic"} \\ |
611 \end{mldecls} |
590 \end{mldecls} |
612 |
591 |
613 \<^descr> @{ML TRY}~@{text "tac"} applies @{text "tac"} to the goal |
592 \<^descr> @{ML TRY}~\<open>tac\<close> applies \<open>tac\<close> to the goal |
614 state and returns the resulting sequence, if non-empty; otherwise it |
593 state and returns the resulting sequence, if non-empty; otherwise it |
615 returns the original state. Thus, it applies @{text "tac"} at most |
594 returns the original state. Thus, it applies \<open>tac\<close> at most |
616 once. |
595 once. |
617 |
596 |
618 Note that for tactics with subgoal addressing, the combinator can be |
597 Note that for tactics with subgoal addressing, the combinator can be |
619 applied via functional composition: @{ML "TRY"}~@{ML_op o}~@{text |
598 applied via functional composition: @{ML "TRY"}~@{ML_op o}~\<open>tac\<close>. There is no need for @{verbatim TRY'}. |
620 "tac"}. There is no need for @{verbatim TRY'}. |
599 |
621 |
600 \<^descr> @{ML REPEAT}~\<open>tac\<close> applies \<open>tac\<close> to the goal |
622 \<^descr> @{ML REPEAT}~@{text "tac"} applies @{text "tac"} to the goal |
|
623 state and, recursively, to each element of the resulting sequence. |
601 state and, recursively, to each element of the resulting sequence. |
624 The resulting sequence consists of those states that make @{text |
602 The resulting sequence consists of those states that make \<open>tac\<close> fail. Thus, it applies \<open>tac\<close> as many times as |
625 "tac"} fail. Thus, it applies @{text "tac"} as many times as |
|
626 possible (including zero times), and allows backtracking over each |
603 possible (including zero times), and allows backtracking over each |
627 invocation of @{text "tac"}. @{ML REPEAT} is more general than @{ML |
604 invocation of \<open>tac\<close>. @{ML REPEAT} is more general than @{ML |
628 REPEAT_DETERM}, but requires more space. |
605 REPEAT_DETERM}, but requires more space. |
629 |
606 |
630 \<^descr> @{ML REPEAT1}~@{text "tac"} is like @{ML REPEAT}~@{text "tac"} |
607 \<^descr> @{ML REPEAT1}~\<open>tac\<close> is like @{ML REPEAT}~\<open>tac\<close> |
631 but it always applies @{text "tac"} at least once, failing if this |
608 but it always applies \<open>tac\<close> at least once, failing if this |
632 is impossible. |
609 is impossible. |
633 |
610 |
634 \<^descr> @{ML REPEAT_DETERM}~@{text "tac"} applies @{text "tac"} to the |
611 \<^descr> @{ML REPEAT_DETERM}~\<open>tac\<close> applies \<open>tac\<close> to the |
635 goal state and, recursively, to the head of the resulting sequence. |
612 goal state and, recursively, to the head of the resulting sequence. |
636 It returns the first state to make @{text "tac"} fail. It is |
613 It returns the first state to make \<open>tac\<close> fail. It is |
637 deterministic, discarding alternative outcomes. |
614 deterministic, discarding alternative outcomes. |
638 |
615 |
639 \<^descr> @{ML REPEAT_DETERM_N}~@{text "n tac"} is like @{ML |
616 \<^descr> @{ML REPEAT_DETERM_N}~\<open>n tac\<close> is like @{ML |
640 REPEAT_DETERM}~@{text "tac"} but the number of repetitions is bound |
617 REPEAT_DETERM}~\<open>tac\<close> but the number of repetitions is bound |
641 by @{text "n"} (where @{ML "~1"} means @{text "\<infinity>"}). |
618 by \<open>n\<close> (where @{ML "~1"} means \<open>\<infinity>\<close>). |
642 \<close> |
619 \<close> |
643 |
620 |
644 text %mlex \<open>The basic tactics and tacticals considered above follow |
621 text %mlex \<open>The basic tactics and tacticals considered above follow |
645 some algebraic laws: |
622 some algebraic laws: |
646 |
623 |
647 \<^item> @{ML all_tac} is the identity element of the tactical @{ML_op |
624 \<^item> @{ML all_tac} is the identity element of the tactical @{ML_op |
648 "THEN"}. |
625 "THEN"}. |
649 |
626 |
650 \<^item> @{ML no_tac} is the identity element of @{ML_op "ORELSE"} and |
627 \<^item> @{ML no_tac} is the identity element of @{ML_op "ORELSE"} and |
651 @{ML_op "APPEND"}. Also, it is a zero element for @{ML_op "THEN"}, |
628 @{ML_op "APPEND"}. Also, it is a zero element for @{ML_op "THEN"}, |
652 which means that @{text "tac"}~@{ML_op THEN}~@{ML no_tac} is |
629 which means that \<open>tac\<close>~@{ML_op THEN}~@{ML no_tac} is |
653 equivalent to @{ML no_tac}. |
630 equivalent to @{ML no_tac}. |
654 |
631 |
655 \<^item> @{ML TRY} and @{ML REPEAT} can be expressed as (recursive) |
632 \<^item> @{ML TRY} and @{ML REPEAT} can be expressed as (recursive) |
656 functions over more basic combinators (ignoring some internal |
633 functions over more basic combinators (ignoring some internal |
657 implementation tricks): |
634 implementation tricks): |
660 ML \<open> |
637 ML \<open> |
661 fun TRY tac = tac ORELSE all_tac; |
638 fun TRY tac = tac ORELSE all_tac; |
662 fun REPEAT tac st = ((tac THEN REPEAT tac) ORELSE all_tac) st; |
639 fun REPEAT tac st = ((tac THEN REPEAT tac) ORELSE all_tac) st; |
663 \<close> |
640 \<close> |
664 |
641 |
665 text \<open>If @{text "tac"} can return multiple outcomes then so can @{ML |
642 text \<open>If \<open>tac\<close> can return multiple outcomes then so can @{ML |
666 REPEAT}~@{text "tac"}. @{ML REPEAT} uses @{ML_op "ORELSE"} and not |
643 REPEAT}~\<open>tac\<close>. @{ML REPEAT} uses @{ML_op "ORELSE"} and not |
667 @{ML_op "APPEND"}, it applies @{text "tac"} as many times as |
644 @{ML_op "APPEND"}, it applies \<open>tac\<close> as many times as |
668 possible in each outcome. |
645 possible in each outcome. |
669 |
646 |
670 \begin{warn} |
647 \begin{warn} |
671 Note the explicit abstraction over the goal state in the ML |
648 Note the explicit abstraction over the goal state in the ML |
672 definition of @{ML REPEAT}. Recursive tacticals must be coded in |
649 definition of @{ML REPEAT}. Recursive tacticals must be coded in |
673 this awkward fashion to avoid infinite recursion of eager functional |
650 this awkward fashion to avoid infinite recursion of eager functional |
674 evaluation in Standard ML. The following attempt would make @{ML |
651 evaluation in Standard ML. The following attempt would make @{ML |
675 REPEAT}~@{text "tac"} loop: |
652 REPEAT}~\<open>tac\<close> loop: |
676 \end{warn} |
653 \end{warn} |
677 \<close> |
654 \<close> |
678 |
655 |
679 ML_val \<open> |
656 ML_val \<open> |
680 (*BAD -- does not terminate!*) |
657 (*BAD -- does not terminate!*) |
688 @{ML_type "int -> tactic"} can be used together with tacticals that |
665 @{ML_type "int -> tactic"} can be used together with tacticals that |
689 act like ``subgoal quantifiers'': guided by success of the body |
666 act like ``subgoal quantifiers'': guided by success of the body |
690 tactic a certain range of subgoals is covered. Thus the body tactic |
667 tactic a certain range of subgoals is covered. Thus the body tactic |
691 is applied to \<^emph>\<open>all\<close> subgoals, \<^emph>\<open>some\<close> subgoal etc. |
668 is applied to \<^emph>\<open>all\<close> subgoals, \<^emph>\<open>some\<close> subgoal etc. |
692 |
669 |
693 Suppose that the goal state has @{text "n \<ge> 0"} subgoals. Many of |
670 Suppose that the goal state has \<open>n \<ge> 0\<close> subgoals. Many of |
694 these tacticals address subgoal ranges counting downwards from |
671 these tacticals address subgoal ranges counting downwards from |
695 @{text "n"} towards @{text "1"}. This has the fortunate effect that |
672 \<open>n\<close> towards \<open>1\<close>. This has the fortunate effect that |
696 newly emerging subgoals are concatenated in the result, without |
673 newly emerging subgoals are concatenated in the result, without |
697 interfering each other. Nonetheless, there might be situations |
674 interfering each other. Nonetheless, there might be situations |
698 where a different order is desired.\<close> |
675 where a different order is desired.\<close> |
699 |
676 |
700 text %mlref \<open> |
677 text %mlref \<open> |
706 @{index_ML REPEAT_SOME: "(int -> tactic) -> tactic"} \\ |
683 @{index_ML REPEAT_SOME: "(int -> tactic) -> tactic"} \\ |
707 @{index_ML REPEAT_FIRST: "(int -> tactic) -> tactic"} \\ |
684 @{index_ML REPEAT_FIRST: "(int -> tactic) -> tactic"} \\ |
708 @{index_ML RANGE: "(int -> tactic) list -> int -> tactic"} \\ |
685 @{index_ML RANGE: "(int -> tactic) list -> int -> tactic"} \\ |
709 \end{mldecls} |
686 \end{mldecls} |
710 |
687 |
711 \<^descr> @{ML ALLGOALS}~@{text "tac"} is equivalent to @{text "tac |
688 \<^descr> @{ML ALLGOALS}~\<open>tac\<close> is equivalent to \<open>tac |
712 n"}~@{ML_op THEN}~@{text "\<dots>"}~@{ML_op THEN}~@{text "tac 1"}. It |
689 n\<close>~@{ML_op THEN}~\<open>\<dots>\<close>~@{ML_op THEN}~\<open>tac 1\<close>. It |
713 applies the @{text tac} to all the subgoals, counting downwards. |
690 applies the \<open>tac\<close> to all the subgoals, counting downwards. |
714 |
691 |
715 \<^descr> @{ML SOMEGOAL}~@{text "tac"} is equivalent to @{text "tac |
692 \<^descr> @{ML SOMEGOAL}~\<open>tac\<close> is equivalent to \<open>tac |
716 n"}~@{ML_op ORELSE}~@{text "\<dots>"}~@{ML_op ORELSE}~@{text "tac 1"}. It |
693 n\<close>~@{ML_op ORELSE}~\<open>\<dots>\<close>~@{ML_op ORELSE}~\<open>tac 1\<close>. It |
717 applies @{text "tac"} to one subgoal, counting downwards. |
694 applies \<open>tac\<close> to one subgoal, counting downwards. |
718 |
695 |
719 \<^descr> @{ML FIRSTGOAL}~@{text "tac"} is equivalent to @{text "tac |
696 \<^descr> @{ML FIRSTGOAL}~\<open>tac\<close> is equivalent to \<open>tac |
720 1"}~@{ML_op ORELSE}~@{text "\<dots>"}~@{ML_op ORELSE}~@{text "tac n"}. It |
697 1\<close>~@{ML_op ORELSE}~\<open>\<dots>\<close>~@{ML_op ORELSE}~\<open>tac n\<close>. It |
721 applies @{text "tac"} to one subgoal, counting upwards. |
698 applies \<open>tac\<close> to one subgoal, counting upwards. |
722 |
699 |
723 \<^descr> @{ML HEADGOAL}~@{text "tac"} is equivalent to @{text "tac 1"}. |
700 \<^descr> @{ML HEADGOAL}~\<open>tac\<close> is equivalent to \<open>tac 1\<close>. |
724 It applies @{text "tac"} unconditionally to the first subgoal. |
701 It applies \<open>tac\<close> unconditionally to the first subgoal. |
725 |
702 |
726 \<^descr> @{ML REPEAT_SOME}~@{text "tac"} applies @{text "tac"} once or |
703 \<^descr> @{ML REPEAT_SOME}~\<open>tac\<close> applies \<open>tac\<close> once or |
727 more to a subgoal, counting downwards. |
704 more to a subgoal, counting downwards. |
728 |
705 |
729 \<^descr> @{ML REPEAT_FIRST}~@{text "tac"} applies @{text "tac"} once or |
706 \<^descr> @{ML REPEAT_FIRST}~\<open>tac\<close> applies \<open>tac\<close> once or |
730 more to a subgoal, counting upwards. |
707 more to a subgoal, counting upwards. |
731 |
708 |
732 \<^descr> @{ML RANGE}~@{text "[tac\<^sub>1, \<dots>, tac\<^sub>k] i"} is equivalent to |
709 \<^descr> @{ML RANGE}~\<open>[tac\<^sub>1, \<dots>, tac\<^sub>k] i\<close> is equivalent to |
733 @{text "tac\<^sub>k (i + k - 1)"}~@{ML_op THEN}~@{text "\<dots>"}~@{ML_op |
710 \<open>tac\<^sub>k (i + k - 1)\<close>~@{ML_op THEN}~\<open>\<dots>\<close>~@{ML_op |
734 THEN}~@{text "tac\<^sub>1 i"}. It applies the given list of tactics to the |
711 THEN}~\<open>tac\<^sub>1 i\<close>. It applies the given list of tactics to the |
735 corresponding range of subgoals, counting downwards. |
712 corresponding range of subgoals, counting downwards. |
736 \<close> |
713 \<close> |
737 |
714 |
738 |
715 |
739 subsection \<open>Control and search tacticals\<close> |
716 subsection \<open>Control and search tacticals\<close> |
755 \begin{mldecls} |
732 \begin{mldecls} |
756 @{index_ML FILTER: "(thm -> bool) -> tactic -> tactic"} \\ |
733 @{index_ML FILTER: "(thm -> bool) -> tactic -> tactic"} \\ |
757 @{index_ML CHANGED: "tactic -> tactic"} \\ |
734 @{index_ML CHANGED: "tactic -> tactic"} \\ |
758 \end{mldecls} |
735 \end{mldecls} |
759 |
736 |
760 \<^descr> @{ML FILTER}~@{text "sat tac"} applies @{text "tac"} to the |
737 \<^descr> @{ML FILTER}~\<open>sat tac\<close> applies \<open>tac\<close> to the |
761 goal state and returns a sequence consisting of those result goal |
738 goal state and returns a sequence consisting of those result goal |
762 states that are satisfactory in the sense of @{text "sat"}. |
739 states that are satisfactory in the sense of \<open>sat\<close>. |
763 |
740 |
764 \<^descr> @{ML CHANGED}~@{text "tac"} applies @{text "tac"} to the goal |
741 \<^descr> @{ML CHANGED}~\<open>tac\<close> applies \<open>tac\<close> to the goal |
765 state and returns precisely those states that differ from the |
742 state and returns precisely those states that differ from the |
766 original state (according to @{ML Thm.eq_thm}). Thus @{ML |
743 original state (according to @{ML Thm.eq_thm}). Thus @{ML |
767 CHANGED}~@{text "tac"} always has some effect on the state. |
744 CHANGED}~\<open>tac\<close> always has some effect on the state. |
768 \<close> |
745 \<close> |
769 |
746 |
770 |
747 |
771 subsubsection \<open>Depth-first search\<close> |
748 subsubsection \<open>Depth-first search\<close> |
772 |
749 |
775 @{index_ML DEPTH_FIRST: "(thm -> bool) -> tactic -> tactic"} \\ |
752 @{index_ML DEPTH_FIRST: "(thm -> bool) -> tactic -> tactic"} \\ |
776 @{index_ML DEPTH_SOLVE: "tactic -> tactic"} \\ |
753 @{index_ML DEPTH_SOLVE: "tactic -> tactic"} \\ |
777 @{index_ML DEPTH_SOLVE_1: "tactic -> tactic"} \\ |
754 @{index_ML DEPTH_SOLVE_1: "tactic -> tactic"} \\ |
778 \end{mldecls} |
755 \end{mldecls} |
779 |
756 |
780 \<^descr> @{ML DEPTH_FIRST}~@{text "sat tac"} returns the goal state if |
757 \<^descr> @{ML DEPTH_FIRST}~\<open>sat tac\<close> returns the goal state if |
781 @{text "sat"} returns true. Otherwise it applies @{text "tac"}, |
758 \<open>sat\<close> returns true. Otherwise it applies \<open>tac\<close>, |
782 then recursively searches from each element of the resulting |
759 then recursively searches from each element of the resulting |
783 sequence. The code uses a stack for efficiency, in effect applying |
760 sequence. The code uses a stack for efficiency, in effect applying |
784 @{text "tac"}~@{ML_op THEN}~@{ML DEPTH_FIRST}~@{text "sat tac"} to |
761 \<open>tac\<close>~@{ML_op THEN}~@{ML DEPTH_FIRST}~\<open>sat tac\<close> to |
785 the state. |
762 the state. |
786 |
763 |
787 \<^descr> @{ML DEPTH_SOLVE}@{text "tac"} uses @{ML DEPTH_FIRST} to |
764 \<^descr> @{ML DEPTH_SOLVE}\<open>tac\<close> uses @{ML DEPTH_FIRST} to |
788 search for states having no subgoals. |
765 search for states having no subgoals. |
789 |
766 |
790 \<^descr> @{ML DEPTH_SOLVE_1}~@{text "tac"} uses @{ML DEPTH_FIRST} to |
767 \<^descr> @{ML DEPTH_SOLVE_1}~\<open>tac\<close> uses @{ML DEPTH_FIRST} to |
791 search for states having fewer subgoals than the given state. Thus, |
768 search for states having fewer subgoals than the given state. Thus, |
792 it insists upon solving at least one subgoal. |
769 it insists upon solving at least one subgoal. |
793 \<close> |
770 \<close> |
794 |
771 |
795 |
772 |
802 @{index_ML THEN_BEST_FIRST: "tactic -> (thm -> bool) * (thm -> int) -> tactic -> tactic"} \\ |
779 @{index_ML THEN_BEST_FIRST: "tactic -> (thm -> bool) * (thm -> int) -> tactic -> tactic"} \\ |
803 \end{mldecls} |
780 \end{mldecls} |
804 |
781 |
805 These search strategies will find a solution if one exists. |
782 These search strategies will find a solution if one exists. |
806 However, they do not enumerate all solutions; they terminate after |
783 However, they do not enumerate all solutions; they terminate after |
807 the first satisfactory result from @{text "tac"}. |
784 the first satisfactory result from \<open>tac\<close>. |
808 |
785 |
809 \<^descr> @{ML BREADTH_FIRST}~@{text "sat tac"} uses breadth-first |
786 \<^descr> @{ML BREADTH_FIRST}~\<open>sat tac\<close> uses breadth-first |
810 search to find states for which @{text "sat"} is true. For most |
787 search to find states for which \<open>sat\<close> is true. For most |
811 applications, it is too slow. |
788 applications, it is too slow. |
812 |
789 |
813 \<^descr> @{ML BEST_FIRST}~@{text "(sat, dist) tac"} does a heuristic |
790 \<^descr> @{ML BEST_FIRST}~\<open>(sat, dist) tac\<close> does a heuristic |
814 search, using @{text "dist"} to estimate the distance from a |
791 search, using \<open>dist\<close> to estimate the distance from a |
815 satisfactory state (in the sense of @{text "sat"}). It maintains a |
792 satisfactory state (in the sense of \<open>sat\<close>). It maintains a |
816 list of states ordered by distance. It applies @{text "tac"} to the |
793 list of states ordered by distance. It applies \<open>tac\<close> to the |
817 head of this list; if the result contains any satisfactory states, |
794 head of this list; if the result contains any satisfactory states, |
818 then it returns them. Otherwise, @{ML BEST_FIRST} adds the new |
795 then it returns them. Otherwise, @{ML BEST_FIRST} adds the new |
819 states to the list, and continues. |
796 states to the list, and continues. |
820 |
797 |
821 The distance function is typically @{ML size_of_thm}, which computes |
798 The distance function is typically @{ML size_of_thm}, which computes |
822 the size of the state. The smaller the state, the fewer and simpler |
799 the size of the state. The smaller the state, the fewer and simpler |
823 subgoals it has. |
800 subgoals it has. |
824 |
801 |
825 \<^descr> @{ML THEN_BEST_FIRST}~@{text "tac\<^sub>0 (sat, dist) tac"} is like |
802 \<^descr> @{ML THEN_BEST_FIRST}~\<open>tac\<^sub>0 (sat, dist) tac\<close> is like |
826 @{ML BEST_FIRST}, except that the priority queue initially contains |
803 @{ML BEST_FIRST}, except that the priority queue initially contains |
827 the result of applying @{text "tac\<^sub>0"} to the goal state. This |
804 the result of applying \<open>tac\<^sub>0\<close> to the goal state. This |
828 tactical permits separate tactics for starting the search and |
805 tactical permits separate tactics for starting the search and |
829 continuing the search. |
806 continuing the search. |
830 \<close> |
807 \<close> |
831 |
808 |
832 |
809 |
838 @{index_ML IF_UNSOLVED: "tactic -> tactic"} \\ |
815 @{index_ML IF_UNSOLVED: "tactic -> tactic"} \\ |
839 @{index_ML SOLVE: "tactic -> tactic"} \\ |
816 @{index_ML SOLVE: "tactic -> tactic"} \\ |
840 @{index_ML DETERM: "tactic -> tactic"} \\ |
817 @{index_ML DETERM: "tactic -> tactic"} \\ |
841 \end{mldecls} |
818 \end{mldecls} |
842 |
819 |
843 \<^descr> @{ML COND}~@{text "sat tac\<^sub>1 tac\<^sub>2"} applies @{text "tac\<^sub>1"} to |
820 \<^descr> @{ML COND}~\<open>sat tac\<^sub>1 tac\<^sub>2\<close> applies \<open>tac\<^sub>1\<close> to |
844 the goal state if it satisfies predicate @{text "sat"}, and applies |
821 the goal state if it satisfies predicate \<open>sat\<close>, and applies |
845 @{text "tac\<^sub>2"}. It is a conditional tactical in that only one of |
822 \<open>tac\<^sub>2\<close>. It is a conditional tactical in that only one of |
846 @{text "tac\<^sub>1"} and @{text "tac\<^sub>2"} is applied to a goal state. |
823 \<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close> is applied to a goal state. |
847 However, both @{text "tac\<^sub>1"} and @{text "tac\<^sub>2"} are evaluated |
824 However, both \<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close> are evaluated |
848 because ML uses eager evaluation. |
825 because ML uses eager evaluation. |
849 |
826 |
850 \<^descr> @{ML IF_UNSOLVED}~@{text "tac"} applies @{text "tac"} to the |
827 \<^descr> @{ML IF_UNSOLVED}~\<open>tac\<close> applies \<open>tac\<close> to the |
851 goal state if it has any subgoals, and simply returns the goal state |
828 goal state if it has any subgoals, and simply returns the goal state |
852 otherwise. Many common tactics, such as @{ML resolve_tac}, fail if |
829 otherwise. Many common tactics, such as @{ML resolve_tac}, fail if |
853 applied to a goal state that has no subgoals. |
830 applied to a goal state that has no subgoals. |
854 |
831 |
855 \<^descr> @{ML SOLVE}~@{text "tac"} applies @{text "tac"} to the goal |
832 \<^descr> @{ML SOLVE}~\<open>tac\<close> applies \<open>tac\<close> to the goal |
856 state and then fails iff there are subgoals left. |
833 state and then fails iff there are subgoals left. |
857 |
834 |
858 \<^descr> @{ML DETERM}~@{text "tac"} applies @{text "tac"} to the goal |
835 \<^descr> @{ML DETERM}~\<open>tac\<close> applies \<open>tac\<close> to the goal |
859 state and returns the head of the resulting sequence. @{ML DETERM} |
836 state and returns the head of the resulting sequence. @{ML DETERM} |
860 limits the search space by making its argument deterministic. |
837 limits the search space by making its argument deterministic. |
861 \<close> |
838 \<close> |
862 |
839 |
863 |
840 |
869 @{index_ML Thm.eq_thm: "thm * thm -> bool"} \\ |
846 @{index_ML Thm.eq_thm: "thm * thm -> bool"} \\ |
870 @{index_ML Thm.eq_thm_prop: "thm * thm -> bool"} \\ |
847 @{index_ML Thm.eq_thm_prop: "thm * thm -> bool"} \\ |
871 @{index_ML size_of_thm: "thm -> int"} \\ |
848 @{index_ML size_of_thm: "thm -> int"} \\ |
872 \end{mldecls} |
849 \end{mldecls} |
873 |
850 |
874 \<^descr> @{ML has_fewer_prems}~@{text "n thm"} reports whether @{text |
851 \<^descr> @{ML has_fewer_prems}~\<open>n thm\<close> reports whether \<open>thm\<close> has fewer than \<open>n\<close> premises. |
875 "thm"} has fewer than @{text "n"} premises. |
852 |
876 |
853 \<^descr> @{ML Thm.eq_thm}~\<open>(thm\<^sub>1, thm\<^sub>2)\<close> reports whether \<open>thm\<^sub>1\<close> and \<open>thm\<^sub>2\<close> are equal. Both theorems must have the |
877 \<^descr> @{ML Thm.eq_thm}~@{text "(thm\<^sub>1, thm\<^sub>2)"} reports whether @{text |
|
878 "thm\<^sub>1"} and @{text "thm\<^sub>2"} are equal. Both theorems must have the |
|
879 same conclusions, the same set of hypotheses, and the same set of sort |
854 same conclusions, the same set of hypotheses, and the same set of sort |
880 hypotheses. Names of bound variables are ignored as usual. |
855 hypotheses. Names of bound variables are ignored as usual. |
881 |
856 |
882 \<^descr> @{ML Thm.eq_thm_prop}~@{text "(thm\<^sub>1, thm\<^sub>2)"} reports whether |
857 \<^descr> @{ML Thm.eq_thm_prop}~\<open>(thm\<^sub>1, thm\<^sub>2)\<close> reports whether |
883 the propositions of @{text "thm\<^sub>1"} and @{text "thm\<^sub>2"} are equal. |
858 the propositions of \<open>thm\<^sub>1\<close> and \<open>thm\<^sub>2\<close> are equal. |
884 Names of bound variables are ignored. |
859 Names of bound variables are ignored. |
885 |
860 |
886 \<^descr> @{ML size_of_thm}~@{text "thm"} computes the size of @{text |
861 \<^descr> @{ML size_of_thm}~\<open>thm\<close> computes the size of \<open>thm\<close>, namely the number of variables, constants and abstractions |
887 "thm"}, namely the number of variables, constants and abstractions |
|
888 in its conclusion. It may serve as a distance function for |
862 in its conclusion. It may serve as a distance function for |
889 @{ML BEST_FIRST}. |
863 @{ML BEST_FIRST}. |
890 \<close> |
864 \<close> |
891 |
865 |
892 end |
866 end |