168 |
181 |
169 Hint: The third term is already quite big, and the pretty printer |
182 Hint: The third term is already quite big, and the pretty printer |
170 may omit parts of it by default. If you want to see all of it, you |
183 may omit parts of it by default. If you want to see all of it, you |
171 can use @{ML "print_depth 50"} to set the limit to a value high enough. |
184 can use @{ML "print_depth 50"} to set the limit to a value high enough. |
172 \end{exercise} |
185 \end{exercise} |
173 *} |
186 |
174 |
187 The anti-quotation @{text "@prop"} constructs terms of proposition type, |
175 ML {* |
188 inserting the invisible @{text "Trueprop"} coercion when necessary. |
176 @{const_name plus} |
189 Consider for example |
177 *} |
190 |
178 |
191 *} |
179 ML {* |
192 |
180 @{term "{ [x::int] | x. x \<le> -2 }"} |
193 ML {* @{term "P x"} *} |
181 *} |
194 |
182 |
195 ML {* @{prop "P x"} *} |
183 text {* |
196 |
184 The internal names of constants like @{term "zero"} or @{text "+"} are |
197 text {* and *} |
|
198 |
|
199 |
|
200 ML {* @{term "P x \<Longrightarrow> Q x"} *} |
|
201 |
|
202 ML {* @{prop "P x \<Longrightarrow> Q x"} *} |
|
203 |
|
204 section {* Construting Terms Manually *} |
|
205 |
|
206 text {* |
|
207 |
|
208 While antiquotations are very convenient for constructing terms, they can |
|
209 only construct fixed terms. However, one often needs to construct terms dynamially. |
|
210 For example in order to write the function that returns the implication |
|
211 @{term "\<And>x. P x \<Longrightarrow> Q x"} taking @{term P} and @{term Q} as arguments, one can |
|
212 only write |
|
213 *} |
|
214 |
|
215 |
|
216 ML {* |
|
217 fun make_PQ_imp P Q = |
|
218 let |
|
219 val nat = HOLogic.natT |
|
220 val x = Free ("x", nat) |
|
221 in Logic.all x (Logic.mk_implies (HOLogic.mk_Trueprop (P $ x), |
|
222 HOLogic.mk_Trueprop (Q $ x))) |
|
223 end |
|
224 *} |
|
225 |
|
226 text {* |
|
227 |
|
228 The reason is that one cannot pass the arguments @{term P} and @{term Q} into |
|
229 an antiquotation. |
|
230 *} |
|
231 |
|
232 text {* |
|
233 |
|
234 The internal names of constants like @{term "zero"} or @{text "+"} are |
185 often more complex than one first expects. Here, the extra prefixes |
235 often more complex than one first expects. Here, the extra prefixes |
186 @{text zero_class} and @{text plus_class} are present because the |
236 @{text zero_class} and @{text plus_class} are present because the |
187 constants are defined within a type class. Guessing such internal |
237 constants are defined within a type class. Guessing such internal |
188 names can be extremely hard, which is why the system provides |
238 names can be extremely hard, which is why the system provides |
189 another antiquotation: @{ML "@{const_name plus}"} gives just this |
239 another antiquotation: @{ML "@{const_name plus}"} gives just this |
190 name. |
240 name. For example |
191 |
241 |
192 FIXME: maybe explain @{text "@{prop \<dots>}"} as a special kind of terms |
242 *} |
193 *} |
243 |
194 |
244 ML {* @{const_name plus} *} |
195 ML {* @{prop "True"} *} |
245 |
196 |
246 text {* produes the fully qualyfied name of the constant plus. *} |
197 |
247 |
198 |
248 |
199 section {* Possible Section on Construting Explicitly Terms *} |
249 |
200 |
250 |
201 text {* |
251 text {* |
202 |
252 |
203 There is a disadvantage of using the @{text "@{term \<dots>}"} antiquotation |
253 There are many funtions in @{ML_file "Pure/logic.ML"} and |
204 directly in order to construct terms. |
254 @{ML_file "HOL/hologic.ML"} that make such manual constructions of terms |
205 *} |
255 easier. Have a look ther and try to solve the following exercises: |
206 |
|
207 ML {* |
|
208 |
|
209 val nat = HOLogic.natT |
|
210 val x = Free ("x", nat) |
|
211 val t = Free ("t", nat) |
|
212 val P = Free ("P", nat --> HOLogic.boolT) |
|
213 val Q = Free ("Q", nat --> HOLogic.boolT) |
|
214 |
|
215 val A1 = Logic.all x |
|
216 (Logic.mk_implies (HOLogic.mk_Trueprop (P $ x), |
|
217 HOLogic.mk_Trueprop (Q $ x))) |
|
218 |
|
219 |
|
220 val A2 = HOLogic.mk_Trueprop (P $ t) |
|
221 |
256 |
222 *} |
257 *} |
223 |
258 |
224 text {* |
259 text {* |
225 |
260 |
341 end |
377 end |
342 |
378 |
343 *} |
379 *} |
344 |
380 |
345 text {* |
381 text {* |
346 FIXME Explain this program more carefully (@{ML_text assume}, @{ML_text "forall_elim"} \ldots) |
382 For how the functions @{text "assume"}, @{text "forall_elim"} and so on work |
347 *} |
383 see \ichcite{sec:thms}. (FIXME correct name) |
348 |
384 |
349 |
385 |
350 section {* Tactical reasoning *} |
386 *} |
|
387 |
|
388 |
|
389 section {* Tactical Reasoning *} |
351 |
390 |
352 text {* |
391 text {* |
353 The goal-oriented tactical style is similar to the @{text apply} |
392 The goal-oriented tactical style is similar to the @{text apply} |
354 style at the user level. Reasoning is centered around a \emph{goal}, |
393 style at the user level. Reasoning is centered around a \emph{goal}, |
355 which is modified in a sequence of proof steps until it is solved. |
394 which is modified in a sequence of proof steps until it is solved. |
356 |
395 |
357 A goal (or goal state) is a special @{ML_type thm}, which by |
396 A goal (or goal state) is a special @{ML_type thm}, which by |
358 convention is an implication: |
397 convention is an implication of the form: |
|
398 |
359 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> #(C)"} |
399 @{text[display] "A\<^isub>1 \<Longrightarrow> \<dots> \<Longrightarrow> A\<^isub>n \<Longrightarrow> #(C)"} |
360 Since the final result @{term C} could again be an implication, there is the |
400 |
361 @{text "#"} around the final result, which protects its premises from being |
401 Since the formula @{term C} could potentially be an implication, there is a |
|
402 @{text "#"} wrapped around it, which prevents that premises are |
362 misinterpreted as open subgoals. The protection @{text "# :: prop \<Rightarrow> |
403 misinterpreted as open subgoals. The protection @{text "# :: prop \<Rightarrow> |
363 prop"} is just the identity and used as a syntactic marker. |
404 prop"} is just the identity function and used as a syntactic marker. |
364 |
405 For more on this goals see \ichcite{sec:tactical-goals}. (FIXME name) |
365 Now tactics are just functions that map a goal state to a (lazy) |
406 |
|
407 Tactics are functions that map a goal state to a (lazy) |
366 sequence of successor states, hence the type of a tactic is |
408 sequence of successor states, hence the type of a tactic is |
367 @{ML_type[display] "thm -> thm Seq.seq"} |
409 @{ML_type[display] "thm -> thm Seq.seq"} |
|
410 |
|
411 \begin{readmore} |
368 See @{ML_file "Pure/General/seq.ML"} for the implementation of lazy |
412 See @{ML_file "Pure/General/seq.ML"} for the implementation of lazy |
369 sequences. |
413 sequences. However one rarly onstructs sequences manually, but uses |
370 |
414 the predefined tactic combinators (tacticals) instead |
371 Of course, tactics are expected to behave nicely and leave the final |
415 (see @{ML_file "Pure/tctical.ML"}). |
372 conclusion @{term C} intact. In order to start a tactical proof for |
416 \end{readmore} |
373 @{term A}, we |
417 |
374 just set up the trivial goal @{text "A \<Longrightarrow> #(A)"} and run the tactic |
418 Note, however, that tactics are expected to behave nicely and leave |
375 on it. When the subgoal is solved, we have just @{text "#(A)"} and |
419 the final conclusion @{term C} intact (that is only work on the @{text "A\<^isub>i"} |
376 can remove the protection. |
420 representing the subgoals to be proved) with the exception of possibly |
377 |
421 instantiating schematic variables. |
378 The operations in @{ML_file "Pure/goal.ML"} do just that and we can use |
422 |
379 them. |
423 To see how tactics work, let us transcribe a simple apply-style proof from the |
380 |
424 tutorial \cite{isa-tutorial} into ML: |
381 Let us transcribe a simple apply style proof from the |
|
382 tutorial\cite{isa-tutorial} into ML: |
|
383 *} |
425 *} |
384 |
426 |
385 lemma disj_swap: "P \<or> Q \<Longrightarrow> Q \<or> P" |
427 lemma disj_swap: "P \<or> Q \<Longrightarrow> Q \<or> P" |
386 apply (erule disjE) |
428 apply (erule disjE) |
387 apply (rule disjI2) |
429 apply (rule disjI2) |
388 apply assumption |
430 apply assumption |
389 apply (rule disjI1) |
431 apply (rule disjI1) |
390 apply assumption |
432 apply assumption |
391 done |
433 done |
|
434 |
|
435 |
|
436 text {* |
|
437 |
|
438 To start the proof, the function @{ML "Goal.prove"}~@{text "ctxt params assms goal tac"} |
|
439 sets up a goal state for proving @{text goal} under the assumptions @{text assms} with |
|
440 additional variables @{text params} (the variables that are generalised once the |
|
441 goal is proved); @{text "tac"} is a function that returns a tactic (FIXME see non-existing |
|
442 explanation in the imp-manual). |
|
443 |
|
444 *} |
|
445 |
|
446 |
392 |
447 |
393 ML {* |
448 ML {* |
394 let |
449 let |
395 val ctxt = @{context} |
450 val ctxt = @{context} |
396 val goal = @{prop "P \<or> Q \<Longrightarrow> Q \<or> P"} |
451 val goal = @{prop "P \<or> Q \<Longrightarrow> Q \<or> P"} |
402 THEN resolve_tac [disjI1] 1 |
457 THEN resolve_tac [disjI1] 1 |
403 THEN assume_tac 1) |
458 THEN assume_tac 1) |
404 end |
459 end |
405 *} |
460 *} |
406 |
461 |
407 text {* |
462 text {* An alternative way to transcribe this proof is as follows *} |
408 Tactics that affect only a certain subgoal, take a subgoal number as |
463 |
409 an integer parameter. Here we always work on the first subgoal, |
464 ML {* |
410 following exactly the @{text "apply"} script. |
465 let |
411 |
466 val ctxt = @{context} |
412 (Fixme: would it make sense to explain THEN' here) |
467 val goal = @{prop "P \<or> Q \<Longrightarrow> Q \<or> P"} |
413 |
468 in |
414 *} |
469 Goal.prove ctxt ["P", "Q"] [] goal (fn _ => |
415 |
470 (eresolve_tac [disjE] |
416 |
471 THEN' resolve_tac [disjI2] |
417 section {* Case Study: Relation Composition *} |
472 THEN' assume_tac |
418 |
473 THEN' resolve_tac [disjI1] |
419 text {* |
474 THEN' assume_tac) 1) |
420 \emph{Note: This is completely unfinished. I hoped to have a section |
|
421 with a nontrivial example, but I ran into several problems.} |
|
422 |
|
423 |
|
424 Recall that HOL has special syntax for set comprehensions: |
|
425 @{term "{ f x y |x y. P x y}"} abbreviates |
|
426 @{term[source] "{u. \<exists>x y. u = f x y \<and> P x y}"}. |
|
427 |
|
428 We will automatically prove statements of the following form: |
|
429 |
|
430 @{lemma[display] "{(l\<^isub>1 x, r\<^isub>1 x) |x. P\<^isub>1 x} O {(l\<^isub>2 x, r\<^isub>2 x) |x. P\<^isub>2 x} |
|
431 = {(l\<^isub>2 x, r\<^isub>1 y) |x y. r\<^isub>2 x = l\<^isub>1 y \<and> |
|
432 P\<^isub>2 x \<and> P\<^isub>1 y}" by auto} |
|
433 |
|
434 In Isabelle, relation composition is defined to be consistent with |
|
435 function composition, that is, the relation applied ``first'' is |
|
436 written on the right hand side. This different from what many |
|
437 textbooks do. |
|
438 |
|
439 The above statement about composition is not proved automatically by |
|
440 @{method simp}, and it cannot be solved by a fixed set of rewrite |
|
441 rules, since the number of (implicit) quantifiers may vary. Here, we |
|
442 only have one bound variable in each comprehension, but in general |
|
443 there can be more. On the other hand, @{method auto} proves the |
|
444 above statement quickly, by breaking the equality into two parts and |
|
445 proving them separately. However, if e.g.\ @{term "P\<^isub>1"} is a |
|
446 complicated expression, the automated tools may get confused. |
|
447 |
|
448 Our goal is now to develop a small procedure that can compute (with proof) the |
|
449 composition of two relation comprehensions, which can be used to |
|
450 extend the simplifier. |
|
451 *} |
|
452 |
|
453 section {*A tactic *} |
|
454 |
|
455 text {* Let's start with a step-by-step proof of the above statement *} |
|
456 |
|
457 lemma "{(l\<^isub>1 x, r\<^isub>1 x) |x. P\<^isub>1 x} O {(l\<^isub>2 |
|
458 x, r\<^isub>2 x) |x. P\<^isub>2 x} |
|
459 = {(l\<^isub>2 x, r\<^isub>1 y) |x y. r\<^isub>2 x = l\<^isub>1 y \<and> P\<^isub>2 x \<and> P\<^isub>1 y}" |
|
460 apply (rule set_ext) |
|
461 apply (rule iffI) |
|
462 apply (erule rel_compE) -- {* @{text "\<subseteq>"} *} |
|
463 apply (erule CollectE) -- {* eliminate @{text "Collect"}, @{text "\<exists>"}, @{text "\<and>"}, and pairs *} |
|
464 apply (erule CollectE) |
|
465 apply (erule exE) |
|
466 apply (erule exE) |
|
467 apply (erule conjE) |
|
468 apply (erule conjE) |
|
469 apply (erule Pair_inject) |
|
470 apply (erule Pair_inject) |
|
471 apply (simp only:) |
|
472 |
|
473 apply (rule CollectI) -- {* introduce them again *} |
|
474 apply (rule exI) |
|
475 apply (rule exI) |
|
476 apply (rule conjI) |
|
477 apply (rule refl) |
|
478 apply (rule conjI) |
|
479 apply (rule sym) |
|
480 apply (assumption) |
|
481 apply (rule conjI) |
|
482 apply assumption |
|
483 apply assumption |
|
484 |
|
485 apply (erule CollectE) -- {* @{text "\<subseteq>"} *} |
|
486 apply (erule exE)+ |
|
487 apply (erule conjE)+ |
|
488 apply (simp only:) |
|
489 apply (rule rel_compI) |
|
490 apply (rule CollectI) |
|
491 apply (rule exI) |
|
492 apply (rule conjI) |
|
493 apply (rule refl) |
|
494 apply assumption |
|
495 |
|
496 apply (rule CollectI) |
|
497 apply (rule exI) |
|
498 apply (rule conjI) |
|
499 apply (subst Pair_eq) |
|
500 apply (rule conjI) |
|
501 apply assumption |
|
502 apply (rule refl) |
|
503 apply assumption |
|
504 done |
|
505 |
|
506 text {* |
|
507 The reader will probably need to step through the proof and verify |
|
508 that there is nothing spectacular going on here. |
|
509 The @{text apply} script just applies the usual elimination and introduction rules in the right order. |
|
510 |
|
511 This script is of course totally unreadable. But we are not trying |
|
512 to produce pretty Isar proofs here. We just want to find out which |
|
513 rules are needed and how they must be applied to complete the |
|
514 proof. And a detailed apply-style proof can often be turned into a |
|
515 tactic quite easily. Of course we must resist the temptation to use |
|
516 @{method auto}, @{method blast} and friends, since their behaviour |
|
517 is not predictable enough. But the simple @{method rule} and |
|
518 @{method erule} methods are fine. |
|
519 |
|
520 Notice that this proof depends only in one detail on the |
|
521 concrete equation that we want to prove: The number of bound |
|
522 variables in the comprehension corresponds to the number of |
|
523 existential quantifiers that we have to eliminate and introduce |
|
524 again. In fact this is the only reason why the equations that we |
|
525 want to prove are not just instances of a single rule. |
|
526 |
|
527 Here is the ML equivalent of the tactic script above: |
|
528 *} |
|
529 |
|
530 ML {* |
|
531 val compr_compose_tac = |
|
532 rtac @{thm set_ext} |
|
533 THEN' rtac @{thm iffI} |
|
534 THEN' etac @{thm rel_compE} |
|
535 THEN' etac @{thm CollectE} |
|
536 THEN' etac @{thm CollectE} |
|
537 THEN' (fn i => REPEAT (etac @{thm exE} i)) |
|
538 THEN' etac @{thm conjE} |
|
539 THEN' etac @{thm conjE} |
|
540 THEN' etac @{thm Pair_inject} |
|
541 THEN' etac @{thm Pair_inject} |
|
542 THEN' asm_full_simp_tac HOL_basic_ss |
|
543 THEN' rtac @{thm CollectI} |
|
544 THEN' (fn i => REPEAT (rtac @{thm exI} i)) |
|
545 THEN' rtac @{thm conjI} |
|
546 THEN' rtac @{thm refl} |
|
547 THEN' rtac @{thm conjI} |
|
548 THEN' rtac @{thm sym} |
|
549 THEN' assume_tac |
|
550 THEN' rtac @{thm conjI} |
|
551 THEN' assume_tac |
|
552 THEN' assume_tac |
|
553 |
|
554 THEN' etac @{thm CollectE} |
|
555 THEN' (fn i => REPEAT (etac @{thm exE} i)) |
|
556 THEN' etac @{thm conjE} |
|
557 THEN' etac @{thm conjE} |
|
558 THEN' etac @{thm conjE} |
|
559 THEN' asm_full_simp_tac HOL_basic_ss |
|
560 THEN' rtac @{thm rel_compI} |
|
561 THEN' rtac @{thm CollectI} |
|
562 THEN' (fn i => REPEAT (rtac @{thm exI} i)) |
|
563 THEN' rtac @{thm conjI} |
|
564 THEN' rtac @{thm refl} |
|
565 THEN' assume_tac |
|
566 THEN' rtac @{thm CollectI} |
|
567 THEN' (fn i => REPEAT (rtac @{thm exI} i)) |
|
568 THEN' rtac @{thm conjI} |
|
569 THEN' simp_tac (HOL_basic_ss addsimps [@{thm Pair_eq}]) |
|
570 THEN' rtac @{thm conjI} |
|
571 THEN' assume_tac |
|
572 THEN' rtac @{thm refl} |
|
573 THEN' assume_tac |
|
574 *} |
|
575 |
|
576 lemma test1: "{(l\<^isub>1 x, r\<^isub>1 x) |x. P\<^isub>1 x} O {(l\<^isub>2 |
|
577 x, r\<^isub>2 x) |x. P\<^isub>2 x} |
|
578 = {(l\<^isub>2 x, r\<^isub>1 y) |x y. r\<^isub>2 x = l\<^isub>1 y \<and> P\<^isub>2 x \<and> P\<^isub>1 y}" |
|
579 by (tactic "compr_compose_tac 1") |
|
580 |
|
581 lemma test3: "{(l\<^isub>1 x, r\<^isub>1 x) |x. P\<^isub>1 x} O {(l\<^isub>2 x z, r\<^isub>2 x z) |x z. P\<^isub>2 x z} |
|
582 = {(l\<^isub>2 x z, r\<^isub>1 y) |x y z. r\<^isub>2 x z = l\<^isub>1 y \<and> P\<^isub>2 x z \<and> P\<^isub>1 y}" |
|
583 by (tactic "compr_compose_tac 1") |
|
584 |
|
585 text {* |
|
586 So we have a tactic that works on at least two examples. |
|
587 Getting it really right requires some more effort. Consider the goal |
|
588 *} |
|
589 lemma "{(n, Suc n) |n. n > 0} O {(n, Suc n) |n. P n} |
|
590 = {(n, Suc m)|n m. Suc n = m \<and> P n \<and> m > 0}" |
|
591 |
|
592 (*lemma "{(l\<^isub>1 x, r\<^isub>1 x) |x. P\<^isub>1 x} O {(l\<^isub>2 |
|
593 x, r\<^isub>2 x) |x. P\<^isub>2 x} |
|
594 = {(l\<^isub>2 x, r\<^isub>1 y) |x y. r\<^isub>2 x = l\<^isub>1 y \<and> P\<^isub>2 x \<and> P\<^isub>1 y}"*) |
|
595 txt {* |
|
596 This is exactly an instance of @{fact test1}, but our tactic fails |
|
597 on it with the usual uninformative |
|
598 \emph{empty result requence}. |
|
599 |
|
600 We are now in the frequent situation that we need to debug. One simple instrument for this is @{ML "print_tac"}, |
|
601 which is the same as @{ML all_tac} (the identity for @{ML_text "THEN"}), |
|
602 i.e.\ it does nothing, but it prints the current goal state as a |
|
603 side effect. |
|
604 Another debugging option is of course to step through the interactive apply script. |
|
605 |
|
606 Finding the problem could be taken as an exercise for the patient |
|
607 reader, and we will go ahead with the solution. |
|
608 |
|
609 The problem is that in this instance the simplifier does more than it did in the general version |
|
610 of lemma @{fact test1}. Since @{text "l\<^isub>1"} and @{text "l\<^isub>2"} are just the identity function, |
|
611 the equation corresponding to @{text "l\<^isub>1 y = r\<^isub>2 x "} |
|
612 becomes @{text "m = Suc n"}. Then the simplifier eagerly replaces |
|
613 all occurences of @{term "m"} by @{term "Suc n"} which destroys the |
|
614 structure of the proof. |
|
615 |
|
616 This is perhaps the most important lesson to learn, when writing tactics: |
|
617 \textbf{Avoid automation at all cost!!!}. |
|
618 |
|
619 Let us look at the proof state at the point where the simplifier is |
|
620 invoked: |
|
621 |
|
622 *} |
|
623 (*<*) |
|
624 apply (rule set_ext) |
|
625 apply (rule iffI) |
|
626 apply (erule rel_compE) |
|
627 apply (erule CollectE) |
|
628 apply (erule CollectE) |
|
629 apply (erule exE) |
|
630 apply (erule exE) |
|
631 apply (erule conjE) |
|
632 apply (erule conjE) |
|
633 apply (erule Pair_inject) |
|
634 apply (erule Pair_inject)(*>*) |
|
635 txt {* |
|
636 |
|
637 @{subgoals[display]} |
|
638 |
|
639 Like in the apply proof, we now want to eliminate the equations that |
|
640 ``define'' @{term x}, @{term xa} and @{term z}. The other equations |
|
641 are just there by coincidence, and we must not touch them. |
|
642 |
|
643 For such purposes, there is the internal tactic @{text "hyp_subst_single"}. |
|
644 Its job is to take exactly one premise of the form @{term "v = t"}, |
|
645 where @{term v} is a variable, and replace @{term "v"} in the whole |
|
646 subgoal. The hypothesis to eliminate is given by its position. |
|
647 |
|
648 We can use this tactic to eliminate @{term x}: |
|
649 *} |
|
650 apply (tactic "single_hyp_subst_tac 0 1") |
|
651 txt {* |
|
652 @{subgoals[display]} |
|
653 *} |
|
654 apply (tactic "single_hyp_subst_tac 2 1") |
|
655 apply (tactic "single_hyp_subst_tac 2 1") |
|
656 apply (tactic "single_hyp_subst_tac 3 1") |
|
657 apply (rule CollectI) -- {* introduce them again *} |
|
658 apply (rule exI) |
|
659 apply (rule exI) |
|
660 apply (rule conjI) |
|
661 apply (rule refl) |
|
662 apply (rule conjI) |
|
663 apply (assumption) |
|
664 apply (rule conjI) |
|
665 apply assumption |
|
666 apply assumption |
|
667 |
|
668 apply (erule CollectE) -- {* @{text "\<subseteq>"} *} |
|
669 apply (erule exE)+ |
|
670 apply (erule conjE)+ |
|
671 apply (tactic "single_hyp_subst_tac 0 1") |
|
672 apply (rule rel_compI) |
|
673 apply (rule CollectI) |
|
674 apply (rule exI) |
|
675 apply (rule conjI) |
|
676 apply (rule refl) |
|
677 apply assumption |
|
678 |
|
679 apply (rule CollectI) |
|
680 apply (rule exI) |
|
681 apply (rule conjI) |
|
682 apply (subst Pair_eq) |
|
683 apply (rule conjI) |
|
684 apply assumption |
|
685 apply (rule refl) |
|
686 apply assumption |
|
687 done |
|
688 |
|
689 ML {* |
|
690 val compr_compose_tac = |
|
691 rtac @{thm set_ext} |
|
692 THEN' rtac @{thm iffI} |
|
693 THEN' etac @{thm rel_compE} |
|
694 THEN' etac @{thm CollectE} |
|
695 THEN' etac @{thm CollectE} |
|
696 THEN' (fn i => REPEAT (etac @{thm exE} i)) |
|
697 THEN' etac @{thm conjE} |
|
698 THEN' etac @{thm conjE} |
|
699 THEN' etac @{thm Pair_inject} |
|
700 THEN' etac @{thm Pair_inject} |
|
701 THEN' single_hyp_subst_tac 0 |
|
702 THEN' single_hyp_subst_tac 2 |
|
703 THEN' single_hyp_subst_tac 2 |
|
704 THEN' single_hyp_subst_tac 3 |
|
705 THEN' rtac @{thm CollectI} |
|
706 THEN' (fn i => REPEAT (rtac @{thm exI} i)) |
|
707 THEN' rtac @{thm conjI} |
|
708 THEN' rtac @{thm refl} |
|
709 THEN' rtac @{thm conjI} |
|
710 THEN' assume_tac |
|
711 THEN' rtac @{thm conjI} |
|
712 THEN' assume_tac |
|
713 THEN' assume_tac |
|
714 |
|
715 THEN' etac @{thm CollectE} |
|
716 THEN' (fn i => REPEAT (etac @{thm exE} i)) |
|
717 THEN' etac @{thm conjE} |
|
718 THEN' etac @{thm conjE} |
|
719 THEN' etac @{thm conjE} |
|
720 THEN' single_hyp_subst_tac 0 |
|
721 THEN' rtac @{thm rel_compI} |
|
722 THEN' rtac @{thm CollectI} |
|
723 THEN' (fn i => REPEAT (rtac @{thm exI} i)) |
|
724 THEN' rtac @{thm conjI} |
|
725 THEN' rtac @{thm refl} |
|
726 THEN' assume_tac |
|
727 THEN' rtac @{thm CollectI} |
|
728 THEN' (fn i => REPEAT (rtac @{thm exI} i)) |
|
729 THEN' rtac @{thm conjI} |
|
730 THEN' stac @{thm Pair_eq} |
|
731 THEN' rtac @{thm conjI} |
|
732 THEN' assume_tac |
|
733 THEN' rtac @{thm refl} |
|
734 THEN' assume_tac |
|
735 *} |
|
736 |
|
737 lemma "{(n, Suc n) |n. n > 0 \<and> A} O {(n, Suc n) |n m. P m n} |
|
738 = {(n, Suc m)|n m' m. Suc n = m \<and> P m' n \<and> (m > 0 \<and> A)}" |
|
739 apply (tactic "compr_compose_tac 1") |
|
740 done |
|
741 |
|
742 text {* |
|
743 The next step is now to turn this tactic into a simplification |
|
744 procedure. This just means that we need some code that builds the |
|
745 term of the composed relation. |
|
746 *} |
|
747 |
|
748 use "comp_simproc" |
|
749 |
|
750 (*<*) |
|
751 (*simproc_setup mysp ("x O y") = {* compose_simproc *}*) |
|
752 |
|
753 lemma "{(n, Suc n) |n. n > 0 \<and> A} O {(n, Suc n) |n m. P m n} = x" |
|
754 (*apply (simp del:ex_simps)*) |
|
755 oops |
|
756 |
|
757 |
|
758 lemma "({(g m, k) | m k. Q m k} |
|
759 O {(h j, f j) | j. R j}) = x" |
|
760 (*apply (simp del:ex_simps) *) |
|
761 oops |
|
762 |
|
763 lemma "{uu. \<exists>j m k. uu = (h j, k) \<and> f j = g m \<and> R j \<and> Q m k} |
|
764 O {(h j, f j) | j. R j} = x" |
|
765 (*apply (simp del:ex_simps)*) |
|
766 oops |
|
767 |
|
768 lemma " |
|
769 { (l x, r x) | x. P x \<and> Q x \<and> Q' x } |
|
770 O { (l1 x, r1 x) | x. P1 x \<and> Q1 x \<and> Q1' x } |
|
771 = A" |
|
772 (*apply (simp del:ex_simps)*) |
|
773 oops |
|
774 |
|
775 lemma " |
|
776 { (l x, r x) | x. P x } |
|
777 O { (l1 x, r1 x) | x. P1 x } |
|
778 O { (l2 x, r2 x) | x. P2 x } |
|
779 = A" |
|
780 (* |
|
781 apply (simp del:ex_simps)*) |
|
782 oops |
|
783 |
|
784 lemma "{(f n, m) |n m. P n m} O ({(g m, k) | m k. Q m k} |
|
785 O {(h j, f j) | j. R j}) = x" |
|
786 (*apply (simp del:ex_simps)*) |
|
787 oops |
|
788 |
|
789 lemma "{u. \<exists>n. u=(f n, g n)} O {u. \<exists>n. u=(h n, j n)} = A" |
|
790 oops |
|
791 |
|
792 |
|
793 (*>*) |
|
794 end |
475 end |
|
476 *} |
|
477 |
|
478 section {* Storing and Changing Theorems and so on *} |
|
479 |
|
480 end |