src/HOL/Tools/res_atp.ML
changeset 21588 cd0dc678a205
parent 21563 b4718f2c15f0
child 21690 552d20ff9a95
equal deleted inserted replaced
21587:a3561bfe0ada 21588:cd0dc678a205
    13   val destdir: string ref
    13   val destdir: string ref
    14   val helper_path: string -> string -> string
    14   val helper_path: string -> string -> string
    15   val problem_name: string ref
    15   val problem_name: string ref
    16   val time_limit: int ref
    16   val time_limit: int ref
    17   val set_prover: string -> unit
    17   val set_prover: string -> unit
    18    
    18 
    19   datatype mode = Auto | Fol | Hol
    19   datatype mode = Auto | Fol | Hol
    20   val linkup_logic_mode : mode ref
    20   val linkup_logic_mode : mode ref
    21   val write_subgoal_file: bool -> mode -> Proof.context -> thm list -> thm list -> int -> string
    21   val write_subgoal_file: bool -> mode -> Proof.context -> thm list -> thm list -> int -> string
    22   val vampire_time: int ref
    22   val vampire_time: int ref
    23   val eprover_time: int ref
    23   val eprover_time: int ref
    63 (* some settings for both background automatic ATP calling procedure*)
    63 (* some settings for both background automatic ATP calling procedure*)
    64 (* and also explicit ATP invocation methods                         *)
    64 (* and also explicit ATP invocation methods                         *)
    65 (********************************************************************)
    65 (********************************************************************)
    66 
    66 
    67 (*** background linkup ***)
    67 (*** background linkup ***)
    68 val call_atp = ref false; 
    68 val call_atp = ref false;
    69 val hook_count = ref 0;
    69 val hook_count = ref 0;
    70 val time_limit = ref 60;
    70 val time_limit = ref 60;
    71 val prover = ref "";   
    71 val prover = ref "";
    72 
    72 
    73 fun set_prover atp = 
    73 fun set_prover atp =
    74   case String.map Char.toLower atp of
    74   case String.map Char.toLower atp of
    75       "e" => 
    75       "e" =>
    76           (ReduceAxiomsN.max_new := 100;
    76           (ReduceAxiomsN.max_new := 100;
    77            ReduceAxiomsN.theory_const := false;
    77            ReduceAxiomsN.theory_const := false;
    78            prover := "E")
    78            prover := "E")
    79     | "spass" => 
    79     | "spass" =>
    80           (ReduceAxiomsN.max_new := 40;
    80           (ReduceAxiomsN.max_new := 40;
    81            ReduceAxiomsN.theory_const := true;
    81            ReduceAxiomsN.theory_const := true;
    82            prover := "spass")
    82            prover := "spass")
    83     | "vampire" => 
    83     | "vampire" =>
    84           (ReduceAxiomsN.max_new := 60;
    84           (ReduceAxiomsN.max_new := 60;
    85            ReduceAxiomsN.theory_const := false;
    85            ReduceAxiomsN.theory_const := false;
    86            prover := "vampire")
    86            prover := "vampire")
    87     | _ => error ("No such prover: " ^ atp);
    87     | _ => error ("No such prover: " ^ atp);
    88 
    88 
    92       ref ["-Auto=0","-FullRed=0","-IORe","-IOFc","-RTaut","-RFSub","-RBSub"];
    92       ref ["-Auto=0","-FullRed=0","-IORe","-IOFc","-RTaut","-RFSub","-RBSub"];
    93 val destdir = ref "";   (*Empty means write files to /tmp*)
    93 val destdir = ref "";   (*Empty means write files to /tmp*)
    94 val problem_name = ref "prob";
    94 val problem_name = ref "prob";
    95 
    95 
    96 (*Return the path to a "helper" like SPASS or tptp2X, first checking that
    96 (*Return the path to a "helper" like SPASS or tptp2X, first checking that
    97   it exists.  FIXME: modify to use Path primitives and move to some central place.*)  
    97   it exists.  FIXME: modify to use Path primitives and move to some central place.*)
    98 fun helper_path evar base =
    98 fun helper_path evar base =
    99   case getenv evar of
    99   case getenv evar of
   100       "" => error  ("Isabelle environment variable " ^ evar ^ " not defined")
   100       "" => error  ("Isabelle environment variable " ^ evar ^ " not defined")
   101     | home => 
   101     | home =>
   102         let val path = home ^ "/" ^ base
   102         let val path = home ^ "/" ^ base
   103         in  if File.exists (File.unpack_platform_path path) then path 
   103         in  if File.exists (File.unpack_platform_path path) then path
   104 	    else error ("Could not find the file " ^ path)
   104             else error ("Could not find the file " ^ path)
   105 	end;  
   105         end;
   106 
   106 
   107 fun probfile_nosuffix _ = 
   107 fun probfile_nosuffix _ =
   108   if !destdir = "" then File.platform_path (File.tmp_path (Path.basic (!problem_name)))
   108   if !destdir = "" then File.platform_path (File.tmp_path (Path.basic (!problem_name)))
   109   else if File.exists (File.unpack_platform_path (!destdir))
   109   else if File.exists (File.unpack_platform_path (!destdir))
   110   then !destdir ^ "/" ^ !problem_name
   110   then !destdir ^ "/" ^ !problem_name
   111   else error ("No such directory: " ^ !destdir);
   111   else error ("No such directory: " ^ !destdir);
   112 
   112 
   116 (*** ATP methods ***)
   116 (*** ATP methods ***)
   117 val vampire_time = ref 60;
   117 val vampire_time = ref 60;
   118 val eprover_time = ref 60;
   118 val eprover_time = ref 60;
   119 val spass_time = ref 60;
   119 val spass_time = ref 60;
   120 
   120 
   121 fun run_vampire time =  
   121 fun run_vampire time =
   122     if (time >0) then vampire_time:= time
   122     if (time >0) then vampire_time:= time
   123     else vampire_time:=60;
   123     else vampire_time:=60;
   124 
   124 
   125 fun run_eprover time = 
   125 fun run_eprover time =
   126     if (time > 0) then eprover_time:= time
   126     if (time > 0) then eprover_time:= time
   127     else eprover_time:=60;
   127     else eprover_time:=60;
   128 
   128 
   129 fun run_spass time = 
   129 fun run_spass time =
   130     if (time > 0) then spass_time:=time
   130     if (time > 0) then spass_time:=time
   131     else spass_time:=60;
   131     else spass_time:=60;
   132 
   132 
   133 
   133 
   134 fun vampireLimit () = !vampire_time;
   134 fun vampireLimit () = !vampire_time;
   139 val hol_full_types = ResHolClause.full_types;
   139 val hol_full_types = ResHolClause.full_types;
   140 val hol_partial_types = ResHolClause.partial_types;
   140 val hol_partial_types = ResHolClause.partial_types;
   141 val hol_const_types_only = ResHolClause.const_types_only;
   141 val hol_const_types_only = ResHolClause.const_types_only;
   142 val hol_no_types = ResHolClause.no_types;
   142 val hol_no_types = ResHolClause.no_types;
   143 fun hol_typ_level () = ResHolClause.find_typ_level ();
   143 fun hol_typ_level () = ResHolClause.find_typ_level ();
   144 fun is_typed_hol () = 
   144 fun is_typed_hol () =
   145     let val tp_level = hol_typ_level()
   145     let val tp_level = hol_typ_level()
   146     in
   146     in
   147 	not (tp_level = ResHolClause.T_NONE)
   147         not (tp_level = ResHolClause.T_NONE)
   148     end;
   148     end;
   149 
   149 
   150 fun atp_input_file () =
   150 fun atp_input_file () =
   151     let val file = !problem_name 
   151     let val file = !problem_name
   152     in
   152     in
   153 	if !destdir = "" then File.platform_path (File.tmp_path (Path.basic file))
   153         if !destdir = "" then File.platform_path (File.tmp_path (Path.basic file))
   154 	else if File.exists (File.unpack_platform_path (!destdir))
   154         else if File.exists (File.unpack_platform_path (!destdir))
   155 	then !destdir ^ "/" ^ file
   155         then !destdir ^ "/" ^ file
   156 	else error ("No such directory: " ^ !destdir)
   156         else error ("No such directory: " ^ !destdir)
   157     end;
   157     end;
   158 
   158 
   159 val include_all = ref true;
   159 val include_all = ref true;
   160 val include_simpset = ref false;
   160 val include_simpset = ref false;
   161 val include_claset = ref false; 
   161 val include_claset = ref false;
   162 val include_atpset = ref true;
   162 val include_atpset = ref true;
   163 
   163 
   164 (*Tests show that follow_defs gives VERY poor results with "include_all"*)
   164 (*Tests show that follow_defs gives VERY poor results with "include_all"*)
   165 fun add_all() = (include_all:=true; ReduceAxiomsN.follow_defs := false);
   165 fun add_all() = (include_all:=true; ReduceAxiomsN.follow_defs := false);
   166 fun rm_all() = include_all:=false;
   166 fun rm_all() = include_all:=false;
   198 
   198 
   199 (*HOLCS will not occur here*)
   199 (*HOLCS will not occur here*)
   200 fun upgrade_lg HOLC _ = HOLC
   200 fun upgrade_lg HOLC _ = HOLC
   201   | upgrade_lg HOL HOLC = HOLC
   201   | upgrade_lg HOL HOLC = HOLC
   202   | upgrade_lg HOL _ = HOL
   202   | upgrade_lg HOL _ = HOL
   203   | upgrade_lg FOL lg = lg; 
   203   | upgrade_lg FOL lg = lg;
   204 
   204 
   205 (* check types *)
   205 (* check types *)
   206 fun has_bool_hfn (Type("bool",_)) = true
   206 fun has_bool_hfn (Type("bool",_)) = true
   207   | has_bool_hfn (Type("fun",_)) = true
   207   | has_bool_hfn (Type("fun",_)) = true
   208   | has_bool_hfn (Type(_, Ts)) = exists has_bool_hfn Ts
   208   | has_bool_hfn (Type(_, Ts)) = exists has_bool_hfn Ts
   209   | has_bool_hfn _ = false;
   209   | has_bool_hfn _ = false;
   210 
   210 
   211 fun is_hol_fn tp =
   211 fun is_hol_fn tp =
   212     let val (targs,tr) = strip_type tp
   212     let val (targs,tr) = strip_type tp
   213     in
   213     in
   214 	exists (has_bool_hfn) (tr::targs)
   214         exists (has_bool_hfn) (tr::targs)
   215     end;
   215     end;
   216 
   216 
   217 fun is_hol_pred tp =
   217 fun is_hol_pred tp =
   218     let val (targs,tr) = strip_type tp
   218     let val (targs,tr) = strip_type tp
   219     in
   219     in
   220 	exists (has_bool_hfn) targs
   220         exists (has_bool_hfn) targs
   221     end;
   221     end;
   222 
   222 
   223 exception FN_LG of term;
   223 exception FN_LG of term;
   224 
   224 
   225 fun fn_lg (t as Const(f,tp)) (lg,seen) = 
   225 fun fn_lg (t as Const(f,tp)) (lg,seen) =
   226     if is_hol_fn tp then (upgrade_lg HOL lg, insert (op =) t seen) else (lg, insert (op =) t seen) 
   226     if is_hol_fn tp then (upgrade_lg HOL lg, insert (op =) t seen) else (lg, insert (op =) t seen)
   227   | fn_lg (t as Free(f,tp)) (lg,seen) = 
   227   | fn_lg (t as Free(f,tp)) (lg,seen) =
   228     if is_hol_fn tp then (upgrade_lg HOL lg, insert (op =) t seen) else (lg, insert (op =) t seen) 
   228     if is_hol_fn tp then (upgrade_lg HOL lg, insert (op =) t seen) else (lg, insert (op =) t seen)
   229   | fn_lg (t as Var(f,tp)) (lg,seen) =
   229   | fn_lg (t as Var(f,tp)) (lg,seen) =
   230     if is_hol_fn tp then (upgrade_lg HOL lg,insert (op =) t seen) else (lg,insert (op =) t seen)
   230     if is_hol_fn tp then (upgrade_lg HOL lg,insert (op =) t seen) else (lg,insert (op =) t seen)
   231   | fn_lg (t as Abs(_,_,_)) (lg,seen) = (upgrade_lg HOLC lg,insert (op =) t seen)
   231   | fn_lg (t as Abs(_,_,_)) (lg,seen) = (upgrade_lg HOLC lg,insert (op =) t seen)
   232   | fn_lg f _ = raise FN_LG(f); 
   232   | fn_lg f _ = raise FN_LG(f);
   233 
   233 
   234 
   234 
   235 fun term_lg [] (lg,seen) = (lg,seen)
   235 fun term_lg [] (lg,seen) = (lg,seen)
   236   | term_lg (tm::tms) (FOL,seen) =
   236   | term_lg (tm::tms) (FOL,seen) =
   237       let val (f,args) = strip_comb tm
   237       let val (f,args) = strip_comb tm
   238 	  val (lg',seen') = if f mem seen then (FOL,seen) 
   238           val (lg',seen') = if f mem seen then (FOL,seen)
   239 			    else fn_lg f (FOL,seen)
   239                             else fn_lg f (FOL,seen)
   240       in
   240       in
   241 	if is_fol_logic lg' then ()
   241         if is_fol_logic lg' then ()
   242         else Output.debug ("Found a HOL term: " ^ Display.raw_string_of_term f);
   242         else Output.debug ("Found a HOL term: " ^ Display.raw_string_of_term f);
   243         term_lg (args@tms) (lg',seen')
   243         term_lg (args@tms) (lg',seen')
   244       end
   244       end
   245   | term_lg _ (lg,seen) = (lg,seen)
   245   | term_lg _ (lg,seen) = (lg,seen)
   246 
   246 
   247 exception PRED_LG of term;
   247 exception PRED_LG of term;
   248 
   248 
   249 fun pred_lg (t as Const(P,tp)) (lg,seen)= 
   249 fun pred_lg (t as Const(P,tp)) (lg,seen)=
   250       if is_hol_pred tp then (upgrade_lg HOL lg, insert (op =) t seen) 
   250       if is_hol_pred tp then (upgrade_lg HOL lg, insert (op =) t seen)
   251       else (lg,insert (op =) t seen) 
   251       else (lg,insert (op =) t seen)
   252   | pred_lg (t as Free(P,tp)) (lg,seen) =
   252   | pred_lg (t as Free(P,tp)) (lg,seen) =
   253       if is_hol_pred tp then (upgrade_lg HOL lg, insert (op =) t seen) 
   253       if is_hol_pred tp then (upgrade_lg HOL lg, insert (op =) t seen)
   254       else (lg,insert (op =) t seen)
   254       else (lg,insert (op =) t seen)
   255   | pred_lg (t as Var(_,_)) (lg,seen) = (upgrade_lg HOL lg, insert (op =) t seen)
   255   | pred_lg (t as Var(_,_)) (lg,seen) = (upgrade_lg HOL lg, insert (op =) t seen)
   256   | pred_lg P _ = raise PRED_LG(P);
   256   | pred_lg P _ = raise PRED_LG(P);
   257 
   257 
   258 
   258 
   259 fun lit_lg (Const("Not",_) $ P) (lg,seen) = lit_lg P (lg,seen)
   259 fun lit_lg (Const("Not",_) $ P) (lg,seen) = lit_lg P (lg,seen)
   260   | lit_lg P (lg,seen) =
   260   | lit_lg P (lg,seen) =
   261       let val (pred,args) = strip_comb P
   261       let val (pred,args) = strip_comb P
   262 	  val (lg',seen') = if pred mem seen then (lg,seen) 
   262           val (lg',seen') = if pred mem seen then (lg,seen)
   263 			    else pred_lg pred (lg,seen)
   263                             else pred_lg pred (lg,seen)
   264       in
   264       in
   265 	if is_fol_logic lg' then ()
   265         if is_fol_logic lg' then ()
   266 	else Output.debug ("Found a HOL predicate: " ^ Display.raw_string_of_term pred);
   266         else Output.debug ("Found a HOL predicate: " ^ Display.raw_string_of_term pred);
   267 	term_lg args (lg',seen')
   267         term_lg args (lg',seen')
   268       end;
   268       end;
   269 
   269 
   270 fun lits_lg [] (lg,seen) = (lg,seen)
   270 fun lits_lg [] (lg,seen) = (lg,seen)
   271   | lits_lg (lit::lits) (FOL,seen) =
   271   | lits_lg (lit::lits) (FOL,seen) =
   272       let val (lg,seen') = lit_lg lit (FOL,seen)
   272       let val (lg,seen') = lit_lg lit (FOL,seen)
   273       in
   273       in
   274 	if is_fol_logic lg then ()
   274         if is_fol_logic lg then ()
   275 	else Output.debug ("Found a HOL literal: " ^ Display.raw_string_of_term lit);
   275         else Output.debug ("Found a HOL literal: " ^ Display.raw_string_of_term lit);
   276 	lits_lg lits (lg,seen')
   276         lits_lg lits (lg,seen')
   277       end
   277       end
   278   | lits_lg lits (lg,seen) = (lg,seen);
   278   | lits_lg lits (lg,seen) = (lg,seen);
   279 
   279 
   280 fun dest_disj_aux (Const("Trueprop",_) $ t) disjs = dest_disj_aux t disjs
   280 fun dest_disj_aux (Const("Trueprop",_) $ t) disjs = dest_disj_aux t disjs
   281   | dest_disj_aux (Const ("op |", _) $ t $ t') disjs = dest_disj_aux t (dest_disj_aux t' disjs)
   281   | dest_disj_aux (Const ("op |", _) $ t $ t') disjs = dest_disj_aux t (dest_disj_aux t' disjs)
   286 fun logic_of_clause tm = lits_lg (dest_disj tm);
   286 fun logic_of_clause tm = lits_lg (dest_disj tm);
   287 
   287 
   288 fun logic_of_clauses [] (lg,seen) = (lg,seen)
   288 fun logic_of_clauses [] (lg,seen) = (lg,seen)
   289   | logic_of_clauses (cls::clss) (FOL,seen) =
   289   | logic_of_clauses (cls::clss) (FOL,seen) =
   290     let val (lg,seen') = logic_of_clause cls (FOL,seen)
   290     let val (lg,seen') = logic_of_clause cls (FOL,seen)
   291 	val _ =
   291         val _ =
   292           if is_fol_logic lg then ()
   292           if is_fol_logic lg then ()
   293           else Output.debug ("Found a HOL clause: " ^ Display.raw_string_of_term cls)
   293           else Output.debug ("Found a HOL clause: " ^ Display.raw_string_of_term cls)
   294     in
   294     in
   295 	logic_of_clauses clss (lg,seen')
   295         logic_of_clauses clss (lg,seen')
   296     end
   296     end
   297   | logic_of_clauses (cls::clss) (lg,seen) = (lg,seen);
   297   | logic_of_clauses (cls::clss) (lg,seen) = (lg,seen);
   298 
   298 
   299 fun problem_logic_goals_aux [] (lg,seen) = lg
   299 fun problem_logic_goals_aux [] (lg,seen) = lg
   300   | problem_logic_goals_aux (subgoal::subgoals) (lg,seen) = 
   300   | problem_logic_goals_aux (subgoal::subgoals) (lg,seen) =
   301     problem_logic_goals_aux subgoals (logic_of_clauses subgoal (lg,seen));
   301     problem_logic_goals_aux subgoals (logic_of_clauses subgoal (lg,seen));
   302     
   302 
   303 fun problem_logic_goals subgoals = problem_logic_goals_aux subgoals (FOL,[]);
   303 fun problem_logic_goals subgoals = problem_logic_goals_aux subgoals (FOL,[]);
   304 
   304 
   305 fun is_fol_thms ths = ((fst(logic_of_clauses (map prop_of ths) (FOL,[]))) = FOL);
   305 fun is_fol_thms ths = ((fst(logic_of_clauses (map prop_of ths) (FOL,[]))) = FOL);
   306 
   306 
   307 (***************************************************************)
   307 (***************************************************************)
   309 (***************************************************************)
   309 (***************************************************************)
   310 
   310 
   311 (*** white list and black list of lemmas ***)
   311 (*** white list and black list of lemmas ***)
   312 
   312 
   313 (*The rule subsetI is frequently omitted by the relevance filter.*)
   313 (*The rule subsetI is frequently omitted by the relevance filter.*)
   314 val whitelist = ref [subsetI]; 
   314 val whitelist = ref [subsetI];
   315   
   315 
   316 (*Names of theorems (not theorem lists! See multi_blacklist below) to be banned. 
   316 (*Names of theorems (not theorem lists! See multi_blacklist below) to be banned.
   317 
   317 
   318   These theorems typically produce clauses that are prolific (match too many equality or
   318   These theorems typically produce clauses that are prolific (match too many equality or
   319   membership literals) and relate to seldom-used facts. Some duplicate other rules.
   319   membership literals) and relate to seldom-used facts. Some duplicate other rules.
   320   FIXME: this blacklist needs to be maintained using theory data and added to using
   320   FIXME: this blacklist needs to be maintained using theory data and added to using
   321   an attribute.*)
   321   an attribute.*)
   445    "SetInterval.greaterThanLessThan_iff", (*obscure and prolific*)
   445    "SetInterval.greaterThanLessThan_iff", (*obscure and prolific*)
   446    "SetInterval.ivl_subset"];  (*excessive case analysis*)
   446    "SetInterval.ivl_subset"];  (*excessive case analysis*)
   447 
   447 
   448 
   448 
   449 (*These might be prolific but are probably OK, and min and max are basic.
   449 (*These might be prolific but are probably OK, and min and max are basic.
   450    "Orderings.max_less_iff_conj", 
   450    "Orderings.max_less_iff_conj",
   451    "Orderings.min_less_iff_conj",
   451    "Orderings.min_less_iff_conj",
   452    "Orderings.min_max.below_inf.below_inf_conv",
   452    "Orderings.min_max.below_inf.below_inf_conv",
   453    "Orderings.min_max.below_sup.above_sup_conv",
   453    "Orderings.min_max.below_sup.above_sup_conv",
   454 Very prolific and somewhat obscure:
   454 Very prolific and somewhat obscure:
   455    "Set.InterD",
   455    "Set.InterD",
   461 (*Hashing to detect duplicate and variant clauses, e.g. from the [iff] attribute*)
   461 (*Hashing to detect duplicate and variant clauses, e.g. from the [iff] attribute*)
   462 
   462 
   463 exception HASH_CLAUSE and HASH_STRING;
   463 exception HASH_CLAUSE and HASH_STRING;
   464 
   464 
   465 (*Catches (for deletion) theorems automatically generated from other theorems*)
   465 (*Catches (for deletion) theorems automatically generated from other theorems*)
   466 fun insert_suffixed_names ht x = 
   466 fun insert_suffixed_names ht x =
   467      (Polyhash.insert ht (x^"_iff1", ()); 
   467      (Polyhash.insert ht (x^"_iff1", ());
   468       Polyhash.insert ht (x^"_iff2", ()); 
   468       Polyhash.insert ht (x^"_iff2", ());
   469       Polyhash.insert ht (x^"_dest", ())); 
   469       Polyhash.insert ht (x^"_dest", ()));
   470 
   470 
   471 (*Reject theorems with names like "List.filter.filter_list_def" or
   471 (*Reject theorems with names like "List.filter.filter_list_def" or
   472   "Accessible_Part.acc.defs", as these are definitions arising from packages.
   472   "Accessible_Part.acc.defs", as these are definitions arising from packages.
   473   FIXME: this will also block definitions within locales*)
   473   FIXME: this will also block definitions within locales*)
   474 fun is_package_def a =
   474 fun is_package_def a =
   475    length (NameSpace.unpack a) > 2 andalso 
   475    length (NameSpace.unpack a) > 2 andalso
   476    String.isSuffix "_def" a  orelse  String.isSuffix "_defs" a;
   476    String.isSuffix "_def" a  orelse  String.isSuffix "_defs" a;
   477 
   477 
   478 fun make_banned_test xs = 
   478 fun make_banned_test xs =
   479   let val ht = Polyhash.mkTable (Polyhash.hash_string, op =)
   479   let val ht = Polyhash.mkTable (Polyhash.hash_string, op =)
   480                                 (6000, HASH_STRING)
   480                                 (6000, HASH_STRING)
   481       fun banned s = 
   481       fun banned s =
   482             isSome (Polyhash.peek ht s) orelse is_package_def s
   482             isSome (Polyhash.peek ht s) orelse is_package_def s
   483   in  app (fn x => Polyhash.insert ht (x,())) (!blacklist);
   483   in  app (fn x => Polyhash.insert ht (x,())) (!blacklist);
   484       app (insert_suffixed_names ht) (!blacklist @ xs); 
   484       app (insert_suffixed_names ht) (!blacklist @ xs);
   485       banned
   485       banned
   486   end;
   486   end;
   487 
   487 
   488 (** a hash function from Term.term to int, and also a hash table **)
   488 (** a hash function from Term.term to int, and also a hash table **)
   489 val xor_words = List.foldl Word.xorb 0w0;
   489 val xor_words = List.foldl Word.xorb 0w0;
   507       Polyhash.mkTable (hash_term o prop_of, equal_thm)
   507       Polyhash.mkTable (hash_term o prop_of, equal_thm)
   508                        (n, HASH_CLAUSE);
   508                        (n, HASH_CLAUSE);
   509 
   509 
   510 (*Use a hash table to eliminate duplicates from xs. Argument is a list of
   510 (*Use a hash table to eliminate duplicates from xs. Argument is a list of
   511   (thm * (string * int)) tuples. The theorems are hashed into the table. *)
   511   (thm * (string * int)) tuples. The theorems are hashed into the table. *)
   512 fun make_unique xs = 
   512 fun make_unique xs =
   513   let val ht = mk_clause_table 7000
   513   let val ht = mk_clause_table 7000
   514   in
   514   in
   515       Output.debug("make_unique gets " ^ Int.toString (length xs) ^ " clauses");
   515       Output.debug("make_unique gets " ^ Int.toString (length xs) ^ " clauses");
   516       app (ignore o Polyhash.peekInsert ht) xs;  
   516       app (ignore o Polyhash.peekInsert ht) xs;
   517       Polyhash.listItems ht
   517       Polyhash.listItems ht
   518   end;
   518   end;
   519 
   519 
   520 (*Remove existing axiom clauses from the conjecture clauses, as this can dramatically
   520 (*Remove existing axiom clauses from the conjecture clauses, as this can dramatically
   521   boost an ATP's performance (for some reason)*)
   521   boost an ATP's performance (for some reason)*)
   522 fun subtract_cls c_clauses ax_clauses = 
   522 fun subtract_cls c_clauses ax_clauses =
   523   let val ht = mk_clause_table 2200
   523   let val ht = mk_clause_table 2200
   524       fun known x = isSome (Polyhash.peek ht x)
   524       fun known x = isSome (Polyhash.peek ht x)
   525   in
   525   in
   526       app (ignore o Polyhash.peekInsert ht) ax_clauses;  
   526       app (ignore o Polyhash.peekInsert ht) ax_clauses;
   527       filter (not o known) c_clauses 
   527       filter (not o known) c_clauses
   528   end;
   528   end;
   529 
   529 
   530 (*Filter axiom clauses, but keep supplied clauses and clauses in whitelist. 
   530 (*Filter axiom clauses, but keep supplied clauses and clauses in whitelist.
   531   Duplicates are removed later.*)
   531   Duplicates are removed later.*)
   532 fun get_relevant_clauses thy cls_thms white_cls goals =
   532 fun get_relevant_clauses thy cls_thms white_cls goals =
   533   white_cls @ (ReduceAxiomsN.relevance_filter thy cls_thms goals);
   533   white_cls @ (ReduceAxiomsN.relevance_filter thy cls_thms goals);
   534 
   534 
   535 fun display_thms [] = ()
   535 fun display_thms [] = ()
   536   | display_thms ((name,thm)::nthms) = 
   536   | display_thms ((name,thm)::nthms) =
   537       let val nthm = name ^ ": " ^ (string_of_thm thm)
   537       let val nthm = name ^ ": " ^ (string_of_thm thm)
   538       in Output.debug nthm; display_thms nthms  end;
   538       in Output.debug nthm; display_thms nthms  end;
   539  
   539 
   540 fun all_valid_thms ctxt =
   540 fun all_valid_thms ctxt =
   541   PureThy.thms_containing (ProofContext.theory_of ctxt) ([], []) @
   541   PureThy.thms_containing (ProofContext.theory_of ctxt) ([], []) @
   542   filter (ProofContext.valid_thms ctxt)
   542   filter (ProofContext.valid_thms ctxt)
   543     (FactIndex.find (ProofContext.fact_index_of ctxt) ([], []));
   543     (FactIndex.find (ProofContext.fact_index_of ctxt) ([], []));
   544 
   544 
   545 fun multi_name a (th, (n,pairs)) = 
   545 fun multi_name a (th, (n,pairs)) =
   546   (n+1, (a ^ "(" ^ Int.toString n ^ ")", th) :: pairs)
   546   (n+1, (a ^ "(" ^ Int.toString n ^ ")", th) :: pairs)
   547 
   547 
   548 fun add_multi_names_aux ((a, []), pairs) = pairs
   548 fun add_multi_names_aux ((a, []), pairs) = pairs
   549   | add_multi_names_aux ((a, [th]), pairs) = (a,th)::pairs
   549   | add_multi_names_aux ((a, [th]), pairs) = (a,th)::pairs
   550   | add_multi_names_aux ((a, ths), pairs) = #2 (foldl (multi_name a) (1,pairs) ths);
   550   | add_multi_names_aux ((a, ths), pairs) = #2 (foldl (multi_name a) (1,pairs) ths);
   555 
   555 
   556 val multi_base_blacklist =
   556 val multi_base_blacklist =
   557   ["defs","select_defs","update_defs","induct","inducts","split","splits","split_asm"];
   557   ["defs","select_defs","update_defs","induct","inducts","split","splits","split_asm"];
   558 
   558 
   559 (*Ignore blacklisted theorem lists*)
   559 (*Ignore blacklisted theorem lists*)
   560 fun add_multi_names ((a, ths), pairs) = 
   560 fun add_multi_names ((a, ths), pairs) =
   561   if a mem_string multi_blacklist orelse (Sign.base_name a) mem_string multi_base_blacklist
   561   if a mem_string multi_blacklist orelse (Sign.base_name a) mem_string multi_base_blacklist
   562   then pairs
   562   then pairs
   563   else add_multi_names_aux ((a, ths), pairs);
   563   else add_multi_names_aux ((a, ths), pairs);
   564 
   564 
   565 fun is_multi (a, ths) = length ths > 1 orelse String.isSuffix ".axioms" a;
   565 fun is_multi (a, ths) = length ths > 1 orelse String.isSuffix ".axioms" a;
   566 
   566 
   567 (*The single theorems go BEFORE the multiple ones*)
   567 (*The single theorems go BEFORE the multiple ones*)
   568 fun name_thm_pairs ctxt = 
   568 fun name_thm_pairs ctxt =
   569   let val (mults,singles) = List.partition is_multi (all_valid_thms ctxt)
   569   let val (mults,singles) = List.partition is_multi (all_valid_thms ctxt)
   570   in  foldl add_multi_names (foldl add_multi_names [] mults) singles  end;
   570   in  foldl add_multi_names (foldl add_multi_names [] mults) singles  end;
   571 
   571 
   572 fun check_named ("",th) = (warning ("No name for theorem " ^ string_of_thm th); false)
   572 fun check_named ("",th) = (warning ("No name for theorem " ^ string_of_thm th); false)
   573   | check_named (_,th) = true;
   573   | check_named (_,th) = true;
   574 
   574 
   575 (* get lemmas from claset, simpset, atpset and extra supplied rules *)
   575 (* get lemmas from claset, simpset, atpset and extra supplied rules *)
   576 fun get_clasimp_atp_lemmas ctxt user_thms = 
   576 fun get_clasimp_atp_lemmas ctxt user_thms =
   577   let val included_thms =
   577   let val included_thms =
   578 	if !include_all 
   578         if !include_all
   579 	then (tap (fn ths => Output.debug
   579         then (tap (fn ths => Output.debug
   580 	             ("Including all " ^ Int.toString (length ths) ^ " theorems")) 
   580                      ("Including all " ^ Int.toString (length ths) ^ " theorems"))
   581 	          (name_thm_pairs ctxt))
   581                   (name_thm_pairs ctxt))
   582 	else 
   582         else
   583 	let val claset_thms =
   583         let val claset_thms =
   584 		if !include_claset then ResAxioms.claset_rules_of ctxt
   584                 if !include_claset then ResAxioms.claset_rules_of ctxt
   585 		else []
   585                 else []
   586 	    val simpset_thms = 
   586             val simpset_thms =
   587 		if !include_simpset then ResAxioms.simpset_rules_of ctxt
   587                 if !include_simpset then ResAxioms.simpset_rules_of ctxt
   588 		else []
   588                 else []
   589 	    val atpset_thms =
   589             val atpset_thms =
   590 		if !include_atpset then ResAxioms.atpset_rules_of ctxt
   590                 if !include_atpset then ResAxioms.atpset_rules_of ctxt
   591 		else []
   591                 else []
   592 	    val _ = if !Output.show_debug_msgs 
   592             val _ = if !Output.show_debug_msgs
   593 		    then (Output.debug "ATP theorems: "; display_thms atpset_thms) 
   593                     then (Output.debug "ATP theorems: "; display_thms atpset_thms)
   594 		    else ()		 
   594                     else ()
   595 	in  claset_thms @ simpset_thms @ atpset_thms  end
   595         in  claset_thms @ simpset_thms @ atpset_thms  end
   596       val user_rules = filter check_named 
   596       val user_rules = filter check_named
   597                          (map (ResAxioms.pairname)
   597                          (map (ResAxioms.pairname)
   598 			   (if null user_thms then !whitelist else user_thms))
   598                            (if null user_thms then !whitelist else user_thms))
   599   in
   599   in
   600       (filter check_named included_thms, user_rules)
   600       (filter check_named included_thms, user_rules)
   601   end;
   601   end;
   602 
   602 
   603 (*Remove lemmas that are banned from the backlist. Also remove duplicates. *)
   603 (*Remove lemmas that are banned from the backlist. Also remove duplicates. *)
   604 fun blacklist_filter ths = 
   604 fun blacklist_filter ths =
   605   if !run_blacklist_filter then 
   605   if !run_blacklist_filter then
   606       let val _ = Output.debug("blacklist filter gets " ^ Int.toString (length ths) ^ " theorems")
   606       let val _ = Output.debug("blacklist filter gets " ^ Int.toString (length ths) ^ " theorems")
   607           val banned = make_banned_test (map #1 ths)
   607           val banned = make_banned_test (map #1 ths)
   608 	  fun ok (a,_) = not (banned a)
   608           fun ok (a,_) = not (banned a)
   609 	  val okthms = filter ok ths
   609           val okthms = filter ok ths
   610           val _ = Output.debug("...and returns " ^ Int.toString (length okthms))
   610           val _ = Output.debug("...and returns " ^ Int.toString (length okthms))
   611       in  okthms end
   611       in  okthms end
   612   else ths;
   612   else ths;
   613 
   613 
   614 (***************************************************************)
   614 (***************************************************************)
   651 
   651 
   652 (***************************************************************)
   652 (***************************************************************)
   653 (* ATP invocation methods setup                                *)
   653 (* ATP invocation methods setup                                *)
   654 (***************************************************************)
   654 (***************************************************************)
   655 
   655 
   656 fun cnf_hyps_thms ctxt = 
   656 fun cnf_hyps_thms ctxt =
   657     let val ths = Assumption.prems_of ctxt
   657     let val ths = Assumption.prems_of ctxt
   658     in fold (fold (insert Thm.eq_thm) o ResAxioms.skolem_thm) ths [] end;
   658     in fold (fold (insert Thm.eq_thm) o ResAxioms.skolem_thm) ths [] end;
   659 
   659 
   660 (*Translation mode can be auto-detected, or forced to be first-order or higher-order*)
   660 (*Translation mode can be auto-detected, or forced to be first-order or higher-order*)
   661 datatype mode = Auto | Fol | Hol;
   661 datatype mode = Auto | Fol | Hol;
   662 
   662 
   663 val linkup_logic_mode = ref Auto;
   663 val linkup_logic_mode = ref Auto;
   664 
   664 
   665 (*Ensures that no higher-order theorems "leak out"*)
   665 (*Ensures that no higher-order theorems "leak out"*)
   666 fun restrict_to_logic logic cls =
   666 fun restrict_to_logic logic cls =
   667   if is_fol_logic logic then filter (Meson.is_fol_term o prop_of o fst) cls 
   667   if is_fol_logic logic then filter (Meson.is_fol_term o prop_of o fst) cls
   668 	                else cls;
   668                         else cls;
   669 
   669 
   670 (**** Predicates to detect unwanted clauses (prolific or likely to cause unsoundness) ****)
   670 (**** Predicates to detect unwanted clauses (prolific or likely to cause unsoundness) ****)
   671 
   671 
   672 (** Too general means, positive equality literal with a variable X as one operand,
   672 (** Too general means, positive equality literal with a variable X as one operand,
   673   when X does not occur properly in the other operand. This rules out clearly
   673   when X does not occur properly in the other operand. This rules out clearly
   674   inconsistent clauses such as V=a|V=b, though it by no means guarantees soundness. **)
   674   inconsistent clauses such as V=a|V=b, though it by no means guarantees soundness. **)
   675  
   675 
   676 fun occurs ix =
   676 fun occurs ix =
   677     let fun occ(Var (jx,_)) = (ix=jx)
   677     let fun occ(Var (jx,_)) = (ix=jx)
   678           | occ(t1$t2)      = occ t1 orelse occ t2
   678           | occ(t1$t2)      = occ t1 orelse occ t2
   679           | occ(Abs(_,_,t)) = occ t
   679           | occ(Abs(_,_,t)) = occ t
   680           | occ _           = false
   680           | occ _           = false
   683 fun is_recordtype T = not (null (RecordPackage.dest_recTs T));
   683 fun is_recordtype T = not (null (RecordPackage.dest_recTs T));
   684 
   684 
   685 (*Unwanted equalities include
   685 (*Unwanted equalities include
   686   (1) those between a variable that does not properly occur in the second operand,
   686   (1) those between a variable that does not properly occur in the second operand,
   687   (2) those between a variable and a record, since these seem to be prolific "cases" thms
   687   (2) those between a variable and a record, since these seem to be prolific "cases" thms
   688 *)  
   688 *)
   689 fun too_general_eqterms (Var (ix,T), t) = not (occurs ix t) orelse is_recordtype T
   689 fun too_general_eqterms (Var (ix,T), t) = not (occurs ix t) orelse is_recordtype T
   690   | too_general_eqterms _ = false;
   690   | too_general_eqterms _ = false;
   691 
   691 
   692 fun too_general_equality (Const ("op =", _) $ x $ y) =
   692 fun too_general_equality (Const ("op =", _) $ x $ y) =
   693       too_general_eqterms (x,y) orelse too_general_eqterms(y,x)
   693       too_general_eqterms (x,y) orelse too_general_eqterms(y,x)
   696 (* tautologous? *)
   696 (* tautologous? *)
   697 fun is_taut (Const ("Trueprop", _) $ Const ("True", _)) = true
   697 fun is_taut (Const ("Trueprop", _) $ Const ("True", _)) = true
   698   | is_taut _ = false;
   698   | is_taut _ = false;
   699 
   699 
   700 (*True if the term contains a variable whose (atomic) type is in the given list.*)
   700 (*True if the term contains a variable whose (atomic) type is in the given list.*)
   701 fun has_typed_var tycons = 
   701 fun has_typed_var tycons =
   702   let fun var_tycon (Var (_, Type(a,_))) = a mem_string tycons
   702   let fun var_tycon (Var (_, Type(a,_))) = a mem_string tycons
   703         | var_tycon _ = false
   703         | var_tycon _ = false
   704   in  exists var_tycon o term_vars  end;
   704   in  exists var_tycon o term_vars  end;
   705 
   705 
   706 fun unwanted t =
   706 fun unwanted t =
   711   likely to lead to unsound proofs.*)
   711   likely to lead to unsound proofs.*)
   712 fun remove_unwanted_clauses cls =
   712 fun remove_unwanted_clauses cls =
   713   filter (not o unwanted o prop_of o fst) cls;
   713   filter (not o unwanted o prop_of o fst) cls;
   714 
   714 
   715 fun tptp_writer logic goals filename (axioms,classrels,arities) user_lemmas =
   715 fun tptp_writer logic goals filename (axioms,classrels,arities) user_lemmas =
   716     if is_fol_logic logic 
   716     if is_fol_logic logic
   717     then ResClause.tptp_write_file goals filename (axioms, classrels, arities)
   717     then ResClause.tptp_write_file goals filename (axioms, classrels, arities)
   718     else ResHolClause.tptp_write_file goals filename (axioms, classrels, arities) user_lemmas;
   718     else ResHolClause.tptp_write_file goals filename (axioms, classrels, arities) user_lemmas;
   719 
   719 
   720 fun dfg_writer logic goals filename (axioms,classrels,arities) user_lemmas =
   720 fun dfg_writer logic goals filename (axioms,classrels,arities) user_lemmas =
   721     if is_fol_logic logic 
   721     if is_fol_logic logic
   722     then ResClause.dfg_write_file goals filename (axioms, classrels, arities)
   722     then ResClause.dfg_write_file goals filename (axioms, classrels, arities)
   723     else ResHolClause.dfg_write_file goals filename (axioms, classrels, arities) user_lemmas;
   723     else ResHolClause.dfg_write_file goals filename (axioms, classrels, arities) user_lemmas;
   724 
   724 
   725 (*Called by the oracle-based methods declared in res_atp_methods.ML*)
   725 (*Called by the oracle-based methods declared in res_atp_methods.ML*)
   726 fun write_subgoal_file dfg mode ctxt conjectures user_thms n =
   726 fun write_subgoal_file dfg mode ctxt conjectures user_thms n =
   727     let val conj_cls = make_clauses conjectures 
   727     let val conj_cls = make_clauses conjectures
   728                          |> ResAxioms.assume_abstract_list |> Meson.finish_cnf
   728                          |> ResAxioms.assume_abstract_list |> Meson.finish_cnf
   729 	val hyp_cls = cnf_hyps_thms ctxt
   729         val hyp_cls = cnf_hyps_thms ctxt
   730 	val goal_cls = conj_cls@hyp_cls
   730         val goal_cls = conj_cls@hyp_cls
   731 	val goal_tms = map prop_of goal_cls
   731         val goal_tms = map prop_of goal_cls
   732 	val logic = case mode of 
   732         val logic = case mode of
   733                             Auto => problem_logic_goals [goal_tms]
   733                             Auto => problem_logic_goals [goal_tms]
   734 			  | Fol => FOL
   734                           | Fol => FOL
   735 			  | Hol => HOL
   735                           | Hol => HOL
   736 	val (included_thms,user_rules) = get_clasimp_atp_lemmas ctxt user_thms
   736         val (included_thms,user_rules) = get_clasimp_atp_lemmas ctxt user_thms
   737 	val cla_simp_atp_clauses = included_thms |> blacklist_filter
   737         val cla_simp_atp_clauses = included_thms |> blacklist_filter
   738 	                             |> ResAxioms.cnf_rules_pairs |> make_unique 
   738                                      |> ResAxioms.cnf_rules_pairs |> make_unique
   739                                      |> restrict_to_logic logic 
   739                                      |> restrict_to_logic logic
   740                                      |> remove_unwanted_clauses
   740                                      |> remove_unwanted_clauses
   741 	val user_cls = ResAxioms.cnf_rules_pairs user_rules
   741         val user_cls = ResAxioms.cnf_rules_pairs user_rules
   742 	val thy = ProofContext.theory_of ctxt
   742         val thy = ProofContext.theory_of ctxt
   743 	val axclauses = make_unique (get_relevant_clauses thy cla_simp_atp_clauses user_cls goal_tms)
   743         val axclauses = make_unique (get_relevant_clauses thy cla_simp_atp_clauses user_cls goal_tms)
   744 	val keep_types = if is_fol_logic logic then !fol_keep_types else is_typed_hol ()
   744         val keep_types = if is_fol_logic logic then !fol_keep_types else is_typed_hol ()
   745         val subs = tfree_classes_of_terms goal_tms
   745         val subs = tfree_classes_of_terms goal_tms
   746         and axtms = map (prop_of o #1) axclauses
   746         and axtms = map (prop_of o #1) axclauses
   747         val supers = tvar_classes_of_terms axtms
   747         val supers = tvar_classes_of_terms axtms
   748         and tycons = type_consts_of_terms thy (goal_tms@axtms)
   748         and tycons = type_consts_of_terms thy (goal_tms@axtms)
   749         (*TFrees in conjecture clauses; TVars in axiom clauses*)
   749         (*TFrees in conjecture clauses; TVars in axiom clauses*)
   750         val classrel_clauses = 
   750         val classrel_clauses =
   751               if keep_types then ResClause.make_classrel_clauses thy subs supers
   751               if keep_types then ResClause.make_classrel_clauses thy subs supers
   752               else []
   752               else []
   753 	val arity_clauses = if keep_types then ResClause.arity_clause_thy thy tycons supers else []
   753         val arity_clauses = if keep_types then ResClause.arity_clause_thy thy tycons supers else []
   754         val writer = if dfg then dfg_writer else tptp_writer 
   754         val writer = if dfg then dfg_writer else tptp_writer
   755 	and file = atp_input_file()
   755         and file = atp_input_file()
   756 	and user_lemmas_names = map #1 user_rules
   756         and user_lemmas_names = map #1 user_rules
   757     in
   757     in
   758 	writer logic goal_cls file (axclauses,classrel_clauses,arity_clauses) user_lemmas_names;
   758         writer logic goal_cls file (axclauses,classrel_clauses,arity_clauses) user_lemmas_names;
   759 	Output.debug ("Writing to " ^ file);
   759         Output.debug ("Writing to " ^ file);
   760 	file
   760         file
   761     end;
   761     end;
   762 
   762 
   763 
   763 
   764 (**** remove tmp files ****)
   764 (**** remove tmp files ****)
   765 fun cond_rm_tmp file = 
   765 fun cond_rm_tmp file =
   766     if !Output.show_debug_msgs orelse !destdir <> "" then Output.debug "ATP input kept..." 
   766     if !Output.show_debug_msgs orelse !destdir <> "" then Output.debug "ATP input kept..."
   767     else OS.FileSys.remove file;
   767     else OS.FileSys.remove file;
   768 
   768 
   769 
   769 
   770 (****** setup ATPs as Isabelle methods ******)
   770 (****** setup ATPs as Isabelle methods ******)
   771 fun atp_meth' tac ths ctxt = 
   771 
   772     Method.SIMPLE_METHOD' HEADGOAL
   772 fun atp_meth tac ths ctxt =
   773     (tac ctxt ths);
       
   774 
       
   775 fun atp_meth tac ths ctxt = 
       
   776     let val thy = ProofContext.theory_of ctxt
   773     let val thy = ProofContext.theory_of ctxt
   777 	val _ = ResClause.init thy
   774         val _ = ResClause.init thy
   778 	val _ = ResHolClause.init thy
   775         val _ = ResHolClause.init thy
   779     in
   776     in Method.SIMPLE_METHOD' (tac ctxt ths) end;
   780 	atp_meth' tac ths ctxt
       
   781     end;
       
   782 
   777 
   783 fun atp_method tac = Method.thms_ctxt_args (atp_meth tac);
   778 fun atp_method tac = Method.thms_ctxt_args (atp_meth tac);
   784 
   779 
   785 (***************************************************************)
   780 (***************************************************************)
   786 (* automatic ATP invocation                                    *)
   781 (* automatic ATP invocation                                    *)
   800             if !prover = "spass"
   795             if !prover = "spass"
   801             then
   796             then
   802               let val spass = helper_path "SPASS_HOME" "SPASS"
   797               let val spass = helper_path "SPASS_HOME" "SPASS"
   803                   val sopts =
   798                   val sopts =
   804    "-Auto%-SOS=1%-PGiven=0%-PProblem=0%-Splits=0%-FullRed=0%-DocProof%-TimeLimit=" ^ time
   799    "-Auto%-SOS=1%-PGiven=0%-PProblem=0%-Splits=0%-FullRed=0%-DocProof%-TimeLimit=" ^ time
   805               in 
   800               in
   806                   ("spass", spass, sopts, probfile) :: make_atp_list xs (n+1)
   801                   ("spass", spass, sopts, probfile) :: make_atp_list xs (n+1)
   807               end
   802               end
   808             else if !prover = "vampire"
   803             else if !prover = "vampire"
   809 	    then 
   804             then
   810               let val vampire = helper_path "VAMPIRE_HOME" "vampire"
   805               let val vampire = helper_path "VAMPIRE_HOME" "vampire"
   811                   val vopts = "--mode casc%-t " ^ time  (*what about -m 100000?*)
   806                   val vopts = "--mode casc%-t " ^ time  (*what about -m 100000?*)
   812               in
   807               in
   813                   ("vampire", vampire, vopts, probfile) :: make_atp_list xs (n+1)
   808                   ("vampire", vampire, vopts, probfile) :: make_atp_list xs (n+1)
   814               end
   809               end
   815       	     else if !prover = "E"
   810              else if !prover = "E"
   816       	     then
   811              then
   817 	       let val Eprover = helper_path "E_HOME" "eproof"
   812                let val Eprover = helper_path "E_HOME" "eproof"
   818 	       in
   813                in
   819 		  ("E", Eprover, 
   814                   ("E", Eprover,
   820 		     "--tstp-in%-l5%-xAutoDev%-tAutoDev%--silent%--cpu-limit=" ^ time, probfile) ::
   815                      "--tstp-in%-l5%-xAutoDev%-tAutoDev%--silent%--cpu-limit=" ^ time, probfile) ::
   821 		   make_atp_list xs (n+1)
   816                    make_atp_list xs (n+1)
   822 	       end
   817                end
   823 	     else error ("Invalid prover name: " ^ !prover)
   818              else error ("Invalid prover name: " ^ !prover)
   824           end
   819           end
   825 
   820 
   826     val atp_list = make_atp_list sg_terms 1
   821     val atp_list = make_atp_list sg_terms 1
   827   in
   822   in
   828     Watcher.callResProvers(childout,atp_list);
   823     Watcher.callResProvers(childout,atp_list);
   829     Output.debug "Sent commands to watcher!"
   824     Output.debug "Sent commands to watcher!"
   830   end
   825   end
   831   
   826 
   832 fun trace_array fname =
   827 fun trace_array fname =
   833   let val path = File.unpack_platform_path fname
   828   let val path = File.unpack_platform_path fname
   834   in  Array.app (File.append path o (fn s => s ^ "\n"))  end;
   829   in  Array.app (File.append path o (fn s => s ^ "\n"))  end;
   835 
   830 
   836 (*Converting a subgoal into negated conjecture clauses*)
   831 (*Converting a subgoal into negated conjecture clauses*)
   837 fun neg_clauses th n =
   832 fun neg_clauses th n =
   838   let val tacs = [rtac ccontr, ObjectLogic.atomize_tac, skolemize_tac]
   833   let val tacs = [rtac ccontr, ObjectLogic.atomize_tac, skolemize_tac]
   839       val st = Seq.hd (EVERY' tacs n th)
   834       val st = Seq.hd (EVERY' tacs n th)
   840       val negs = Option.valOf (metahyps_thms n st)
   835       val negs = Option.valOf (metahyps_thms n st)
   841   in make_clauses negs |> ResAxioms.assume_abstract_list |> Meson.finish_cnf end;
   836   in make_clauses negs |> ResAxioms.assume_abstract_list |> Meson.finish_cnf end;
   842 		                       
   837 
   843 (*We write out problem files for each subgoal. Argument probfile generates filenames,
   838 (*We write out problem files for each subgoal. Argument probfile generates filenames,
   844   and allows the suppression of the suffix "_1" in problem-generation mode.
   839   and allows the suppression of the suffix "_1" in problem-generation mode.
   845   FIXME: does not cope with &&, and it isn't easy because one could have multiple
   840   FIXME: does not cope with &&, and it isn't easy because one could have multiple
   846   subgoals, each involving &&.*)
   841   subgoals, each involving &&.*)
   847 fun write_problem_files probfile (ctxt,th)  =
   842 fun write_problem_files probfile (ctxt,th)  =
   850       val thy = ProofContext.theory_of ctxt
   845       val thy = ProofContext.theory_of ctxt
   851       fun get_neg_subgoals [] _ = []
   846       fun get_neg_subgoals [] _ = []
   852         | get_neg_subgoals (gl::gls) n = neg_clauses th n :: get_neg_subgoals gls (n+1)
   847         | get_neg_subgoals (gl::gls) n = neg_clauses th n :: get_neg_subgoals gls (n+1)
   853       val goal_cls = get_neg_subgoals goals 1
   848       val goal_cls = get_neg_subgoals goals 1
   854       val logic = case !linkup_logic_mode of
   849       val logic = case !linkup_logic_mode of
   855 		Auto => problem_logic_goals (map ((map prop_of)) goal_cls)
   850                 Auto => problem_logic_goals (map ((map prop_of)) goal_cls)
   856 	      | Fol => FOL
   851               | Fol => FOL
   857 	      | Hol => HOL
   852               | Hol => HOL
   858       val (included_thms,white_thms) = get_clasimp_atp_lemmas ctxt []
   853       val (included_thms,white_thms) = get_clasimp_atp_lemmas ctxt []
   859       val included_cls = included_thms |> blacklist_filter
   854       val included_cls = included_thms |> blacklist_filter
   860                                        |> ResAxioms.cnf_rules_pairs |> make_unique 
   855                                        |> ResAxioms.cnf_rules_pairs |> make_unique
   861                                        |> restrict_to_logic logic
   856                                        |> restrict_to_logic logic
   862                                        |> remove_unwanted_clauses
   857                                        |> remove_unwanted_clauses
   863       val _ = Output.debug ("clauses = " ^ Int.toString(length included_cls))
   858       val _ = Output.debug ("clauses = " ^ Int.toString(length included_cls))
   864       val white_cls = ResAxioms.cnf_rules_pairs white_thms
   859       val white_cls = ResAxioms.cnf_rules_pairs white_thms
   865       (*clauses relevant to goal gl*)
   860       (*clauses relevant to goal gl*)
   866       val axcls_list = map (fn ngcls => get_relevant_clauses thy included_cls white_cls (map prop_of ngcls)) goal_cls
   861       val axcls_list = map (fn ngcls => get_relevant_clauses thy included_cls white_cls (map prop_of ngcls)) goal_cls
   867       val _ = app (fn axcls => Output.debug ("filtered clauses = " ^ Int.toString(length axcls)))
   862       val _ = app (fn axcls => Output.debug ("filtered clauses = " ^ Int.toString(length axcls)))
   868                   axcls_list
   863                   axcls_list
   869       val keep_types = if is_fol_logic logic then !ResClause.keep_types 
   864       val keep_types = if is_fol_logic logic then !ResClause.keep_types
   870                        else is_typed_hol ()
   865                        else is_typed_hol ()
   871       val writer = if !prover = "spass" then dfg_writer else tptp_writer 
   866       val writer = if !prover = "spass" then dfg_writer else tptp_writer
   872       fun write_all [] [] _ = []
   867       fun write_all [] [] _ = []
   873 	| write_all (ccls::ccls_list) (axcls::axcls_list) k =
   868         | write_all (ccls::ccls_list) (axcls::axcls_list) k =
   874             let val fname = probfile k
   869             let val fname = probfile k
   875                 val axcls = make_unique axcls
   870                 val axcls = make_unique axcls
   876                 val ccls = subtract_cls ccls axcls
   871                 val ccls = subtract_cls ccls axcls
   877                 val ccltms = map prop_of ccls
   872                 val ccltms = map prop_of ccls
   878                 and axtms = map (prop_of o #1) axcls
   873                 and axtms = map (prop_of o #1) axcls
   879                 val subs = tfree_classes_of_terms ccltms
   874                 val subs = tfree_classes_of_terms ccltms
   880                 and supers = tvar_classes_of_terms axtms
   875                 and supers = tvar_classes_of_terms axtms
   881                 and tycons = type_consts_of_terms thy (ccltms@axtms)
   876                 and tycons = type_consts_of_terms thy (ccltms@axtms)
   882                 (*TFrees in conjecture clauses; TVars in axiom clauses*)
   877                 (*TFrees in conjecture clauses; TVars in axiom clauses*)
   883                 val classrel_clauses = 
   878                 val classrel_clauses =
   884                       if keep_types then ResClause.make_classrel_clauses thy subs supers
   879                       if keep_types then ResClause.make_classrel_clauses thy subs supers
   885                       else []
   880                       else []
   886                 val _ = Output.debug ("classrel clauses = " ^ Int.toString (length classrel_clauses))
   881                 val _ = Output.debug ("classrel clauses = " ^ Int.toString (length classrel_clauses))
   887                 val arity_clauses = if keep_types then ResClause.arity_clause_thy thy tycons supers
   882                 val arity_clauses = if keep_types then ResClause.arity_clause_thy thy tycons supers
   888                                     else []
   883                                     else []
   889                 val _ = Output.debug ("arity clauses = " ^ Int.toString (length arity_clauses))
   884                 val _ = Output.debug ("arity clauses = " ^ Int.toString (length arity_clauses))
   890                 val clnames = writer logic ccls fname (axcls,classrel_clauses,arity_clauses) []
   885                 val clnames = writer logic ccls fname (axcls,classrel_clauses,arity_clauses) []
   891                 val thm_names = Array.fromList clnames
   886                 val thm_names = Array.fromList clnames
   892                 val _ = if !Output.show_debug_msgs 
   887                 val _ = if !Output.show_debug_msgs
   893                         then trace_array (fname ^ "_thm_names") thm_names else ()
   888                         then trace_array (fname ^ "_thm_names") thm_names else ()
   894             in  (thm_names,fname) :: write_all ccls_list axcls_list (k+1)  end
   889             in  (thm_names,fname) :: write_all ccls_list axcls_list (k+1)  end
   895       val (thm_names_list, filenames) = ListPair.unzip (write_all goal_cls axcls_list 1)
   890       val (thm_names_list, filenames) = ListPair.unzip (write_all goal_cls axcls_list 1)
   896   in
   891   in
   897       (filenames, thm_names_list)
   892       (filenames, thm_names_list)
   898   end;
   893   end;
   899 
   894 
   900 val last_watcher_pid = ref (NONE : (TextIO.instream * TextIO.outstream * 
   895 val last_watcher_pid = ref (NONE : (TextIO.instream * TextIO.outstream *
   901                                     Posix.Process.pid * string list) option);
   896                                     Posix.Process.pid * string list) option);
   902 
   897 
   903 fun kill_last_watcher () =
   898 fun kill_last_watcher () =
   904     (case !last_watcher_pid of 
   899     (case !last_watcher_pid of
   905          NONE => ()
   900          NONE => ()
   906        | SOME (_, _, pid, files) => 
   901        | SOME (_, _, pid, files) =>
   907 	  (Output.debug ("Killing old watcher, pid = " ^ string_of_pid pid);
   902           (Output.debug ("Killing old watcher, pid = " ^ string_of_pid pid);
   908 	   Watcher.killWatcher pid;  
   903            Watcher.killWatcher pid;
   909 	   ignore (map (try cond_rm_tmp) files)))
   904            ignore (map (try cond_rm_tmp) files)))
   910      handle OS.SysErr _ => Output.debug "Attempt to kill watcher failed";
   905      handle OS.SysErr _ => Output.debug "Attempt to kill watcher failed";
   911 
   906 
   912 (*writes out the current clasimpset to a tptp file;
   907 (*writes out the current clasimpset to a tptp file;
   913   turns off xsymbol at start of function, restoring it at end    *)
   908   turns off xsymbol at start of function, restoring it at end    *)
   914 fun isar_atp_body (ctxt, th) =
   909 fun isar_atp_body (ctxt, th) =
   918       val _ = kill_last_watcher()
   913       val _ = kill_last_watcher()
   919       val (files,thm_names_list) = write_problem_files prob_pathname (ctxt,th)
   914       val (files,thm_names_list) = write_problem_files prob_pathname (ctxt,th)
   920       val (childin, childout, pid) = Watcher.createWatcher (th, thm_names_list)
   915       val (childin, childout, pid) = Watcher.createWatcher (th, thm_names_list)
   921     in
   916     in
   922       last_watcher_pid := SOME (childin, childout, pid, files);
   917       last_watcher_pid := SOME (childin, childout, pid, files);
   923       Output.debug ("problem files: " ^ space_implode ", " files); 
   918       Output.debug ("problem files: " ^ space_implode ", " files);
   924       Output.debug ("pid: " ^ string_of_pid pid);
   919       Output.debug ("pid: " ^ string_of_pid pid);
   925       watcher_call_provers (sign_of_thm th) (Thm.prems_of th) (childin, childout, pid)
   920       watcher_call_provers (sign_of_thm th) (Thm.prems_of th) (childin, childout, pid)
   926     end;
   921     end;
   927 
   922 
   928 val isar_atp = setmp print_mode [] isar_atp_body;
   923 val isar_atp = setmp print_mode [] isar_atp_body;
   929 
   924 
   930 (*For ML scripts, and primarily, for debugging*)
   925 (*For ML scripts, and primarily, for debugging*)
   931 fun callatp () = 
   926 fun callatp () =
   932   let val th = topthm()
   927   let val th = topthm()
   933       val ctxt = ProofContext.init (theory_of_thm th)
   928       val ctxt = ProofContext.init (theory_of_thm th)
   934   in  isar_atp_body (ctxt, th)  end;
   929   in  isar_atp_body (ctxt, th)  end;
   935 
   930 
   936 val isar_atp_writeonly = setmp print_mode [] 
   931 val isar_atp_writeonly = setmp print_mode []
   937       (fn (ctxt,th) =>
   932       (fn (ctxt,th) =>
   938        if Thm.no_prems th then ()
   933        if Thm.no_prems th then ()
   939        else 
   934        else
   940          let val probfile = if Thm.nprems_of th = 1 then probfile_nosuffix 
   935          let val probfile = if Thm.nprems_of th = 1 then probfile_nosuffix
   941           	            else prob_pathname
   936                             else prob_pathname
   942          in ignore (write_problem_files probfile (ctxt,th)) end);
   937          in ignore (write_problem_files probfile (ctxt,th)) end);
   943 
   938 
   944 
   939 
   945 (** the Isar toplevel hook **)
   940 (** the Isar toplevel hook **)
   946 
   941 
   947 fun invoke_atp_ml (ctxt, goal) =
   942 fun invoke_atp_ml (ctxt, goal) =
   948   let val thy = ProofContext.theory_of ctxt;
   943   let val thy = ProofContext.theory_of ctxt;
   949   in
   944   in
   950     Output.debug ("subgoals in isar_atp:\n" ^ 
   945     Output.debug ("subgoals in isar_atp:\n" ^
   951 		  Pretty.string_of (ProofContext.pretty_term ctxt
   946                   Pretty.string_of (ProofContext.pretty_term ctxt
   952 		    (Logic.mk_conjunction_list (Thm.prems_of goal))));
   947                     (Logic.mk_conjunction_list (Thm.prems_of goal))));
   953     Output.debug ("current theory: " ^ Context.theory_name thy);
   948     Output.debug ("current theory: " ^ Context.theory_name thy);
   954     inc hook_count;
   949     inc hook_count;
   955     Output.debug ("in hook for time: " ^ Int.toString (!hook_count));
   950     Output.debug ("in hook for time: " ^ Int.toString (!hook_count));
   956     ResClause.init thy;
   951     ResClause.init thy;
   957     ResHolClause.init thy;
   952     ResHolClause.init thy;
   963  (fn state =>
   958  (fn state =>
   964   let val (ctxt, (_, goal)) = Proof.get_goal (Toplevel.proof_of state)
   959   let val (ctxt, (_, goal)) = Proof.get_goal (Toplevel.proof_of state)
   965   in  invoke_atp_ml (ctxt, goal)  end);
   960   in  invoke_atp_ml (ctxt, goal)  end);
   966 
   961 
   967 val call_atpP =
   962 val call_atpP =
   968   OuterSyntax.command 
   963   OuterSyntax.command
   969     "ProofGeneral.call_atp" 
   964     "ProofGeneral.call_atp"
   970     "call automatic theorem provers" 
   965     "call automatic theorem provers"
   971     OuterKeyword.diag
   966     OuterKeyword.diag
   972     (Scan.succeed invoke_atp);
   967     (Scan.succeed invoke_atp);
   973 
   968 
   974 val _ = OuterSyntax.add_parsers [call_atpP];
   969 val _ = OuterSyntax.add_parsers [call_atpP];
   975 
   970