18 considerably lessen the burden of manual reasoning. They are centred around |
18 considerably lessen the burden of manual reasoning. They are centred around |
19 the idea of refining a goal state using tactics. This is similar to the |
19 the idea of refining a goal state using tactics. This is similar to the |
20 \isacommand{apply}-style reasoning at the user-level, where goals are |
20 \isacommand{apply}-style reasoning at the user-level, where goals are |
21 modified in a sequence of proof steps until all of them are discharged. |
21 modified in a sequence of proof steps until all of them are discharged. |
22 In this chapter we will explain simple tactics and how to combine them using |
22 In this chapter we will explain simple tactics and how to combine them using |
23 tactic combinators. We also explain briefly the simplifier and conversions. |
23 tactic combinators. We also describe the simplifier, simprocs and conversions. |
24 *} |
24 *} |
25 |
25 |
26 |
26 |
27 section {* Basics of Reasoning with Tactics*} |
27 section {* Basics of Reasoning with Tactics*} |
28 |
28 |
47 "let |
47 "let |
48 val ctxt = @{context} |
48 val ctxt = @{context} |
49 val goal = @{prop \"P \<or> Q \<Longrightarrow> Q \<or> P\"} |
49 val goal = @{prop \"P \<or> Q \<Longrightarrow> Q \<or> P\"} |
50 in |
50 in |
51 Goal.prove ctxt [\"P\", \"Q\"] [] goal |
51 Goal.prove ctxt [\"P\", \"Q\"] [] goal |
52 (fn _ => |
52 (fn _ => etac @{thm disjE} 1 |
53 etac @{thm disjE} 1 |
53 THEN rtac @{thm disjI2} 1 |
54 THEN rtac @{thm disjI2} 1 |
54 THEN atac 1 |
55 THEN atac 1 |
55 THEN rtac @{thm disjI1} 1 |
56 THEN rtac @{thm disjI1} 1 |
56 THEN atac 1) |
57 THEN atac 1) |
|
58 end" "?P \<or> ?Q \<Longrightarrow> ?Q \<or> ?P"} |
57 end" "?P \<or> ?Q \<Longrightarrow> ?Q \<or> ?P"} |
59 |
58 |
60 To start the proof, the function @{ML_ind prove in Goal} sets up a goal |
59 To start the proof, the function @{ML_ind prove in Goal} sets up a goal |
61 state for proving the goal @{prop "P \<or> Q \<Longrightarrow> Q \<or> P"}. We can give this |
60 state for proving the goal @{prop "P \<or> Q \<Longrightarrow> Q \<or> P"}. We can give this |
62 function some assumptions in the third argument (there are no assumption in |
61 function some assumptions in the third argument (there are no assumption in |
63 the proof at hand). The second argument stands for a list of variables |
62 the proof at hand). The second argument stands for a list of variables |
64 (given as strings). This list contains the variables that will be turned |
63 (given as strings). This list contains the variables that will be turned |
65 into schematic variables once the goal is proved (in our case @{text P} and |
64 into schematic variables once the goal is proved (in our case @{text P} and |
66 @{text Q}). The last argument is the tactic that proves the goal. This |
65 @{text Q}). The last argument is the tactic that proves the goal. This |
67 tactic can make use of the local assumptions (there are none in this |
66 tactic can make use of the local assumptions (there are none in this |
68 example). The tactics @{ML_ind etac}, @{ML_ind rtac} and @{ML_ind atac} in |
67 example). The tactics @{ML_ind etac in Tactic}, @{ML_ind rtac in Tactic} and |
69 the code above correspond roughly to @{text erule}, @{text rule} and @{text |
68 @{ML_ind atac in Tactic} in the code above correspond roughly to @{text |
70 assumption}, respectively. The combinator @{ML_ind THEN} strings the tactics |
69 erule}, @{text rule} and @{text assumption}, respectively. The combinator |
71 together. |
70 @{ML THEN} strings the tactics together. |
72 |
71 |
73 \begin{readmore} |
72 \begin{readmore} |
74 To learn more about the function @{ML_ind prove in Goal} see |
73 To learn more about the function @{ML_ind prove in Goal} see |
75 \isccite{sec:results} and the file @{ML_file "Pure/goal.ML"}. See @{ML_file |
74 \isccite{sec:results} and the file @{ML_file "Pure/goal.ML"}. See @{ML_file |
76 "Pure/tactic.ML"} and @{ML_file "Pure/tactical.ML"} for the code of basic |
75 "Pure/tactic.ML"} and @{ML_file "Pure/tactical.ML"} for the code of basic |
78 Isabelle Reference Manual, and Chapter 3 in the Isabelle/Isar Implementation |
77 Isabelle Reference Manual, and Chapter 3 in the Isabelle/Isar Implementation |
79 Manual. |
78 Manual. |
80 \end{readmore} |
79 \end{readmore} |
81 |
80 |
82 Note that in the code above we use antiquotations for referencing the |
81 Note that in the code above we use antiquotations for referencing the |
83 theorems. We could also just have written @{ML "etac disjE 1"}. The reason |
82 theorems. We could also just have written @{ML "etac disjE 1"} because |
84 is that many of the basic theorems have a corresponding ML-binding: |
83 many of the basic theorems have a corresponding ML-binding: |
85 |
84 |
86 @{ML_response_fake [gray,display] |
85 @{ML_response_fake [gray,display] |
87 "disjE" |
86 "disjE" |
88 "\<lbrakk>?P \<or> ?Q; ?P \<Longrightarrow> ?R; ?Q \<Longrightarrow> ?R\<rbrakk> \<Longrightarrow> ?R"} |
87 "\<lbrakk>?P \<or> ?Q; ?P \<Longrightarrow> ?R; ?Q \<Longrightarrow> ?R\<rbrakk> \<Longrightarrow> ?R"} |
89 |
88 |
90 In case where there is no ML-binding theorems can also be obtained dynamically using |
89 In case where no ML-binding exists, theorems can also be looked up dynamically |
91 the function @{ML thm} and the (string) name of the theorem; for example: |
90 using the function @{ML thm} and the (string) name of the theorem. For example: |
92 |
91 |
93 @{ML_response_fake [gray,display] |
92 @{ML_response_fake [gray,display] |
94 "thm \"disjE\"" |
93 "thm \"disjE\"" |
95 "\<lbrakk>?P \<or> ?Q; ?P \<Longrightarrow> ?R; ?Q \<Longrightarrow> ?R\<rbrakk> \<Longrightarrow> ?R"} |
94 "\<lbrakk>?P \<or> ?Q; ?P \<Longrightarrow> ?R; ?Q \<Longrightarrow> ?R\<rbrakk> \<Longrightarrow> ?R"} |
96 |
95 |
97 Both ways however are considered bad style! The reason is that the binding |
96 Both ways however are considered \emph{bad} style! The reason is that the binding |
98 for @{ML disjE} can be re-assigned by the user and thus one does not have |
97 for @{ML disjE} can be re-assigned and thus one does not have |
99 complete control over which theorem is actually applied. Similarly with the |
98 complete control over which theorem is actually applied. Similarly with the |
100 string @{text [quotes] "disjE"}. Although theorems in the theorem database |
99 lookup of @{text [quotes] "disjE"}. Although theorems must have a unique name |
101 must have a unique name, the string can stand for a dynamically updated |
100 in the theorem database, the string can stand for a dynamically updatable |
102 theorem list. Also in this case we cannot be sure which theorem is applied. |
101 theorem list. Also in this case we cannot be sure which theorem is applied. |
103 These problems can be nicely prevented by using antiquotations, because then |
102 These problems can be nicely prevented by using antiquotations, because then |
104 the theorems are fixed statically at compile-time. |
103 the theorems are fixed statically at compile-time. |
105 |
104 |
106 |
105 |
144 THEN' atac |
143 THEN' atac |
145 THEN' rtac @{thm disjI1} |
144 THEN' rtac @{thm disjI1} |
146 THEN' atac)*}text_raw{*\label{tac:footacprime}*} |
145 THEN' atac)*}text_raw{*\label{tac:footacprime}*} |
147 |
146 |
148 text {* |
147 text {* |
149 where @{ML_ind THEN'} is used instead of @{ML THEN}. (For most combinators |
148 where @{ML_ind THEN' in Tactical} is used instead of @{ML THEN in |
150 that combine tactics---@{ML THEN} is only one such combinator---a ``primed'' |
149 Tactical}. (For most combinators that combine tactics---@{ML THEN} is only |
151 version exists.) With @{ML foo_tac'} you can give the number for the |
150 one such combinator---a ``primed'' version exists.) With @{ML foo_tac'} you |
152 subgoal explicitly when the tactic is called. So in the next proof you can |
151 can give the number for the subgoal explicitly when the tactic is called. So |
153 first discharge the second subgoal, and subsequently the first. |
152 in the next proof you can first discharge the second subgoal, and |
|
153 subsequently the first. |
154 *} |
154 *} |
155 |
155 |
156 lemma |
156 lemma |
157 shows "P1 \<or> Q1 \<Longrightarrow> Q1 \<or> P1" |
157 shows "P1 \<or> Q1 \<Longrightarrow> Q1 \<or> P1" |
158 and "P2 \<or> Q2 \<Longrightarrow> Q2 \<or> P2" |
158 and "P2 \<or> Q2 \<Longrightarrow> Q2 \<or> P2" |
165 hard-coded inside the tactic. |
165 hard-coded inside the tactic. |
166 |
166 |
167 The tactics @{ML foo_tac} and @{ML foo_tac'} are very specific for analysing |
167 The tactics @{ML foo_tac} and @{ML foo_tac'} are very specific for analysing |
168 goals being only of the form @{prop "P \<or> Q \<Longrightarrow> Q \<or> P"}. If the goal is not of |
168 goals being only of the form @{prop "P \<or> Q \<Longrightarrow> Q \<or> P"}. If the goal is not of |
169 this form, then these tactics return the error message:\footnote{To be |
169 this form, then these tactics return the error message:\footnote{To be |
170 precise, tactics do not produce this error message, it originates from the |
170 precise, tactics do not produce this error message; the message originates from the |
171 \isacommand{apply} wrapper.} |
171 \isacommand{apply} wrapper that calls the tactic.} |
172 |
172 |
173 |
173 |
174 \begin{isabelle} |
174 \begin{isabelle} |
175 @{text "*** empty result sequence -- proof command failed"}\\ |
175 @{text "*** empty result sequence -- proof command failed"}\\ |
176 @{text "*** At command \"apply\"."} |
176 @{text "*** At command \"apply\"."} |
187 By convention, if a tactic fails, then it should return the empty sequence. |
187 By convention, if a tactic fails, then it should return the empty sequence. |
188 Therefore, if you write your own tactics, they should not raise exceptions |
188 Therefore, if you write your own tactics, they should not raise exceptions |
189 willy-nilly; only in very grave failure situations should a tactic raise the |
189 willy-nilly; only in very grave failure situations should a tactic raise the |
190 exception @{text THM}. |
190 exception @{text THM}. |
191 |
191 |
192 The simplest tactics are @{ML_ind no_tac} and @{ML_ind all_tac}. The first returns |
192 The simplest tactics are @{ML_ind no_tac in Tactical} and |
193 the empty sequence and is defined as |
193 @{ML_ind all_tac in Tactical}. The first returns the empty sequence and |
|
194 is defined as |
194 *} |
195 *} |
195 |
196 |
196 ML{*fun no_tac thm = Seq.empty*} |
197 ML{*fun no_tac thm = Seq.empty*} |
197 |
198 |
198 text {* |
199 text {* |
244 let |
245 let |
245 val _ = tracing (string_of_thm_no_vars ctxt thm) |
246 val _ = tracing (string_of_thm_no_vars ctxt thm) |
246 in |
247 in |
247 Seq.single thm |
248 Seq.single thm |
248 end*} |
249 end*} |
|
250 |
|
251 text {* |
|
252 which prints out the given theorem (using the string-function defined in |
|
253 Section~\ref{sec:printing}) and then behaves like @{ML all_tac}. With this |
|
254 tactic we are in the position to inspect every goal state in a proof. For |
|
255 this consider the proof in Figure~\ref{fig:goalstates}: as can be seen, |
|
256 internally every goal state is an implication of the form |
|
257 |
|
258 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> #C"} |
|
259 |
|
260 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are |
|
261 the subgoals. So after setting up the lemma, the goal state is always of the |
|
262 form @{text "C \<Longrightarrow> #C"}; when the proof is finished we are left with @{text |
|
263 "#C"}. Since the goal @{term C} can potentially be an implication, there is a |
|
264 ``protector'' wrapped around it (the wrapper is the outermost constant |
|
265 @{text "Const (\"prop\", bool \<Rightarrow> bool)"}; in the figure we make it visible |
|
266 as a @{text #}). This wrapper prevents that premises of @{text C} are |
|
267 misinterpreted as open subgoals. While tactics can operate on the subgoals |
|
268 (the @{text "A\<^isub>i"} above), they are expected to leave the conclusion |
|
269 @{term C} intact, with the exception of possibly instantiating schematic |
|
270 variables. This instantiations of schematic variables can be observed |
|
271 on the user level. Have a look at the following definition and proof. |
|
272 *} |
249 |
273 |
250 text_raw {* |
274 text_raw {* |
251 \begin{figure}[p] |
275 \begin{figure}[p] |
252 \begin{boxedminipage}{\textwidth} |
276 \begin{boxedminipage}{\textwidth} |
253 \begin{isabelle} |
277 \begin{isabelle} |
331 you finish the proof the theorem is @{text "#(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> |
355 you finish the proof the theorem is @{text "#(\<lbrakk>A; B\<rbrakk> \<Longrightarrow> A \<and> |
332 B)"}.\label{fig:goalstates}} |
356 B)"}.\label{fig:goalstates}} |
333 \end{figure} |
357 \end{figure} |
334 *} |
358 *} |
335 |
359 |
336 text {* |
|
337 which prints out the given theorem (using the string-function defined in |
|
338 Section~\ref{sec:printing}) and then behaves like @{ML all_tac}. With this |
|
339 tactic we are in the position to inspect every goal state in a proof. For |
|
340 this consider the proof in Figure~\ref{fig:goalstates}: as can be seen, |
|
341 internally every goal state is an implication of the form |
|
342 |
|
343 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> #C"} |
|
344 |
|
345 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are |
|
346 the subgoals. So after setting up the lemma, the goal state is always of the |
|
347 form @{text "C \<Longrightarrow> #C"}; when the proof is finished we are left with @{text |
|
348 "#C"}. Since the goal @{term C} can potentially be an implication, there is a |
|
349 ``protector'' wrapped around it (the wrapper is the outermost constant |
|
350 @{text "Const (\"prop\", bool \<Rightarrow> bool)"}; in the figure we make it visible |
|
351 as an @{text #}). This wrapper prevents that premises of @{text C} are |
|
352 misinterpreted as open subgoals. While tactics can operate on the subgoals |
|
353 (the @{text "A\<^isub>i"} above), they are expected to leave the conclusion |
|
354 @{term C} intact, with the exception of possibly instantiating schematic |
|
355 variables. This instantiations of schematic variables can be observed |
|
356 on the user level. Have a look at the following definition and proof. |
|
357 *} |
|
358 |
|
359 definition |
360 definition |
360 EQ_TRUE |
361 EQ_TRUE |
361 where |
362 where |
362 "EQ_TRUE X \<equiv> (X = True)" |
363 "EQ_TRUE X \<equiv> (X = True)" |
363 |
364 |
364 lemma test: |
365 lemma test: |
365 shows "EQ_TRUE ?X" |
366 shows "EQ_TRUE ?X" |
366 unfolding EQ_TRUE_def |
367 unfolding EQ_TRUE_def |
367 by (rule refl) |
368 by (rule refl) |
368 |
369 |
369 text {* |
370 text {* |
370 Although Isabelle issues a warning message when stating goals involving |
371 Although Isabelle issues a warning message when stating goals involving |
371 meta-variables, it is possible to prove this theorem. The reason for the warning |
372 meta-variables, it is possible to prove this theorem. The reason for the warning |
372 message is that the proved theorem is not @{text "EQ_TRUE ?X"}, as one might |
373 message is that the proved theorem is not @{text "EQ_TRUE ?X"}, as one might |
376 \isacommand{thm}~@{thm [source] test}\\ |
377 \isacommand{thm}~@{thm [source] test}\\ |
377 @{text ">"}~@{thm test} |
378 @{text ">"}~@{thm test} |
378 \end{isabelle} |
379 \end{isabelle} |
379 |
380 |
380 The reason for this result is that the schematic variable @{text "?X"} |
381 The reason for this result is that the schematic variable @{text "?X"} |
381 is instantiated inside the proof and then the instantiation propagated |
382 is instantiated inside the proof to be @{term True} and then the |
382 to the ``outside''. |
383 instantiation propagated to the ``outside''. |
383 |
384 |
384 \begin{readmore} |
385 \begin{readmore} |
385 For more information about the internals of goals see \isccite{sec:tactical-goals}. |
386 For more information about the internals of goals see \isccite{sec:tactical-goals}. |
386 \end{readmore} |
387 \end{readmore} |
387 |
388 |
388 *} |
389 *} |
389 |
390 |
390 section {* Simple Tactics\label{sec:simpletacs} *} |
391 section {* Simple Tactics\label{sec:simpletacs} *} |
391 |
392 |
392 text {* |
393 text {* |
393 In this section we will describe more of the simple tactics in Isabelle. The |
394 In this section we will introduce more simple tactics. The |
394 first one is @{ML_ind print_tac}, which is quite useful |
395 first one is @{ML_ind print_tac in Tactical}, which is quite useful |
395 for low-level debugging of tactics. It just prints out a message and the current |
396 for low-level debugging of tactics. It just prints out a message and the current |
396 goal state. Unlike @{ML my_print_tac} shown earlier, it prints the goal state |
397 goal state. Unlike @{ML my_print_tac} shown earlier, it prints the goal state |
397 as the user would see it. For example, processing the proof |
398 as the user would see it. For example, processing the proof |
398 *} |
399 *} |
399 |
400 |
426 (*<*)oops(*>*) |
427 (*<*)oops(*>*) |
427 |
428 |
428 text {* |
429 text {* |
429 This tactic works however only if the quick-and-dirty mode of Isabelle |
430 This tactic works however only if the quick-and-dirty mode of Isabelle |
430 is switched on. This is done automatically in the ``interactive |
431 is switched on. This is done automatically in the ``interactive |
431 mode'' of Isabelle, but must ne done manually in the ``batch mode''. |
432 mode'' of Isabelle, but must be done manually in the ``batch mode'' |
432 |
433 with for example the assignment |
433 Another simple tactic is the function @{ML_ind atac}, which, as shown |
434 *} |
|
435 |
|
436 ML{*quick_and_dirty := true*} |
|
437 |
|
438 text {* |
|
439 Another simple tactic is the function @{ML_ind atac in Tactic}, which, as shown |
434 earlier, corresponds to the assumption method. |
440 earlier, corresponds to the assumption method. |
435 *} |
441 *} |
436 |
442 |
437 lemma |
443 lemma |
438 shows "P \<Longrightarrow> P" |
444 shows "P \<Longrightarrow> P" |
441 @{subgoals [display]} |
447 @{subgoals [display]} |
442 \end{minipage}*} |
448 \end{minipage}*} |
443 (*<*)oops(*>*) |
449 (*<*)oops(*>*) |
444 |
450 |
445 text {* |
451 text {* |
446 Similarly, @{ML_ind rtac}, @{ML_ind dtac}, @{ML_ind etac} and |
452 Similarly, @{ML_ind rtac in Tactic}, @{ML_ind dtac in Tactic}, @{ML_ind etac |
447 @{ML_ind ftac} correspond (roughly) |
453 in Tactic} and @{ML_ind ftac in Tactic} correspond (roughly) to @{text |
448 to @{text rule}, @{text drule}, @{text erule} and @{text frule}, |
454 rule}, @{text drule}, @{text erule} and @{text frule}, respectively. Each of |
449 respectively. Each of them takes a theorem as argument and attempts to |
455 them takes a theorem as argument and attempts to apply it to a goal. Below |
450 apply it to a goal. Below are three self-explanatory examples. |
456 are three self-explanatory examples. |
451 *} |
457 *} |
452 |
458 |
453 lemma |
459 lemma |
454 shows "P \<and> Q" |
460 shows "P \<and> Q" |
455 apply(tactic {* rtac @{thm conjI} 1 *}) |
461 apply(tactic {* rtac @{thm conjI} 1 *}) |
498 \end{minipage}*} |
504 \end{minipage}*} |
499 (*<*)oops(*>*) |
505 (*<*)oops(*>*) |
500 |
506 |
501 text {* |
507 text {* |
502 Similar versions taking a list of theorems exist for the tactics |
508 Similar versions taking a list of theorems exist for the tactics |
503 @{ML dtac} (@{ML_ind dresolve_tac}), @{ML etac} |
509 @{ML dtac} (@{ML_ind dresolve_tac in Tactic}), @{ML etac} |
504 (@{ML_ind eresolve_tac}) and so on. |
510 (@{ML_ind eresolve_tac in Tactic}) and so on. |
505 |
511 |
506 |
512 Another simple tactic is @{ML_ind cut_facts_tac in Tactic}. It inserts a |
507 Another simple tactic is @{ML_ind cut_facts_tac}. It inserts a list of theorems |
513 list of theorems into the assumptions of the current goal state. Below we |
508 into the assumptions of the current goal state. Below we will insert the definitions |
514 will insert the definitions for the constants @{term True} and @{term |
509 for the constants @{term True} and @{term False}. So |
515 False}. So |
510 *} |
516 *} |
511 |
517 |
512 lemma |
518 lemma |
513 shows "True \<noteq> False" |
519 shows "True \<noteq> False" |
514 apply(tactic {* cut_facts_tac [@{thm True_def}, @{thm False_def}] 1 *}) |
520 apply(tactic {* cut_facts_tac [@{thm True_def}, @{thm False_def}] 1 *}) |
521 |
527 |
522 text {* |
528 text {* |
523 Often proofs on the ML-level involve elaborate operations on assumptions and |
529 Often proofs on the ML-level involve elaborate operations on assumptions and |
524 @{text "\<And>"}-quantified variables. To do such operations using the basic tactics |
530 @{text "\<And>"}-quantified variables. To do such operations using the basic tactics |
525 shown so far is very unwieldy and brittle. Some convenience and |
531 shown so far is very unwieldy and brittle. Some convenience and |
526 safety is provided by the functions @{ML_ind FOCUS in Subgoal} and |
532 safety is provided by the functions @{ML_ind FOCUS in Subgoal} and |
527 @{ML_ind SUBPROOF}. These tactics fix the parameters |
533 @{ML_ind SUBPROOF in Subgoal}. These tactics fix the parameters |
528 and bind the various components of a goal state to a record. |
534 and bind the various components of a goal state to a record. |
529 To see what happens, suppose the function defined in Figure~\ref{fig:sptac}, which |
535 To see what happens, suppose the function defined in Figure~\ref{fig:sptac}, which |
530 takes a record and just prints out the contents of this record. Consider |
536 takes a record and just prints out the contents of this record. Then consider |
531 now the proof: |
537 the proof: |
532 *} |
538 *} |
533 |
539 |
534 ML {* Subgoal.FOCUS *} |
|
535 |
540 |
536 text_raw{* |
541 text_raw{* |
537 \begin{figure}[t] |
542 \begin{figure}[t] |
538 \begin{minipage}{\textwidth} |
543 \begin{minipage}{\textwidth} |
539 \begin{isabelle} |
544 \begin{isabelle} |
586 conclusion: & @{term "B y x \<longrightarrow> C (z y) x"}\\ |
591 conclusion: & @{term "B y x \<longrightarrow> C (z y) x"}\\ |
587 premises: & @{term "A x y"} |
592 premises: & @{term "A x y"} |
588 \end{tabular} |
593 \end{tabular} |
589 \end{quote} |
594 \end{quote} |
590 |
595 |
591 The @{text params} and @{text schematics} stand or list of pairs where the left-hand |
596 The @{text params} and @{text schematics} stand or list of pairs where the |
592 side of @{text ":="} is replaced by the right-hand side inside the tactic. |
597 left-hand side of @{text ":="} is replaced by the right-hand side inside the |
593 Notice that in the actual output the brown colour of the variables @{term x}, |
598 tactic. Notice that in the actual output the variables @{term x} and @{term |
594 and @{term y}. Although they are parameters in the original goal, they are fixed inside |
599 y} have a brown colour. Although they are parameters in the original goal, |
595 the tactic. By convention these fixed variables are printed in brown colour. |
600 they are fixed inside the tactic. By convention these fixed variables are |
596 Similarly the schematic variable @{text ?z}. The assumption, or premise, |
601 printed in brown colour. Similarly the schematic variable @{text ?z}. The |
597 @{prop "A x y"} is bound as @{ML_type cterm} to the record-variable |
602 assumption, or premise, @{prop "A x y"} is bound as @{ML_type cterm} to the |
598 @{text asms}, but also as @{ML_type thm} to @{text prems}. |
603 record-variable @{text asms}, but also as @{ML_type thm} to @{text prems}. |
599 |
604 |
600 If we continue the proof script by applying the @{text impI}-rule |
605 If we continue the proof script by applying the @{text impI}-rule |
601 *} |
606 *} |
602 |
607 |
603 apply(rule impI) |
608 apply(rule impI) |
621 text {* |
626 text {* |
622 Now also @{term "B y x"} is an assumption bound to @{text asms} and @{text prems}. |
627 Now also @{term "B y x"} is an assumption bound to @{text asms} and @{text prems}. |
623 |
628 |
624 One difference between the tactics @{ML SUBPROOF} and @{ML FOCUS in Subgoal} |
629 One difference between the tactics @{ML SUBPROOF} and @{ML FOCUS in Subgoal} |
625 is that the former expects that the goal is solved completely, which the |
630 is that the former expects that the goal is solved completely, which the |
626 latter does not. Another is that @{ML SUBPROOF} can not instantiate any schematic |
631 latter does not. Another is that @{ML SUBPROOF} cannot instantiate any schematic |
627 variables. |
632 variables. |
628 |
633 |
629 One convenience of both @{ML FOCUS in Subgoal} and @{ML SUBPROOF} is that we |
634 One convenience of both @{ML FOCUS in Subgoal} and @{ML SUBPROOF} is that we |
630 can apply the assumptions using the usual tactics, because the parameter |
635 can apply the assumptions using the usual tactics, because the parameter |
631 @{text prems} contains them as theorems. With this you can easily implement |
636 @{text prems} contains them as theorems. With this you can easily implement |
674 Similar but less powerful functions than @{ML FOCUS in Subgoal}, respectively |
679 Similar but less powerful functions than @{ML FOCUS in Subgoal}, respectively |
675 @{ML SUBPROOF}, are |
680 @{ML SUBPROOF}, are |
676 @{ML_ind SUBGOAL} and @{ML_ind CSUBGOAL}. They allow you to |
681 @{ML_ind SUBGOAL} and @{ML_ind CSUBGOAL}. They allow you to |
677 inspect a given subgoal (the former |
682 inspect a given subgoal (the former |
678 presents the subgoal as a @{ML_type term}, while the latter as a @{ML_type |
683 presents the subgoal as a @{ML_type term}, while the latter as a @{ML_type |
679 cterm}). With this you can implement a tactic that applies a rule according |
684 cterm}). With them you can implement a tactic that applies a rule according |
680 to the topmost logic connective in the subgoal (to illustrate this we only |
685 to the topmost logic connective in the subgoal (to illustrate this we only |
681 analyse a few connectives). The code of the tactic is as |
686 analyse a few connectives). The code of the tactic is as |
682 follows. |
687 follows. |
683 *} |
688 *} |
684 |
689 |
699 analyse. Otherwise goals like @{prop "A \<and> B"} are not properly |
704 analyse. Otherwise goals like @{prop "A \<and> B"} are not properly |
700 analysed. Similarly with meta-implications in the next line. While for the |
705 analysed. Similarly with meta-implications in the next line. While for the |
701 first five patterns we can use the @{text "@term"}-antiquotation to |
706 first five patterns we can use the @{text "@term"}-antiquotation to |
702 construct the patterns, the pattern in Line 8 cannot be constructed in this |
707 construct the patterns, the pattern in Line 8 cannot be constructed in this |
703 way. The reason is that an antiquotation would fix the type of the |
708 way. The reason is that an antiquotation would fix the type of the |
704 quantified variable. So you really have to construct the pattern using the |
709 quantified variable. So you really have to construct this pattern using the |
705 basic term-constructors. This is not necessary in other cases, because their |
710 basic term-constructors. This is not necessary in the other cases, because their |
706 type is always fixed to function types involving only the type @{typ |
711 type is always fixed to function types involving only the type @{typ |
707 bool}. (See Section \ref{sec:terms_types_manually} about constructing terms |
712 bool}. (See Section \ref{sec:terms_types_manually} about constructing terms |
708 manually.) For the catch-all pattern, we chose to just return @{ML all_tac}. |
713 manually.) For the catch-all pattern, we chose to just return @{ML all_tac}. |
709 Consequently, @{ML select_tac} never fails. |
714 Consequently, @{ML select_tac} never fails. |
710 |
715 |
746 |
751 |
747 Of course, this example is |
752 Of course, this example is |
748 contrived: there are much simpler methods available in Isabelle for |
753 contrived: there are much simpler methods available in Isabelle for |
749 implementing a tactic analysing a goal according to its topmost |
754 implementing a tactic analysing a goal according to its topmost |
750 connective. These simpler methods use tactic combinators, which we will |
755 connective. These simpler methods use tactic combinators, which we will |
751 explain in the next section, but before that we will show how |
756 explain in the next section. But before that we will show how |
752 tactic application can be constraint. |
757 tactic application can be constrained. |
753 |
758 |
754 Since rules are applied using higher-order unification, an automatic proof |
759 Since rules are applied using higher-order unification, an automatic proof |
755 procedure might become too fragile, if it just applies inference rules as |
760 procedure might become too fragile, if it just applies inference rules as |
756 shown above. The reason is that a number of rules introduce meta-variables |
761 shown above. The reason is that a number of rules introduce schematic variables |
757 into the goal state. Consider for example the proof |
762 into the goal state. Consider for example the proof |
758 *} |
763 *} |
759 |
764 |
760 lemma |
765 lemma |
761 shows "\<forall>x \<in> A. P x \<Longrightarrow> Q x" |
766 shows "\<forall>x \<in> A. P x \<Longrightarrow> Q x" |
765 \end{minipage}*} |
770 \end{minipage}*} |
766 (*<*)oops(*>*) |
771 (*<*)oops(*>*) |
767 |
772 |
768 text {* |
773 text {* |
769 where the application of rule @{text bspec} generates two subgoals involving the |
774 where the application of rule @{text bspec} generates two subgoals involving the |
770 meta-variable @{text "?x"}. Now, if you are not careful, tactics |
775 schematic variable @{text "?x"}. Now, if you are not careful, tactics |
771 applied to the first subgoal might instantiate this meta-variable in such a |
776 applied to the first subgoal might instantiate this schematic variable in such a |
772 way that the second subgoal becomes unprovable. If it is clear what the @{text "?x"} |
777 way that the second subgoal becomes unprovable. If it is clear what the @{text "?x"} |
773 should be, then this situation can be avoided by introducing a more |
778 should be, then this situation can be avoided by introducing a more |
774 constrained version of the @{text bspec}-rule. One way to give such |
779 constrained version of the @{text bspec}-rule. One way to give such |
775 constraints is by pre-instantiating theorems with other theorems. |
780 constraints is by pre-instantiating theorems with other theorems. |
776 The function @{ML_ind "RS"}, for example, does this. |
781 The function @{ML_ind RS in Drule}, for example, does this. |
777 |
782 |
778 @{ML_response_fake [display,gray] |
783 @{ML_response_fake [display,gray] |
779 "@{thm disjI1} RS @{thm conjI}" "\<lbrakk>?P1; ?Q\<rbrakk> \<Longrightarrow> (?P1 \<or> ?Q1) \<and> ?Q"} |
784 "@{thm disjI1} RS @{thm conjI}" "\<lbrakk>?P1; ?Q\<rbrakk> \<Longrightarrow> (?P1 \<or> ?Q1) \<and> ?Q"} |
780 |
785 |
781 In this example it instantiates the first premise of the @{text conjI}-rule |
786 In this example it instantiates the first premise of the @{text conjI}-rule |
785 @{ML_response_fake_both [display,gray] |
790 @{ML_response_fake_both [display,gray] |
786 "@{thm conjI} RS @{thm mp}" |
791 "@{thm conjI} RS @{thm mp}" |
787 "*** Exception- THM (\"RSN: no unifiers\", 1, |
792 "*** Exception- THM (\"RSN: no unifiers\", 1, |
788 [\"\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q\", \"\<lbrakk>?P \<longrightarrow> ?Q; ?P\<rbrakk> \<Longrightarrow> ?Q\"]) raised"} |
793 [\"\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q\", \"\<lbrakk>?P \<longrightarrow> ?Q; ?P\<rbrakk> \<Longrightarrow> ?Q\"]) raised"} |
789 |
794 |
790 then the function raises an exception. The function @{ML_ind RSN} is similar to @{ML RS}, but |
795 then the function raises an exception. The function @{ML_ind RSN in Drule} |
791 takes an additional number as argument that makes explicit which premise |
796 is similar to @{ML RS}, but takes an additional number as argument. This |
792 should be instantiated. |
797 number makes explicit which premise should be instantiated. |
793 |
798 |
794 To improve readability of the theorems we shall produce below, we will use the |
799 To improve readability of the theorems we shall produce below, we will use the |
795 function @{ML no_vars} from Section~\ref{sec:printing}, which transforms |
800 function @{ML no_vars} from Section~\ref{sec:printing}, which transforms |
796 schematic variables into free ones. Using this function for the first @{ML |
801 schematic variables into free ones. Using this function for the first @{ML |
797 RS}-expression above produces the more readable result: |
802 RS}-expression above produces the more readable result: |
798 |
803 |
799 @{ML_response_fake [display,gray] |
804 @{ML_response_fake [display,gray] |
800 "no_vars @{context} (@{thm disjI1} RS @{thm conjI})" "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> (P \<or> Qa) \<and> Q"} |
805 "no_vars @{context} (@{thm disjI1} RS @{thm conjI})" "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> (P \<or> Qa) \<and> Q"} |
801 |
806 |
802 If you want to instantiate more than one premise of a theorem, you can use |
807 If you want to instantiate more than one premise of a theorem, you can use |
803 the function @{ML_ind MRS}: |
808 the function @{ML_ind MRS in Drule}: |
804 |
809 |
805 @{ML_response_fake [display,gray] |
810 @{ML_response_fake [display,gray] |
806 "no_vars @{context} ([@{thm disjI1}, @{thm disjI2}] MRS @{thm conjI})" |
811 "no_vars @{context} ([@{thm disjI1}, @{thm disjI2}] MRS @{thm conjI})" |
807 "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> (P \<or> Qa) \<and> (Pa \<or> Q)"} |
812 "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> (P \<or> Qa) \<and> (Pa \<or> Q)"} |
808 |
813 |
809 If you need to instantiate lists of theorems, you can use the |
814 If you need to instantiate lists of theorems, you can use the |
810 functions @{ML RL} and @{ML_ind MRL}. For example in the code below, |
815 functions @{ML_ind RL in Drule} and @{ML_ind MRL in Drule}. For |
811 every theorem in the second list is instantiated with every |
816 example in the code below, every theorem in the second list is |
812 theorem in the first. |
817 instantiated with every theorem in the first. |
813 |
818 |
814 @{ML_response_fake [display,gray] |
819 @{ML_response_fake [display,gray] |
815 "map (no_vars @{context}) |
820 "let |
816 ([@{thm impI}, @{thm disjI2}] RL [@{thm conjI}, @{thm disjI1}])" |
821 val list1 = [@{thm impI}, @{thm disjI2}] |
|
822 val list2 = [@{thm conjI}, @{thm disjI1}] |
|
823 in |
|
824 map (no_vars @{context}) (list1 RL list2) |
|
825 end" |
817 "[\<lbrakk>P \<Longrightarrow> Q; Qa\<rbrakk> \<Longrightarrow> (P \<longrightarrow> Q) \<and> Qa, |
826 "[\<lbrakk>P \<Longrightarrow> Q; Qa\<rbrakk> \<Longrightarrow> (P \<longrightarrow> Q) \<and> Qa, |
818 \<lbrakk>Q; Qa\<rbrakk> \<Longrightarrow> (P \<or> Q) \<and> Qa, |
827 \<lbrakk>Q; Qa\<rbrakk> \<Longrightarrow> (P \<or> Q) \<and> Qa, |
819 (P \<Longrightarrow> Q) \<Longrightarrow> (P \<longrightarrow> Q) \<or> Qa, |
828 (P \<Longrightarrow> Q) \<Longrightarrow> (P \<longrightarrow> Q) \<or> Qa, |
820 Q \<Longrightarrow> (P \<or> Q) \<or> Qa]"} |
829 Q \<Longrightarrow> (P \<or> Q) \<or> Qa]"} |
821 |
830 |
844 @{subgoals [display]} |
853 @{subgoals [display]} |
845 \end{minipage}*} |
854 \end{minipage}*} |
846 (*<*)oops(*>*) |
855 (*<*)oops(*>*) |
847 |
856 |
848 text {* |
857 text {* |
849 As you can see this is unfortunately \emph{not} the case. The problem is |
858 As you can see this is unfortunately \emph{not} the case if we apply @{thm [source] |
|
859 cong} with the method @{text rule}. The problem is |
850 that higher-order unification produces an instantiation that is not the |
860 that higher-order unification produces an instantiation that is not the |
851 intended one. While we can use \isacommand{back} to interactively find the |
861 intended one. While we can use \isacommand{back} to interactively find the |
852 intended instantiation, this is not an option for an automatic proof |
862 intended instantiation, this is not an option for an automatic proof |
853 procedure. Fortunately, the tactic @{ML_ind cong_tac in Cong_Tac} helps |
863 procedure. Fortunately, the tactic @{ML_ind cong_tac in Cong_Tac} helps |
854 with applying congruence rules and finding the intended instantiation. |
864 with applying congruence rules and finding the intended instantiation. |
|
865 For example |
855 *} |
866 *} |
856 |
867 |
857 lemma |
868 lemma |
858 fixes x y u w::"'a" |
869 fixes x y u w::"'a" |
859 shows "t x y = s u w" |
870 shows "t x y = s u w" |
862 @{subgoals [display]} |
873 @{subgoals [display]} |
863 \end{minipage}*} |
874 \end{minipage}*} |
864 (*<*)oops(*>*) |
875 (*<*)oops(*>*) |
865 |
876 |
866 text {* |
877 text {* |
867 However, sometimes it is necessary to expicitly match a theroem against a proof |
878 However, frequently it is necessary to explicitly match a theorem against a proof |
868 state and in doing so finding manually an appropriate instantiation. Imagine |
879 state and in doing so construct manually an appropriate instantiation. Imagine |
869 you have the theorem |
880 you have the theorem |
870 *} |
881 *} |
871 |
882 |
872 lemma rule: |
883 lemma rule: |
873 shows "\<lbrakk>f = g; x = y\<rbrakk> \<Longrightarrow> R (f x) (g y)" |
884 shows "\<lbrakk>f = g; x = y\<rbrakk> \<Longrightarrow> R (f x) (g y)" |
874 sorry |
885 sorry |
875 |
886 |
876 text {* |
887 text {* |
877 and you want to apply it to the goal @{term "(t\<^isub>1 t\<^isub>2) \<le> |
888 and you want to apply it to the goal @{term "(t\<^isub>1 t\<^isub>2) \<le> |
878 (s\<^isub>1 s\<^isub>2)"}. Since in this theorem, all variables are |
889 (s\<^isub>1 s\<^isub>2)"}. Since in the theorem all variables are |
879 schematic, we have a nasty higher-order unification problem and @{text rtac} |
890 schematic, we have a nasty higher-order unification problem and @{text rtac} |
880 will not be able to apply this rule as we want. However, in the proof below |
891 will not be able to apply this rule in the way we want. For the goal at hand |
881 we are only interested where @{term R} is instantiated to a constant and |
892 we want to use it so that @{term R} is instantiated to the constant @{text \<le>} and |
882 similarly the instantiation for the other variables is ``obvious'' from the |
893 similarly ``obvious'' instantiations for the other variables. To achieve this |
883 proof state. To use this rule we essentially match the conclusion of |
894 we need to match the conclusion of |
884 @{thm [source] rule} against the goal state reading of an instantiation for |
895 @{thm [source] rule} against the goal reading off an instantiation for |
885 @{thm [source] rule}. For this the function @{ML_ind first_order_match in Thm} |
896 @{thm [source] rule}. For this the function @{ML_ind first_order_match in Thm} |
886 matches two @{ML_type cterm}s and produces, in the sucessful case, a matcher |
897 matches two @{ML_type cterm}s and produces, in the successful case, a matcher |
887 that can be used to instantiate the @{thm [source] rule}. The instantiation |
898 that can be used to instantiate the theorem. The instantiation |
888 can be done with the function @{ML_ind instantiate in Drule}. To automate |
899 can be done with the function @{ML_ind instantiate in Drule}. To automate |
889 this we implement the following function. |
900 this we implement the following function. |
890 *} |
901 *} |
891 |
902 |
892 ML{*fun fo_rtac thm = |
903 ML %linenosgray{*fun fo_rtac thm = Subgoal.FOCUS (fn {concl, ...} => |
893 Subgoal.FOCUS (fn {concl, ...} => |
|
894 let |
904 let |
895 val concl_pat = Drule.strip_imp_concl (cprop_of thm) |
905 val concl_pat = Drule.strip_imp_concl (cprop_of thm) |
896 val insts = Thm.first_order_match (concl_pat, concl) |
906 val insts = Thm.first_order_match (concl_pat, concl) |
897 in |
907 in |
898 rtac (Drule.instantiate insts thm) 1 |
908 rtac (Drule.instantiate insts thm) 1 |
899 end)*} |
909 end)*} |
900 |
910 |
901 text {* |
911 text {* |
902 Note that we use @{ML FOCUS in Subgoal} because we have directly access |
912 Note that we use @{ML FOCUS in Subgoal} because it gives us directly access |
903 to the conclusion of the goal state and also because this function also |
913 to the conclusion of the goal state, but also because this function |
904 takes care about correctly handling parameters that might be present |
914 takes care of correctly handling parameters that might be present |
905 in the goal state. An example for @{ML fo_rtac} is as follows. |
915 in the goal state. In Line 3 we use the function @{ML_ind strip_imp_concl in Drule} |
|
916 for calculating the conclusion of a theorem (produced as @{ML_type cterm}). |
|
917 An example of @{ML fo_rtac} is as follows. |
906 *} |
918 *} |
907 |
919 |
908 lemma |
920 lemma |
909 shows "\<And>t\<^isub>1 s\<^isub>1 (t\<^isub>2::'a) (s\<^isub>2::'a). (t\<^isub>1 t\<^isub>2) \<le> (s\<^isub>1 s\<^isub>2)" |
921 shows "\<And>t\<^isub>1 s\<^isub>1 (t\<^isub>2::'a) (s\<^isub>2::'a). (t\<^isub>1 t\<^isub>2) \<le> (s\<^isub>1 s\<^isub>2)" |
910 apply(tactic {* fo_rtac @{thm rule} @{context} 1 *}) |
922 apply(tactic {* fo_rtac @{thm rule} @{context} 1 *}) |
914 (*<*)oops(*>*) |
926 (*<*)oops(*>*) |
915 |
927 |
916 text {* |
928 text {* |
917 We obtain the intended subgoals and also the parameters are correctly |
929 We obtain the intended subgoals and also the parameters are correctly |
918 introduced in both of them. Such manual instantiations are quite frequently |
930 introduced in both of them. Such manual instantiations are quite frequently |
919 necessary in order to contrain the application of inference rules. Otherwise |
931 necessary in order to appropriately constrain the application of inference |
920 one ends up with ``wild'' higher-order unification problems that make |
932 rules. Otherwise one would end up with ``wild'' higher-order unification |
921 automatic proofs fails. |
933 problems that make automatic proofs fail. |
922 *} |
934 *} |
923 |
935 |
924 section {* Tactic Combinators *} |
936 section {* Tactic Combinators *} |
925 |
937 |
926 text {* |
938 text {* |
927 The purpose of tactic combinators is to build compound tactics out of |
939 The purpose of tactic combinators is to build compound tactics out of |
928 smaller tactics. In the previous section we already used @{ML THEN}, which |
940 smaller tactics. In the previous section we already used @{ML_ind THEN in Tactical}, |
929 just strings together two tactics in a sequence. For example: |
941 which just strings together two tactics in a sequence. For example: |
930 *} |
942 *} |
931 |
943 |
932 lemma |
944 lemma |
933 shows "(Foo \<and> Bar) \<and> False" |
945 shows "(Foo \<and> Bar) \<and> False" |
934 apply(tactic {* rtac @{thm conjI} 1 THEN rtac @{thm conjI} 1 *}) |
946 apply(tactic {* rtac @{thm conjI} 1 THEN rtac @{thm conjI} 1 *}) |
956 it is consistently applied to the component tactics. |
968 it is consistently applied to the component tactics. |
957 For most tactic combinators such a ``primed'' version exists and |
969 For most tactic combinators such a ``primed'' version exists and |
958 in what follows we will usually prefer it over the ``unprimed'' one. |
970 in what follows we will usually prefer it over the ``unprimed'' one. |
959 |
971 |
960 If there is a list of tactics that should all be tried out in |
972 If there is a list of tactics that should all be tried out in |
961 sequence, you can use the combinator @{ML_ind EVERY'}. For example |
973 sequence, you can use the combinator @{ML_ind EVERY' in Tactical}. For example |
962 the function @{ML foo_tac'} from page~\pageref{tac:footacprime} can also |
974 the function @{ML foo_tac'} from page~\pageref{tac:footacprime} can also |
963 be written as: |
975 be written as: |
964 *} |
976 *} |
965 |
977 |
966 ML{*val foo_tac'' = EVERY' [etac @{thm disjE}, rtac @{thm disjI2}, |
978 ML{*val foo_tac'' = EVERY' [etac @{thm disjE}, rtac @{thm disjI2}, |
978 atac, rtac @{thm disjI1}, atac]*} |
990 atac, rtac @{thm disjI1}, atac]*} |
979 |
991 |
980 text {* |
992 text {* |
981 and call @{ML foo_tac1}. |
993 and call @{ML foo_tac1}. |
982 |
994 |
983 With the combinators @{ML THEN'}, @{ML EVERY'} and @{ML_ind EVERY1} it must be |
995 With the combinators @{ML THEN'}, @{ML EVERY'} and @{ML_ind EVERY1 in Tactical} it must be |
984 guaranteed that all component tactics successfully apply; otherwise the |
996 guaranteed that all component tactics successfully apply; otherwise the |
985 whole tactic will fail. If you rather want to try out a number of tactics, |
997 whole tactic will fail. If you rather want to try out a number of tactics, |
986 then you can use the combinator @{ML_ind ORELSE'} for two tactics, and @{ML_ind |
998 then you can use the combinator @{ML_ind ORELSE' in Tactical} for two tactics, and @{ML_ind |
987 FIRST'} (or @{ML_ind FIRST1}) for a list of tactics. For example, the tactic |
999 FIRST' in Tactical} (or @{ML_ind FIRST1 in Tactical}) for a list of tactics. For example, the tactic |
988 |
1000 |
989 *} |
1001 *} |
990 |
1002 |
991 ML{*val orelse_xmp_tac = rtac @{thm disjI1} ORELSE' rtac @{thm conjI}*} |
1003 ML{*val orelse_xmp_tac = rtac @{thm disjI1} ORELSE' rtac @{thm conjI}*} |
992 |
1004 |
1304 Implement a tactic that explores all possibilites of applying these rules to |
1316 Implement a tactic that explores all possibilites of applying these rules to |
1305 a propositional formula until a goal state is reached in which all subgoals |
1317 a propositional formula until a goal state is reached in which all subgoals |
1306 are discharged. Note that in Isabelle the left-rules need to be implemented |
1318 are discharged. Note that in Isabelle the left-rules need to be implemented |
1307 as elimination rules. You need to prove separate lemmas corresponding to |
1319 as elimination rules. You need to prove separate lemmas corresponding to |
1308 $\longrightarrow_{L_{1..4}}$. In order to explore all possibilities of applying |
1320 $\longrightarrow_{L_{1..4}}$. In order to explore all possibilities of applying |
1309 the rules, use the tactic combinator @{ML_ind DEPTH_SOLVE}, which searches |
1321 the rules, use the tactic combinator @{ML_ind DEPTH_SOLVE in Search}, which searches |
1310 for a state in which all subgoals are solved. Add also rules for equality and |
1322 for a state in which all subgoals are solved. Add also rules for equality and |
1311 run your tactic on the de Bruijn formulae discussed in Exercise~\ref{ex:debruijn}. |
1323 run your tactic on the de Bruijn formulae discussed in Exercise~\ref{ex:debruijn}. |
1312 \end{exercise} |
1324 \end{exercise} |
1313 |
|
1314 \footnote{\bf FIXME: explain @{ML_ind Cong_Tac.cong_tac}} |
|
1315 |
|
1316 *} |
1325 *} |
1317 |
1326 |
1318 section {* Simplifier Tactics *} |
1327 section {* Simplifier Tactics *} |
1319 |
1328 |
1320 text {* |
1329 text {* |