Nominal/activities/tphols09/IDW/Conversions.thy
author Christian Urban <christian.urban@kcl.ac.uk>
Tue, 07 Jan 2025 12:42:42 +0000
changeset 653 2807ec31d144
parent 415 f1be8028a4a9
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
415
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     1
theory Conversions
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     2
imports Main
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     3
begin
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     4
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     5
section {* Basic conversions *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     6
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     7
ML {* Conv.all_conv : cterm -> thm *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     8
ML {* Conv.all_conv *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     9
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    10
text {* Always succeeds *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    11
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    12
ML {* Conv.all_conv @{cterm "42::int"} *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    13
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    14
text {* Always fails *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    15
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    16
(*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    17
ML {* Conv.no_conv @{cterm "42::int"} *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    18
*)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    19
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    20
text {* Rewrite with a single rule *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    21
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    22
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    23
val rev_Cons = mk_meta_eq @{thm rev.simps(2)}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    24
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    25
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    26
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    27
Conv.rewr_conv rev_Cons @{cterm "rev [1::int, 2]"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    28
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    29
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    30
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    31
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    32
section {* Combining conversions (``conversionals'') *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    33
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    34
text {* Sequencing *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    35
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    36
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    37
val add_0_right = mk_meta_eq @{thm monoid_add_class.add_0_right}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    38
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    39
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    40
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    41
val mult_1_left = mk_meta_eq @{thm monoid_mult_class.mult_1_left}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    42
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    43
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    44
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    45
(Conv.rewr_conv add_0_right then_conv Conv.rewr_conv mult_1_left)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    46
@{cterm "((1::int) * x) + 0"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    47
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    48
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    49
text {* Alternative *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    50
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    51
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    52
val rev_Nil = mk_meta_eq @{thm rev.simps(1)}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    53
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    54
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    55
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    56
(Conv.rewr_conv rev_Nil else_conv Conv.rewr_conv rev_Cons)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    57
@{cterm "rev [1::int, 2, 3]"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    58
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    59
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    60
text {* Try conversion (yields reflexivity instead of exception) *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    61
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    62
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    63
Conv.try_conv (Conv.rewr_conv rev_Nil) @{cterm "[1::int, 2]"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    64
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    65
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    66
text {* Descend into subterms *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    67
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    68
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    69
Conv.combination_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    70
  (Conv.combination_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    71
    Conv.all_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    72
    (Conv.rewr_conv rev_Cons))
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    73
  (Conv.rewr_conv rev_Cons)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    74
  @{cterm "rev [1::int, 2] @ rev [3, 4]"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    75
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    76
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    77
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    78
Conv.combination_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    79
  (Conv.arg_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    80
    (Conv.rewr_conv rev_Cons))
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    81
  (Conv.rewr_conv rev_Cons)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    82
  @{cterm "rev [1::int, 2] @ rev [3, 4]"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    83
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    84
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    85
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    86
Conv.abs_conv (fn (v, ctxt) =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    87
  Conv.abs_conv (fn (v', ctxt') =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    88
    Conv.rewr_conv rev_Cons) ctxt)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    89
  @{context}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    90
  @{cterm "\<lambda>x y. rev [x, y]"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    91
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    92
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    93
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    94
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    95
section {* Simple bottom-up rewriting, using Isabelle's conversion library *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    96
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    97
text {* Descend into immediate subterms *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    98
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    99
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   100
fun subc conv ctxt = 
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   101
  Conv.comb_conv (conv ctxt) else_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   102
  Conv.abs_conv (conv o snd) ctxt else_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   103
  Conv.all_conv;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   104
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   105
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   106
text {* The ct argument is necessary to avoid nontermination! *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   107
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   108
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   109
fun botc conv ctxt ct =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   110
  (subc (botc conv) ctxt then_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   111
   Conv.try_conv (conv then_conv botc conv ctxt)) ct
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   112
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   113
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   114
text {* Running example: reversing lists *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   115
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   116
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   117
val eqns = map mk_meta_eq (@{thms "append.simps"} @ @{thms "rev.simps"});
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   118
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   119
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   120
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   121
val rev_int = @{cterm "rev :: int list \<Rightarrow> int list"};
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   122
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   123
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   124
text {* Produce lists of length i *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   125
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   126
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   127
fun mk_upto thy i = Thm.cterm_of thy (HOLogic.mk_list HOLogic.intT
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   128
  (map (HOLogic.mk_number HOLogic.intT) (1 upto i)));
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   129
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   130
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   131
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   132
val ct = Thm.capply rev_int (mk_upto @{theory} 100)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   133
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   134
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   135
text {* Fully rewrite the term (slow, i.e. 40 secs on my laptop) *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   136
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   137
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   138
timeit (fn () =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   139
  botc (Conv.first_conv (map Conv.rewr_conv eqns)) @{context} ct)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   140
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   141
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   142
text {* Also rewrites inside quantifiers, thanks to abs_conv *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   143
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   144
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   145
botc (Conv.first_conv (map Conv.rewr_conv eqns)) @{context}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   146
  @{cterm "\<forall>x y z. P (rev [x, y, z])"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   147
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   148
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   149
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   150
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   151
section {* Using exceptions for signalling unchanged terms *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   152
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   153
text {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   154
  Motivation: avoid unnecessary applications of reflexivity
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   155
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   156
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   157
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   158
infix 1 then_conv';
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   159
infix 0 else_conv';
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   160
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   161
exception Fail;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   162
exception Unchanged;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   163
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   164
fun (cv1 else_conv' cv2) ct =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   165
  cv1 ct handle Fail => cv2 ct;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   166
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   167
fun all_conv' ct = raise Unchanged;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   168
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   169
fun no_conv' ct = raise Fail;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   170
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   171
fun try_conv' cv ct = cv ct handle Fail => raise Unchanged;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   172
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   173
fun (cv1 then_conv' cv2) ct =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   174
  let val eq = cv1 ct
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   175
  in Thm.transitive eq (cv2 (Thm.rhs_of eq)) handle Unchanged => eq
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   176
  end handle Unchanged => cv2 ct;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   177
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   178
fun first_conv' cvs = fold_rev (curry op else_conv') cvs no_conv';
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   179
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   180
fun comb_conv' cv ct =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   181
  let val (ct1, ct2) = Thm.dest_comb ct
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   182
  in
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   183
    let val eq1 = cv ct1
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   184
    in Thm.combination eq1 (cv ct2) handle Unchanged =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   185
       Thm.combination eq1 (Thm.reflexive ct2)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   186
    end handle Unchanged =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   187
    let val eq2 = cv ct2
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   188
    in Thm.combination (Thm.reflexive ct1) eq2 end
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   189
  end handle CTERM _ => raise Fail;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   190
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   191
fun abs_conv' cv ctxt ct =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   192
  (case Thm.term_of ct of
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   193
    Abs (x, _, _) =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   194
      let
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   195
        val ([u], ctxt') = Variable.variant_fixes ["u"] ctxt;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   196
        val (v, ct') = Thm.dest_abs (SOME u) ct;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   197
        val eq = cv (v, ctxt') ct';
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   198
      in Thm.abstract_rule x v eq end
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   199
  | _ => raise Fail);
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   200
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   201
fun subc' conv ctxt = 
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   202
  comb_conv' (conv ctxt) else_conv'
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   203
  abs_conv' (conv o snd) ctxt else_conv'
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   204
  all_conv';
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   205
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   206
fun botc' conv ctxt ct =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   207
  (subc' (botc' conv) ctxt then_conv'
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   208
   try_conv' (conv then_conv' botc' conv ctxt)) ct
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   209
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   210
fun rewr_conv' rule ct =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   211
  Conv.rewr_conv rule ct handle CTERM _ => raise Fail;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   212
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   213
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   214
text {* Fully rewrite the term (32 secs on my laptop) *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   215
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   216
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   217
timeit (fn () =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   218
  botc' (first_conv' (map rewr_conv' eqns)) @{context} ct)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   219
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   220
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   221
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   222
botc' (first_conv' (map rewr_conv' eqns)) @{context}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   223
  @{cterm "\<forall>x y z. P (rev [x, y, z])"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   224
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   225
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   226
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   227
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   228
section {* Bottom-up writing using skeletons *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   229
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   230
text {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   231
  Motivation: avoid re-inspecting terms that are already
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   232
  in normal form
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   233
  Skeleton = rhs of last rewrite rule applied
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   234
  decomposed in parallel with the term to be normalized
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   235
  if skeleton is a variable, then the corresponding
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   236
  term must already be in normal form.
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   237
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   238
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   239
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   240
infix 1 then_conv'';
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   241
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   242
fun (cv1 then_conv'' cv2) cts =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   243
  let val (eq1, skel1) = cv1 cts
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   244
  in 
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   245
    let val (eq2, skel2) = cv2 (Thm.rhs_of eq1, skel1)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   246
    in (Thm.transitive eq1 eq2, skel2) end handle Unchanged => (eq1, skel1)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   247
  end handle Unchanged => cv2 cts;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   248
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   249
val dummy_skel = Bound 0;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   250
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   251
fun comb_conv'' cv (ct, skel) =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   252
  let
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   253
    val (ct1, ct2) = Thm.dest_comb ct
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   254
    val (skel1, skel2) = (case skel of
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   255
        skel1 $ skel2 => (skel1, skel2)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   256
      | _ => (dummy_skel, dummy_skel));
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   257
  in
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   258
    let val (eq1, skel1') = cv (ct1, skel1)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   259
    in 
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   260
      let val (eq2, skel2') = cv (ct2, skel2)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   261
      in (Thm.combination eq1 eq2, skel1' $ skel2') end
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   262
      handle Unchanged =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   263
      (Thm.combination eq1 (Thm.reflexive ct2), skel1' $ skel2)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   264
    end handle Unchanged =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   265
    let val (eq2, skel2') = cv (ct2, skel2)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   266
    in (Thm.combination (Thm.reflexive ct1) eq2, skel1 $ skel2') end
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   267
  end handle CTERM _ => raise Fail;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   268
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   269
fun abs_conv'' cv ctxt (ct, skel) =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   270
  (case Thm.term_of ct of
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   271
    Abs (x, T, _) =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   272
      let
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   273
        val ([u], ctxt') = Variable.variant_fixes ["u"] ctxt;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   274
        val (v, ct') = Thm.dest_abs (SOME u) ct;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   275
        val skel' = (case skel of
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   276
            Abs (_, _, skel') => skel'
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   277
          | _ => dummy_skel)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   278
        val (eq, skel'') = cv (v, ctxt') (ct', skel');
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   279
      in (Thm.abstract_rule x v eq, Abs (x, T, skel'')) end
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   280
  | _ => raise Fail);
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   281
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   282
fun subc'' conv ctxt =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   283
  comb_conv'' (conv ctxt) else_conv'
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   284
  abs_conv'' (conv o snd) ctxt else_conv'
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   285
  all_conv';
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   286
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   287
fun botc'' conv ctxt (_, Var _) = raise Unchanged
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   288
  | botc'' conv ctxt cts =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   289
      (subc'' (botc'' conv) ctxt then_conv''
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   290
       try_conv' (conv then_conv'' botc'' conv ctxt)) cts
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   291
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   292
fun rewr_conv'' rule (ct, _) =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   293
  (Conv.rewr_conv rule ct, term_of (Thm.rhs_of rule))
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   294
  handle CTERM _ => raise Fail;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   295
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   296
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   297
text {* Fully rewrite the term (1.5 secs on my laptop) *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   298
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   299
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   300
timeit (fn () =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   301
  fst (botc'' (first_conv' (map rewr_conv'' eqns)) @{context} (ct, dummy_skel)))
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   302
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   303
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   304
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   305
fst (botc'' (first_conv' (map rewr_conv'' eqns)) @{context}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   306
  (@{cterm "\<forall>x y z. P (rev [x, y, z])"}, dummy_skel))
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   307
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   308
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   309
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   310
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   311
section {* The simplifier *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   312
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   313
text {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   314
  The simplifier is a conversion itself, using many of
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   315
  the techniques just described.
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   316
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   317
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   318
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   319
Simplifier.rewrite (HOL_basic_ss addsimps eqns) ct
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   320
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   321
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   322
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   323
Simplifier.rewrite @{simpset}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   324
  @{cterm "\<And>(x::int) (y::int). P x \<Longrightarrow> x = 42 \<Longrightarrow> Q x \<Longrightarrow> R (y + 0) \<Longrightarrow> S (1 * x)"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   325
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   326
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   327
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   328
Simplifier.asm_rewrite @{simpset}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   329
  @{cterm "\<And>(x::int) (y::int). P x \<Longrightarrow> x = 42 \<Longrightarrow> Q x \<Longrightarrow> R (y + 0) \<Longrightarrow> S (1 * x)"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   330
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   331
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   332
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   333
Simplifier.full_rewrite @{simpset}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   334
  @{cterm "\<And>(x::int) (y::int). P x \<Longrightarrow> x = 42 \<Longrightarrow> Q x \<Longrightarrow> R (y + 0) \<Longrightarrow> S (1 * x)"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   335
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   336
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   337
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   338
Simplifier.asm_full_rewrite @{simpset}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   339
  @{cterm "\<And>(x::int) (y::int). P x \<Longrightarrow> x = 42 \<Longrightarrow> Q x \<Longrightarrow> R (y + 0) \<Longrightarrow> S (1 * x)"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   340
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   341
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   342
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   343
Simplifier.asm_lr_rewrite @{simpset}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   344
  @{cterm "\<And>(x::int) (y::int). P x \<Longrightarrow> x = 42 \<Longrightarrow> Q x \<Longrightarrow> R (y + 0) \<Longrightarrow> S (1 * x)"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   345
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   346
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   347
section {* Simplification procedures *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   348
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   349
text {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   350
  A simplification procedure is a function of type
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   351
  @{ML_type "cterm -> thm option"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   352
  It can be used to prove rewrite rules on-the-fly.
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   353
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   354
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   355
text {* Example 1: One-point rules *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   356
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   357
text {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   358
  Problem: how to rewrite
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   359
  @{term "\<And>x y z. P y \<Longrightarrow> y = t \<Longrightarrow> Q y"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   360
  to
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   361
  @{term "\<And>x z. P t \<Longrightarrow> Q t"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   362
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   363
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   364
lemma meta_onepoint1: "(\<And>x. x = t \<Longrightarrow> PROP P x) \<equiv> PROP P t"
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   365
proof
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   366
  assume R: "\<And>x. x = t \<Longrightarrow> PROP P x"
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   367
  show "PROP P t" by (rule R [OF refl])
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   368
next
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   369
  fix x assume "PROP P t" "x = t"
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   370
  then show "PROP P x" by simp
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   371
qed
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   372
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   373
lemma meta_onepoint2: "(\<And>x. t = x \<Longrightarrow> PROP P x) \<equiv> PROP P t"
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   374
proof
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   375
  assume R: "\<And>x. t = x \<Longrightarrow> PROP P x"
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   376
  show "PROP P t" by (rule R [OF refl])
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   377
next
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   378
  fix x assume "PROP P t" "t = x"
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   379
  then show "PROP P x" by simp
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   380
qed
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   381
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   382
lemmas meta_onepoint = meta_onepoint1 meta_onepoint2
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   383
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   384
text {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   385
  Note: only works with formulae like
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   386
  @{term "\<And>x z y. y = t \<Longrightarrow> P y \<Longrightarrow> Q y"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   387
  but not
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   388
  @{term "\<And>x y z. P y \<Longrightarrow> y = t \<Longrightarrow> Q y"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   389
  Solution: reorder quantifiers and premises
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   390
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   391
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   392
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   393
Simplifier.rewrite
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   394
  (HOL_basic_ss addsimps @{thms meta_onepoint})
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   395
  @{cterm "\<And>x z y. y = t \<Longrightarrow> P y \<Longrightarrow> Q y"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   396
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   397
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   398
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   399
Simplifier.rewrite
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   400
  (HOL_basic_ss addsimps @{thms meta_onepoint})
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   401
  @{cterm "\<And>x y z. P y \<Longrightarrow> y = t \<Longrightarrow> Q y"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   402
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   403
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   404
text {* Move parameters to the right *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   405
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   406
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   407
fun swap_params_conv ctxt i j cv =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   408
  let
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   409
    fun conv1 0 ctxt = Conv.forall_conv (cv o snd) ctxt
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   410
      | conv1 k ctxt =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   411
          Conv.rewr_conv @{thm swap_params} then_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   412
          Conv.forall_conv (conv1 (k-1) o snd) ctxt
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   413
    fun conv2 0 ctxt = conv1 j ctxt
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   414
      | conv2 k ctxt = Conv.forall_conv (conv2 (k-1) o snd) ctxt
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   415
  in conv2 i ctxt end;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   416
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   417
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   418
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   419
swap_params_conv @{context} 2 3 (K Conv.all_conv)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   420
  @{cterm "\<And>a b c d e f. P a b c d e f"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   421
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   422
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   423
text {* Move premises to the left *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   424
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   425
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   426
fun swap_prems_conv 0 = Conv.all_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   427
  | swap_prems_conv i =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   428
      Conv.implies_concl_conv (swap_prems_conv (i-1)) then_conv
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   429
      Conv.rewr_conv Drule.swap_prems_eq
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   430
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   431
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   432
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   433
swap_prems_conv 3
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   434
  @{cterm "A \<Longrightarrow> B \<Longrightarrow> C \<Longrightarrow> D \<Longrightarrow> E \<Longrightarrow> F"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   435
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   436
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   437
text {* Find out which equation to move *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   438
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   439
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   440
fun find_eq t =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   441
  let
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   442
    val l = length (Logic.strip_params t);
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   443
    val Hs = Logic.strip_assums_hyp t;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   444
    fun find (i, (_ $ (Const ("op =", _) $ Bound j $ _))) = SOME (i, j)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   445
      | find (i, (_ $ (Const ("op =", _) $ _ $ Bound j))) = SOME (i, j)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   446
      | find _ = NONE
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   447
  in
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   448
    case get_first find (map_index I Hs) of
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   449
      NONE => NONE
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   450
    | SOME (0, 0) => NONE
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   451
    | SOME (i, j) => SOME (i, l - j - 1, j)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   452
  end;
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   453
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   454
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   455
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   456
find_eq @{term "\<And>x y z. P y \<Longrightarrow> y = t \<Longrightarrow> Q y"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   457
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   458
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   459
text {* Turn it into a simproc *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   460
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   461
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   462
fun mk_rrule ctxt ct = case find_eq (term_of ct) of
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   463
    NONE => NONE
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   464
  | SOME (i, k, j) => SOME (swap_params_conv ctxt k j (K (swap_prems_conv i)) ct);
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   465
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   466
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   467
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   468
val rearrange_eqs_simproc =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   469
  Simplifier.simproc @{theory} "rearrange_eqs" ["all t"] (fn thy => fn ss => fn t =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   470
    mk_rrule (Simplifier.the_context ss) (cterm_of thy t))
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   471
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   472
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   473
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   474
Simplifier.rewrite
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   475
  (HOL_basic_ss addsimps @{thms meta_onepoint}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   476
     addsimprocs [rearrange_eqs_simproc])
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   477
  @{cterm "\<And>x y z. P y \<Longrightarrow> y = t \<Longrightarrow> Q y"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   478
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   479
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   480
subsection {* Example 2: Simplifying set comprehensions *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   481
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   482
text {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   483
  Problem: How to simplify
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   484
  @{term "{(x, y, z). (x, y, z) \<in> S}"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   485
  to
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   486
  @{term S}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   487
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   488
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   489
ML {* @{thm Collect_mem_eq} *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   490
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   491
text {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   492
  Note: does not work with pairs
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   493
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   494
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   495
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   496
Simplifier.rewrite
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   497
  (HOL_basic_ss addsimps @{thms Collect_mem_eq})
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   498
  @{cterm "P {x. x \<in> S}"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   499
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   500
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   501
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   502
Simplifier.rewrite
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   503
  (HOL_basic_ss addsimps @{thms Collect_mem_eq})
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   504
  @{cterm "P {(x, y). (x, y) \<in> S}"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   505
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   506
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   507
text {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   508
  Write a simproc to prove
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   509
  @{term "{(x, y). (x, y) \<in> S} \<equiv> S"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   510
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   511
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   512
lemma test: "{(x, y). (x, y) \<in> S} \<equiv> S"
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   513
  apply (rule eq_reflection)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   514
  apply (rule subset_antisym)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   515
  apply (rule subsetI)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   516
  apply (drule CollectD)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   517
  apply (simp only: split_paired_all split_conv)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   518
  apply (rule subsetI)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   519
  apply (rule CollectI)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   520
  apply (simp only: split_paired_all split_conv)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   521
  done
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   522
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   523
text {* The same in ML *}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   524
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   525
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   526
let
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   527
  val simp = full_simp_tac
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   528
    (HOL_basic_ss addsimps [split_paired_all, split_conv]) 1
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   529
in
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   530
  Goal.prove @{context} [] []
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   531
    @{term "{(x, y). (x, y) \<in> S} \<equiv> S"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   532
    (K (EVERY
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   533
      [rtac eq_reflection 1, rtac @{thm subset_antisym} 1,
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   534
       rtac subsetI 1, dtac CollectD 1, simp,
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   535
       rtac subsetI 1, rtac CollectI 1, simp]))
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   536
end
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   537
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   538
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   539
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   540
val (u, Ts, ps) = HOLogic.strip_split
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   541
  @{term "\<lambda>(x, y). (x, y) \<in> S"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   542
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   543
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   544
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   545
val collect_mem_simproc =
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   546
  Simplifier.simproc (theory "Set") "Collect_mem" ["Collect t"] (fn thy => fn ss =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   547
    fn S as Const ("Collect", Type ("fun", [_, T])) $ t =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   548
         let val (u, Ts, ps) = HOLogic.strip_split t
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   549
         in case u of
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   550
           (c as Const ("op :", _)) $ q $ S' =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   551
             (case try (HOLogic.dest_tuple' ps) q of
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   552
                NONE => NONE
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   553
              | SOME ts =>
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   554
                  if not (loose_bvar (S', 0)) andalso
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   555
                    ts = map Bound (length ps downto 0)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   556
                  then
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   557
                    let val simp = full_simp_tac (Simplifier.inherit_context ss
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   558
                      (HOL_basic_ss addsimps [split_paired_all, split_conv])) 1
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   559
                    in
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   560
                      SOME (Goal.prove (Simplifier.the_context ss) [] []
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   561
                        (Const ("==", T --> T --> propT) $ S $ S')
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   562
                        (K (EVERY
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   563
                          [rtac eq_reflection 1, rtac @{thm subset_antisym} 1,
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   564
                           rtac subsetI 1, dtac CollectD 1, simp,
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   565
                           rtac subsetI 1, rtac CollectI 1, simp])))
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   566
                    end
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   567
                  else NONE)
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   568
         | _ => NONE
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   569
         end
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   570
     | _ => NONE);
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   571
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   572
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   573
ML {*
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   574
Simplifier.rewrite
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   575
  (HOL_basic_ss addsimps @{thms Collect_mem_eq}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   576
     addsimprocs [collect_mem_simproc])
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   577
  @{cterm "P {(x, y). (x, y) \<in> S}"}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   578
*}
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   579
f1be8028a4a9 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   580
end