33 fun type_has_empty_sort (TFree (_, [])) = true |
33 fun type_has_empty_sort (TFree (_, [])) = true |
34 | type_has_empty_sort (TVar (_, [])) = true |
34 | type_has_empty_sort (TVar (_, [])) = true |
35 | type_has_empty_sort (Type (_, Ts)) = exists type_has_empty_sort Ts |
35 | type_has_empty_sort (Type (_, Ts)) = exists type_has_empty_sort Ts |
36 | type_has_empty_sort _ = false; |
36 | type_has_empty_sort _ = false; |
37 |
37 |
|
38 |
38 (**** Transformation of Elimination Rules into First-Order Formulas****) |
39 (**** Transformation of Elimination Rules into First-Order Formulas****) |
39 |
40 |
40 val cfalse = cterm_of HOL.thy HOLogic.false_const; |
41 val cfalse = cterm_of HOL.thy HOLogic.false_const; |
41 val ctp_false = cterm_of HOL.thy (HOLogic.mk_Trueprop HOLogic.false_const); |
42 val ctp_false = cterm_of HOL.thy (HOLogic.mk_Trueprop HOLogic.false_const); |
42 |
43 |
51 Thm.instantiate ([], [(cterm_of HOL.thy v, ctp_false)]) th |
52 Thm.instantiate ([], [(cterm_of HOL.thy v, ctp_false)]) th |
52 | _ => th; |
53 | _ => th; |
53 |
54 |
54 (*To enforce single-threading*) |
55 (*To enforce single-threading*) |
55 exception Clausify_failure of theory; |
56 exception Clausify_failure of theory; |
|
57 |
56 |
58 |
57 (**** SKOLEMIZATION BY INFERENCE (lcp) ****) |
59 (**** SKOLEMIZATION BY INFERENCE (lcp) ****) |
58 |
60 |
59 fun rhs_extra_types lhsT rhs = |
61 fun rhs_extra_types lhsT rhs = |
60 let val lhs_vars = Term.add_tfreesT lhsT [] |
62 let val lhs_vars = Term.add_tfreesT lhsT [] |
74 let |
76 let |
75 val cname = "sko_" ^ s ^ "_" ^ Int.toString (inc nref) |
77 val cname = "sko_" ^ s ^ "_" ^ Int.toString (inc nref) |
76 val args0 = term_frees xtp (*get the formal parameter list*) |
78 val args0 = term_frees xtp (*get the formal parameter list*) |
77 val Ts = map type_of args0 |
79 val Ts = map type_of args0 |
78 val extraTs = rhs_extra_types (Ts ---> T) xtp |
80 val extraTs = rhs_extra_types (Ts ---> T) xtp |
79 val _ = if null extraTs then () else |
|
80 warning ("Skolemization: extra type vars: " ^ |
|
81 commas_quote (map (Syntax.string_of_typ_global thy) extraTs)) |
|
82 val argsx = map (fn T => Free (gensym "vsk", T)) extraTs |
81 val argsx = map (fn T => Free (gensym "vsk", T)) extraTs |
83 val args = argsx @ args0 |
82 val args = argsx @ args0 |
84 val cT = extraTs ---> Ts ---> T |
83 val cT = extraTs ---> Ts ---> T |
85 val rhs = list_abs_free (map dest_Free args, HOLogic.choice_const T $ xtp) |
84 val rhs = list_abs_free (map dest_Free args, HOLogic.choice_const T $ xtp) |
86 (*Forms a lambda-abstraction over the formal parameters*) |
85 (*Forms a lambda-abstraction over the formal parameters*) |
163 val [g_C,f_C] = map (cterm_of (the_context ())) (term_vars (prop_of @{thm abs_C})); |
162 val [g_C,f_C] = map (cterm_of (the_context ())) (term_vars (prop_of @{thm abs_C})); |
164 val [f_S,g_S] = map (cterm_of (the_context ())) (term_vars (prop_of @{thm abs_S})); |
163 val [f_S,g_S] = map (cterm_of (the_context ())) (term_vars (prop_of @{thm abs_S})); |
165 |
164 |
166 (*FIXME: requires more use of cterm constructors*) |
165 (*FIXME: requires more use of cterm constructors*) |
167 fun abstract ct = |
166 fun abstract ct = |
168 let val _ = Output.debug (fn()=>" abstraction: " ^ Display.string_of_cterm ct) |
167 let |
|
168 val thy = theory_of_cterm ct |
169 val Abs(x,_,body) = term_of ct |
169 val Abs(x,_,body) = term_of ct |
170 val thy = theory_of_cterm ct |
|
171 val Type("fun",[xT,bodyT]) = typ_of (ctyp_of_term ct) |
170 val Type("fun",[xT,bodyT]) = typ_of (ctyp_of_term ct) |
172 val cxT = ctyp_of thy xT and cbodyT = ctyp_of thy bodyT |
171 val cxT = ctyp_of thy xT and cbodyT = ctyp_of thy bodyT |
173 fun makeK() = instantiate' [SOME cxT, SOME cbodyT] [SOME (cterm_of thy body)] @{thm abs_K} |
172 fun makeK() = instantiate' [SOME cxT, SOME cbodyT] [SOME (cterm_of thy body)] @{thm abs_K} |
174 in |
173 in |
175 case body of |
174 case body of |
207 else makeK() |
206 else makeK() |
208 | _ => error "abstract: Bad term" |
207 | _ => error "abstract: Bad term" |
209 end; |
208 end; |
210 |
209 |
211 (*Traverse a theorem, declaring abstraction function definitions. String s is the suggested |
210 (*Traverse a theorem, declaring abstraction function definitions. String s is the suggested |
212 prefix for the constants. Resulting theory is returned in the first theorem. *) |
211 prefix for the constants.*) |
213 fun combinators_aux ct = |
212 fun combinators_aux ct = |
214 if lambda_free (term_of ct) then reflexive ct |
213 if lambda_free (term_of ct) then reflexive ct |
215 else |
214 else |
216 case term_of ct of |
215 case term_of ct of |
217 Abs _ => |
216 Abs _ => |
218 let val (cv,cta) = Thm.dest_abs NONE ct |
217 let val (cv,cta) = Thm.dest_abs NONE ct |
219 val (v,Tv) = (dest_Free o term_of) cv |
218 val (v,Tv) = (dest_Free o term_of) cv |
220 val _ = Output.debug (fn()=>" recursion: " ^ Display.string_of_cterm cta); |
|
221 val u_th = combinators_aux cta |
219 val u_th = combinators_aux cta |
222 val _ = Output.debug (fn()=>" returned " ^ Display.string_of_thm u_th); |
|
223 val cu = Thm.rhs_of u_th |
220 val cu = Thm.rhs_of u_th |
224 val comb_eq = abstract (Thm.cabs cv cu) |
221 val comb_eq = abstract (Thm.cabs cv cu) |
225 in Output.debug (fn()=>" abstraction result: " ^ Display.string_of_thm comb_eq); |
222 in transitive (abstract_rule v cv u_th) comb_eq end |
226 (transitive (abstract_rule v cv u_th) comb_eq) end |
|
227 | t1 $ t2 => |
223 | t1 $ t2 => |
228 let val (ct1,ct2) = Thm.dest_comb ct |
224 let val (ct1,ct2) = Thm.dest_comb ct |
229 in combination (combinators_aux ct1) (combinators_aux ct2) end; |
225 in combination (combinators_aux ct1) (combinators_aux ct2) end; |
230 |
226 |
231 fun combinators th = |
227 fun combinators th = |
232 if lambda_free (prop_of th) then th |
228 if lambda_free (prop_of th) then th |
233 else |
229 else |
234 let val _ = Output.debug (fn()=>"Conversion to combinators: " ^ Display.string_of_thm th); |
230 let val th = Drule.eta_contraction_rule th |
235 val th = Drule.eta_contraction_rule th |
|
236 val eqth = combinators_aux (cprop_of th) |
231 val eqth = combinators_aux (cprop_of th) |
237 val _ = Output.debug (fn()=>"Conversion result: " ^ Display.string_of_thm eqth); |
|
238 in equal_elim eqth th end |
232 in equal_elim eqth th end |
239 handle THM (msg,_,_) => |
233 handle THM (msg,_,_) => |
240 (warning ("Error in the combinator translation of " ^ Display.string_of_thm th); |
234 (warning ("Error in the combinator translation of " ^ Display.string_of_thm th); |
241 warning (" Exception message: " ^ msg); |
235 warning (" Exception message: " ^ msg); |
242 TrueI); (*A type variable of sort {} will cause make abstraction fail.*) |
236 TrueI); (*A type variable of sort {} will cause make abstraction fail.*) |
357 val (nnfth, ctxt1) = to_nnf th ctxt0 |
351 val (nnfth, ctxt1) = to_nnf th ctxt0 |
358 val (cnfs, ctxt2) = Meson.make_cnf (assume_skolem_of_def s nnfth) nnfth ctxt1 |
352 val (cnfs, ctxt2) = Meson.make_cnf (assume_skolem_of_def s nnfth) nnfth ctxt1 |
359 in cnfs |> map combinators |> Variable.export ctxt2 ctxt0 |> Meson.finish_cnf end |
353 in cnfs |> map combinators |> Variable.export ctxt2 ctxt0 |> Meson.finish_cnf end |
360 handle THM _ => []; |
354 handle THM _ => []; |
361 |
355 |
362 (*Declare Skolem functions for a theorem, supplied in nnf and with its name. |
|
363 It returns a modified theory, unless skolemization fails.*) |
|
364 fun skolem (name, th0) thy = |
|
365 let |
|
366 val th = Thm.transfer thy th0 |
|
367 val ctxt0 = Variable.thm_context th |
|
368 in |
|
369 try (to_nnf th) ctxt0 |> Option.map (fn (nnfth, ctxt1) => |
|
370 let |
|
371 val s = flatten_name name |
|
372 val (defs, thy') = declare_skofuns s nnfth thy |
|
373 val (cnfs, ctxt2) = Meson.make_cnf (map skolem_of_def defs) nnfth ctxt1 |
|
374 val cnfs' = cnfs |> map combinators |> Variable.export ctxt2 ctxt0 |
|
375 |> Meson.finish_cnf |> map Thm.close_derivation |
|
376 in (cnfs', thy') end) |
|
377 end; |
|
378 |
|
379 (*The cache prevents repeated clausification of a theorem, and also repeated declaration of |
356 (*The cache prevents repeated clausification of a theorem, and also repeated declaration of |
380 Skolem functions.*) |
357 Skolem functions.*) |
381 structure ThmCache = TheoryDataFun |
358 structure ThmCache = TheoryDataFun |
382 ( |
359 ( |
383 type T = thm list Thmtab.table * unit Symtab.table |
360 type T = thm list Thmtab.table * unit Symtab.table; |
384 val empty = (Thmtab.empty, Symtab.empty) |
361 val empty = (Thmtab.empty, Symtab.empty); |
385 val copy = I; |
362 val copy = I; |
386 val extend = I; |
363 val extend = I; |
387 fun merge _ ((cache1, seen1), (cache2, seen2)) : T = |
364 fun merge _ ((cache1, seen1), (cache2, seen2)) : T = |
388 (Thmtab.merge (K true) (cache1, cache2), Symtab.merge (K true) (seen1, seen2)); |
365 (Thmtab.merge (K true) (cache1, cache2), Symtab.merge (K true) (seen1, seen2)); |
389 ); |
366 ); |
409 |
386 |
410 fun rules_of_claset cs = |
387 fun rules_of_claset cs = |
411 let val {safeIs,safeEs,hazIs,hazEs,...} = rep_cs cs |
388 let val {safeIs,safeEs,hazIs,hazEs,...} = rep_cs cs |
412 val intros = safeIs @ hazIs |
389 val intros = safeIs @ hazIs |
413 val elims = map Classical.classical_rule (safeEs @ hazEs) |
390 val elims = map Classical.classical_rule (safeEs @ hazEs) |
414 in |
391 in map pairname (intros @ elims) end; |
415 Output.debug (fn () => "rules_of_claset intros: " ^ Int.toString(length intros) ^ |
|
416 " elims: " ^ Int.toString(length elims)); |
|
417 map pairname (intros @ elims) |
|
418 end; |
|
419 |
392 |
420 fun rules_of_simpset ss = |
393 fun rules_of_simpset ss = |
421 let val ({rules,...}, _) = rep_ss ss |
394 let val ({rules,...}, _) = rep_ss ss |
422 val simps = Net.entries rules |
395 val simps = Net.entries rules |
423 in |
396 in map (fn r => (#name r, #thm r)) simps end; |
424 Output.debug (fn () => "rules_of_simpset: " ^ Int.toString(length simps)); |
|
425 map (fn r => (#name r, #thm r)) simps |
|
426 end; |
|
427 |
397 |
428 fun claset_rules_of ctxt = rules_of_claset (local_claset_of ctxt); |
398 fun claset_rules_of ctxt = rules_of_claset (local_claset_of ctxt); |
429 fun simpset_rules_of ctxt = rules_of_simpset (local_simpset_of ctxt); |
399 fun simpset_rules_of ctxt = rules_of_simpset (local_simpset_of ctxt); |
430 |
400 |
431 fun atpset_rules_of ctxt = map pairname (ResAtpset.get ctxt); |
401 fun atpset_rules_of ctxt = map pairname (ResAtpset.get ctxt); |
446 fun cnf_rules_pairs thy l = cnf_rules_pairs_aux thy [] (rev l); |
416 fun cnf_rules_pairs thy l = cnf_rules_pairs_aux thy [] (rev l); |
447 |
417 |
448 |
418 |
449 (**** Convert all facts of the theory into clauses (ResClause.clause, or ResHolClause.clause) ****) |
419 (**** Convert all facts of the theory into clauses (ResClause.clause, or ResHolClause.clause) ****) |
450 |
420 |
451 (*Populate the clause cache using the supplied theorem. Return the clausal form |
421 local |
452 and modified theory.*) |
422 |
453 fun skolem_cache_thm name (i, th) thy = |
423 fun skolem_def (name, th) thy = |
454 if bad_for_atp th then thy |
424 let val ctxt0 = Variable.thm_context th in |
455 else |
425 (case try (to_nnf th) ctxt0 of |
456 (case lookup_cache thy th of |
426 NONE => (NONE, thy) |
457 SOME _ => thy |
427 | SOME (nnfth, ctxt1) => |
458 | NONE => |
428 let val (defs, thy') = declare_skofuns (flatten_name name) nnfth thy |
459 (case skolem (name ^ "_" ^ string_of_int (i + 1), th) thy of |
429 in (SOME (th, ctxt0, ctxt1, nnfth, defs), thy') end) |
460 NONE => thy |
430 end; |
461 | SOME (cls, thy') => update_cache (th, cls) thy')); |
431 |
462 |
432 fun skolem_cnfs (th, ctxt0, ctxt1, nnfth, defs) = |
463 fun skolem_cache_fact (name, ths) (changed, thy) = |
433 let |
464 if (Sign.base_name name) mem_string multi_base_blacklist orelse already_seen thy name |
434 val (cnfs, ctxt2) = Meson.make_cnf (map skolem_of_def defs) nnfth ctxt1; |
465 then (changed, thy) |
435 val cnfs' = cnfs |
466 else (true, thy |> mark_seen name |> fold_index (skolem_cache_thm name) ths); |
436 |> map combinators |
|
437 |> Variable.export ctxt2 ctxt0 |
|
438 |> Meson.finish_cnf |
|
439 |> map Thm.close_derivation; |
|
440 in (th, cnfs') end; |
|
441 |
|
442 in |
467 |
443 |
468 fun saturate_skolem_cache thy = |
444 fun saturate_skolem_cache thy = |
469 (case Facts.fold_static skolem_cache_fact (PureThy.facts_of thy) (false, thy) of |
445 let |
470 (false, _) => NONE |
446 val new_facts = (PureThy.facts_of thy, []) |-> Facts.fold_static (fn (name, ths) => |
471 | (true, thy') => SOME thy'); |
447 if already_seen thy name then I else cons (name, ths)); |
472 |
448 val new_thms = (new_facts, []) |-> fold (fn (name, ths) => |
|
449 if member (op =) multi_base_blacklist (Sign.base_name name) then I |
|
450 else fold_index (fn (i, th) => |
|
451 if bad_for_atp th orelse is_some (lookup_cache thy th) then I |
|
452 else cons (name ^ "_" ^ string_of_int (i + 1), Thm.transfer thy th)) ths); |
|
453 in |
|
454 if null new_facts then NONE |
|
455 else |
|
456 let |
|
457 val (defs, thy') = thy |
|
458 |> fold (mark_seen o #1) new_facts |
|
459 |> fold_map skolem_def (sort_distinct (Thm.thm_ord o pairself snd) new_thms) |
|
460 |>> map_filter I; |
|
461 val cache_entries = ParList.map skolem_cnfs defs; |
|
462 in SOME (fold update_cache cache_entries thy') end |
|
463 end; |
|
464 |
|
465 end; |
473 |
466 |
474 val suppress_endtheory = ref false; |
467 val suppress_endtheory = ref false; |
475 |
468 |
476 fun clause_cache_endtheory thy = |
469 fun clause_cache_endtheory thy = |
477 if ! suppress_endtheory then NONE |
470 if ! suppress_endtheory then NONE |
482 lambda_free, but then the individual theory caches become much bigger.*) |
475 lambda_free, but then the individual theory caches become much bigger.*) |
483 |
476 |
484 |
477 |
485 (*** meson proof methods ***) |
478 (*** meson proof methods ***) |
486 |
479 |
487 (*Expand all new*definitions of abstraction or Skolem functions in a proof state.*) |
480 (*Expand all new definitions of abstraction or Skolem functions in a proof state.*) |
488 fun is_absko (Const ("==", _) $ Free (a,_) $ u) = String.isPrefix "sko_" a |
481 fun is_absko (Const ("==", _) $ Free (a,_) $ u) = String.isPrefix "sko_" a |
489 | is_absko _ = false; |
482 | is_absko _ = false; |
490 |
483 |
491 fun is_okdef xs (Const ("==", _) $ t $ u) = (*Definition of Free, not in certain terms*) |
484 fun is_okdef xs (Const ("==", _) $ t $ u) = (*Definition of Free, not in certain terms*) |
492 is_Free t andalso not (member (op aconv) xs t) |
485 is_Free t andalso not (member (op aconv) xs t) |
502 val defs = filter (is_absko o Thm.term_of) newhyps |
495 val defs = filter (is_absko o Thm.term_of) newhyps |
503 val remaining_hyps = filter_out (member (op aconv) (map Thm.term_of defs)) |
496 val remaining_hyps = filter_out (member (op aconv) (map Thm.term_of defs)) |
504 (map Thm.term_of hyps) |
497 (map Thm.term_of hyps) |
505 val fixed = term_frees (concl_of st) @ |
498 val fixed = term_frees (concl_of st) @ |
506 foldl (gen_union (op aconv)) [] (map term_frees remaining_hyps) |
499 foldl (gen_union (op aconv)) [] (map term_frees remaining_hyps) |
507 in Output.debug (fn _ => "expand_defs_tac: " ^ Display.string_of_thm st); |
500 in Seq.of_list [LocalDefs.expand (filter (is_okdef fixed o Thm.term_of) defs) st] end; |
508 Output.debug (fn _ => " st0: " ^ Display.string_of_thm st0); |
|
509 Output.debug (fn _ => " defs: " ^ commas (map Display.string_of_cterm defs)); |
|
510 Seq.of_list [LocalDefs.expand (filter (is_okdef fixed o Thm.term_of) defs) st] |
|
511 end; |
|
512 |
501 |
513 |
502 |
514 fun meson_general_tac ths i st0 = |
503 fun meson_general_tac ths i st0 = |
515 let |
504 let |
516 val thy = Thm.theory_of_thm st0 |
505 val thy = Thm.theory_of_thm st0 |
517 val _ = Output.debug (fn () => "Meson called: " ^ cat_lines (map Display.string_of_thm ths)) |
|
518 in (Meson.meson_claset_tac (maps (cnf_axiom thy) ths) HOL_cs i THEN expand_defs_tac st0) st0 end; |
506 in (Meson.meson_claset_tac (maps (cnf_axiom thy) ths) HOL_cs i THEN expand_defs_tac st0) st0 end; |
519 |
507 |
520 val meson_method_setup = Method.add_methods |
508 val meson_method_setup = Method.add_methods |
521 [("meson", Method.thms_args (fn ths => |
509 [("meson", Method.thms_args (fn ths => |
522 Method.SIMPLE_METHOD' (CHANGED_PROP o meson_general_tac ths)), |
510 Method.SIMPLE_METHOD' (CHANGED_PROP o meson_general_tac ths)), |