98 lemma "P \<or> Q \<Longrightarrow> Q \<or> P" |
98 lemma "P \<or> Q \<Longrightarrow> Q \<or> P" |
99 apply(tactic {* foo_tac *}) |
99 apply(tactic {* foo_tac *}) |
100 done |
100 done |
101 |
101 |
102 text {* |
102 text {* |
103 By using @{text "tactic \<verbopen> \<dots> \<verbclose>"} in the apply-step, |
103 By using @{text "tactic \<verbopen> \<dots> \<verbclose>"} you can call from the |
104 you can call from the user level of Isabelle the tactic @{ML foo_tac} or |
104 user level of Isabelle the tactic @{ML foo_tac} or |
105 any other function that returns a tactic. |
105 any other function that returns a tactic. |
106 |
106 |
107 The tactic @{ML foo_tac} is just a sequence of simple tactics stringed |
107 The tactic @{ML foo_tac} is just a sequence of simple tactics stringed |
108 together by @{ML THEN}. As can be seen, each simple tactic in @{ML foo_tac} |
108 together by @{ML THEN}. As can be seen, each simple tactic in @{ML foo_tac} |
109 has a hard-coded number that stands for the subgoal analysed by the |
109 has a hard-coded number that stands for the subgoal analysed by the |
194 sequences. However in day-to-day Isabelle programming, one rarely |
194 sequences. However in day-to-day Isabelle programming, one rarely |
195 constructs sequences explicitly, but uses the predefined functions |
195 constructs sequences explicitly, but uses the predefined functions |
196 instead. |
196 instead. |
197 \end{readmore} |
197 \end{readmore} |
198 |
198 |
199 For a beginner it might be surprising that tactics, which transform |
199 It might be surprising that tactics, which transform |
200 one proof state to the next, are functions from theorems to theorem |
200 one proof state to the next, are functions from theorems to theorem |
201 (sequences). The surprise resolves by knowing that every |
201 (sequences). The surprise resolves by knowing that every |
202 proof state is indeed a theorem. To shed more light on this, |
202 goal state is indeed a theorem. To shed more light on this, |
203 let us modify the code of @{ML all_tac} to obtain the following |
203 let us modify the code of @{ML all_tac} to obtain the following |
204 tactic |
204 tactic |
205 *} |
205 *} |
206 |
206 |
207 ML{*fun my_print_tac ctxt thm = |
207 ML{*fun my_print_tac ctxt thm = |
273 As can be seen, internally every goal state is an implication of the form |
273 As can be seen, internally every goal state is an implication of the form |
274 |
274 |
275 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> (C)"} |
275 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> (C)"} |
276 |
276 |
277 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are the |
277 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are the |
278 subgoals. Since the goal @{term C} can potentially be an implication, |
278 subgoals. So in the first step the goal state is always of the form |
279 there is a protector (invisible in the print out above) wrapped around |
279 @{text "C \<Longrightarrow> (C)"}. Since the goal @{term C} can potentially be an implication, |
280 it. This prevents that premises are misinterpreted as open subgoals. |
280 there is a ``protector'' wrapped around it (in from of an outermost constant |
|
281 @{text "Const (\"prop\", bool \<Rightarrow> bool)"} applied to each goal; |
|
282 however this constant is invisible in the print out above). This |
|
283 prevents that premises are misinterpreted as open subgoals. |
281 While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they |
284 While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they |
282 are expected to leave the conclusion @{term C} intact, with the |
285 are expected to leave the conclusion @{term C} intact, with the |
283 exception of possibly instantiating schematic variables. |
286 exception of possibly instantiating schematic variables. |
284 |
287 |
285 *} |
288 *} |
295 done |
298 done |
296 |
299 |
297 text {* |
300 text {* |
298 Similarly, @{ML rtac}, @{ML dtac}, @{ML etac} and @{ML ftac} correspond |
301 Similarly, @{ML rtac}, @{ML dtac}, @{ML etac} and @{ML ftac} correspond |
299 to @{text rule}, @{text drule}, @{text erule} and @{text frule}, |
302 to @{text rule}, @{text drule}, @{text erule} and @{text frule}, |
300 respectively. Below are three examples with the resulting goal state. How |
303 respectively. Each of them takes a theorem as argument. Below are three |
301 they work should therefore be self-explanatory. |
304 examples with the resulting goal state. How |
|
305 they work should be self-explanatory. |
302 *} |
306 *} |
303 |
307 |
304 lemma shows "P \<and> Q" |
308 lemma shows "P \<and> Q" |
305 apply(tactic {* rtac @{thm conjI} 1 *}) |
309 apply(tactic {* rtac @{thm conjI} 1 *}) |
306 txt{*@{subgoals [display]}*} |
310 txt{*\begin{minipage}{\textwidth} |
|
311 @{subgoals [display]} |
|
312 \end{minipage}*} |
307 (*<*)oops(*>*) |
313 (*<*)oops(*>*) |
308 |
314 |
309 lemma shows "P \<and> Q \<Longrightarrow> False" |
315 lemma shows "P \<and> Q \<Longrightarrow> False" |
310 apply(tactic {* etac @{thm conjE} 1 *}) |
316 apply(tactic {* etac @{thm conjE} 1 *}) |
311 txt{*@{subgoals [display]}*} |
317 txt{*\begin{minipage}{\textwidth} |
|
318 @{subgoals [display]} |
|
319 \end{minipage}*} |
312 (*<*)oops(*>*) |
320 (*<*)oops(*>*) |
313 |
321 |
314 lemma shows "False \<and> True \<Longrightarrow> False" |
322 lemma shows "False \<and> True \<Longrightarrow> False" |
315 apply(tactic {* dtac @{thm conjunct2} 1 *}) |
323 apply(tactic {* dtac @{thm conjunct2} 1 *}) |
316 txt{*@{subgoals [display]}*} |
324 txt{*\begin{minipage}{\textwidth} |
|
325 @{subgoals [display]} |
|
326 \end{minipage}*} |
317 (*<*)oops(*>*) |
327 (*<*)oops(*>*) |
318 |
328 |
319 text {* |
329 text {* |
320 As mentioned above, most basic tactics take a number as argument, which |
330 As mentioned above, most basic tactics take a number as argument, which |
321 addresses to subgoal they are analysing. |
331 addresses to subgoal they are analysing. |
322 *} |
332 *} |
323 |
333 |
324 lemma shows "Foo" and "P \<and> Q" |
334 lemma shows "Foo" and "P \<and> Q" |
325 apply(tactic {* rtac @{thm conjI} 2 *}) |
335 apply(tactic {* rtac @{thm conjI} 2 *}) |
326 txt {*@{subgoals [display]}*} |
336 txt {*\begin{minipage}{\textwidth} |
|
337 @{subgoals [display]} |
|
338 \end{minipage}*} |
327 (*<*)oops(*>*) |
339 (*<*)oops(*>*) |
328 |
340 |
329 text {* |
341 text {* |
330 Corresponding to @{ML rtac}, there is also the tactic @{ML resolve_tac}, which |
342 Corresponding to @{ML rtac}, there is also the tactic @{ML resolve_tac}, which |
331 however expects a list of theorems as arguments. From this list it will apply with |
343 however expects a list of theorems as arguments. From this list it will apply with |
357 lemma shows "False \<Longrightarrow> True" |
371 lemma shows "False \<Longrightarrow> True" |
358 apply(tactic {* print_tac "foo message" *}) |
372 apply(tactic {* print_tac "foo message" *}) |
359 (*<*)oops(*>*) |
373 (*<*)oops(*>*) |
360 |
374 |
361 text {* |
375 text {* |
362 Also for useful for debugging purposes are the tactics @{ML all_tac} and |
376 |
363 @{ML no_tac}. The former always succeeds (but does not change the goal state), and |
|
364 the latter always fails. |
|
365 |
|
366 (FIXME explain RS MRS) |
377 (FIXME explain RS MRS) |
367 |
378 |
368 Often proofs involve elaborate operations on assumptions and variables |
379 Often proofs involve elaborate operations on assumptions and |
369 @{text "\<And>"}-quantified in the goal state. To do such operations on the ML-level |
380 @{text "\<And>"}-quantified variables. To do such operations on the ML-level |
370 using the basic tactics, is very unwieldy and brittle. Some convenience and |
381 using the basic tactics is very unwieldy and brittle. Some convenience and |
371 safety is provided by the tactic @{ML SUBPROOF}. This tactic fixes the parameters |
382 safety is provided by the tactic @{ML SUBPROOF}. This tactic fixes the parameters |
372 and binds the various components of a proof state into a record. |
383 and binds the various components of a proof state into a record. |
373 *} |
384 *} |
374 |
385 |
375 text_raw{* |
386 text_raw{* |
424 \end{quote} |
435 \end{quote} |
425 |
436 |
426 Note in the actual output the brown colour of the variables @{term x} and |
437 Note in the actual output the brown colour of the variables @{term x} and |
427 @{term y}. Although parameters in the original goal, they are fixed inside |
438 @{term y}. Although parameters in the original goal, they are fixed inside |
428 the subproof. Similarly the schematic variable @{term z}. The assumption |
439 the subproof. Similarly the schematic variable @{term z}. The assumption |
429 is bound once as @{ML_type cterm} to the record-variable @{text asms} and |
440 @{prop "A x y"} is bound once as @{ML_type cterm} to the record-variable |
430 another time as @{ML_type thm} to @{text prems}. |
441 @{text asms} and another time as @{ML_type thm} to @{text prems}. |
431 |
442 |
432 Notice also that we had to append @{text "?"} to \isacommand{apply}. The |
443 Notice also that we had to append @{text "?"} to \isacommand{apply}. The |
433 reason is that @{ML SUBPROOF} normally expects that the subgoal is solved completely. |
444 reason is that @{ML SUBPROOF} normally expects that the subgoal is solved completely. |
434 Since in the function @{ML sp_tac} we returned the tactic @{ML no_tac}, the subproof |
445 Since in the function @{ML sp_tac} we returned the tactic @{ML no_tac}, the subproof |
435 obviously fails. The question-mark allows us to recover from this failure |
446 obviously fails. The question-mark allows us to recover from this failure |
436 in a graceful manner so that the warning messages are not overwritten |
447 in a graceful manner so that the warning messages are not overwritten |
437 by the error message. |
448 by an error message. |
438 |
449 |
439 If we continue the proof script by applying the @{text impI}-rule |
450 If we continue the proof script by applying the @{text impI}-rule |
440 *} |
451 *} |
441 |
452 |
442 apply(rule impI) |
453 apply(rule impI) |
456 \end{quote} |
467 \end{quote} |
457 *} |
468 *} |
458 (*<*)oops(*>*) |
469 (*<*)oops(*>*) |
459 |
470 |
460 text {* |
471 text {* |
461 where we now also have @{term "B y x"} as assumption. |
472 where we now also have @{term "B y x"} as an assumption. |
462 |
473 |
463 One convenience of @{ML SUBPROOF} is that we can apply assumption |
474 One convenience of @{ML SUBPROOF} is that we can apply assumption |
464 using the usual tactics, because the parameter @{text prems} |
475 using the usual tactics, because the parameter @{text prems} |
465 contains the assumptions as theorems. With this we can easily |
476 contains the assumptions as theorems. With this we can easily |
466 implement a tactic that almost behaves like @{ML atac}: |
477 implement a tactic that almost behaves like @{ML atac}: |
467 *} |
478 *} |
468 |
479 |
|
480 ML{*val atac' = SUBPROOF (fn {prems, ...} => resolve_tac prems 1)*} |
469 lemma shows "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y" |
481 lemma shows "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y" |
470 apply(tactic |
482 apply(tactic {* atac' @{context} 1 *}) |
471 {* SUBPROOF (fn {prems, ...} => resolve_tac prems 1) @{context} 1 *}) |
|
472 txt{* yields |
483 txt{* yields |
473 @{subgoals [display]} *} |
484 @{subgoals [display]} *} |
474 (*<*)oops(*>*) |
485 (*<*)oops(*>*) |
475 |
|
476 |
486 |
477 text {* |
487 text {* |
478 The restriction in this tactic is that it cannot instantiate any |
488 The restriction in this tactic is that it cannot instantiate any |
479 schematic variables. This might be seen as a defect, but is actually |
489 schematic variables. This might be seen as a defect, but is actually |
480 an advantage in the situations for which @{ML SUBPROOF} was designed: |
490 an advantage in the situations for which @{ML SUBPROOF} was designed: |
481 the reason is that instantiation of schematic variables can potentially |
491 the reason is that instantiation of schematic variables can affect |
482 has affect several goals and can render them unprovable. |
492 several goals and can render them unprovable. @{ML SUBPROOF} is meant |
483 |
493 to avoid this. |
484 A similar but less powerful function is @{ML SUBGOAL}. It allows you to |
494 |
485 inspect a subgoal specified by a number. |
495 Notice that @{ML atac'} calls @{ML resolve_tac} with the subgoal |
|
496 number @{text "1"} and also the ``outer'' call to @{ML SUBPROOF} in |
|
497 the \isacommand{apply}-step uses @{text "1"}. Another advantage |
|
498 of @{ML SUBGOAL} is that the addressing inside it is completely |
|
499 local to the proof inside. It is therefore possible to also apply |
|
500 @{ML atac'} to the second goal: |
|
501 *} |
|
502 |
|
503 lemma shows "True" and "\<And>x y. \<lbrakk>B x y; A x y; C x y\<rbrakk> \<Longrightarrow> A x y" |
|
504 apply(tactic {* atac' @{context} 2 *}) |
|
505 txt{* This gives: |
|
506 @{subgoals [display]} *} |
|
507 (*<*)oops(*>*) |
|
508 |
|
509 |
|
510 text {* |
|
511 A similar but less powerful function than @{ML SUBPROOF} is @{ML SUBGOAL}. |
|
512 It allows you to inspect a subgoal specified by a number. With this we can |
|
513 implement a little tactic that applies a rule corresponding to its |
|
514 topmost connective. The tactic should only apply ``safe'' rules (that is |
|
515 which do not render the goal unprovable). For this we can write: |
486 *} |
516 *} |
487 |
517 |
488 ML %linenumbers{*fun select_tac (t,i) = |
518 ML %linenumbers{*fun select_tac (t,i) = |
489 case t of |
519 case t of |
490 @{term "Trueprop"} $ t' => select_tac (t',i) |
520 @{term "Trueprop"} $ t' => select_tac (t',i) |
491 | @{term "op \<and>"} $ _ $ _ => rtac @{thm conjI} i |
521 | @{term "op \<and>"} $ _ $ _ => rtac @{thm conjI} i |
492 | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i |
522 | @{term "op \<longrightarrow>"} $ _ $ _ => rtac @{thm impI} i |
493 | @{term "Not"} $ _ => rtac @{thm notI} i |
523 | @{term "Not"} $ _ => rtac @{thm notI} i |
494 | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i |
524 | Const (@{const_name "All"}, _) $ _ => rtac @{thm allI} i |
495 | _ => no_tac*} |
525 | _ => all_tac*} |
496 |
526 |
497 lemma shows "A \<and> B" "A \<longrightarrow> B" "\<forall>x. C x" |
527 lemma shows "A \<and> B" "A \<longrightarrow> B" "\<forall>x. C x" "D \<Longrightarrow> E" |
|
528 apply(tactic {* SUBGOAL select_tac 4 *}) |
|
529 apply(tactic {* SUBGOAL select_tac 3 *}) |
|
530 apply(tactic {* SUBGOAL select_tac 2 *}) |
498 apply(tactic {* SUBGOAL select_tac 1 *}) |
531 apply(tactic {* SUBGOAL select_tac 1 *}) |
499 apply(tactic {* SUBGOAL select_tac 3 *}) |
|
500 apply(tactic {* SUBGOAL select_tac 4 *}) |
|
501 txt{* @{subgoals [display]} *} |
532 txt{* @{subgoals [display]} *} |
502 (*<*)oops(*>*) |
533 (*<*)oops(*>*) |
503 |
534 |
504 text {* |
535 text {* |
505 However, this example is contrived, as there are much simpler ways |
536 However, this example is contrived, as there are much simpler ways |
506 to implement a proof procedure like the one above. They will be explained |
537 to implement a proof procedure like the one above. They will be explained |
507 in the next section. |
538 in the next section. |
|
539 |
|
540 (Notice that we applied the goals in reverse order) |
508 |
541 |
509 A variant of @{ML SUBGOAL} is @{ML CSUBGOAL} which allows access to the goal |
542 A variant of @{ML SUBGOAL} is @{ML CSUBGOAL} which allows access to the goal |
510 as @{ML_type cterm} instead of a @{ML_type term}. |
543 as @{ML_type cterm} instead of a @{ML_type term}. |
511 *} |
544 *} |
512 |
545 |