54 end; |
54 end; |
55 |
55 |
56 structure ResAtp = |
56 structure ResAtp = |
57 struct |
57 struct |
58 |
58 |
59 fun timestamp s = Output.debug ("At " ^ Time.toString (Time.now()) ^ ": " ^ s); |
59 fun timestamp s = Output.debug (fn () => ("At " ^ Time.toString (Time.now()) ^ ": " ^ s)); |
60 |
60 |
61 (********************************************************************) |
61 (********************************************************************) |
62 (* some settings for both background automatic ATP calling procedure*) |
62 (* some settings for both background automatic ATP calling procedure*) |
63 (* and also explicit ATP invocation methods *) |
63 (* and also explicit ATP invocation methods *) |
64 (********************************************************************) |
64 (********************************************************************) |
235 let val (f,args) = strip_comb tm |
235 let val (f,args) = strip_comb tm |
236 val (lg',seen') = if f mem seen then (FOL,seen) |
236 val (lg',seen') = if f mem seen then (FOL,seen) |
237 else fn_lg f (FOL,seen) |
237 else fn_lg f (FOL,seen) |
238 in |
238 in |
239 if is_fol_logic lg' then () |
239 if is_fol_logic lg' then () |
240 else Output.debug ("Found a HOL term: " ^ Display.raw_string_of_term f); |
240 else Output.debug (fn () => ("Found a HOL term: " ^ Display.raw_string_of_term f)); |
241 term_lg (args@tms) (lg',seen') |
241 term_lg (args@tms) (lg',seen') |
242 end |
242 end |
243 | term_lg _ (lg,seen) = (lg,seen) |
243 | term_lg _ (lg,seen) = (lg,seen) |
244 |
244 |
245 exception PRED_LG of term; |
245 exception PRED_LG of term; |
259 let val (pred,args) = strip_comb P |
259 let val (pred,args) = strip_comb P |
260 val (lg',seen') = if pred mem seen then (lg,seen) |
260 val (lg',seen') = if pred mem seen then (lg,seen) |
261 else pred_lg pred (lg,seen) |
261 else pred_lg pred (lg,seen) |
262 in |
262 in |
263 if is_fol_logic lg' then () |
263 if is_fol_logic lg' then () |
264 else Output.debug ("Found a HOL predicate: " ^ Display.raw_string_of_term pred); |
264 else Output.debug (fn () => ("Found a HOL predicate: " ^ Display.raw_string_of_term pred)); |
265 term_lg args (lg',seen') |
265 term_lg args (lg',seen') |
266 end; |
266 end; |
267 |
267 |
268 fun lits_lg [] (lg,seen) = (lg,seen) |
268 fun lits_lg [] (lg,seen) = (lg,seen) |
269 | lits_lg (lit::lits) (FOL,seen) = |
269 | lits_lg (lit::lits) (FOL,seen) = |
270 let val (lg,seen') = lit_lg lit (FOL,seen) |
270 let val (lg,seen') = lit_lg lit (FOL,seen) |
271 in |
271 in |
272 if is_fol_logic lg then () |
272 if is_fol_logic lg then () |
273 else Output.debug ("Found a HOL literal: " ^ Display.raw_string_of_term lit); |
273 else Output.debug (fn () => ("Found a HOL literal: " ^ Display.raw_string_of_term lit)); |
274 lits_lg lits (lg,seen') |
274 lits_lg lits (lg,seen') |
275 end |
275 end |
276 | lits_lg lits (lg,seen) = (lg,seen); |
276 | lits_lg lits (lg,seen) = (lg,seen); |
277 |
277 |
278 fun dest_disj_aux (Const("Trueprop",_) $ t) disjs = dest_disj_aux t disjs |
278 fun dest_disj_aux (Const("Trueprop",_) $ t) disjs = dest_disj_aux t disjs |
286 fun logic_of_clauses [] (lg,seen) = (lg,seen) |
286 fun logic_of_clauses [] (lg,seen) = (lg,seen) |
287 | logic_of_clauses (cls::clss) (FOL,seen) = |
287 | logic_of_clauses (cls::clss) (FOL,seen) = |
288 let val (lg,seen') = logic_of_clause cls (FOL,seen) |
288 let val (lg,seen') = logic_of_clause cls (FOL,seen) |
289 val _ = |
289 val _ = |
290 if is_fol_logic lg then () |
290 if is_fol_logic lg then () |
291 else Output.debug ("Found a HOL clause: " ^ Display.raw_string_of_term cls) |
291 else Output.debug (fn () => ("Found a HOL clause: " ^ Display.raw_string_of_term cls)) |
292 in |
292 in |
293 logic_of_clauses clss (lg,seen') |
293 logic_of_clauses clss (lg,seen') |
294 end |
294 end |
295 | logic_of_clauses (cls::clss) (lg,seen) = (lg,seen); |
295 | logic_of_clauses (cls::clss) (lg,seen) = (lg,seen); |
296 |
296 |
504 (*Use a hash table to eliminate duplicates from xs. Argument is a list of |
504 (*Use a hash table to eliminate duplicates from xs. Argument is a list of |
505 (thm * (string * int)) tuples. The theorems are hashed into the table. *) |
505 (thm * (string * int)) tuples. The theorems are hashed into the table. *) |
506 fun make_unique xs = |
506 fun make_unique xs = |
507 let val ht = mk_clause_table 7000 |
507 let val ht = mk_clause_table 7000 |
508 in |
508 in |
509 Output.debug("make_unique gets " ^ Int.toString (length xs) ^ " clauses"); |
509 Output.debug (fn () => ("make_unique gets " ^ Int.toString (length xs) ^ " clauses")); |
510 app (ignore o Polyhash.peekInsert ht) xs; |
510 app (ignore o Polyhash.peekInsert ht) xs; |
511 Polyhash.listItems ht |
511 Polyhash.listItems ht |
512 end; |
512 end; |
513 |
513 |
514 (*Remove existing axiom clauses from the conjecture clauses, as this can dramatically |
514 (*Remove existing axiom clauses from the conjecture clauses, as this can dramatically |
527 white_cls @ (ReduceAxiomsN.relevance_filter thy cls_thms goals); |
527 white_cls @ (ReduceAxiomsN.relevance_filter thy cls_thms goals); |
528 |
528 |
529 fun display_thms [] = () |
529 fun display_thms [] = () |
530 | display_thms ((name,thm)::nthms) = |
530 | display_thms ((name,thm)::nthms) = |
531 let val nthm = name ^ ": " ^ (string_of_thm thm) |
531 let val nthm = name ^ ": " ^ (string_of_thm thm) |
532 in Output.debug nthm; display_thms nthms end; |
532 in Output.debug (fn () => nthm); display_thms nthms end; |
533 |
533 |
534 fun all_valid_thms ctxt = |
534 fun all_valid_thms ctxt = |
535 PureThy.thms_containing (ProofContext.theory_of ctxt) ([], []) @ |
535 PureThy.thms_containing (ProofContext.theory_of ctxt) ([], []) @ |
536 filter (ProofContext.valid_thms ctxt) |
536 filter (ProofContext.valid_thms ctxt) |
537 (FactIndex.find (ProofContext.fact_index_of ctxt) ([], [])); |
537 (FactIndex.find (ProofContext.fact_index_of ctxt) ([], [])); |
569 (* get lemmas from claset, simpset, atpset and extra supplied rules *) |
569 (* get lemmas from claset, simpset, atpset and extra supplied rules *) |
570 fun get_clasimp_atp_lemmas ctxt user_thms = |
570 fun get_clasimp_atp_lemmas ctxt user_thms = |
571 let val included_thms = |
571 let val included_thms = |
572 if !include_all |
572 if !include_all |
573 then (tap (fn ths => Output.debug |
573 then (tap (fn ths => Output.debug |
574 ("Including all " ^ Int.toString (length ths) ^ " theorems")) |
574 (fn () => ("Including all " ^ Int.toString (length ths) ^ " theorems"))) |
575 (name_thm_pairs ctxt)) |
575 (name_thm_pairs ctxt)) |
576 else |
576 else |
577 let val claset_thms = |
577 let val claset_thms = |
578 if !include_claset then ResAxioms.claset_rules_of ctxt |
578 if !include_claset then ResAxioms.claset_rules_of ctxt |
579 else [] |
579 else [] |
581 if !include_simpset then ResAxioms.simpset_rules_of ctxt |
581 if !include_simpset then ResAxioms.simpset_rules_of ctxt |
582 else [] |
582 else [] |
583 val atpset_thms = |
583 val atpset_thms = |
584 if !include_atpset then ResAxioms.atpset_rules_of ctxt |
584 if !include_atpset then ResAxioms.atpset_rules_of ctxt |
585 else [] |
585 else [] |
586 val _ = if !Output.show_debug_msgs |
586 val _ = if !Output.debugging |
587 then (Output.debug "ATP theorems: "; display_thms atpset_thms) |
587 then (Output.debug (fn () => "ATP theorems: "); display_thms atpset_thms) |
588 else () |
588 else () |
589 in claset_thms @ simpset_thms @ atpset_thms end |
589 in claset_thms @ simpset_thms @ atpset_thms end |
590 val user_rules = filter check_named |
590 val user_rules = filter check_named |
591 (map (ResAxioms.pairname) |
591 (map (ResAxioms.pairname) |
592 (if null user_thms then !whitelist else user_thms)) |
592 (if null user_thms then !whitelist else user_thms)) |
598 fun blacklist_filter ths = |
598 fun blacklist_filter ths = |
599 if !run_blacklist_filter then |
599 if !run_blacklist_filter then |
600 let val banned = make_banned_test (map #1 ths) |
600 let val banned = make_banned_test (map #1 ths) |
601 fun ok (a,_) = not (banned a) |
601 fun ok (a,_) = not (banned a) |
602 val (good,bad) = List.partition ok ths |
602 val (good,bad) = List.partition ok ths |
603 in if !Output.show_debug_msgs then |
603 in |
604 (Output.debug("blacklist filter gets " ^ Int.toString (length ths) ^ " theorems"); |
604 Output.debug (fn () => "blacklist filter gets " ^ Int.toString (length ths) ^ " theorems"); |
605 Output.debug("filtered: " ^ space_implode ", " (map #1 bad)); |
605 Output.debug (fn () => "filtered: " ^ space_implode ", " (map #1 bad)); |
606 Output.debug("...and returns " ^ Int.toString (length good))) |
606 Output.debug (fn () => "...and returns " ^ Int.toString (length good)); |
607 else (); |
607 good |
608 good |
|
609 end |
608 end |
610 else ths; |
609 else ths; |
611 |
610 |
612 (***************************************************************) |
611 (***************************************************************) |
613 (* Type Classes Present in the Axiom or Conjecture Clauses *) |
612 (* Type Classes Present in the Axiom or Conjecture Clauses *) |
749 val writer = if dfg then dfg_writer else tptp_writer |
748 val writer = if dfg then dfg_writer else tptp_writer |
750 and file = atp_input_file() |
749 and file = atp_input_file() |
751 and user_lemmas_names = map #1 user_rules |
750 and user_lemmas_names = map #1 user_rules |
752 in |
751 in |
753 writer logic goal_cls file (axclauses,classrel_clauses,arity_clauses) user_lemmas_names; |
752 writer logic goal_cls file (axclauses,classrel_clauses,arity_clauses) user_lemmas_names; |
754 Output.debug ("Writing to " ^ file); |
753 Output.debug (fn () => "Writing to " ^ file); |
755 file |
754 file |
756 end; |
755 end; |
757 |
756 |
758 |
757 |
759 (**** remove tmp files ****) |
758 (**** remove tmp files ****) |
760 fun cond_rm_tmp file = |
759 fun cond_rm_tmp file = |
761 if !Output.show_debug_msgs orelse !destdir <> "" then Output.debug "ATP input kept..." |
760 if !Output.debugging orelse !destdir <> "" |
|
761 then Output.debug (fn () => "ATP input kept...") |
762 else OS.FileSys.remove file; |
762 else OS.FileSys.remove file; |
763 |
763 |
764 |
764 |
765 (****** setup ATPs as Isabelle methods ******) |
765 (****** setup ATPs as Isabelle methods ******) |
766 |
766 |
783 | make_atp_list (sg_term::xs) n = |
783 | make_atp_list (sg_term::xs) n = |
784 let |
784 let |
785 val probfile = prob_pathname n |
785 val probfile = prob_pathname n |
786 val time = Int.toString (!time_limit) |
786 val time = Int.toString (!time_limit) |
787 in |
787 in |
788 Output.debug ("problem file in watcher_call_provers is " ^ probfile); |
788 Output.debug (fn () => "problem file in watcher_call_provers is " ^ probfile); |
789 (*options are separated by Watcher.setting_sep, currently #"%"*) |
789 (*options are separated by Watcher.setting_sep, currently #"%"*) |
790 if !prover = "spass" |
790 if !prover = "spass" |
791 then |
791 then |
792 let val spass = helper_path "SPASS_HOME" "SPASS" |
792 let val spass = helper_path "SPASS_HOME" "SPASS" |
793 val sopts = |
793 val sopts = |
814 end |
814 end |
815 |
815 |
816 val atp_list = make_atp_list sg_terms 1 |
816 val atp_list = make_atp_list sg_terms 1 |
817 in |
817 in |
818 Watcher.callResProvers(childout,atp_list); |
818 Watcher.callResProvers(childout,atp_list); |
819 Output.debug "Sent commands to watcher!" |
819 Output.debug (fn () => "Sent commands to watcher!") |
820 end |
820 end |
821 |
821 |
822 fun trace_vector fname = |
822 fun trace_vector fname = |
823 let val path = File.explode_platform_path fname |
823 let val path = File.explode_platform_path fname |
824 in Vector.app (File.append path o (fn s => s ^ "\n")) end; |
824 in Vector.app (File.append path o (fn s => s ^ "\n")) end; |
827 and allows the suppression of the suffix "_1" in problem-generation mode. |
827 and allows the suppression of the suffix "_1" in problem-generation mode. |
828 FIXME: does not cope with &&, and it isn't easy because one could have multiple |
828 FIXME: does not cope with &&, and it isn't easy because one could have multiple |
829 subgoals, each involving &&.*) |
829 subgoals, each involving &&.*) |
830 fun write_problem_files probfile (ctxt,th) = |
830 fun write_problem_files probfile (ctxt,th) = |
831 let val goals = Thm.prems_of th |
831 let val goals = Thm.prems_of th |
832 val _ = Output.debug ("number of subgoals = " ^ Int.toString (length goals)) |
832 val _ = Output.debug (fn () => "number of subgoals = " ^ Int.toString (length goals)) |
833 val thy = ProofContext.theory_of ctxt |
833 val thy = ProofContext.theory_of ctxt |
834 fun get_neg_subgoals [] _ = [] |
834 fun get_neg_subgoals [] _ = [] |
835 | get_neg_subgoals (gl::gls) n = #1 (ResAxioms.neg_conjecture_clauses th n) :: |
835 | get_neg_subgoals (gl::gls) n = #1 (ResAxioms.neg_conjecture_clauses th n) :: |
836 get_neg_subgoals gls (n+1) |
836 get_neg_subgoals gls (n+1) |
837 val goal_cls = get_neg_subgoals goals 1 |
837 val goal_cls = get_neg_subgoals goals 1 |
842 val (included_thms,white_thms) = get_clasimp_atp_lemmas ctxt [] |
842 val (included_thms,white_thms) = get_clasimp_atp_lemmas ctxt [] |
843 val included_cls = included_thms |> blacklist_filter |
843 val included_cls = included_thms |> blacklist_filter |
844 |> ResAxioms.cnf_rules_pairs |> make_unique |
844 |> ResAxioms.cnf_rules_pairs |> make_unique |
845 |> restrict_to_logic logic |
845 |> restrict_to_logic logic |
846 |> remove_unwanted_clauses |
846 |> remove_unwanted_clauses |
847 val _ = Output.debug ("included clauses = " ^ Int.toString(length included_cls)) |
847 val _ = Output.debug (fn () => "included clauses = " ^ Int.toString(length included_cls)) |
848 val white_cls = ResAxioms.cnf_rules_pairs white_thms |
848 val white_cls = ResAxioms.cnf_rules_pairs white_thms |
849 (*clauses relevant to goal gl*) |
849 (*clauses relevant to goal gl*) |
850 val axcls_list = map (fn ngcls => get_relevant_clauses thy included_cls white_cls (map prop_of ngcls)) goal_cls |
850 val axcls_list = map (fn ngcls => get_relevant_clauses thy included_cls white_cls (map prop_of ngcls)) goal_cls |
851 val _ = app (fn axcls => Output.debug ("filtered clauses = " ^ Int.toString(length axcls))) |
851 val _ = app (fn axcls => Output.debug (fn () => "filtered clauses = " ^ Int.toString(length axcls))) |
852 axcls_list |
852 axcls_list |
853 val writer = if !prover = "spass" then dfg_writer else tptp_writer |
853 val writer = if !prover = "spass" then dfg_writer else tptp_writer |
854 fun write_all [] [] _ = [] |
854 fun write_all [] [] _ = [] |
855 | write_all (ccls::ccls_list) (axcls::axcls_list) k = |
855 | write_all (ccls::ccls_list) (axcls::axcls_list) k = |
856 let val fname = probfile k |
856 let val fname = probfile k |
861 val subs = tfree_classes_of_terms ccltms |
861 val subs = tfree_classes_of_terms ccltms |
862 and supers = tvar_classes_of_terms axtms |
862 and supers = tvar_classes_of_terms axtms |
863 and tycons = type_consts_of_terms thy (ccltms@axtms) |
863 and tycons = type_consts_of_terms thy (ccltms@axtms) |
864 (*TFrees in conjecture clauses; TVars in axiom clauses*) |
864 (*TFrees in conjecture clauses; TVars in axiom clauses*) |
865 val classrel_clauses = ResClause.make_classrel_clauses thy subs supers |
865 val classrel_clauses = ResClause.make_classrel_clauses thy subs supers |
866 val _ = Output.debug ("classrel clauses = " ^ Int.toString (length classrel_clauses)) |
866 val _ = Output.debug (fn () => "classrel clauses = " ^ Int.toString (length classrel_clauses)) |
867 val arity_clauses = ResClause.arity_clause_thy thy tycons supers |
867 val arity_clauses = ResClause.arity_clause_thy thy tycons supers |
868 val _ = Output.debug ("arity clauses = " ^ Int.toString (length arity_clauses)) |
868 val _ = Output.debug (fn () => "arity clauses = " ^ Int.toString (length arity_clauses)) |
869 val clnames = writer logic ccls fname (axcls,classrel_clauses,arity_clauses) [] |
869 val clnames = writer logic ccls fname (axcls,classrel_clauses,arity_clauses) [] |
870 val thm_names = Vector.fromList clnames |
870 val thm_names = Vector.fromList clnames |
871 val _ = if !Output.show_debug_msgs |
871 val _ = if !Output.debugging |
872 then trace_vector (fname ^ "_thm_names") thm_names else () |
872 then trace_vector (fname ^ "_thm_names") thm_names else () |
873 in (thm_names,fname) :: write_all ccls_list axcls_list (k+1) end |
873 in (thm_names,fname) :: write_all ccls_list axcls_list (k+1) end |
874 val (thm_names_list, filenames) = ListPair.unzip (write_all goal_cls axcls_list 1) |
874 val (thm_names_list, filenames) = ListPair.unzip (write_all goal_cls axcls_list 1) |
875 in |
875 in |
876 (filenames, thm_names_list) |
876 (filenames, thm_names_list) |
881 |
881 |
882 fun kill_last_watcher () = |
882 fun kill_last_watcher () = |
883 (case !last_watcher_pid of |
883 (case !last_watcher_pid of |
884 NONE => () |
884 NONE => () |
885 | SOME (_, _, pid, files) => |
885 | SOME (_, _, pid, files) => |
886 (Output.debug ("Killing old watcher, pid = " ^ string_of_pid pid); |
886 (Output.debug (fn () => "Killing old watcher, pid = " ^ string_of_pid pid); |
887 Watcher.killWatcher pid; |
887 Watcher.killWatcher pid; |
888 ignore (map (try cond_rm_tmp) files))) |
888 ignore (map (try cond_rm_tmp) files))) |
889 handle OS.SysErr _ => Output.debug "Attempt to kill watcher failed"; |
889 handle OS.SysErr _ => Output.debug (fn () => "Attempt to kill watcher failed"); |
890 |
890 |
891 (*writes out the current problems and calls ATPs*) |
891 (*writes out the current problems and calls ATPs*) |
892 fun isar_atp (ctxt, th) = |
892 fun isar_atp (ctxt, th) = |
893 if Thm.no_prems th then () |
893 if Thm.no_prems th then () |
894 else |
894 else |
896 val _ = kill_last_watcher() |
896 val _ = kill_last_watcher() |
897 val (files,thm_names_list) = write_problem_files prob_pathname (ctxt,th) |
897 val (files,thm_names_list) = write_problem_files prob_pathname (ctxt,th) |
898 val (childin, childout, pid) = Watcher.createWatcher (ctxt, th, thm_names_list) |
898 val (childin, childout, pid) = Watcher.createWatcher (ctxt, th, thm_names_list) |
899 in |
899 in |
900 last_watcher_pid := SOME (childin, childout, pid, files); |
900 last_watcher_pid := SOME (childin, childout, pid, files); |
901 Output.debug ("problem files: " ^ space_implode ", " files); |
901 Output.debug (fn () => "problem files: " ^ space_implode ", " files); |
902 Output.debug ("pid: " ^ string_of_pid pid); |
902 Output.debug (fn () => "pid: " ^ string_of_pid pid); |
903 watcher_call_provers (sign_of_thm th) (Thm.prems_of th) (childin, childout, pid) |
903 watcher_call_provers (sign_of_thm th) (Thm.prems_of th) (childin, childout, pid) |
904 end; |
904 end; |
905 |
905 |
906 (*For ML scripts, and primarily, for debugging*) |
906 (*For ML scripts, and primarily, for debugging*) |
907 fun callatp () = |
907 fun callatp () = |
921 (** the Isar toplevel hook **) |
921 (** the Isar toplevel hook **) |
922 |
922 |
923 fun invoke_atp_ml (ctxt, goal) = |
923 fun invoke_atp_ml (ctxt, goal) = |
924 let val thy = ProofContext.theory_of ctxt; |
924 let val thy = ProofContext.theory_of ctxt; |
925 in |
925 in |
926 Output.debug ("subgoals in isar_atp:\n" ^ |
926 Output.debug (fn () => "subgoals in isar_atp:\n" ^ |
927 Pretty.string_of (ProofContext.pretty_term ctxt |
927 Pretty.string_of (ProofContext.pretty_term ctxt |
928 (Logic.mk_conjunction_list (Thm.prems_of goal)))); |
928 (Logic.mk_conjunction_list (Thm.prems_of goal)))); |
929 Output.debug ("current theory: " ^ Context.theory_name thy); |
929 Output.debug (fn () => "current theory: " ^ Context.theory_name thy); |
930 inc hook_count; |
930 inc hook_count; |
931 Output.debug ("in hook for time: " ^ Int.toString (!hook_count)); |
931 Output.debug (fn () => "in hook for time: " ^ Int.toString (!hook_count)); |
932 ResClause.init thy; |
932 ResClause.init thy; |
933 ResHolClause.init thy; |
933 ResHolClause.init thy; |
934 if !time_limit > 0 then isar_atp (ctxt, goal) |
934 if !time_limit > 0 then isar_atp (ctxt, goal) |
935 else (warning "Writing problem file only"; isar_atp_writeonly (ctxt, goal)) |
935 else (warning "Writing problem file only"; isar_atp_writeonly (ctxt, goal)) |
936 end; |
936 end; |