1 (* Title: HOL/Tools/transfer.ML |
1 (* Title: HOL/Tools/transfer.ML |
2 Author: Brian Huffman, TU Muenchen |
2 Author: Brian Huffman, TU Muenchen |
|
3 Author: Ondrej Kuncar, TU Muenchen |
3 |
4 |
4 Generic theorem transfer method. |
5 Generic theorem transfer method. |
5 *) |
6 *) |
6 |
7 |
7 signature TRANSFER = |
8 signature TRANSFER = |
8 sig |
9 sig |
9 val prep_conv: conv |
10 val prep_conv: conv |
|
11 val get_transfer_raw: Proof.context -> thm list |
10 val get_relator_eq: Proof.context -> thm list |
12 val get_relator_eq: Proof.context -> thm list |
11 val get_sym_relator_eq: Proof.context -> thm list |
13 val get_sym_relator_eq: Proof.context -> thm list |
12 val get_relator_eq_raw: Proof.context -> thm list |
14 val get_relator_eq_raw: Proof.context -> thm list |
13 val get_transfer_raw: Proof.context -> thm list |
15 val get_relator_domain: Proof.context -> thm list |
14 val transfer_add: attribute |
16 val transfer_add: attribute |
15 val transfer_del: attribute |
17 val transfer_del: attribute |
|
18 val transfer_domain_add: attribute |
|
19 val transfer_domain_del: attribute |
16 val transfer_rule_of_term: Proof.context -> term -> thm |
20 val transfer_rule_of_term: Proof.context -> term -> thm |
17 val transfer_tac: bool -> Proof.context -> int -> tactic |
21 val transfer_tac: bool -> Proof.context -> int -> tactic |
18 val transfer_prover_tac: Proof.context -> int -> tactic |
22 val transfer_prover_tac: Proof.context -> int -> tactic |
19 val setup: theory -> theory |
23 val setup: theory -> theory |
20 end |
24 end |
29 type T = |
33 type T = |
30 { transfer_raw : thm Item_Net.T, |
34 { transfer_raw : thm Item_Net.T, |
31 known_frees : (string * typ) list, |
35 known_frees : (string * typ) list, |
32 compound_rhs : unit Net.net, |
36 compound_rhs : unit Net.net, |
33 relator_eq : thm Item_Net.T, |
37 relator_eq : thm Item_Net.T, |
34 relator_eq_raw : thm Item_Net.T } |
38 relator_eq_raw : thm Item_Net.T, |
|
39 relator_domain : thm Item_Net.T } |
35 val empty = |
40 val empty = |
36 { transfer_raw = Thm.full_rules, |
41 { transfer_raw = Thm.full_rules, |
37 known_frees = [], |
42 known_frees = [], |
38 compound_rhs = Net.empty, |
43 compound_rhs = Net.empty, |
39 relator_eq = Thm.full_rules, |
44 relator_eq = Thm.full_rules, |
40 relator_eq_raw = Thm.full_rules } |
45 relator_eq_raw = Thm.full_rules, |
|
46 relator_domain = Thm.full_rules } |
41 val extend = I |
47 val extend = I |
42 fun merge |
48 fun merge |
43 ( { transfer_raw = t1, known_frees = k1, |
49 ( { transfer_raw = t1, known_frees = k1, |
44 compound_rhs = c1, relator_eq = r1, |
50 compound_rhs = c1, relator_eq = r1, |
45 relator_eq_raw = rw1 }, |
51 relator_eq_raw = rw1, relator_domain = rd1 }, |
46 { transfer_raw = t2, known_frees = k2, |
52 { transfer_raw = t2, known_frees = k2, |
47 compound_rhs = c2, relator_eq = r2, |
53 compound_rhs = c2, relator_eq = r2, |
48 relator_eq_raw = rw2 } ) = |
54 relator_eq_raw = rw2, relator_domain = rd2 } ) = |
49 { transfer_raw = Item_Net.merge (t1, t2), |
55 { transfer_raw = Item_Net.merge (t1, t2), |
50 known_frees = Library.merge (op =) (k1, k2), |
56 known_frees = Library.merge (op =) (k1, k2), |
51 compound_rhs = Net.merge (K true) (c1, c2), |
57 compound_rhs = Net.merge (K true) (c1, c2), |
52 relator_eq = Item_Net.merge (r1, r2), |
58 relator_eq = Item_Net.merge (r1, r2), |
53 relator_eq_raw = Item_Net.merge (rw1, rw2) } |
59 relator_eq_raw = Item_Net.merge (rw1, rw2), |
|
60 relator_domain = Item_Net.merge (rd1, rd2) } |
54 ) |
61 ) |
|
62 |
|
63 fun get_transfer_raw ctxt = ctxt |
|
64 |> (Item_Net.content o #transfer_raw o Data.get o Context.Proof) |
|
65 |
|
66 fun get_known_frees ctxt = ctxt |
|
67 |> (#known_frees o Data.get o Context.Proof) |
|
68 |
|
69 fun get_compound_rhs ctxt = ctxt |
|
70 |> (#compound_rhs o Data.get o Context.Proof) |
55 |
71 |
56 fun get_relator_eq ctxt = ctxt |
72 fun get_relator_eq ctxt = ctxt |
57 |> (Item_Net.content o #relator_eq o Data.get o Context.Proof) |
73 |> (Item_Net.content o #relator_eq o Data.get o Context.Proof) |
58 |> map safe_mk_meta_eq |
74 |> map safe_mk_meta_eq |
59 |
75 |
62 |> map (Thm.symmetric o safe_mk_meta_eq) |
78 |> map (Thm.symmetric o safe_mk_meta_eq) |
63 |
79 |
64 fun get_relator_eq_raw ctxt = ctxt |
80 fun get_relator_eq_raw ctxt = ctxt |
65 |> (Item_Net.content o #relator_eq_raw o Data.get o Context.Proof) |
81 |> (Item_Net.content o #relator_eq_raw o Data.get o Context.Proof) |
66 |
82 |
67 fun get_transfer_raw ctxt = ctxt |
83 fun get_relator_domain ctxt = ctxt |
68 |> (Item_Net.content o #transfer_raw o Data.get o Context.Proof) |
84 |> (Item_Net.content o #relator_domain o Data.get o Context.Proof) |
69 |
85 |
70 fun get_known_frees ctxt = ctxt |
86 fun map_data f1 f2 f3 f4 f5 f6 |
71 |> (#known_frees o Data.get o Context.Proof) |
87 { transfer_raw, known_frees, compound_rhs, relator_eq, relator_eq_raw, relator_domain } = |
72 |
|
73 fun get_compound_rhs ctxt = ctxt |
|
74 |> (#compound_rhs o Data.get o Context.Proof) |
|
75 |
|
76 fun map_data f1 f2 f3 f4 f5 |
|
77 { transfer_raw, known_frees, compound_rhs, relator_eq, relator_eq_raw } = |
|
78 { transfer_raw = f1 transfer_raw, |
88 { transfer_raw = f1 transfer_raw, |
79 known_frees = f2 known_frees, |
89 known_frees = f2 known_frees, |
80 compound_rhs = f3 compound_rhs, |
90 compound_rhs = f3 compound_rhs, |
81 relator_eq = f4 relator_eq, |
91 relator_eq = f4 relator_eq, |
82 relator_eq_raw = f5 relator_eq_raw } |
92 relator_eq_raw = f5 relator_eq_raw, |
83 |
93 relator_domain = f6 relator_domain } |
84 fun map_transfer_raw f = map_data f I I I I |
94 |
85 fun map_known_frees f = map_data I f I I I |
95 fun map_transfer_raw f = map_data f I I I I I |
86 fun map_compound_rhs f = map_data I I f I I |
96 fun map_known_frees f = map_data I f I I I I |
87 fun map_relator_eq f = map_data I I I f I |
97 fun map_compound_rhs f = map_data I I f I I I |
88 fun map_relator_eq_raw f = map_data I I I I f |
98 fun map_relator_eq f = map_data I I I f I I |
|
99 fun map_relator_eq_raw f = map_data I I I I f I |
|
100 fun map_relator_domain f = map_data I I I I I f |
89 |
101 |
90 fun add_transfer_thm thm = Data.map |
102 fun add_transfer_thm thm = Data.map |
91 (map_transfer_raw (Item_Net.update thm) o |
103 (map_transfer_raw (Item_Net.update thm) o |
92 map_compound_rhs |
104 map_compound_rhs |
93 (case HOLogic.dest_Trueprop (Thm.concl_of thm) of |
105 (case HOLogic.dest_Trueprop (Thm.concl_of thm) of |
94 _ $ _ $ (rhs as (_ $ _)) => Net.insert_term (K true) (rhs, ()) |
106 (Const (@{const_name Rel}, _)) $ _ $ _ $ (rhs as (_ $ _)) => Net.insert_term (K true) (rhs, ()) |
95 | _ => I) o |
107 | _ => I) o |
96 map_known_frees (Term.add_frees (Thm.concl_of thm))) |
108 map_known_frees (Term.add_frees (Thm.concl_of thm))) |
97 |
109 |
98 fun del_transfer_thm thm = Data.map (map_transfer_raw (Item_Net.remove thm)) |
110 fun del_transfer_thm thm = Data.map (map_transfer_raw (Item_Net.remove thm)) |
99 |
111 |
109 let val (cT, cT') = dest_funcT (Thm.ctyp_of_term ct) |
121 let val (cT, cT') = dest_funcT (Thm.ctyp_of_term ct) |
110 val (cU, _) = dest_funcT cT' |
122 val (cU, _) = dest_funcT cT' |
111 in Drule.instantiate' [SOME cT, SOME cU] [SOME ct] Rel_rule end |
123 in Drule.instantiate' [SOME cT, SOME cU] [SOME ct] Rel_rule end |
112 |
124 |
113 (* Conversion to preprocess a transfer rule *) |
125 (* Conversion to preprocess a transfer rule *) |
114 fun strip_args n = funpow n (fst o dest_comb) |
|
115 |
|
116 fun safe_Rel_conv ct = |
126 fun safe_Rel_conv ct = |
117 let |
127 Conv.try_conv (HOLogic.Trueprop_conv (Conv.fun_conv (Conv.fun_conv Rel_conv))) ct |
118 val head = ct |> term_of |> HOLogic.dest_Trueprop |> strip_args 2 |
|
119 fun is_known (Const (s, _)) = (s = @{const_name DOM}) |
|
120 | is_known _ = false |
|
121 in |
|
122 if not (is_known head) |
|
123 then HOLogic.Trueprop_conv (Conv.fun_conv (Conv.fun_conv Rel_conv)) ct |
|
124 else Conv.all_conv ct |
|
125 end |
|
126 handle TERM _ => Conv.all_conv ct |
|
127 ; |
|
128 |
128 |
129 fun prep_conv ct = ( |
129 fun prep_conv ct = ( |
130 Conv.implies_conv safe_Rel_conv prep_conv |
130 Conv.implies_conv safe_Rel_conv prep_conv |
131 else_conv |
131 else_conv |
132 safe_Rel_conv |
132 safe_Rel_conv |
183 |
183 |
184 fun abstract_equalities_relator_eq rel_eq_thm = |
184 fun abstract_equalities_relator_eq rel_eq_thm = |
185 gen_abstract_equalities (fn x => (x, I)) |
185 gen_abstract_equalities (fn x => (x, I)) |
186 (rel_eq_thm RS @{thm is_equality_def [THEN iffD2]}) |
186 (rel_eq_thm RS @{thm is_equality_def [THEN iffD2]}) |
187 |
187 |
|
188 fun abstract_equalities_domain thm = |
|
189 let |
|
190 fun dest prop = |
|
191 let |
|
192 val prems = Logic.strip_imp_prems prop |
|
193 val concl = HOLogic.dest_Trueprop (Logic.strip_imp_concl prop) |
|
194 val ((dom, x), y) = apfst Term.dest_comb (Term.dest_comb concl) |
|
195 in |
|
196 (x $ y, fn comb' => |
|
197 let |
|
198 val (x', y') = dest_comb comb' |
|
199 in |
|
200 Logic.list_implies (prems, HOLogic.mk_Trueprop (dom $ x' $ y')) |
|
201 end) |
|
202 end |
|
203 in |
|
204 gen_abstract_equalities dest thm |
|
205 end |
|
206 |
|
207 |
|
208 (** Replacing explicit Domainp predicates with Domainp assumptions **) |
|
209 |
|
210 fun mk_Domainp_assm (T, R) = |
|
211 HOLogic.mk_eq ((Const (@{const_name Domainp}, Term.fastype_of T --> Term.fastype_of R) $ T), R) |
|
212 |
|
213 val Domainp_lemma = |
|
214 @{lemma "(!!R. Domainp T = R ==> PROP (P R)) == PROP (P (Domainp T))" |
|
215 by (rule, drule meta_spec, |
|
216 erule meta_mp, rule refl, simp)} |
|
217 |
|
218 fun fold_Domainp f (t as Const (@{const_name Domainp},_) $ (Var (_,_))) = f t |
|
219 | fold_Domainp f (t $ u) = fold_Domainp f t #> fold_Domainp f u |
|
220 | fold_Domainp f (Abs (_, _, t)) = fold_Domainp f t |
|
221 | fold_Domainp _ _ = I |
|
222 |
|
223 fun subst_terms tab t = |
|
224 let |
|
225 val t' = Termtab.lookup tab t |
|
226 in |
|
227 case t' of |
|
228 SOME t' => t' |
|
229 | NONE => |
|
230 (case t of |
|
231 u $ v => (subst_terms tab u) $ (subst_terms tab v) |
|
232 | Abs (a, T, t) => Abs (a, T, subst_terms tab t) |
|
233 | t => t) |
|
234 end |
|
235 |
|
236 fun gen_abstract_domains (dest : term -> term * (term -> term)) thm = |
|
237 let |
|
238 val thy = Thm.theory_of_thm thm |
|
239 val prop = Thm.prop_of thm |
|
240 val (t, mk_prop') = dest prop |
|
241 val Domainp_tms = rev (fold_Domainp (fn t => insert op= t) t []) |
|
242 val Domainp_Ts = map (snd o dest_funT o snd o dest_Const o fst o dest_comb) Domainp_tms |
|
243 val used = Term.add_free_names t [] |
|
244 val rels = map (snd o dest_comb) Domainp_tms |
|
245 val rel_names = map (fst o fst o dest_Var) rels |
|
246 val names = map (fn name => ("D" ^ name)) rel_names |> Name.variant_list used |
|
247 val frees = map Free (names ~~ Domainp_Ts) |
|
248 val prems = map (HOLogic.mk_Trueprop o mk_Domainp_assm) (rels ~~ frees); |
|
249 val t' = subst_terms (fold Termtab.update (Domainp_tms ~~ frees) Termtab.empty) t |
|
250 val prop1 = fold Logic.all frees (Logic.list_implies (prems, mk_prop' t')) |
|
251 val prop2 = Logic.list_rename_params (rev names) prop1 |
|
252 val cprop = Thm.cterm_of thy prop2 |
|
253 val equal_thm = Raw_Simplifier.rewrite false [Domainp_lemma] cprop |
|
254 fun forall_elim thm = Thm.forall_elim_vars (Thm.maxidx_of thm + 1) thm; |
|
255 in |
|
256 forall_elim (thm COMP (equal_thm COMP @{thm equal_elim_rule2})) |
|
257 end |
|
258 handle TERM _ => thm |
|
259 |
|
260 fun abstract_domains_transfer thm = |
|
261 let |
|
262 fun dest prop = |
|
263 let |
|
264 val prems = Logic.strip_imp_prems prop |
|
265 val concl = HOLogic.dest_Trueprop (Logic.strip_imp_concl prop) |
|
266 val ((rel, x), y) = apfst Term.dest_comb (Term.dest_comb concl) |
|
267 in |
|
268 (x, fn x' => |
|
269 Logic.list_implies (prems, HOLogic.mk_Trueprop (rel $ x' $ y))) |
|
270 end |
|
271 in |
|
272 gen_abstract_domains dest thm |
|
273 end |
|
274 |
|
275 fun detect_transfer_rules thm = |
|
276 let |
|
277 fun is_transfer_rule tm = case (HOLogic.dest_Trueprop tm) of |
|
278 (Const (@{const_name HOL.eq}, _)) $ ((Const (@{const_name Domainp}, _)) $ _) $ _ => false |
|
279 | _ $ _ $ _ => true |
|
280 | _ => false |
|
281 fun safe_transfer_rule_conv ctm = |
|
282 if is_transfer_rule (term_of ctm) then safe_Rel_conv ctm else Conv.all_conv ctm |
|
283 in |
|
284 Conv.fconv_rule (Conv.prems_conv ~1 safe_transfer_rule_conv) thm |
|
285 end |
|
286 |
|
287 (** Adding transfer domain rules **) |
|
288 |
|
289 fun add_transfer_domain_thm thm = |
|
290 (add_transfer_thm o abstract_equalities_domain o detect_transfer_rules) thm |
|
291 |
|
292 fun del_transfer_domain_thm thm = |
|
293 (del_transfer_thm o abstract_equalities_domain o detect_transfer_rules) thm |
188 |
294 |
189 (** Transfer proof method **) |
295 (** Transfer proof method **) |
190 |
296 |
191 val post_simps = |
297 val post_simps = |
192 @{thms transfer_forall_eq [symmetric] |
298 @{thms transfer_forall_eq [symmetric] |
361 val transfer_prover_method : (Proof.context -> Method.method) context_parser = |
467 val transfer_prover_method : (Proof.context -> Method.method) context_parser = |
362 Scan.succeed (fn ctxt => SIMPLE_METHOD' (transfer_prover_tac ctxt)) |
468 Scan.succeed (fn ctxt => SIMPLE_METHOD' (transfer_prover_tac ctxt)) |
363 |
469 |
364 (* Attribute for transfer rules *) |
470 (* Attribute for transfer rules *) |
365 |
471 |
366 val prep_rule = abstract_equalities_transfer o Conv.fconv_rule prep_conv |
472 val prep_rule = abstract_domains_transfer o abstract_equalities_transfer o Conv.fconv_rule prep_conv |
367 |
473 |
368 val transfer_add = |
474 val transfer_add = |
369 Thm.declaration_attribute (add_transfer_thm o prep_rule) |
475 Thm.declaration_attribute (add_transfer_thm o prep_rule) |
370 |
476 |
371 val transfer_del = |
477 val transfer_del = |
372 Thm.declaration_attribute (del_transfer_thm o prep_rule) |
478 Thm.declaration_attribute (del_transfer_thm o prep_rule) |
373 |
479 |
374 val transfer_attribute = |
480 val transfer_attribute = |
375 Attrib.add_del transfer_add transfer_del |
481 Attrib.add_del transfer_add transfer_del |
|
482 |
|
483 (* Attributes for transfer domain rules *) |
|
484 |
|
485 val transfer_domain_add = Thm.declaration_attribute add_transfer_domain_thm |
|
486 |
|
487 val transfer_domain_del = Thm.declaration_attribute del_transfer_domain_thm |
|
488 |
|
489 val transfer_domain_attribute = |
|
490 Attrib.add_del transfer_domain_add transfer_domain_del |
376 |
491 |
377 (* Theory setup *) |
492 (* Theory setup *) |
378 |
493 |
379 val relator_eq_setup = |
494 val relator_eq_setup = |
380 let |
495 let |
390 in |
505 in |
391 Attrib.setup name (Attrib.add_del add del) text |
506 Attrib.setup name (Attrib.add_del add del) text |
392 #> Global_Theory.add_thms_dynamic (name, content) |
507 #> Global_Theory.add_thms_dynamic (name, content) |
393 end |
508 end |
394 |
509 |
|
510 val relator_domain_setup = |
|
511 let |
|
512 val name = @{binding relator_domain} |
|
513 fun add_thm thm = Data.map (map_relator_domain (Item_Net.update thm)) |
|
514 #> add_transfer_domain_thm thm |
|
515 fun del_thm thm = Data.map (map_relator_domain (Item_Net.remove thm)) |
|
516 #> del_transfer_domain_thm thm |
|
517 val add = Thm.declaration_attribute add_thm |
|
518 val del = Thm.declaration_attribute del_thm |
|
519 val text = "declaration of relator domain rule (used by transfer method)" |
|
520 val content = Item_Net.content o #relator_domain o Data.get |
|
521 in |
|
522 Attrib.setup name (Attrib.add_del add del) text |
|
523 #> Global_Theory.add_thms_dynamic (name, content) |
|
524 end |
|
525 |
|
526 |
395 val setup = |
527 val setup = |
396 relator_eq_setup |
528 relator_eq_setup |
|
529 #> relator_domain_setup |
397 #> Attrib.setup @{binding transfer_rule} transfer_attribute |
530 #> Attrib.setup @{binding transfer_rule} transfer_attribute |
398 "transfer rule for transfer method" |
531 "transfer rule for transfer method" |
399 #> Global_Theory.add_thms_dynamic |
532 #> Global_Theory.add_thms_dynamic |
400 (@{binding transfer_raw}, Item_Net.content o #transfer_raw o Data.get) |
533 (@{binding transfer_raw}, Item_Net.content o #transfer_raw o Data.get) |
|
534 #> Attrib.setup @{binding transfer_domain_rule} transfer_domain_attribute |
|
535 "transfer domain rule for transfer method" |
401 #> Global_Theory.add_thms_dynamic |
536 #> Global_Theory.add_thms_dynamic |
402 (@{binding relator_eq_raw}, Item_Net.content o #relator_eq_raw o Data.get) |
537 (@{binding relator_eq_raw}, Item_Net.content o #relator_eq_raw o Data.get) |
403 #> Method.setup @{binding transfer} (transfer_method true) |
538 #> Method.setup @{binding transfer} (transfer_method true) |
404 "generic theorem transfer method" |
539 "generic theorem transfer method" |
405 #> Method.setup @{binding transfer'} (transfer_method false) |
540 #> Method.setup @{binding transfer'} (transfer_method false) |