12 val trace_msg: (unit -> string) -> unit |
12 val trace_msg: (unit -> string) -> unit |
13 val skolem_prefix: string |
13 val skolem_prefix: string |
14 val skolem_infix: string |
14 val skolem_infix: string |
15 val cnf_axiom: theory -> thm -> thm list |
15 val cnf_axiom: theory -> thm -> thm list |
16 val multi_base_blacklist: string list |
16 val multi_base_blacklist: string list |
17 val is_bad_for_atp: thm -> bool |
17 val is_theorem_bad_for_atps: thm -> bool |
18 val type_has_topsort: typ -> bool |
18 val type_has_topsort: typ -> bool |
19 val cnf_rules_pairs: theory -> (string * thm) list -> (thm * (string * int)) list |
19 val cnf_rules_pairs: |
20 val suppress_endtheory: bool Unsynchronized.ref |
20 theory -> (string * thm) list -> (thm * (string * int)) list |
21 (*for emergency use where endtheory causes problems*) |
21 val use_skolem_cache: bool Unsynchronized.ref |
|
22 (* for emergency use where the Skolem cache causes problems *) |
22 val strip_subgoal : thm -> int -> (string * typ) list * term list * term |
23 val strip_subgoal : thm -> int -> (string * typ) list * term list * term |
23 val neg_clausify: thm -> thm list |
24 val neg_clausify: thm -> thm list |
24 val neg_conjecture_clauses: |
25 val neg_conjecture_clauses: |
25 Proof.context -> thm -> int -> thm list list * (string * typ) list |
26 Proof.context -> thm -> int -> thm list list * (string * typ) list |
26 val neg_clausify_tac: Proof.context -> int -> tactic |
27 val neg_clausify_tac: Proof.context -> int -> tactic |
84 if member (op =) lhs_vars v then I else insert (op =) (TFree v) |
85 if member (op =) lhs_vars v then I else insert (op =) (TFree v) |
85 | add_new_TFrees _ = I |
86 | add_new_TFrees _ = I |
86 val rhs_consts = fold_aterms (fn Const c => insert (op =) c | _ => I) rhs [] |
87 val rhs_consts = fold_aterms (fn Const c => insert (op =) c | _ => I) rhs [] |
87 in fold (#2 #> Term.fold_atyps add_new_TFrees) rhs_consts [] end; |
88 in fold (#2 #> Term.fold_atyps add_new_TFrees) rhs_consts [] end; |
88 |
89 |
89 (*Traverse a theorem, declaring Skolem function definitions. String s is the suggested |
90 (* Traverse a theorem, declaring Skolem function definitions. String "s" is the |
90 prefix for the Skolem constant.*) |
91 suggested prefix for the Skolem constants. *) |
91 fun declare_skofuns s th = |
92 fun declare_skolem_funs s th = |
92 let |
93 let |
93 val nref = Unsynchronized.ref 0 (* FIXME ??? *) |
94 val nref = Unsynchronized.ref 0 (* FIXME ??? *) |
94 fun dec_sko (Const (@{const_name Ex}, _) $ (xtp as Abs (s', T, p))) (axs, thy) = |
95 fun dec_sko (Const (@{const_name Ex}, _) $ (xtp as Abs (s', T, p))) (axs, thy) = |
95 (*Existential: declare a Skolem function, then insert into body and continue*) |
96 (*Existential: declare a Skolem function, then insert into body and continue*) |
96 let |
97 let |
119 | dec_sko (@{const Trueprop} $ p) thx = dec_sko p thx |
120 | dec_sko (@{const Trueprop} $ p) thx = dec_sko p thx |
120 | dec_sko t thx = thx (*Do nothing otherwise*) |
121 | dec_sko t thx = thx (*Do nothing otherwise*) |
121 in fn thy => dec_sko (Thm.prop_of th) ([], thy) end; |
122 in fn thy => dec_sko (Thm.prop_of th) ([], thy) end; |
122 |
123 |
123 (*Traverse a theorem, accumulating Skolem function definitions.*) |
124 (*Traverse a theorem, accumulating Skolem function definitions.*) |
124 fun assume_skofuns s th = |
125 fun assume_skolem_funs s th = |
125 let val sko_count = Unsynchronized.ref 0 (* FIXME ??? *) |
126 let val sko_count = Unsynchronized.ref 0 (* FIXME ??? *) |
126 fun dec_sko (Const (@{const_name Ex}, _) $ (xtp as Abs (s', T, p))) defs = |
127 fun dec_sko (Const (@{const_name Ex}, _) $ (xtp as Abs (s', T, p))) defs = |
127 (*Existential: declare a Skolem function, then insert into body and continue*) |
128 (*Existential: declare a Skolem function, then insert into body and continue*) |
128 let val skos = map (#1 o Logic.dest_equals) defs (*existing sko fns*) |
129 let val skos = map (#1 o Logic.dest_equals) defs (*existing sko fns*) |
129 val args = subtract (op =) skos (OldTerm.term_frees xtp) (*the formal parameters*) |
130 val args = subtract (op =) skos (OldTerm.term_frees xtp) (*the formal parameters*) |
300 |> Meson.make_nnf ctxt |> strip_lambdas ~1 |
301 |> Meson.make_nnf ctxt |> strip_lambdas ~1 |
301 in (th3, ctxt) end; |
302 in (th3, ctxt) end; |
302 |
303 |
303 (*Generate Skolem functions for a theorem supplied in nnf*) |
304 (*Generate Skolem functions for a theorem supplied in nnf*) |
304 fun assume_skolem_of_def s th = |
305 fun assume_skolem_of_def s th = |
305 map (skolem_of_def o Thm.assume o (cterm_of (theory_of_thm th))) (assume_skofuns s th); |
306 map (skolem_of_def o Thm.assume o (cterm_of (theory_of_thm th))) |
|
307 (assume_skolem_funs s th) |
306 |
308 |
307 |
309 |
308 (*** Blacklisting (FIXME: duplicated in "Sledgehammer_Fact_Filter"?) ***) |
310 (*** Blacklisting (FIXME: duplicated in "Sledgehammer_Fact_Filter"?) ***) |
309 |
311 |
310 val max_lambda_nesting = 3; |
312 val max_lambda_nesting = 3 |
311 |
313 |
312 fun excessive_lambdas (f$t, k) = excessive_lambdas (f,k) orelse excessive_lambdas (t,k) |
314 fun term_has_too_many_lambdas max (t1 $ t2) = |
313 | excessive_lambdas (Abs(_,_,t), k) = k=0 orelse excessive_lambdas (t,k-1) |
315 exists (term_has_too_many_lambdas max) [t1, t2] |
314 | excessive_lambdas _ = false; |
316 | term_has_too_many_lambdas max (Abs (_, _, t)) = |
315 |
317 max = 0 orelse term_has_too_many_lambdas (max - 1) t |
316 fun is_formula_type T = (T = HOLogic.boolT orelse T = propT); |
318 | term_has_too_many_lambdas _ _ = false |
317 |
319 |
318 (*Don't count nested lambdas at the level of formulas, as they are quantifiers*) |
320 fun is_formula_type T = (T = HOLogic.boolT orelse T = propT) |
319 fun excessive_lambdas_fm Ts (Abs(_,T,t)) = excessive_lambdas_fm (T::Ts) t |
321 |
320 | excessive_lambdas_fm Ts t = |
322 (* Don't count nested lambdas at the level of formulas, since they are |
321 if is_formula_type (fastype_of1 (Ts, t)) |
323 quantifiers. *) |
322 then exists (excessive_lambdas_fm Ts) (#2 (strip_comb t)) |
324 fun formula_has_too_many_lambdas Ts (Abs (_, T, t)) = |
323 else excessive_lambdas (t, max_lambda_nesting); |
325 formula_has_too_many_lambdas (T :: Ts) t |
324 |
326 | formula_has_too_many_lambdas Ts t = |
325 (*The max apply_depth of any metis call in Metis_Examples (on 31-10-2007) was 11.*) |
327 if is_formula_type (fastype_of1 (Ts, t)) then |
326 val max_apply_depth = 15; |
328 exists (formula_has_too_many_lambdas Ts) (#2 (strip_comb t)) |
327 |
329 else |
328 fun apply_depth (f$t) = Int.max (apply_depth f, apply_depth t + 1) |
330 term_has_too_many_lambdas max_lambda_nesting t |
329 | apply_depth (Abs(_,_,t)) = apply_depth t |
331 |
330 | apply_depth _ = 0; |
332 (* The max apply depth of any "metis" call in "Metis_Examples" (on 31-10-2007) |
331 |
333 was 11. *) |
332 fun too_complex t = |
334 val max_apply_depth = 15 |
333 apply_depth t > max_apply_depth orelse |
335 |
334 Meson.too_many_clauses NONE t orelse |
336 fun apply_depth (f $ t) = Int.max (apply_depth f, apply_depth t + 1) |
335 excessive_lambdas_fm [] t; |
337 | apply_depth (Abs (_, _, t)) = apply_depth t |
|
338 | apply_depth _ = 0 |
|
339 |
|
340 fun is_formula_too_complex t = |
|
341 apply_depth t > max_apply_depth orelse Meson.too_many_clauses NONE t orelse |
|
342 formula_has_too_many_lambdas [] t |
336 |
343 |
337 fun is_strange_thm th = |
344 fun is_strange_thm th = |
338 case head_of (concl_of th) of |
345 case head_of (concl_of th) of |
339 Const (a, _) => (a <> @{const_name Trueprop} andalso |
346 Const (a, _) => (a <> @{const_name Trueprop} andalso |
340 a <> @{const_name "=="}) |
347 a <> @{const_name "=="}) |
341 | _ => false; |
348 | _ => false; |
342 |
349 |
343 fun is_bad_for_atp th = |
350 fun is_theorem_bad_for_atps thm = |
344 too_complex (prop_of th) orelse |
351 let val t = prop_of thm in |
345 exists_type type_has_topsort (prop_of th) orelse is_strange_thm th |
352 is_formula_too_complex t orelse exists_type type_has_topsort t orelse |
|
353 is_strange_thm thm |
|
354 end |
346 |
355 |
347 (* FIXME: put other record thms here, or declare as "no_atp" *) |
356 (* FIXME: put other record thms here, or declare as "no_atp" *) |
348 val multi_base_blacklist = |
357 val multi_base_blacklist = |
349 ["defs", "select_defs", "update_defs", "induct", "inducts", "split", "splits", |
358 ["defs", "select_defs", "update_defs", "induct", "inducts", "split", "splits", |
350 "split_asm", "cases", "ext_cases"]; |
359 "split_asm", "cases", "ext_cases"]; |
412 |
421 |
413 local |
422 local |
414 |
423 |
415 fun skolem_def (name, th) thy = |
424 fun skolem_def (name, th) thy = |
416 let val ctxt0 = Variable.global_thm_context th in |
425 let val ctxt0 = Variable.global_thm_context th in |
417 (case try (to_nnf th) ctxt0 of |
426 case try (to_nnf th) ctxt0 of |
418 NONE => (NONE, thy) |
427 NONE => (NONE, thy) |
419 | SOME (nnfth, ctxt1) => |
428 | SOME (nnfth, ctxt1) => |
420 let val (defs, thy') = declare_skofuns (flatten_name name) nnfth thy |
429 let val (defs, thy') = declare_skolem_funs (flatten_name name) nnfth thy |
421 in (SOME (th, ctxt0, ctxt1, nnfth, defs), thy') end) |
430 in (SOME (th, ctxt0, ctxt1, nnfth, defs), thy') end |
422 end; |
431 end; |
423 |
432 |
424 fun skolem_cnfs (th, ctxt0, ctxt1, nnfth, defs) = |
433 fun skolem_cnfs (th, ctxt0, ctxt1, nnfth, defs) = |
425 let |
434 let |
426 val (cnfs, ctxt2) = Meson.make_cnf (map skolem_of_def defs) nnfth ctxt1; |
435 val (cnfs, ctxt2) = Meson.make_cnf (map skolem_of_def defs) nnfth ctxt1; |
440 if Facts.is_concealed facts name orelse already_seen thy name then I |
449 if Facts.is_concealed facts name orelse already_seen thy name then I |
441 else cons (name, ths)); |
450 else cons (name, ths)); |
442 val new_thms = (new_facts, []) |-> fold (fn (name, ths) => |
451 val new_thms = (new_facts, []) |-> fold (fn (name, ths) => |
443 if member (op =) multi_base_blacklist (Long_Name.base_name name) then I |
452 if member (op =) multi_base_blacklist (Long_Name.base_name name) then I |
444 else fold_index (fn (i, th) => |
453 else fold_index (fn (i, th) => |
445 if is_bad_for_atp th orelse is_some (lookup_cache thy th) then I |
454 if is_theorem_bad_for_atps th orelse is_some (lookup_cache thy th) then |
446 else cons (name ^ "_" ^ string_of_int (i + 1), Thm.transfer thy th)) ths); |
455 I |
|
456 else |
|
457 cons (name ^ "_" ^ string_of_int (i + 1), Thm.transfer thy th)) ths) |
447 in |
458 in |
448 if null new_facts then NONE |
459 if null new_facts then NONE |
449 else |
460 else |
450 let |
461 let |
451 val (defs, thy') = thy |
462 val (defs, thy') = thy |