| author | nipkow |
| Tue, 17 Nov 2015 11:44:10 +0100 | |
| changeset 61692 | cb595e12451d |
| parent 61656 | cfabbc083977 |
| child 61854 | 38b049cd3aad |
| permissions | -rw-r--r-- |
| 61656 | 1 |
(*:maxLineLen=78:*) |
2 |
||
| 29755 | 3 |
theory Tactic |
4 |
imports Base |
|
5 |
begin |
|
| 18537 | 6 |
|
| 58618 | 7 |
chapter \<open>Tactical reasoning\<close> |
| 18537 | 8 |
|
| 58618 | 9 |
text \<open>Tactical reasoning works by refining an initial claim in a |
| 61493 | 10 |
backwards fashion, until a solved form is reached. A \<open>goal\<close> |
| 20474 | 11 |
consists of several subgoals that need to be solved in order to |
12 |
achieve the main statement; zero subgoals means that the proof may |
|
| 61493 | 13 |
be finished. A \<open>tactic\<close> is a refinement operation that maps |
14 |
a goal to a lazy sequence of potential successors. A \<open>tactical\<close> is a combinator for composing tactics.\<close> |
|
| 18537 | 15 |
|
16 |
||
| 58618 | 17 |
section \<open>Goals \label{sec:tactical-goals}\<close>
|
| 18537 | 18 |
|
| 58618 | 19 |
text \<open> |
| 29758 | 20 |
Isabelle/Pure represents a goal as a theorem stating that the |
| 61493 | 21 |
subgoals imply the main goal: \<open>A\<^sub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^sub>n \<Longrightarrow> |
22 |
C\<close>. The outermost goal structure is that of a Horn Clause: i.e.\ |
|
| 61572 | 23 |
an iterated implication without any quantifiers\<^footnote>\<open>Recall that |
| 61493 | 24 |
outermost \<open>\<And>x. \<phi>[x]\<close> is always represented via schematic |
25 |
variables in the body: \<open>\<phi>[?x]\<close>. These variables may get |
|
| 61572 | 26 |
instantiated during the course of reasoning.\<close>. For \<open>n = 0\<close> |
| 29758 | 27 |
a goal is called ``solved''. |
| 18537 | 28 |
|
| 61493 | 29 |
The structure of each subgoal \<open>A\<^sub>i\<close> is that of a |
30 |
general Hereditary Harrop Formula \<open>\<And>x\<^sub>1 \<dots> |
|
31 |
\<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.\ |
|
32 |
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 |
|
| 29761 | 33 |
be assumed locally. Together, this forms the goal context of the |
| 61493 | 34 |
conclusion \<open>B\<close> to be established. The goal hypotheses may be |
| 29761 | 35 |
again arbitrary Hereditary Harrop Formulas, although the level of |
36 |
nesting rarely exceeds 1--2 in practice. |
|
| 18537 | 37 |
|
| 61493 | 38 |
The main conclusion \<open>C\<close> is internally marked as a protected |
39 |
proposition, which is represented explicitly by the notation \<open>#C\<close> here. This ensures that the decomposition into subgoals and |
|
| 34930 | 40 |
main conclusion is well-defined for arbitrarily structured claims. |
| 18537 | 41 |
|
| 61416 | 42 |
\<^medskip> |
43 |
Basic goal management is performed via the following |
|
| 20451 | 44 |
Isabelle/Pure rules: |
| 18537 | 45 |
|
46 |
\[ |
|
| 61493 | 47 |
\infer[\<open>(init)\<close>]{\<open>C \<Longrightarrow> #C\<close>}{} \qquad
|
48 |
\infer[\<open>(finish)\<close>]{\<open>C\<close>}{\<open>#C\<close>}
|
|
| 18537 | 49 |
\] |
50 |
||
| 61416 | 51 |
\<^medskip> |
52 |
The following low-level variants admit general reasoning |
|
| 18537 | 53 |
with protected propositions: |
54 |
||
55 |
\[ |
|
| 61493 | 56 |
\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>}
|
| 52456 | 57 |
\] |
58 |
\[ |
|
| 61493 | 59 |
\infer[\<open>(conclude)\<close>]{\<open>A \<Longrightarrow> \<dots> \<Longrightarrow> C\<close>}{\<open>A \<Longrightarrow> \<dots> \<Longrightarrow> #C\<close>}
|
| 18537 | 60 |
\] |
| 58618 | 61 |
\<close> |
| 18537 | 62 |
|
| 58618 | 63 |
text %mlref \<open> |
| 18537 | 64 |
\begin{mldecls}
|
65 |
@{index_ML Goal.init: "cterm -> thm"} \\
|
|
|
32201
3689b647356d
updated Variable.focus, SUBPROOF, Obtain.result, Goal.finish;
wenzelm
parents:
30272
diff
changeset
|
66 |
@{index_ML Goal.finish: "Proof.context -> thm -> thm"} \\
|
| 52456 | 67 |
@{index_ML Goal.protect: "int -> thm -> thm"} \\
|
| 18537 | 68 |
@{index_ML Goal.conclude: "thm -> thm"} \\
|
69 |
\end{mldecls}
|
|
70 |
||
| 61493 | 71 |
\<^descr> @{ML "Goal.init"}~\<open>C\<close> initializes a tactical goal from
|
72 |
the well-formed proposition \<open>C\<close>. |
|
| 18537 | 73 |
|
| 61493 | 74 |
\<^descr> @{ML "Goal.finish"}~\<open>ctxt thm\<close> checks whether theorem
|
75 |
\<open>thm\<close> is a solved goal (no subgoals), and concludes the |
|
|
32201
3689b647356d
updated Variable.focus, SUBPROOF, Obtain.result, Goal.finish;
wenzelm
parents:
30272
diff
changeset
|
76 |
result by removing the goal protection. The context is only |
|
3689b647356d
updated Variable.focus, SUBPROOF, Obtain.result, Goal.finish;
wenzelm
parents:
30272
diff
changeset
|
77 |
required for printing error messages. |
| 18537 | 78 |
|
| 61493 | 79 |
\<^descr> @{ML "Goal.protect"}~\<open>n thm\<close> protects the statement
|
80 |
of theorem \<open>thm\<close>. The parameter \<open>n\<close> indicates the |
|
| 52456 | 81 |
number of premises to be retained. |
| 18537 | 82 |
|
| 61493 | 83 |
\<^descr> @{ML "Goal.conclude"}~\<open>thm\<close> removes the goal
|
| 20474 | 84 |
protection, even if there are pending subgoals. |
| 58618 | 85 |
\<close> |
| 18537 | 86 |
|
87 |
||
| 58618 | 88 |
section \<open>Tactics\label{sec:tactics}\<close>
|
| 18537 | 89 |
|
| 61493 | 90 |
text \<open>A \<open>tactic\<close> is a function \<open>goal \<rightarrow> goal\<^sup>*\<^sup>*\<close> that |
| 28781 | 91 |
maps a given goal state (represented as a theorem, cf.\ |
92 |
\secref{sec:tactical-goals}) to a lazy sequence of potential
|
|
93 |
successor states. The underlying sequence implementation is lazy |
|
| 61477 | 94 |
both in head and tail, and is purely functional in \<^emph>\<open>not\<close> |
| 61572 | 95 |
supporting memoing.\<^footnote>\<open>The lack of memoing and the strict |
| 57421 | 96 |
nature of ML requires some care when working with low-level |
| 28781 | 97 |
sequence operations, to avoid duplicate or premature evaluation of |
| 34930 | 98 |
results. It also means that modified runtime behavior, such as |
| 61572 | 99 |
timeout, is very hard to achieve for general tactics.\<close> |
| 18537 | 100 |
|
| 61477 | 101 |
An \<^emph>\<open>empty result sequence\<close> means that the tactic has failed: in |
| 34930 | 102 |
a compound tactic expression other tactics might be tried instead, |
| 28781 | 103 |
or the whole refinement step might fail outright, producing a |
| 34930 | 104 |
toplevel error message in the end. When implementing tactics from |
105 |
scratch, one should take care to observe the basic protocol of |
|
106 |
mapping regular error conditions to an empty result; only serious |
|
107 |
faults should emerge as exceptions. |
|
| 28781 | 108 |
|
| 61477 | 109 |
By enumerating \<^emph>\<open>multiple results\<close>, a tactic can easily express |
| 28781 | 110 |
the potential outcome of an internal search process. There are also |
111 |
combinators for building proof tools that involve search |
|
112 |
systematically, see also \secref{sec:tacticals}.
|
|
113 |
||
| 61416 | 114 |
\<^medskip> |
115 |
As explained before, a goal state essentially consists of a |
|
| 34930 | 116 |
list of subgoals that imply the main goal (conclusion). Tactics may |
117 |
operate on all subgoals or on a particularly specified subgoal, but |
|
118 |
must not change the main conclusion (apart from instantiating |
|
119 |
schematic goal variables). |
|
| 18537 | 120 |
|
| 61477 | 121 |
Tactics with explicit \<^emph>\<open>subgoal addressing\<close> are of the form |
| 61493 | 122 |
\<open>int \<rightarrow> tactic\<close> and may be applied to a particular subgoal |
| 28781 | 123 |
(counting from 1). If the subgoal number is out of range, the |
124 |
tactic should fail with an empty result sequence, but must not raise |
|
125 |
an exception! |
|
126 |
||
127 |
Operating on a particular subgoal means to replace it by an interval |
|
128 |
of zero or more subgoals in the same place; other subgoals must not |
|
129 |
be affected, apart from instantiating schematic variables ranging |
|
130 |
over the whole goal state. |
|
131 |
||
132 |
A common pattern of composing tactics with subgoal addressing is to |
|
133 |
try the first one, and then the second one only if the subgoal has |
|
134 |
not been solved yet. Special care is required here to avoid bumping |
|
| 28782 | 135 |
into unrelated subgoals that happen to come after the original |
136 |
subgoal. Assuming that there is only a single initial subgoal is a |
|
137 |
very common error when implementing tactics! |
|
138 |
||
139 |
Tactics with internal subgoal addressing should expose the subgoal |
|
| 61493 | 140 |
index as \<open>int\<close> argument in full generality; a hardwired |
| 34930 | 141 |
subgoal 1 is not acceptable. |
| 28781 | 142 |
|
| 61416 | 143 |
\<^medskip> |
144 |
The main well-formedness conditions for proper tactics are |
|
| 28781 | 145 |
summarized as follows. |
146 |
||
| 61416 | 147 |
\<^item> General tactic failure is indicated by an empty result, only |
| 28781 | 148 |
serious faults may produce an exception. |
149 |
||
| 61416 | 150 |
\<^item> The main conclusion must not be changed, apart from |
| 28781 | 151 |
instantiating schematic variables. |
152 |
||
| 61416 | 153 |
\<^item> A tactic operates either uniformly on all subgoals, or |
| 28781 | 154 |
specifically on a selected subgoal (without bumping into unrelated |
155 |
subgoals). |
|
156 |
||
| 61416 | 157 |
\<^item> Range errors in subgoal addressing produce an empty result. |
| 28781 | 158 |
|
| 28782 | 159 |
|
160 |
Some of these conditions are checked by higher-level goal |
|
| 34930 | 161 |
infrastructure (\secref{sec:struct-goals}); others are not checked
|
| 28782 | 162 |
explicitly, and violating them merely results in ill-behaved tactics |
163 |
experienced by the user (e.g.\ tactics that insist in being |
|
| 34930 | 164 |
applicable only to singleton goals, or prevent composition via |
| 46260 | 165 |
standard tacticals such as @{ML REPEAT}).
|
| 58618 | 166 |
\<close> |
| 28782 | 167 |
|
| 58618 | 168 |
text %mlref \<open> |
| 28782 | 169 |
\begin{mldecls}
|
170 |
@{index_ML_type tactic: "thm -> thm Seq.seq"} \\
|
|
| 28783 | 171 |
@{index_ML no_tac: tactic} \\
|
172 |
@{index_ML all_tac: tactic} \\
|
|
| 56491 | 173 |
@{index_ML print_tac: "Proof.context -> string -> tactic"} \\[1ex]
|
| 28783 | 174 |
@{index_ML PRIMITIVE: "(thm -> thm) -> tactic"} \\[1ex]
|
| 28782 | 175 |
@{index_ML SUBGOAL: "(term * int -> tactic) -> int -> tactic"} \\
|
176 |
@{index_ML CSUBGOAL: "(cterm * int -> tactic) -> int -> tactic"} \\
|
|
| 52463 | 177 |
@{index_ML SELECT_GOAL: "tactic -> int -> tactic"} \\
|
178 |
@{index_ML PREFER_GOAL: "tactic -> int -> tactic"} \\
|
|
| 28782 | 179 |
\end{mldecls}
|
180 |
||
| 61439 | 181 |
\<^descr> Type @{ML_type tactic} represents tactics. The
|
| 39864 | 182 |
well-formedness conditions described above need to be observed. See |
|
40800
330eb65c9469
Parse.liberal_name for document antiquotations and attributes;
wenzelm
parents:
39864
diff
changeset
|
183 |
also @{file "~~/src/Pure/General/seq.ML"} for the underlying
|
| 39864 | 184 |
implementation of lazy sequences. |
| 28782 | 185 |
|
| 61439 | 186 |
\<^descr> Type @{ML_type "int -> tactic"} represents tactics with
|
| 39864 | 187 |
explicit subgoal addressing, with well-formedness conditions as |
188 |
described above. |
|
| 28782 | 189 |
|
| 61439 | 190 |
\<^descr> @{ML no_tac} is a tactic that always fails, returning the
|
| 28783 | 191 |
empty sequence. |
192 |
||
| 61439 | 193 |
\<^descr> @{ML all_tac} is a tactic that always succeeds, returning a
|
| 28783 | 194 |
singleton sequence with unchanged goal state. |
195 |
||
| 61493 | 196 |
\<^descr> @{ML print_tac}~\<open>ctxt message\<close> is like @{ML all_tac}, but
|
| 28783 | 197 |
prints a message together with the goal state on the tracing |
198 |
channel. |
|
199 |
||
| 61493 | 200 |
\<^descr> @{ML PRIMITIVE}~\<open>rule\<close> turns a primitive inference rule
|
| 28782 | 201 |
into a tactic with unique result. Exception @{ML THM} is considered
|
202 |
a regular tactic failure and produces an empty result; other |
|
203 |
exceptions are passed through. |
|
204 |
||
| 61493 | 205 |
\<^descr> @{ML SUBGOAL}~\<open>(fn (subgoal, i) => tactic)\<close> is the
|
| 28783 | 206 |
most basic form to produce a tactic with subgoal addressing. The |
| 28782 | 207 |
given abstraction over the subgoal term and subgoal number allows to |
208 |
peek at the relevant information of the full goal state. The |
|
209 |
subgoal range is checked as required above. |
|
210 |
||
| 61439 | 211 |
\<^descr> @{ML CSUBGOAL} is similar to @{ML SUBGOAL}, but passes the
|
| 28783 | 212 |
subgoal as @{ML_type cterm} instead of raw @{ML_type term}. This
|
| 28782 | 213 |
avoids expensive re-certification in situations where the subgoal is |
214 |
used directly for primitive inferences. |
|
215 |
||
| 61493 | 216 |
\<^descr> @{ML SELECT_GOAL}~\<open>tac i\<close> confines a tactic to the
|
217 |
specified subgoal \<open>i\<close>. This rearranges subgoals and the |
|
| 52463 | 218 |
main goal protection (\secref{sec:tactical-goals}), while retaining
|
219 |
the syntactic context of the overall goal state (concerning |
|
220 |
schematic variables etc.). |
|
221 |
||
| 61493 | 222 |
\<^descr> @{ML PREFER_GOAL}~\<open>tac i\<close> rearranges subgoals to put
|
223 |
\<open>i\<close> in front. This is similar to @{ML SELECT_GOAL}, but
|
|
| 52463 | 224 |
without changing the main goal protection. |
| 58618 | 225 |
\<close> |
| 18537 | 226 |
|
227 |
||
| 58618 | 228 |
subsection \<open>Resolution and assumption tactics \label{sec:resolve-assume-tac}\<close>
|
| 28783 | 229 |
|
| 61477 | 230 |
text \<open>\<^emph>\<open>Resolution\<close> is the most basic mechanism for refining a |
| 28783 | 231 |
subgoal using a theorem as object-level rule. |
| 61477 | 232 |
\<^emph>\<open>Elim-resolution\<close> is particularly suited for elimination rules: |
| 28783 | 233 |
it resolves with a rule, proves its first premise by assumption, and |
234 |
finally deletes that assumption from any new subgoals. |
|
| 61477 | 235 |
\<^emph>\<open>Destruct-resolution\<close> is like elim-resolution, but the given |
| 28783 | 236 |
destruction rules are first turned into canonical elimination |
| 61477 | 237 |
format. \<^emph>\<open>Forward-resolution\<close> is like destruct-resolution, but |
| 61493 | 238 |
without deleting the selected assumption. The \<open>r/e/d/f\<close> |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
239 |
naming convention is maintained for several different kinds of |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
240 |
resolution rules and tactics. |
| 28783 | 241 |
|
242 |
Assumption tactics close a subgoal by unifying some of its premises |
|
243 |
against its conclusion. |
|
244 |
||
| 61416 | 245 |
\<^medskip> |
246 |
All the tactics in this section operate on a subgoal |
|
| 28783 | 247 |
designated by a positive integer. Other subgoals might be affected |
248 |
indirectly, due to instantiation of schematic variables. |
|
249 |
||
250 |
There are various sources of non-determinism, the tactic result |
|
251 |
sequence enumerates all possibilities of the following choices (if |
|
252 |
applicable): |
|
253 |
||
| 61416 | 254 |
\<^enum> selecting one of the rules given as argument to the tactic; |
| 28783 | 255 |
|
| 61416 | 256 |
\<^enum> selecting a subgoal premise to eliminate, unifying it against |
| 28783 | 257 |
the first premise of the rule; |
258 |
||
| 61416 | 259 |
\<^enum> unifying the conclusion of the subgoal to the conclusion of |
| 28783 | 260 |
the rule. |
261 |
||
262 |
||
263 |
Recall that higher-order unification may produce multiple results |
|
264 |
that are enumerated here. |
|
| 58618 | 265 |
\<close> |
| 28783 | 266 |
|
| 58618 | 267 |
text %mlref \<open> |
| 28783 | 268 |
\begin{mldecls}
|
|
59498
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
269 |
@{index_ML resolve_tac: "Proof.context -> thm list -> int -> tactic"} \\
|
|
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
270 |
@{index_ML eresolve_tac: "Proof.context -> thm list -> int -> tactic"} \\
|
|
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
271 |
@{index_ML dresolve_tac: "Proof.context -> thm list -> int -> tactic"} \\
|
|
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
272 |
@{index_ML forward_tac: "Proof.context -> thm list -> int -> tactic"} \\
|
|
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
273 |
@{index_ML biresolve_tac: "Proof.context -> (bool * thm) list -> int -> tactic"} \\[1ex]
|
|
58963
26bf09b95dda
proper context for assume_tac (atac remains as fall-back without context);
wenzelm
parents:
58957
diff
changeset
|
274 |
@{index_ML assume_tac: "Proof.context -> int -> tactic"} \\
|
| 28783 | 275 |
@{index_ML eq_assume_tac: "int -> tactic"} \\[1ex]
|
| 58957 | 276 |
@{index_ML match_tac: "Proof.context -> thm list -> int -> tactic"} \\
|
277 |
@{index_ML ematch_tac: "Proof.context -> thm list -> int -> tactic"} \\
|
|
278 |
@{index_ML dmatch_tac: "Proof.context -> thm list -> int -> tactic"} \\
|
|
279 |
@{index_ML bimatch_tac: "Proof.context -> (bool * thm) list -> int -> tactic"} \\
|
|
| 28783 | 280 |
\end{mldecls}
|
281 |
||
| 61493 | 282 |
\<^descr> @{ML resolve_tac}~\<open>ctxt thms i\<close> refines the goal state
|
| 28783 | 283 |
using the given theorems, which should normally be introduction |
| 61493 | 284 |
rules. The tactic resolves a rule's conclusion with subgoal \<open>i\<close>, replacing it by the corresponding versions of the rule's |
| 28783 | 285 |
premises. |
286 |
||
| 61493 | 287 |
\<^descr> @{ML eresolve_tac}~\<open>ctxt thms i\<close> performs elim-resolution
|
| 46278 | 288 |
with the given theorems, which are normally be elimination rules. |
289 |
||
|
59498
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
290 |
Note that @{ML_text "eresolve_tac ctxt [asm_rl]"} is equivalent to @{ML_text
|
|
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
291 |
"assume_tac ctxt"}, which facilitates mixing of assumption steps with |
| 46278 | 292 |
genuine eliminations. |
| 28783 | 293 |
|
| 61493 | 294 |
\<^descr> @{ML dresolve_tac}~\<open>ctxt thms i\<close> performs
|
| 28783 | 295 |
destruct-resolution with the given theorems, which should normally |
296 |
be destruction rules. This replaces an assumption by the result of |
|
297 |
applying one of the rules. |
|
298 |
||
| 61439 | 299 |
\<^descr> @{ML forward_tac} is like @{ML dresolve_tac} except that the
|
| 28783 | 300 |
selected assumption is not deleted. It applies a rule to an |
301 |
assumption, adding the result as a new assumption. |
|
302 |
||
| 61493 | 303 |
\<^descr> @{ML biresolve_tac}~\<open>ctxt brls i\<close> refines the proof state
|
| 50072 | 304 |
by resolution or elim-resolution on each rule, as indicated by its |
| 61493 | 305 |
flag. It affects subgoal \<open>i\<close> of the proof state. |
| 50072 | 306 |
|
| 61493 | 307 |
For each pair \<open>(flag, rule)\<close>, it applies resolution if the |
308 |
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 |
|
| 50072 | 309 |
elimination rules, which is useful to organize the search process |
310 |
systematically in proof tools. |
|
311 |
||
| 61493 | 312 |
\<^descr> @{ML assume_tac}~\<open>ctxt i\<close> attempts to solve subgoal \<open>i\<close>
|
| 28783 | 313 |
by assumption (modulo higher-order unification). |
314 |
||
| 61439 | 315 |
\<^descr> @{ML eq_assume_tac} is similar to @{ML assume_tac}, but checks
|
| 61493 | 316 |
only for immediate \<open>\<alpha>\<close>-convertibility instead of using |
| 28783 | 317 |
unification. It succeeds (with a unique next state) if one of the |
318 |
assumptions is equal to the subgoal's conclusion. Since it does not |
|
319 |
instantiate variables, it cannot make other subgoals unprovable. |
|
320 |
||
| 61439 | 321 |
\<^descr> @{ML match_tac}, @{ML ematch_tac}, @{ML dmatch_tac}, and @{ML
|
| 50072 | 322 |
bimatch_tac} are similar to @{ML resolve_tac}, @{ML eresolve_tac},
|
323 |
@{ML dresolve_tac}, and @{ML biresolve_tac}, respectively, but do
|
|
| 61572 | 324 |
not instantiate schematic variables in the goal state.\<^footnote>\<open>Strictly speaking, |
325 |
matching means to treat the unknowns in the goal |
|
| 53096 | 326 |
state as constants, but these tactics merely discard unifiers that would |
327 |
update the goal state. In rare situations (where the conclusion and |
|
328 |
goal state have flexible terms at the same position), the tactic |
|
| 61572 | 329 |
will fail even though an acceptable unifier exists.\<close> |
| 53096 | 330 |
These tactics were written for a specific application within the classical reasoner. |
| 28783 | 331 |
|
332 |
Flexible subgoals are not updated at will, but are left alone. |
|
| 58618 | 333 |
\<close> |
| 28783 | 334 |
|
335 |
||
| 58618 | 336 |
subsection \<open>Explicit instantiation within a subgoal context\<close> |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
337 |
|
| 58618 | 338 |
text \<open>The main resolution tactics (\secref{sec:resolve-assume-tac})
|
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
339 |
use higher-order unification, which works well in many practical |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
340 |
situations despite its daunting theoretical properties. |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
341 |
Nonetheless, there are important problem classes where unguided |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
342 |
higher-order unification is not so useful. This typically involves |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
343 |
rules like universal elimination, existential introduction, or |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
344 |
equational substitution. Here the unification problem involves |
| 61493 | 345 |
fully flexible \<open>?P ?x\<close> schemes, which are hard to manage |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
346 |
without further hints. |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
347 |
|
| 61493 | 348 |
By providing a (small) rigid term for \<open>?x\<close> explicitly, the |
349 |
remaining unification problem is to assign a (large) term to \<open>?P\<close>, according to the shape of the given subgoal. This is |
|
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
350 |
sufficiently well-behaved in most practical situations. |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
351 |
|
| 61416 | 352 |
\<^medskip> |
| 61493 | 353 |
Isabelle provides separate versions of the standard \<open>r/e/d/f\<close> resolution tactics that allow to provide explicit |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
354 |
instantiations of unknowns of the given rule, wrt.\ terms that refer |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
355 |
to the implicit context of the selected subgoal. |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
356 |
|
| 61493 | 357 |
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 |
358 |
the given rule, and \<open>t\<close> is a term from the current proof |
|
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
359 |
context, augmented by the local goal parameters of the selected |
| 61493 | 360 |
subgoal; cf.\ the \<open>focus\<close> operation described in |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
361 |
\secref{sec:variables}.
|
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
362 |
|
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
363 |
Entering the syntactic context of a subgoal is a brittle operation, |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
364 |
because its exact form is somewhat accidental, and the choice of |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
365 |
bound variable names depends on the presence of other local and |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
366 |
global names. Explicit renaming of subgoal parameters prior to |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
367 |
explicit instantiation might help to achieve a bit more robustness. |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
368 |
|
| 61493 | 369 |
Type instantiations may be given as well, via pairs like \<open>(?'a, \<tau>)\<close>. Type instantiations are distinguished from term |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
370 |
instantiations by the syntactic form of the schematic variable. |
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
371 |
Types are instantiated before terms are. Since term instantiation |
| 34930 | 372 |
already performs simple type-inference, so explicit type |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
373 |
instantiations are seldom necessary. |
| 58618 | 374 |
\<close> |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
375 |
|
| 58618 | 376 |
text %mlref \<open> |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
377 |
\begin{mldecls}
|
| 59763 | 378 |
@{index_ML Rule_Insts.res_inst_tac: "Proof.context ->
|
| 59780 | 379 |
((indexname * Position.T) * string) list -> (binding * string option * mixfix) list -> |
380 |
thm -> int -> tactic"} \\ |
|
| 59763 | 381 |
@{index_ML Rule_Insts.eres_inst_tac: "Proof.context ->
|
| 59780 | 382 |
((indexname * Position.T) * string) list -> (binding * string option * mixfix) list -> |
383 |
thm -> int -> tactic"} \\ |
|
| 59763 | 384 |
@{index_ML Rule_Insts.dres_inst_tac: "Proof.context ->
|
| 59780 | 385 |
((indexname * Position.T) * string) list -> (binding * string option * mixfix) list -> |
386 |
thm -> int -> tactic"} \\ |
|
| 59763 | 387 |
@{index_ML Rule_Insts.forw_inst_tac: "Proof.context ->
|
| 59780 | 388 |
((indexname * Position.T) * string) list -> (binding * string option * mixfix) list -> |
389 |
thm -> int -> tactic"} \\ |
|
390 |
@{index_ML Rule_Insts.subgoal_tac: "Proof.context -> string ->
|
|
391 |
(binding * string option * mixfix) list -> int -> tactic"} \\ |
|
392 |
@{index_ML Rule_Insts.thin_tac: "Proof.context -> string ->
|
|
393 |
(binding * string option * mixfix) list -> int -> tactic"} \\ |
|
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
394 |
@{index_ML rename_tac: "string list -> int -> tactic"} \\
|
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
395 |
\end{mldecls}
|
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
396 |
|
| 61493 | 397 |
\<^descr> @{ML Rule_Insts.res_inst_tac}~\<open>ctxt insts thm i\<close> instantiates the
|
398 |
rule \<open>thm\<close> with the instantiations \<open>insts\<close>, as described |
|
399 |
above, and then performs resolution on subgoal \<open>i\<close>. |
|
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
400 |
|
| 61439 | 401 |
\<^descr> @{ML Rule_Insts.eres_inst_tac} is like @{ML Rule_Insts.res_inst_tac},
|
| 59763 | 402 |
but performs elim-resolution. |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
403 |
|
| 61439 | 404 |
\<^descr> @{ML Rule_Insts.dres_inst_tac} is like @{ML Rule_Insts.res_inst_tac},
|
| 59763 | 405 |
but performs destruct-resolution. |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
406 |
|
| 61439 | 407 |
\<^descr> @{ML Rule_Insts.forw_inst_tac} is like @{ML Rule_Insts.dres_inst_tac}
|
| 59763 | 408 |
except that the selected assumption is not deleted. |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
409 |
|
| 61493 | 410 |
\<^descr> @{ML Rule_Insts.subgoal_tac}~\<open>ctxt \<phi> i\<close> adds the proposition
|
411 |
\<open>\<phi>\<close> as local premise to subgoal \<open>i\<close>, and poses the |
|
412 |
same as a new subgoal \<open>i + 1\<close> (in the original context). |
|
| 46271 | 413 |
|
| 61493 | 414 |
\<^descr> @{ML Rule_Insts.thin_tac}~\<open>ctxt \<phi> i\<close> deletes the specified
|
415 |
premise from subgoal \<open>i\<close>. Note that \<open>\<phi>\<close> may contain |
|
| 46277 | 416 |
schematic variables, to abbreviate the intended proposition; the |
417 |
first matching subgoal premise will be deleted. Removing useless |
|
418 |
premises from a subgoal increases its readability and can make |
|
419 |
search tactics run faster. |
|
420 |
||
| 61493 | 421 |
\<^descr> @{ML rename_tac}~\<open>names i\<close> renames the innermost
|
422 |
parameters of subgoal \<open>i\<close> according to the provided \<open>names\<close> (which need to be distinct identifiers). |
|
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
423 |
|
| 34930 | 424 |
|
425 |
For historical reasons, the above instantiation tactics take |
|
426 |
unparsed string arguments, which makes them hard to use in general |
|
427 |
ML code. The slightly more advanced @{ML Subgoal.FOCUS} combinator
|
|
428 |
of \secref{sec:struct-goals} allows to refer to internal goal
|
|
429 |
structure with explicit context management. |
|
| 58618 | 430 |
\<close> |
|
28785
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
431 |
|
|
64163cddf3e6
added section "Explicit instantiation within a subgoal context";
wenzelm
parents:
28783
diff
changeset
|
432 |
|
| 58618 | 433 |
subsection \<open>Rearranging goal states\<close> |
| 46274 | 434 |
|
| 58618 | 435 |
text \<open>In rare situations there is a need to rearrange goal states: |
| 46274 | 436 |
either the overall collection of subgoals, or the local structure of |
437 |
a subgoal. Various administrative tactics allow to operate on the |
|
| 58618 | 438 |
concrete presentation these conceptual sets of formulae.\<close> |
| 46274 | 439 |
|
| 58618 | 440 |
text %mlref \<open> |
| 46274 | 441 |
\begin{mldecls}
|
442 |
@{index_ML rotate_tac: "int -> int -> tactic"} \\
|
|
| 46276 | 443 |
@{index_ML distinct_subgoals_tac: tactic} \\
|
|
58950
d07464875dd4
optional proof context for unify operations, for the sake of proper local options;
wenzelm
parents:
58618
diff
changeset
|
444 |
@{index_ML flexflex_tac: "Proof.context -> tactic"} \\
|
| 46274 | 445 |
\end{mldecls}
|
446 |
||
| 61493 | 447 |
\<^descr> @{ML rotate_tac}~\<open>n i\<close> rotates the premises of subgoal
|
448 |
\<open>i\<close> by \<open>n\<close> positions: from right to left if \<open>n\<close> is |
|
449 |
positive, and from left to right if \<open>n\<close> is negative. |
|
| 46274 | 450 |
|
| 61439 | 451 |
\<^descr> @{ML distinct_subgoals_tac} removes duplicate subgoals from a
|
| 46276 | 452 |
proof state. This is potentially inefficient. |
453 |
||
| 61439 | 454 |
\<^descr> @{ML flexflex_tac} removes all flex-flex pairs from the proof
|
| 46276 | 455 |
state by applying the trivial unifier. This drastic step loses |
456 |
information. It is already part of the Isar infrastructure for |
|
457 |
facts resulting from goals, and rarely needs to be invoked manually. |
|
458 |
||
459 |
Flex-flex constraints arise from difficult cases of higher-order |
|
| 59763 | 460 |
unification. To prevent this, use @{ML Rule_Insts.res_inst_tac} to
|
461 |
instantiate some variables in a rule. Normally flex-flex constraints |
|
462 |
can be ignored; they often disappear as unknowns get instantiated. |
|
| 58618 | 463 |
\<close> |
| 46274 | 464 |
|
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
465 |
|
| 58618 | 466 |
subsection \<open>Raw composition: resolution without lifting\<close> |
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
467 |
|
| 58618 | 468 |
text \<open> |
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
469 |
Raw composition of two rules means resolving them without prior |
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
470 |
lifting or renaming of unknowns. This low-level operation, which |
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
471 |
underlies the resolution tactics, may occasionally be useful for |
| 52467 | 472 |
special effects. Schematic variables are not renamed by default, so |
473 |
beware of clashes! |
|
| 58618 | 474 |
\<close> |
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
475 |
|
| 58618 | 476 |
text %mlref \<open> |
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
477 |
\begin{mldecls}
|
|
58956
a816aa3ff391
proper context for compose_tac, Splitter.split_tac (relevant for unify trace options);
wenzelm
parents:
58950
diff
changeset
|
478 |
@{index_ML compose_tac: "Proof.context -> (bool * thm * int) -> int -> tactic"} \\
|
| 52467 | 479 |
@{index_ML Drule.compose: "thm * int * thm -> thm"} \\
|
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
480 |
@{index_ML_op COMP: "thm * thm -> thm"} \\
|
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
481 |
\end{mldecls}
|
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
482 |
|
| 61493 | 483 |
\<^descr> @{ML compose_tac}~\<open>ctxt (flag, rule, m) i\<close> refines subgoal
|
484 |
\<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 |
|
485 |
\<open>\<psi>\<close> need not be atomic; thus \<open>m\<close> determines the |
|
486 |
number of new subgoals. If \<open>flag\<close> is \<open>true\<close> then it |
|
487 |
performs elim-resolution --- it solves the first premise of \<open>rule\<close> by assumption and deletes that assumption. |
|
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
488 |
|
| 61493 | 489 |
\<^descr> @{ML Drule.compose}~\<open>(thm\<^sub>1, i, thm\<^sub>2)\<close> uses \<open>thm\<^sub>1\<close>,
|
490 |
regarded as an atomic formula, to solve premise \<open>i\<close> of |
|
491 |
\<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 |
|
492 |
unifies \<open>\<psi>\<close> and \<open>\<phi>\<^sub>i\<close> yields the theorem \<open>(\<phi>\<^sub>1 \<Longrightarrow> |
|
493 |
\<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 |
|
| 52467 | 494 |
error (exception @{ML THM}).
|
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
495 |
|
| 61493 | 496 |
\<^descr> \<open>thm\<^sub>1 COMP thm\<^sub>2\<close> is the same as \<open>Drule.compose |
497 |
(thm\<^sub>1, 1, thm\<^sub>2)\<close>. |
|
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
498 |
|
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
499 |
|
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
500 |
\begin{warn}
|
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
501 |
These low-level operations are stepping outside the structure |
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
502 |
imposed by regular rule resolution. Used without understanding of |
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
503 |
the consequences, they may produce results that cause problems with |
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
504 |
standard rules and tactics later on. |
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
505 |
\end{warn}
|
| 58618 | 506 |
\<close> |
|
50074
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
507 |
|
|
0b02aaf7c7c5
some coverage of "resolution without lifting", which should be normally avoided;
wenzelm
parents:
50072
diff
changeset
|
508 |
|
| 58618 | 509 |
section \<open>Tacticals \label{sec:tacticals}\<close>
|
| 18537 | 510 |
|
| 61477 | 511 |
text \<open>A \<^emph>\<open>tactical\<close> is a functional combinator for building up |
| 46258 | 512 |
complex tactics from simpler ones. Common tacticals perform |
513 |
sequential composition, disjunctive choice, iteration, or goal |
|
514 |
addressing. Various search strategies may be expressed via |
|
515 |
tacticals. |
|
| 58618 | 516 |
\<close> |
| 46258 | 517 |
|
518 |
||
| 58618 | 519 |
subsection \<open>Combining tactics\<close> |
| 46258 | 520 |
|
| 58618 | 521 |
text \<open>Sequential composition and alternative choices are the most |
| 61503 | 522 |
basic ways to combine tactics, similarly to ``\<^verbatim>\<open>,\<close>'' and |
523 |
``\<^verbatim>\<open>|\<close>'' in Isar method notation. This corresponds to |
|
| 46262 | 524 |
@{ML_op "THEN"} and @{ML_op "ORELSE"} in ML, but there are further
|
525 |
possibilities for fine-tuning alternation of tactics such as @{ML_op
|
|
| 46258 | 526 |
"APPEND"}. Further details become visible in ML due to explicit |
| 46262 | 527 |
subgoal addressing. |
| 58618 | 528 |
\<close> |
| 46258 | 529 |
|
| 58618 | 530 |
text %mlref \<open> |
| 46258 | 531 |
\begin{mldecls}
|
| 46262 | 532 |
@{index_ML_op "THEN": "tactic * tactic -> tactic"} \\
|
533 |
@{index_ML_op "ORELSE": "tactic * tactic -> tactic"} \\
|
|
534 |
@{index_ML_op "APPEND": "tactic * tactic -> tactic"} \\
|
|
| 46258 | 535 |
@{index_ML "EVERY": "tactic list -> tactic"} \\
|
536 |
@{index_ML "FIRST": "tactic list -> tactic"} \\[0.5ex]
|
|
537 |
||
| 46262 | 538 |
@{index_ML_op "THEN'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\
|
539 |
@{index_ML_op "ORELSE'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\
|
|
540 |
@{index_ML_op "APPEND'": "('a -> tactic) * ('a -> tactic) -> 'a -> tactic"} \\
|
|
| 46258 | 541 |
@{index_ML "EVERY'": "('a -> tactic) list -> 'a -> tactic"} \\
|
542 |
@{index_ML "FIRST'": "('a -> tactic) list -> 'a -> tactic"} \\
|
|
543 |
\end{mldecls}
|
|
544 |
||
| 61493 | 545 |
\<^descr> \<open>tac\<^sub>1\<close>~@{ML_op THEN}~\<open>tac\<^sub>2\<close> is the sequential
|
546 |
composition of \<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close>. Applied to a goal |
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
547 |
state, it returns all states reachable in two steps by applying |
| 61493 | 548 |
\<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 |
549 |
states; then, it applies \<open>tac\<^sub>2\<close> to each of these and |
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
550 |
concatenates the results to produce again one flat sequence of |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
551 |
states. |
| 46258 | 552 |
|
| 61493 | 553 |
\<^descr> \<open>tac\<^sub>1\<close>~@{ML_op ORELSE}~\<open>tac\<^sub>2\<close> makes a choice
|
554 |
between \<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close>. Applied to a state, it |
|
555 |
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 |
|
556 |
choice: if \<open>tac\<^sub>1\<close> succeeds then \<open>tac\<^sub>2\<close> is excluded |
|
| 46262 | 557 |
from the result. |
| 46258 | 558 |
|
| 61493 | 559 |
\<^descr> \<open>tac\<^sub>1\<close>~@{ML_op APPEND}~\<open>tac\<^sub>2\<close> concatenates the
|
560 |
possible results of \<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close>. Unlike |
|
| 61477 | 561 |
@{ML_op "ORELSE"} there is \<^emph>\<open>no commitment\<close> to either tactic, so
|
| 46262 | 562 |
@{ML_op "APPEND"} helps to avoid incompleteness during search, at
|
563 |
the cost of potential inefficiencies. |
|
| 39852 | 564 |
|
| 61493 | 565 |
\<^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>.
|
| 46262 | 566 |
Note that @{ML "EVERY []"} is the same as @{ML all_tac}: it always
|
567 |
succeeds. |
|
| 46258 | 568 |
|
| 61493 | 569 |
\<^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
|
| 46262 | 570 |
always fails. |
| 46258 | 571 |
|
| 61439 | 572 |
\<^descr> @{ML_op "THEN'"} is the lifted version of @{ML_op "THEN"}, for
|
| 61493 | 573 |
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>.
|
| 46258 | 574 |
|
| 46264 | 575 |
The other primed tacticals work analogously. |
| 58618 | 576 |
\<close> |
| 30272 | 577 |
|
| 46259 | 578 |
|
| 58618 | 579 |
subsection \<open>Repetition tacticals\<close> |
| 46259 | 580 |
|
| 58618 | 581 |
text \<open>These tacticals provide further control over repetition of |
| 61503 | 582 |
tactics, beyond the stylized forms of ``\<^verbatim>\<open>?\<close>'' and |
583 |
``\<^verbatim>\<open>+\<close>'' in Isar method expressions.\<close> |
|
| 46259 | 584 |
|
| 58618 | 585 |
text %mlref \<open> |
| 46259 | 586 |
\begin{mldecls}
|
587 |
@{index_ML "TRY": "tactic -> tactic"} \\
|
|
| 46266 | 588 |
@{index_ML "REPEAT": "tactic -> tactic"} \\
|
589 |
@{index_ML "REPEAT1": "tactic -> tactic"} \\
|
|
| 46259 | 590 |
@{index_ML "REPEAT_DETERM": "tactic -> tactic"} \\
|
591 |
@{index_ML "REPEAT_DETERM_N": "int -> tactic -> tactic"} \\
|
|
592 |
\end{mldecls}
|
|
593 |
||
| 61493 | 594 |
\<^descr> @{ML TRY}~\<open>tac\<close> applies \<open>tac\<close> to the goal
|
| 46259 | 595 |
state and returns the resulting sequence, if non-empty; otherwise it |
| 61493 | 596 |
returns the original state. Thus, it applies \<open>tac\<close> at most |
| 46259 | 597 |
once. |
598 |
||
| 46266 | 599 |
Note that for tactics with subgoal addressing, the combinator can be |
| 61503 | 600 |
applied via functional composition: @{ML "TRY"}~@{ML_op o}~\<open>tac\<close>.
|
601 |
There is no need for \<^verbatim>\<open>TRY'\<close>. |
|
| 46259 | 602 |
|
| 61493 | 603 |
\<^descr> @{ML REPEAT}~\<open>tac\<close> applies \<open>tac\<close> to the goal
|
| 46259 | 604 |
state and, recursively, to each element of the resulting sequence. |
| 61493 | 605 |
The resulting sequence consists of those states that make \<open>tac\<close> fail. Thus, it applies \<open>tac\<close> as many times as |
| 46259 | 606 |
possible (including zero times), and allows backtracking over each |
| 61493 | 607 |
invocation of \<open>tac\<close>. @{ML REPEAT} is more general than @{ML
|
| 46259 | 608 |
REPEAT_DETERM}, but requires more space. |
609 |
||
| 61493 | 610 |
\<^descr> @{ML REPEAT1}~\<open>tac\<close> is like @{ML REPEAT}~\<open>tac\<close>
|
611 |
but it always applies \<open>tac\<close> at least once, failing if this |
|
| 46259 | 612 |
is impossible. |
613 |
||
| 61493 | 614 |
\<^descr> @{ML REPEAT_DETERM}~\<open>tac\<close> applies \<open>tac\<close> to the
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
615 |
goal state and, recursively, to the head of the resulting sequence. |
| 61493 | 616 |
It returns the first state to make \<open>tac\<close> fail. It is |
| 46266 | 617 |
deterministic, discarding alternative outcomes. |
618 |
||
| 61493 | 619 |
\<^descr> @{ML REPEAT_DETERM_N}~\<open>n tac\<close> is like @{ML
|
620 |
REPEAT_DETERM}~\<open>tac\<close> but the number of repetitions is bound |
|
621 |
by \<open>n\<close> (where @{ML "~1"} means \<open>\<infinity>\<close>).
|
|
| 58618 | 622 |
\<close> |
| 46259 | 623 |
|
| 58618 | 624 |
text %mlex \<open>The basic tactics and tacticals considered above follow |
| 46260 | 625 |
some algebraic laws: |
| 46259 | 626 |
|
| 61416 | 627 |
\<^item> @{ML all_tac} is the identity element of the tactical @{ML_op
|
| 46262 | 628 |
"THEN"}. |
| 46259 | 629 |
|
| 61416 | 630 |
\<^item> @{ML no_tac} is the identity element of @{ML_op "ORELSE"} and
|
| 46262 | 631 |
@{ML_op "APPEND"}. Also, it is a zero element for @{ML_op "THEN"},
|
| 61493 | 632 |
which means that \<open>tac\<close>~@{ML_op THEN}~@{ML no_tac} is
|
| 46262 | 633 |
equivalent to @{ML no_tac}.
|
| 46259 | 634 |
|
| 61416 | 635 |
\<^item> @{ML TRY} and @{ML REPEAT} can be expressed as (recursive)
|
| 46260 | 636 |
functions over more basic combinators (ignoring some internal |
637 |
implementation tricks): |
|
| 58618 | 638 |
\<close> |
| 46259 | 639 |
|
| 58618 | 640 |
ML \<open> |
| 46259 | 641 |
fun TRY tac = tac ORELSE all_tac; |
642 |
fun REPEAT tac st = ((tac THEN REPEAT tac) ORELSE all_tac) st; |
|
| 58618 | 643 |
\<close> |
| 46259 | 644 |
|
| 61493 | 645 |
text \<open>If \<open>tac\<close> can return multiple outcomes then so can @{ML
|
646 |
REPEAT}~\<open>tac\<close>. @{ML REPEAT} uses @{ML_op "ORELSE"} and not
|
|
647 |
@{ML_op "APPEND"}, it applies \<open>tac\<close> as many times as
|
|
| 46259 | 648 |
possible in each outcome. |
649 |
||
650 |
\begin{warn}
|
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
651 |
Note the explicit abstraction over the goal state in the ML |
| 46260 | 652 |
definition of @{ML REPEAT}. Recursive tacticals must be coded in
|
653 |
this awkward fashion to avoid infinite recursion of eager functional |
|
654 |
evaluation in Standard ML. The following attempt would make @{ML
|
|
| 61493 | 655 |
REPEAT}~\<open>tac\<close> loop: |
| 46259 | 656 |
\end{warn}
|
| 58618 | 657 |
\<close> |
| 46259 | 658 |
|
| 59902 | 659 |
ML_val \<open> |
| 46260 | 660 |
(*BAD -- does not terminate!*) |
661 |
fun REPEAT tac = (tac THEN REPEAT tac) ORELSE all_tac; |
|
| 58618 | 662 |
\<close> |
| 46259 | 663 |
|
| 46263 | 664 |
|
| 58618 | 665 |
subsection \<open>Applying tactics to subgoal ranges\<close> |
| 46263 | 666 |
|
| 58618 | 667 |
text \<open>Tactics with explicit subgoal addressing |
| 46263 | 668 |
@{ML_type "int -> tactic"} can be used together with tacticals that
|
669 |
act like ``subgoal quantifiers'': guided by success of the body |
|
670 |
tactic a certain range of subgoals is covered. Thus the body tactic |
|
| 61477 | 671 |
is applied to \<^emph>\<open>all\<close> subgoals, \<^emph>\<open>some\<close> subgoal etc. |
| 46263 | 672 |
|
| 61493 | 673 |
Suppose that the goal state has \<open>n \<ge> 0\<close> subgoals. Many of |
| 46263 | 674 |
these tacticals address subgoal ranges counting downwards from |
| 61493 | 675 |
\<open>n\<close> towards \<open>1\<close>. This has the fortunate effect that |
| 46263 | 676 |
newly emerging subgoals are concatenated in the result, without |
677 |
interfering each other. Nonetheless, there might be situations |
|
| 58618 | 678 |
where a different order is desired.\<close> |
| 46263 | 679 |
|
| 58618 | 680 |
text %mlref \<open> |
| 46263 | 681 |
\begin{mldecls}
|
682 |
@{index_ML ALLGOALS: "(int -> tactic) -> tactic"} \\
|
|
683 |
@{index_ML SOMEGOAL: "(int -> tactic) -> tactic"} \\
|
|
684 |
@{index_ML FIRSTGOAL: "(int -> tactic) -> tactic"} \\
|
|
| 46267 | 685 |
@{index_ML HEADGOAL: "(int -> tactic) -> tactic"} \\
|
| 46263 | 686 |
@{index_ML REPEAT_SOME: "(int -> tactic) -> tactic"} \\
|
687 |
@{index_ML REPEAT_FIRST: "(int -> tactic) -> tactic"} \\
|
|
| 46267 | 688 |
@{index_ML RANGE: "(int -> tactic) list -> int -> tactic"} \\
|
| 46263 | 689 |
\end{mldecls}
|
690 |
||
| 61493 | 691 |
\<^descr> @{ML ALLGOALS}~\<open>tac\<close> is equivalent to \<open>tac
|
692 |
n\<close>~@{ML_op THEN}~\<open>\<dots>\<close>~@{ML_op THEN}~\<open>tac 1\<close>. It
|
|
693 |
applies the \<open>tac\<close> to all the subgoals, counting downwards. |
|
| 46263 | 694 |
|
| 61493 | 695 |
\<^descr> @{ML SOMEGOAL}~\<open>tac\<close> is equivalent to \<open>tac
|
696 |
n\<close>~@{ML_op ORELSE}~\<open>\<dots>\<close>~@{ML_op ORELSE}~\<open>tac 1\<close>. It
|
|
697 |
applies \<open>tac\<close> to one subgoal, counting downwards. |
|
| 46263 | 698 |
|
| 61493 | 699 |
\<^descr> @{ML FIRSTGOAL}~\<open>tac\<close> is equivalent to \<open>tac
|
700 |
1\<close>~@{ML_op ORELSE}~\<open>\<dots>\<close>~@{ML_op ORELSE}~\<open>tac n\<close>. It
|
|
701 |
applies \<open>tac\<close> to one subgoal, counting upwards. |
|
| 46263 | 702 |
|
| 61493 | 703 |
\<^descr> @{ML HEADGOAL}~\<open>tac\<close> is equivalent to \<open>tac 1\<close>.
|
704 |
It applies \<open>tac\<close> unconditionally to the first subgoal. |
|
| 46267 | 705 |
|
| 61493 | 706 |
\<^descr> @{ML REPEAT_SOME}~\<open>tac\<close> applies \<open>tac\<close> once or
|
| 46263 | 707 |
more to a subgoal, counting downwards. |
708 |
||
| 61493 | 709 |
\<^descr> @{ML REPEAT_FIRST}~\<open>tac\<close> applies \<open>tac\<close> once or
|
| 46263 | 710 |
more to a subgoal, counting upwards. |
711 |
||
| 61493 | 712 |
\<^descr> @{ML RANGE}~\<open>[tac\<^sub>1, \<dots>, tac\<^sub>k] i\<close> is equivalent to
|
713 |
\<open>tac\<^sub>k (i + k - 1)\<close>~@{ML_op THEN}~\<open>\<dots>\<close>~@{ML_op
|
|
714 |
THEN}~\<open>tac\<^sub>1 i\<close>. It applies the given list of tactics to the |
|
| 46267 | 715 |
corresponding range of subgoals, counting downwards. |
| 58618 | 716 |
\<close> |
| 46263 | 717 |
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
718 |
|
| 58618 | 719 |
subsection \<open>Control and search tacticals\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
720 |
|
| 58618 | 721 |
text \<open>A predicate on theorems @{ML_type "thm -> bool"} can test
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
722 |
whether a goal state enjoys some desirable property --- such as |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
723 |
having no subgoals. Tactics that search for satisfactory goal |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
724 |
states are easy to express. The main search procedures, |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
725 |
depth-first, breadth-first and best-first, are provided as |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
726 |
tacticals. They generate the search tree by repeatedly applying a |
| 58618 | 727 |
given tactic.\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
728 |
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
729 |
|
| 46270 | 730 |
text %mlref "" |
731 |
||
| 58618 | 732 |
subsubsection \<open>Filtering a tactic's results\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
733 |
|
| 58618 | 734 |
text \<open> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
735 |
\begin{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
736 |
@{index_ML FILTER: "(thm -> bool) -> tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
737 |
@{index_ML CHANGED: "tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
738 |
\end{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
739 |
|
| 61493 | 740 |
\<^descr> @{ML FILTER}~\<open>sat tac\<close> applies \<open>tac\<close> to the
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
741 |
goal state and returns a sequence consisting of those result goal |
| 61493 | 742 |
states that are satisfactory in the sense of \<open>sat\<close>. |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
743 |
|
| 61493 | 744 |
\<^descr> @{ML CHANGED}~\<open>tac\<close> applies \<open>tac\<close> to the goal
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
745 |
state and returns precisely those states that differ from the |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
746 |
original state (according to @{ML Thm.eq_thm}). Thus @{ML
|
| 61493 | 747 |
CHANGED}~\<open>tac\<close> always has some effect on the state. |
| 58618 | 748 |
\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
749 |
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
750 |
|
| 58618 | 751 |
subsubsection \<open>Depth-first search\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
752 |
|
| 58618 | 753 |
text \<open> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
754 |
\begin{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
755 |
@{index_ML DEPTH_FIRST: "(thm -> bool) -> tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
756 |
@{index_ML DEPTH_SOLVE: "tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
757 |
@{index_ML DEPTH_SOLVE_1: "tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
758 |
\end{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
759 |
|
| 61493 | 760 |
\<^descr> @{ML DEPTH_FIRST}~\<open>sat tac\<close> returns the goal state if
|
761 |
\<open>sat\<close> returns true. Otherwise it applies \<open>tac\<close>, |
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
762 |
then recursively searches from each element of the resulting |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
763 |
sequence. The code uses a stack for efficiency, in effect applying |
| 61493 | 764 |
\<open>tac\<close>~@{ML_op THEN}~@{ML DEPTH_FIRST}~\<open>sat tac\<close> to
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
765 |
the state. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
766 |
|
| 61493 | 767 |
\<^descr> @{ML DEPTH_SOLVE}\<open>tac\<close> uses @{ML DEPTH_FIRST} to
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
768 |
search for states having no subgoals. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
769 |
|
| 61493 | 770 |
\<^descr> @{ML DEPTH_SOLVE_1}~\<open>tac\<close> uses @{ML DEPTH_FIRST} to
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
771 |
search for states having fewer subgoals than the given state. Thus, |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
772 |
it insists upon solving at least one subgoal. |
| 58618 | 773 |
\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
774 |
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
775 |
|
| 58618 | 776 |
subsubsection \<open>Other search strategies\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
777 |
|
| 58618 | 778 |
text \<open> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
779 |
\begin{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
780 |
@{index_ML BREADTH_FIRST: "(thm -> bool) -> tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
781 |
@{index_ML BEST_FIRST: "(thm -> bool) * (thm -> int) -> tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
782 |
@{index_ML THEN_BEST_FIRST: "tactic -> (thm -> bool) * (thm -> int) -> tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
783 |
\end{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
784 |
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
785 |
These search strategies will find a solution if one exists. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
786 |
However, they do not enumerate all solutions; they terminate after |
| 61493 | 787 |
the first satisfactory result from \<open>tac\<close>. |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
788 |
|
| 61493 | 789 |
\<^descr> @{ML BREADTH_FIRST}~\<open>sat tac\<close> uses breadth-first
|
790 |
search to find states for which \<open>sat\<close> is true. For most |
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
791 |
applications, it is too slow. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
792 |
|
| 61493 | 793 |
\<^descr> @{ML BEST_FIRST}~\<open>(sat, dist) tac\<close> does a heuristic
|
794 |
search, using \<open>dist\<close> to estimate the distance from a |
|
795 |
satisfactory state (in the sense of \<open>sat\<close>). It maintains a |
|
796 |
list of states ordered by distance. It applies \<open>tac\<close> to the |
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
797 |
head of this list; if the result contains any satisfactory states, |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
798 |
then it returns them. Otherwise, @{ML BEST_FIRST} adds the new
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
799 |
states to the list, and continues. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
800 |
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
801 |
The distance function is typically @{ML size_of_thm}, which computes
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
802 |
the size of the state. The smaller the state, the fewer and simpler |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
803 |
subgoals it has. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
804 |
|
| 61493 | 805 |
\<^descr> @{ML THEN_BEST_FIRST}~\<open>tac\<^sub>0 (sat, dist) tac\<close> is like
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
806 |
@{ML BEST_FIRST}, except that the priority queue initially contains
|
| 61493 | 807 |
the result of applying \<open>tac\<^sub>0\<close> to the goal state. This |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
808 |
tactical permits separate tactics for starting the search and |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
809 |
continuing the search. |
| 58618 | 810 |
\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
811 |
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
812 |
|
| 58618 | 813 |
subsubsection \<open>Auxiliary tacticals for searching\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
814 |
|
| 58618 | 815 |
text \<open> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
816 |
\begin{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
817 |
@{index_ML COND: "(thm -> bool) -> tactic -> tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
818 |
@{index_ML IF_UNSOLVED: "tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
819 |
@{index_ML SOLVE: "tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
820 |
@{index_ML DETERM: "tactic -> tactic"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
821 |
\end{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
822 |
|
| 61493 | 823 |
\<^descr> @{ML COND}~\<open>sat tac\<^sub>1 tac\<^sub>2\<close> applies \<open>tac\<^sub>1\<close> to
|
824 |
the goal state if it satisfies predicate \<open>sat\<close>, and applies |
|
825 |
\<open>tac\<^sub>2\<close>. It is a conditional tactical in that only one of |
|
826 |
\<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close> is applied to a goal state. |
|
827 |
However, both \<open>tac\<^sub>1\<close> and \<open>tac\<^sub>2\<close> are evaluated |
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
828 |
because ML uses eager evaluation. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
829 |
|
| 61493 | 830 |
\<^descr> @{ML IF_UNSOLVED}~\<open>tac\<close> applies \<open>tac\<close> to the
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
831 |
goal state if it has any subgoals, and simply returns the goal state |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
832 |
otherwise. Many common tactics, such as @{ML resolve_tac}, fail if
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
833 |
applied to a goal state that has no subgoals. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
834 |
|
| 61493 | 835 |
\<^descr> @{ML SOLVE}~\<open>tac\<close> applies \<open>tac\<close> to the goal
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
836 |
state and then fails iff there are subgoals left. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
837 |
|
| 61493 | 838 |
\<^descr> @{ML DETERM}~\<open>tac\<close> applies \<open>tac\<close> to the goal
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
839 |
state and returns the head of the resulting sequence. @{ML DETERM}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
840 |
limits the search space by making its argument deterministic. |
| 58618 | 841 |
\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
842 |
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
843 |
|
| 58618 | 844 |
subsubsection \<open>Predicates and functions useful for searching\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
845 |
|
| 58618 | 846 |
text \<open> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
847 |
\begin{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
848 |
@{index_ML has_fewer_prems: "int -> thm -> bool"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
849 |
@{index_ML Thm.eq_thm: "thm * thm -> bool"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
850 |
@{index_ML Thm.eq_thm_prop: "thm * thm -> bool"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
851 |
@{index_ML size_of_thm: "thm -> int"} \\
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
852 |
\end{mldecls}
|
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
853 |
|
| 61493 | 854 |
\<^descr> @{ML has_fewer_prems}~\<open>n thm\<close> reports whether \<open>thm\<close> has fewer than \<open>n\<close> premises.
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
855 |
|
| 61493 | 856 |
\<^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
|
|
55547
384bfd19ee61
subtle change of semantics of Thm.eq_thm, e.g. relevant for merge of src/HOL/Tools/Predicate_Compile/core_data.ML (cf. HOL-IMP);
wenzelm
parents:
53096
diff
changeset
|
857 |
same conclusions, the same set of hypotheses, and the same set of sort |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
858 |
hypotheses. Names of bound variables are ignored as usual. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
859 |
|
| 61493 | 860 |
\<^descr> @{ML Thm.eq_thm_prop}~\<open>(thm\<^sub>1, thm\<^sub>2)\<close> reports whether
|
861 |
the propositions of \<open>thm\<^sub>1\<close> and \<open>thm\<^sub>2\<close> are equal. |
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
862 |
Names of bound variables are ignored. |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
863 |
|
| 61493 | 864 |
\<^descr> @{ML size_of_thm}~\<open>thm\<close> computes the size of \<open>thm\<close>, namely the number of variables, constants and abstractions
|
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
865 |
in its conclusion. It may serve as a distance function for |
|
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
866 |
@{ML BEST_FIRST}.
|
| 58618 | 867 |
\<close> |
|
46269
e75181672150
updated "Control and search tacticals" (moved from ref to implementation);
wenzelm
parents:
46267
diff
changeset
|
868 |
|
| 18537 | 869 |
end |