src/HOL/Tools/Sledgehammer/sledgehammer_filter_mash.ML
changeset 49333 325c8fd0d762
parent 49331 252f45c04042
child 49334 340187063d84
equal deleted inserted replaced
49332:e5420161d11d 49333:325c8fd0d762
    24   val unescape_meta : string -> string
    24   val unescape_meta : string -> string
    25   val unescape_metas : string -> string list
    25   val unescape_metas : string -> string list
    26   val extract_query : string -> string * string list
    26   val extract_query : string -> string * string list
    27   val suggested_facts : string list -> fact list -> fact list
    27   val suggested_facts : string list -> fact list -> fact list
    28   val mesh_facts : int -> (fact list * int option) list -> fact list
    28   val mesh_facts : int -> (fact list * int option) list -> fact list
    29   val is_likely_tautology : thm -> bool
    29   val is_likely_tautology : Proof.context -> string -> thm -> bool
    30   val is_too_meta : thm -> bool
    30   val is_too_meta : thm -> bool
    31   val theory_ord : theory * theory -> order
    31   val theory_ord : theory * theory -> order
    32   val thm_ord : thm * thm -> order
    32   val thm_ord : thm * thm -> order
    33   val features_of : theory -> status -> term list -> string list
    33   val features_of :
       
    34     Proof.context -> string -> theory -> status -> term list -> string list
    34   val isabelle_dependencies_of : unit Symtab.table -> thm -> string list
    35   val isabelle_dependencies_of : unit Symtab.table -> thm -> string list
    35   val goal_of_thm : theory -> thm -> thm
    36   val goal_of_thm : theory -> thm -> thm
    36   val run_prover : Proof.context -> params -> fact list -> thm -> prover_result
    37   val run_prover :
       
    38     Proof.context -> params -> string -> fact list -> thm -> prover_result
    37   val mash_RESET : Proof.context -> unit
    39   val mash_RESET : Proof.context -> unit
    38   val mash_INIT :
    40   val mash_INIT :
    39     Proof.context -> bool
    41     Proof.context -> bool
    40     -> (string * string list * string list * string list) list -> unit
    42     -> (string * string list * string list * string list) list -> unit
    41   val mash_ADD :
    43   val mash_ADD :
    42     Proof.context -> bool
    44     Proof.context -> bool
    43     -> (string * string list * string list * string list) list -> unit
    45     -> (string * string list * string list * string list) list -> unit
    44   val mash_QUERY :
    46   val mash_QUERY :
    45     Proof.context -> bool -> string list * string list -> string list
    47     Proof.context -> bool -> int -> string list * string list -> string list
    46   val mash_reset : Proof.context -> unit
    48   val mash_reset : Proof.context -> unit
    47   val mash_can_suggest_facts : Proof.context -> bool
    49   val mash_could_suggest_facts : unit -> bool
       
    50   val mash_can_suggest_facts : unit -> bool
    48   val mash_suggest_facts :
    51   val mash_suggest_facts :
    49     Proof.context -> params -> string -> term list -> term -> fact list
    52     Proof.context -> params -> string -> int -> term list -> term -> fact list
    50     -> fact list
    53     -> fact list
    51   val mash_learn_thy : Proof.context -> params -> theory -> real -> unit
    54   val mash_learn_thy : Proof.context -> params -> theory -> Time.time -> unit
    52   val mash_learn_proof :
    55   val mash_learn_proof :
    53     Proof.context -> params -> term -> thm list -> fact list -> unit
    56     Proof.context -> params -> term -> thm list -> fact list -> unit
    54   val relevant_facts :
    57   val relevant_facts :
    55     Proof.context -> params -> string -> int -> fact_override -> term list
    58     Proof.context -> params -> string -> int -> fact_override -> term list
    56     -> term -> fact list -> fact list
    59     -> term -> fact list -> fact list
    63 open ATP_Problem_Generate
    66 open ATP_Problem_Generate
    64 open Sledgehammer_Util
    67 open Sledgehammer_Util
    65 open Sledgehammer_Fact
    68 open Sledgehammer_Fact
    66 open Sledgehammer_Filter_Iter
    69 open Sledgehammer_Filter_Iter
    67 open Sledgehammer_Provers
    70 open Sledgehammer_Provers
       
    71 open Sledgehammer_Minimize
    68 
    72 
    69 val trace =
    73 val trace =
    70   Attrib.setup_config_bool @{binding sledgehammer_filter_mash_trace} (K false)
    74   Attrib.setup_config_bool @{binding sledgehammer_filter_mash_trace} (K false)
    71 fun trace_msg ctxt msg = if Config.get ctxt trace then tracing (msg ()) else ()
    75 fun trace_msg ctxt msg = if Config.get ctxt trace then tracing (msg ()) else ()
    72 
    76 
   184          has_bool_arg_const t orelse exists_Const (higher_inst_const thy) t)
   188          has_bool_arg_const t orelse exists_Const (higher_inst_const thy) t)
   185   end
   189   end
   186 
   190 
   187 end
   191 end
   188 
   192 
   189 fun interesting_terms_types_and_classes term_max_depth type_max_depth ts =
   193 fun interesting_terms_types_and_classes ctxt prover term_max_depth
       
   194                                         type_max_depth ts =
   190   let
   195   let
   191     val bad_types = [@{type_name prop}, @{type_name bool}, @{type_name fun}]
   196     val bad_types = [@{type_name prop}, @{type_name bool}, @{type_name fun}]
   192     val bad_consts = atp_widely_irrelevant_consts
   197     fun is_bad_const (x as (s, _)) args =
       
   198       member (op =) atp_logical_consts s orelse
       
   199       fst (is_built_in_const_for_prover ctxt prover x args)
   193     fun add_classes @{sort type} = I
   200     fun add_classes @{sort type} = I
   194       | add_classes S = union (op =) (map class_name_of S)
   201       | add_classes S = union (op =) (map class_name_of S)
   195     fun do_add_type (Type (s, Ts)) =
   202     fun do_add_type (Type (s, Ts)) =
   196         (not (member (op =) bad_types s) ? insert (op =) (type_name_of s))
   203         (not (member (op =) bad_types s) ? insert (op =) (type_name_of s))
   197         #> fold do_add_type Ts
   204         #> fold do_add_type Ts
   213         #> add_term_patterns (depth - 1) t
   220         #> add_term_patterns (depth - 1) t
   214     val add_term = add_term_patterns term_max_depth
   221     val add_term = add_term_patterns term_max_depth
   215     fun add_patterns t =
   222     fun add_patterns t =
   216       let val (head, args) = strip_comb t in
   223       let val (head, args) = strip_comb t in
   217         (case head of
   224         (case head of
   218            Const (s, T) =>
   225            Const (x as (_, T)) =>
   219            not (member (op =) bad_consts s) ? (add_term t #> add_type T)
   226            not (is_bad_const x args) ? (add_term t #> add_type T)
   220          | Free (_, T) => add_type T
   227          | Free (_, T) => add_type T
   221          | Var (_, T) => add_type T
   228          | Var (_, T) => add_type T
   222          | Abs (_, T, body) => add_type T #> add_patterns body
   229          | Abs (_, T, body) => add_type T #> add_patterns body
   223          | _ => I)
   230          | _ => I)
   224         #> fold add_patterns args
   231         #> fold add_patterns args
   225       end
   232       end
   226   in [] |> fold add_patterns ts |> sort string_ord end
   233   in [] |> fold add_patterns ts |> sort string_ord end
   227 
   234 
   228 fun is_likely_tautology th =
   235 fun is_likely_tautology ctxt prover th =
   229   null (interesting_terms_types_and_classes 0 ~1 [prop_of th]) andalso
   236   null (interesting_terms_types_and_classes ctxt prover 0 ~1 [prop_of th])
   230   not (Thm.eq_thm_prop (@{thm ext}, th))
   237   andalso not (Thm.eq_thm_prop (@{thm ext}, th))
   231 
   238 
   232 (* ### FIXME: optimize *)
   239 (* ### FIXME: optimize *)
   233 fun is_too_meta th =
   240 fun is_too_meta th =
   234   fastype_of (Object_Logic.atomize_term (theory_of_thm th) (prop_of th))
   241   fastype_of (Object_Logic.atomize_term (theory_of_thm th) (prop_of th))
   235   <> @{typ bool}
   242   <> @{typ bool}
   251 
   258 
   252 val term_max_depth = 1
   259 val term_max_depth = 1
   253 val type_max_depth = 1
   260 val type_max_depth = 1
   254 
   261 
   255 (* TODO: Generate type classes for types? *)
   262 (* TODO: Generate type classes for types? *)
   256 fun features_of thy status ts =
   263 fun features_of ctxt prover thy status ts =
   257   thy_feature_name_of (Context.theory_name thy) ::
   264   thy_feature_name_of (Context.theory_name thy) ::
   258   interesting_terms_types_and_classes term_max_depth type_max_depth ts
   265   interesting_terms_types_and_classes ctxt prover term_max_depth type_max_depth
       
   266                                       ts
   259   |> exists (not o is_lambda_free) ts ? cons "lambdas"
   267   |> exists (not o is_lambda_free) ts ? cons "lambdas"
   260   |> exists (exists_Const is_exists) ts ? cons "skolems"
   268   |> exists (exists_Const is_exists) ts ? cons "skolems"
   261   |> exists (not o is_fo_term thy) ts ? cons "ho"
   269   |> exists (not o is_fo_term thy) ts ? cons "ho"
   262   |> (case status of
   270   |> (case status of
   263         General => I
   271         General => I
   280   | freeze (Free (s, T)) = Free (s, freezeT T)
   288   | freeze (Free (s, T)) = Free (s, freezeT T)
   281   | freeze t = t
   289   | freeze t = t
   282 
   290 
   283 fun goal_of_thm thy = prop_of #> freeze #> cterm_of thy #> Goal.init
   291 fun goal_of_thm thy = prop_of #> freeze #> cterm_of thy #> Goal.init
   284 
   292 
   285 fun run_prover ctxt (params as {provers, ...}) facts goal =
   293 fun run_prover ctxt params prover facts goal =
   286   let
   294   let
   287     val problem =
   295     val problem =
   288       {state = Proof.init ctxt, goal = goal, subgoal = 1, subgoal_count = 1,
   296       {state = Proof.init ctxt, goal = goal, subgoal = 1, subgoal_count = 1,
   289        facts = facts |> map (apfst (apfst (fn name => name ())))
   297        facts = facts |> map (apfst (apfst (fn name => name ())))
   290                      |> map Sledgehammer_Provers.Untranslated_Fact}
   298                      |> map Untranslated_Fact}
   291     val prover =
   299     val prover = get_minimizing_prover ctxt Normal prover
   292       Sledgehammer_Minimize.get_minimizing_prover ctxt
       
   293           Sledgehammer_Provers.Normal (hd provers)
       
   294   in prover params (K (K (K ""))) problem end
   300   in prover params (K (K (K ""))) problem end
   295 
   301 
   296 
   302 
   297 (*** Low-level communication with MaSh ***)
   303 (*** Low-level communication with MaSh ***)
   298 
   304 
   299 val max_preds = 500
   305 fun write_file write file =
       
   306   let val path = Path.explode file in
       
   307     File.write path ""; write (File.append path)
       
   308   end
   300 
   309 
   301 fun mash_info overlord =
   310 fun mash_info overlord =
   302   if overlord then (getenv "ISABELLE_HOME_USER", "")
   311   if overlord then (getenv "ISABELLE_HOME_USER", "")
   303   else (getenv "ISABELLE_TMP", serial_string ())
   312   else (getenv "ISABELLE_TMP", serial_string ())
   304 
   313 
   309     val command =
   318     val command =
   310       mash_home () ^ "/mash.py --quiet --outputDir " ^ mash_state_dir () ^
   319       mash_home () ^ "/mash.py --quiet --outputDir " ^ mash_state_dir () ^
   311       " --log " ^ log_file ^ " " ^ core ^ " 2>&1 > " ^ err_file
   320       " --log " ^ log_file ^ " " ^ core ^ " 2>&1 > " ^ err_file
   312   in
   321   in
   313     trace_msg ctxt (fn () => "Running " ^ command);
   322     trace_msg ctxt (fn () => "Running " ^ command);
       
   323     write_file (K ()) log_file;
       
   324     write_file (K ()) err_file;
   314     Isabelle_System.bash command; ()
   325     Isabelle_System.bash command; ()
   315   end
       
   316 
       
   317 fun write_file write file =
       
   318   let val path = Path.explode file in
       
   319     File.write path ""; write (File.append path)
       
   320   end
   326   end
   321 
   327 
   322 fun run_mash_init ctxt overlord write_access write_feats write_deps =
   328 fun run_mash_init ctxt overlord write_access write_feats write_deps =
   323   let
   329   let
   324     val info as (temp_dir, serial) = mash_info overlord
   330     val info as (temp_dir, serial) = mash_info overlord
   329     write_file write_feats (in_dir ^ "/mash_features");
   335     write_file write_feats (in_dir ^ "/mash_features");
   330     write_file write_deps (in_dir ^ "/mash_dependencies");
   336     write_file write_deps (in_dir ^ "/mash_dependencies");
   331     run_mash ctxt info ("--init --inputDir " ^ in_dir)
   337     run_mash ctxt info ("--init --inputDir " ^ in_dir)
   332   end
   338   end
   333 
   339 
   334 fun run_mash_commands ctxt overlord save write_cmds read_preds =
   340 fun run_mash_commands ctxt overlord save max_suggs write_cmds read_suggs =
   335   let
   341   let
   336     val info as (temp_dir, serial) = mash_info overlord
   342     val info as (temp_dir, serial) = mash_info overlord
       
   343     val sugg_file = temp_dir ^ "/mash_suggs" ^ serial
   337     val cmd_file = temp_dir ^ "/mash_commands" ^ serial
   344     val cmd_file = temp_dir ^ "/mash_commands" ^ serial
   338     val pred_file = temp_dir ^ "/mash_preds" ^ serial
       
   339   in
   345   in
       
   346     write_file (K ()) sugg_file;
   340     write_file write_cmds cmd_file;
   347     write_file write_cmds cmd_file;
   341     run_mash ctxt info
   348     run_mash ctxt info
   342              ("--inputFile " ^ cmd_file ^ " --predictions " ^ pred_file ^
   349              ("--inputFile " ^ cmd_file ^ " --predictions " ^ sugg_file ^
   343               " --numberOfPredictions " ^ string_of_int max_preds ^
   350               " --numberOfPredictions " ^ string_of_int max_suggs ^
   344               (if save then " --saveModel" else ""));
   351               (if save then " --saveModel" else ""));
   345     read_preds (fn () => File.read_lines (Path.explode pred_file))
   352     read_suggs (fn () => File.read_lines (Path.explode sugg_file))
   346   end
   353   end
   347 
   354 
   348 fun str_of_update (name, parents, feats, deps) =
   355 fun str_of_update (name, parents, feats, deps) =
   349   "! " ^ escape_meta name ^ ": " ^ escape_metas parents ^ "; " ^
   356   "! " ^ escape_meta name ^ ": " ^ escape_metas parents ^ "; " ^
   350   escape_metas feats ^ "; " ^ escape_metas deps ^ "\n"
   357   escape_metas feats ^ "; " ^ escape_metas deps ^ "\n"
   374 
   381 
   375 fun mash_ADD _ _ [] = ()
   382 fun mash_ADD _ _ [] = ()
   376   | mash_ADD ctxt overlord upds =
   383   | mash_ADD ctxt overlord upds =
   377     (trace_msg ctxt (fn () => "MaSh ADD " ^
   384     (trace_msg ctxt (fn () => "MaSh ADD " ^
   378          elide_string 1000 (space_implode " " (map #1 upds)));
   385          elide_string 1000 (space_implode " " (map #1 upds)));
   379      run_mash_commands ctxt overlord true
   386      run_mash_commands ctxt overlord true 0
   380          (fn append => List.app (append o str_of_update) upds) (K ()))
   387          (fn append => List.app (append o str_of_update) upds) (K ()))
   381 
   388 
   382 fun mash_QUERY ctxt overlord (query as (_, feats)) =
   389 fun mash_QUERY ctxt overlord max_suggs (query as (_, feats)) =
   383   (trace_msg ctxt (fn () => "MaSh QUERY " ^ space_implode " " feats);
   390   (trace_msg ctxt (fn () => "MaSh QUERY " ^ space_implode " " feats);
   384    run_mash_commands ctxt overlord false
   391    run_mash_commands ctxt overlord false max_suggs
   385        (fn append => append (str_of_query query))
   392        (fn append => append (str_of_query query))
   386        (fn preds => snd (extract_query (List.last (preds ()))))
   393        (fn suggs => snd (extract_query (List.last (suggs ()))))
   387    handle List.Empty => [])
   394    handle List.Empty => [])
   388 
   395 
   389 
   396 
   390 (*** High-level communication with MaSh ***)
   397 (*** High-level communication with MaSh ***)
   391 
   398 
   421 
   428 
   422 fun mash_save ({thys, fact_graph, ...} : mash_state) =
   429 fun mash_save ({thys, fact_graph, ...} : mash_state) =
   423   let
   430   let
   424     val path = mash_state_path ()
   431     val path = mash_state_path ()
   425     val thys = Symtab.dest thys
   432     val thys = Symtab.dest thys
   426     fun line_for_thys comp = AList.find (op =) thys comp |> escape_metas
   433     val line_for_thys = escape_metas o AList.find (op =) thys
   427     fun fact_line_for name parents = name :: parents |> escape_metas
   434     fun fact_line_for name parents =
       
   435       escape_meta name ^ ": " ^ escape_metas parents
   428     val append_fact = File.append path o suffix "\n" oo fact_line_for
   436     val append_fact = File.append path o suffix "\n" oo fact_line_for
   429   in
   437   in
   430     File.write path (line_for_thys true ^ "\n" ^ line_for_thys false ^ "\n");
   438     File.write path (line_for_thys true ^ "\n" ^ line_for_thys false ^ "\n");
   431     Graph.fold (fn (name, ((), (parents, _))) => fn () =>
   439     Graph.fold (fn (name, ((), (parents, _))) => fn () =>
   432                    append_fact name (Graph.Keys.dest parents))
   440                    append_fact name (Graph.Keys.dest parents))
   448       (mash_RESET ctxt; File.write (mash_state_path ()) "";
   456       (mash_RESET ctxt; File.write (mash_state_path ()) "";
   449        (true, empty_state)))
   457        (true, empty_state)))
   450 
   458 
   451 end
   459 end
   452 
   460 
   453 fun mash_can_suggest_facts (_ : Proof.context) =
   461 fun mash_could_suggest_facts () = mash_home () <> ""
   454   mash_home () <> "" andalso not (Graph.is_empty (#fact_graph (mash_get ())))
   462 fun mash_can_suggest_facts () = not (Graph.is_empty (#fact_graph (mash_get ())))
   455 
   463 
   456 fun parents_wrt facts fact_graph =
   464 fun parents_wrt_facts facts fact_graph =
   457   let
   465   let
       
   466     val graph_facts = Symtab.make (map (rpair ()) (Graph.keys fact_graph))
   458     val facts =
   467     val facts =
   459       Symtab.empty
   468       [] |> fold (cons o Thm.get_name_hint o snd) facts
   460       |> fold (fn (_, th) => Symtab.update (Thm.get_name_hint th, ())) facts
   469          |> filter (Symtab.defined graph_facts)
       
   470          |> Graph.all_preds fact_graph
       
   471     val facts = Symtab.empty |> fold (fn name => Symtab.update (name, ())) facts
   461   in fact_graph |> Graph.restrict (Symtab.defined facts) |> Graph.maximals end
   472   in fact_graph |> Graph.restrict (Symtab.defined facts) |> Graph.maximals end
   462 
   473 
   463 fun mash_suggest_facts ctxt ({overlord, ...} : params) prover hyp_ts concl_t
   474 (* Generate more suggestions than requested, because some might be thrown out
   464                        facts =
   475    later for various reasons and "meshing" gives better results with some
       
   476    slack. *)
       
   477 fun max_suggs_of max_facts = max_facts + Int.min (200, max_facts)
       
   478 
       
   479 fun mash_suggest_facts ctxt ({overlord, ...} : params) prover max_facts hyp_ts
       
   480                        concl_t facts =
   465   let
   481   let
   466     val thy = Proof_Context.theory_of ctxt
   482     val thy = Proof_Context.theory_of ctxt
   467     val fact_graph = #fact_graph (mash_get ())
   483     val fact_graph = #fact_graph (mash_get ())
   468     val parents = parents_wrt facts fact_graph
   484 val _ = warning (PolyML.makestring (length (fact_graph |> Graph.keys), length (fact_graph |> Graph.maximals),
   469     val feats = features_of thy General (concl_t :: hyp_ts)
   485 length (fact_graph |> Graph.minimals))) (*###*)
   470     val suggs = mash_QUERY ctxt overlord (parents, feats)
   486     val parents = parents_wrt_facts facts fact_graph
       
   487     val feats = features_of ctxt prover thy General (concl_t :: hyp_ts)
       
   488     val suggs =
       
   489       mash_QUERY ctxt overlord (max_suggs_of max_facts) (parents, feats)
   471   in suggested_facts suggs facts end
   490   in suggested_facts suggs facts end
   472 
   491 
   473 fun add_thys_for thy =
   492 fun add_thys_for thy =
   474   let fun add comp thy = Symtab.update (Context.theory_name thy, comp) in
   493   let fun add comp thy = Symtab.update (Context.theory_name thy, comp) in
   475     add false thy #> fold (add true) (Theory.ancestors_of thy)
   494     add false thy #> fold (add true) (Theory.ancestors_of thy)
   487     val graph = graph |> Graph.new_node (name, ())
   506     val graph = graph |> Graph.new_node (name, ())
   488     val (parents, graph) = ([], graph) |> fold maybe_add_from parents
   507     val (parents, graph) = ([], graph) |> fold maybe_add_from parents
   489     val (deps, graph) = ([], graph) |> fold maybe_add_from deps
   508     val (deps, graph) = ([], graph) |> fold maybe_add_from deps
   490   in ((name, parents, feats, deps) :: upds, graph) end
   509   in ((name, parents, feats, deps) :: upds, graph) end
   491 
   510 
   492 fun mash_learn_thy ctxt ({overlord, ...} : params) thy timeout =
   511 val pass1_learn_timeout_factor = 0.5
   493   let
   512 val pass2_learn_timeout_factor = 10.0
   494     val css_table = Sledgehammer_Fact.clasimpset_rule_table_of ctxt
   513 
       
   514 (* The timeout is understood in a very slack fashion. *)
       
   515 fun mash_learn_thy ctxt ({provers, verbose, overlord, ...} : params) thy
       
   516                    timeout =
       
   517   let
       
   518     val timer = Timer.startRealTimer ()
       
   519     val prover = hd provers
       
   520     fun timed_out frac =
       
   521       Time.> (Timer.checkRealTimer timer, time_mult frac timeout)
       
   522     val css_table = clasimpset_rule_table_of ctxt
   495     val facts = all_facts_of thy css_table
   523     val facts = all_facts_of thy css_table
   496     val {fact_graph, ...} = mash_get ()
   524     val {fact_graph, ...} = mash_get ()
   497     fun is_old (_, th) = can (Graph.get_node fact_graph) (Thm.get_name_hint th)
   525     fun is_old (_, th) = can (Graph.get_node fact_graph) (Thm.get_name_hint th)
   498     val new_facts = facts |> filter_out is_old |> sort (thm_ord o pairself snd)
   526     val new_facts = facts |> filter_out is_old |> sort (thm_ord o pairself snd)
   499   in
   527   in
   500     if null new_facts then
   528     if null new_facts then
   501       ()
   529       ()
   502     else
   530     else
   503       let
   531       let
       
   532         val n = length new_facts
       
   533         val _ =
       
   534           if verbose then
       
   535             "MaShing " ^ string_of_int n ^ " fact" ^ plural_s n ^
       
   536             " (advisory timeout: " ^ string_from_time timeout ^ ")..."
       
   537             |> Output.urgent_message
       
   538           else
       
   539             ()
   504         val ths = facts |> map snd
   540         val ths = facts |> map snd
   505         val all_names =
   541         val all_names =
   506           ths |> filter_out (is_likely_tautology orf is_too_meta)
   542           ths |> filter_out (is_likely_tautology ctxt prover orf is_too_meta)
   507               |> map (rpair () o Thm.get_name_hint)
   543               |> map (rpair () o Thm.get_name_hint)
   508               |> Symtab.make
   544               |> Symtab.make
   509         fun do_fact ((_, (_, status)), th) (parents, upds) =
   545         fun do_fact _ (accum as (_, true)) = accum
   510           let
   546           | do_fact ((_, (_, status)), th) ((parents, upds), false) =
   511             val name = Thm.get_name_hint th
   547             let
   512             val feats = features_of thy status [prop_of th]
   548               val name = Thm.get_name_hint th
   513             val deps = isabelle_dependencies_of all_names th
   549               val feats = features_of ctxt prover thy status [prop_of th]
   514             val upd = (name, parents, feats, deps)
   550               val deps = isabelle_dependencies_of all_names th
   515           in ([name], upd :: upds) end
   551               val upd = (name, parents, feats, deps)
   516         val parents = parents_wrt facts fact_graph
   552             in (([name], upd :: upds), timed_out pass1_learn_timeout_factor) end
   517         val (_, upds) = (parents, []) |> fold do_fact new_facts ||> rev
   553         val parents = parents_wrt_facts facts fact_graph
       
   554         val ((_, upds), _) =
       
   555           ((parents, []), false) |> fold do_fact new_facts |>> apsnd rev
       
   556         val n = length upds
   518         fun trans {thys, fact_graph} =
   557         fun trans {thys, fact_graph} =
   519           let
   558           let
   520             val mash_INIT_or_ADD =
   559             val mash_INIT_or_ADD =
   521               if Graph.is_empty fact_graph then mash_INIT else mash_ADD
   560               if Graph.is_empty fact_graph then mash_INIT else mash_ADD
   522             val (upds, fact_graph) =
   561             val (upds, fact_graph) =
   524           in
   563           in
   525             (mash_INIT_or_ADD ctxt overlord (rev upds);
   564             (mash_INIT_or_ADD ctxt overlord (rev upds);
   526              {thys = thys |> add_thys_for thy,
   565              {thys = thys |> add_thys_for thy,
   527               fact_graph = fact_graph})
   566               fact_graph = fact_graph})
   528           end
   567           end
   529       in mash_map trans end
   568       in
   530   end
   569         TimeLimit.timeLimit (time_mult pass2_learn_timeout_factor timeout)
   531 
   570                             mash_map trans
   532 fun mash_learn_proof ctxt ({overlord, ...} : params) t used_ths facts =
   571         handle TimeLimit.TimeOut =>
       
   572                (if verbose then
       
   573                   "MaSh timed out trying to learn " ^ string_of_int n ^
       
   574                   " fact" ^ plural_s n ^ " in " ^
       
   575                   string_from_time (Timer.checkRealTimer timer) ^ "."
       
   576                   |> Output.urgent_message
       
   577                 else
       
   578                   ());
       
   579         (if verbose then
       
   580            "MaSh learned " ^ string_of_int n ^ " fact" ^ plural_s n ^ " in " ^
       
   581            string_from_time (Timer.checkRealTimer timer) ^ "."
       
   582            |> Output.urgent_message
       
   583          else
       
   584            ())
       
   585       end
       
   586   end
       
   587 
       
   588 fun mash_learn_proof ctxt ({provers, overlord, ...} : params) t used_ths facts =
   533   let
   589   let
   534     val thy = Proof_Context.theory_of ctxt
   590     val thy = Proof_Context.theory_of ctxt
   535     val name = ATP_Util.timestamp () (* should be fairly fresh *)
   591     val prover = hd provers
   536     val feats = features_of thy General [t]
   592     val name = ATP_Util.timestamp () ^ serial_string () (* fresh enough *)
       
   593     val feats = features_of ctxt prover thy General [t]
   537     val deps = used_ths |> map Thm.get_name_hint
   594     val deps = used_ths |> map Thm.get_name_hint
   538   in
   595   in
   539     mash_map (fn {thys, fact_graph} =>
   596     mash_map (fn {thys, fact_graph} =>
   540         let
   597         let
   541           val parents = parents_wrt facts fact_graph
   598           val parents = parents_wrt_facts facts fact_graph
   542           val upds = [(name, parents, feats, deps)]
   599           val upds = [(name, parents, feats, deps)]
   543           val (upds, fact_graph) =
   600           val (upds, fact_graph) =
   544             ([], fact_graph) |> fold (update_fact_graph ctxt) upds
   601             ([], fact_graph) |> fold (update_fact_graph ctxt) upds
   545         in
   602         in
   546           mash_ADD ctxt overlord upds;
   603           mash_ADD ctxt overlord upds;
   547           {thys = thys, fact_graph = fact_graph}
   604           {thys = thys, fact_graph = fact_graph}
   548         end)
   605         end)
   549   end
   606   end
   550 
   607 
   551 fun relevant_facts ctxt (params as {fact_filter, ...}) prover max_facts
   608 (* The threshold should be large enough so that MaSh doesn't kick in for Auto
       
   609    Sledgehammer and Try. *)
       
   610 val min_secs_for_learning = 15
       
   611 val short_learn_timeout_factor = 0.2
       
   612 val long_learn_timeout_factor = 4.0
       
   613 
       
   614 fun relevant_facts ctxt (params as {fact_filter, timeout, ...}) prover max_facts
   552         ({add, only, ...} : fact_override) hyp_ts concl_t facts =
   615         ({add, only, ...} : fact_override) hyp_ts concl_t facts =
   553   if not (subset (op =) (the_list fact_filter, fact_filters)) then
   616   if not (subset (op =) (the_list fact_filter, fact_filters)) then
   554     error ("Unknown fact filter: " ^ quote (the fact_filter) ^ ".")
   617     error ("Unknown fact filter: " ^ quote (the fact_filter) ^ ".")
   555   else if only then
   618   else if only then
   556     facts
   619     facts
   557   else if max_facts <= 0 then
   620   else if max_facts <= 0 then
   558     []
   621     []
   559   else
   622   else
   560     let
   623     let
       
   624       val thy = Proof_Context.theory_of ctxt
       
   625       fun maybe_learn can_suggest =
       
   626         if Time.toSeconds timeout >= min_secs_for_learning then
       
   627           if Multithreading.enabled () then
       
   628             let
       
   629               val factor =
       
   630                 if can_suggest then short_learn_timeout_factor
       
   631                 else long_learn_timeout_factor
       
   632             in
       
   633               Future.fork (fn () => mash_learn_thy ctxt params thy
       
   634                                         (time_mult factor timeout)); ()
       
   635             end
       
   636           else
       
   637             mash_learn_thy ctxt params thy
       
   638                            (time_mult short_learn_timeout_factor timeout)
       
   639         else
       
   640           ()
   561       val fact_filter =
   641       val fact_filter =
   562         case fact_filter of
   642         case fact_filter of
   563           SOME ff => ff
   643           SOME ff =>
   564         | NONE => if mash_can_suggest_facts ctxt then meshN else iterN
   644           (if ff <> iterN then maybe_learn (mash_can_suggest_facts ()) else ();
       
   645            ff)
       
   646         | NONE =>
       
   647           if mash_can_suggest_facts () then (maybe_learn true; meshN)
       
   648           else if mash_could_suggest_facts () then (maybe_learn false; iterN)
       
   649           else iterN
   565       val add_ths = Attrib.eval_thms ctxt add
   650       val add_ths = Attrib.eval_thms ctxt add
   566       fun prepend_facts ths accepts =
   651       fun prepend_facts ths accepts =
   567         ((facts |> filter (member Thm.eq_thm_prop ths o snd)) @
   652         ((facts |> filter (member Thm.eq_thm_prop ths o snd)) @
   568          (accepts |> filter_out (member Thm.eq_thm_prop ths o snd)))
   653          (accepts |> filter_out (member Thm.eq_thm_prop ths o snd)))
   569         |> take max_facts
   654         |> take max_facts
   570       fun iter () =
   655       fun iter () =
   571         iterative_relevant_facts ctxt params prover max_facts NONE hyp_ts
   656         iterative_relevant_facts ctxt params prover max_facts NONE hyp_ts
   572                                  concl_t facts
   657                                  concl_t facts
   573         |> (fn facts => (facts, SOME (length facts)))
   658         |> (fn facts => (facts, SOME (length facts)))
   574       fun mash () =
   659       fun mash () =
   575         (facts |> mash_suggest_facts ctxt params prover hyp_ts concl_t, NONE)
   660         (mash_suggest_facts ctxt params prover max_facts hyp_ts concl_t facts,
       
   661          NONE)
   576       val mess =
   662       val mess =
   577         [] |> (if fact_filter <> mashN then cons (iter ()) else I)
   663         [] |> (if fact_filter <> mashN then cons (iter ()) else I)
   578            |> (if fact_filter <> iterN then cons (mash ()) else I)
   664            |> (if fact_filter <> iterN then cons (mash ()) else I)
   579     in
   665     in
   580       mesh_facts max_facts mess
   666       mesh_facts max_facts mess