tune
authorblanchet
Mon May 19 23:43:53 2014 +0200 (2014-05-19)
changeset 5700620e5b110d19b
parent 57005 33f3d2ea803d
child 57007 d3eed0518882
tune
src/HOL/Tools/Sledgehammer/sledgehammer_mash.ML
     1.1 --- a/src/HOL/Tools/Sledgehammer/sledgehammer_mash.ML	Mon May 19 23:43:53 2014 +0200
     1.2 +++ b/src/HOL/Tools/Sledgehammer/sledgehammer_mash.ML	Mon May 19 23:43:53 2014 +0200
     1.3 @@ -37,64 +37,51 @@
     1.4    structure MaSh:
     1.5    sig
     1.6      val unlearn : Proof.context -> bool -> unit
     1.7 -    val learn :
     1.8 -      Proof.context -> bool -> bool
     1.9 -      -> (string * string list * string list list * string list) list -> unit
    1.10 -    val relearn :
    1.11 -      Proof.context -> bool -> bool -> (string * string list) list -> unit
    1.12 -    val query :
    1.13 -      Proof.context -> bool -> int
    1.14 -      -> (string * string list * string list list * string list) list
    1.15 -         * string list * string list * (string list * real) list
    1.16 -      -> string list
    1.17 +    val learn : Proof.context -> bool -> bool ->
    1.18 +      (string * string list * string list list * string list) list -> unit
    1.19 +    val relearn : Proof.context -> bool -> bool -> (string * string list) list -> unit
    1.20 +    val query : Proof.context -> bool -> int ->
    1.21 +      (string * string list * string list list * string list) list * string list * string list *
    1.22 +        (string list * real) list ->
    1.23 +      string list
    1.24    end
    1.25  
    1.26    val mash_unlearn : Proof.context -> params -> unit
    1.27    val is_mash_enabled : unit -> bool
    1.28    val nickname_of_thm : thm -> string
    1.29 -  val find_suggested_facts :
    1.30 -    Proof.context -> ('b * thm) list -> string list -> ('b * thm) list
    1.31 -  val mesh_facts :
    1.32 -    ('a * 'a -> bool) -> int -> (real * (('a * real) list * 'a list)) list
    1.33 -    -> 'a list
    1.34 +  val find_suggested_facts : Proof.context -> ('b * thm) list -> string list -> ('b * thm) list
    1.35 +  val mesh_facts : ('a * 'a -> bool) -> int -> (real * (('a * real) list * 'a list)) list -> 'a list
    1.36    val crude_thm_ord : thm * thm -> order
    1.37    val thm_less : thm * thm -> bool
    1.38    val goal_of_thm : theory -> thm -> thm
    1.39 -  val run_prover_for_mash :
    1.40 -    Proof.context -> params -> string -> string -> fact list -> thm -> prover_result
    1.41 -  val features_of :
    1.42 -    Proof.context -> theory -> int -> int Symtab.table -> stature -> bool -> term list ->
    1.43 -    (string list * real) list
    1.44 +  val run_prover_for_mash : Proof.context -> params -> string -> string -> fact list -> thm ->
    1.45 +    prover_result
    1.46 +  val features_of : Proof.context -> theory -> int -> int Symtab.table -> stature -> bool ->
    1.47 +    term list -> (string list * real) list
    1.48    val trim_dependencies : string list -> string list option
    1.49 -  val isar_dependencies_of :
    1.50 -    string Symtab.table * string Symtab.table -> thm -> string list
    1.51 -  val prover_dependencies_of :
    1.52 -    Proof.context -> params -> string -> int -> raw_fact list
    1.53 -    -> string Symtab.table * string Symtab.table -> thm
    1.54 -    -> bool * string list
    1.55 -  val attach_parents_to_facts :
    1.56 -    ('a * thm) list -> ('a * thm) list -> (string list * ('a * thm)) list
    1.57 +  val isar_dependencies_of : string Symtab.table * string Symtab.table -> thm -> string list
    1.58 +  val prover_dependencies_of : Proof.context -> params -> string -> int -> raw_fact list ->
    1.59 +    string Symtab.table * string Symtab.table -> thm -> bool * string list
    1.60 +  val attach_parents_to_facts : ('a * thm) list -> ('a * thm) list ->
    1.61 +    (string list * ('a * thm)) list
    1.62    val num_extra_feature_facts : int
    1.63    val extra_feature_factor : real
    1.64    val weight_facts_smoothly : 'a list -> ('a * real) list
    1.65    val weight_facts_steeply : 'a list -> ('a * real) list
    1.66 -  val find_mash_suggestions :
    1.67 -    Proof.context -> int -> string list -> ('b * thm) list -> ('b * thm) list
    1.68 -    -> ('b * thm) list -> ('b * thm) list * ('b * thm) list
    1.69 +  val find_mash_suggestions : Proof.context -> int -> string list -> ('b * thm) list ->
    1.70 +    ('b * thm) list -> ('b * thm) list -> ('b * thm) list * ('b * thm) list
    1.71    val add_const_counts : term -> int Symtab.table -> int Symtab.table
    1.72 -  val mash_suggested_facts :
    1.73 -    Proof.context -> params -> int -> term list -> term -> raw_fact list -> fact list * fact list
    1.74 +  val mash_suggested_facts : Proof.context -> params -> int -> term list -> term -> raw_fact list ->
    1.75 +    fact list * fact list
    1.76    val mash_learn_proof : Proof.context -> params -> term -> ('a * thm) list -> thm list -> unit
    1.77 -  val mash_learn :
    1.78 -    Proof.context -> params -> fact_override -> thm list -> bool -> unit
    1.79 +  val mash_learn : Proof.context -> params -> fact_override -> thm list -> bool -> unit
    1.80  
    1.81    val mash_can_suggest_facts : Proof.context -> bool -> bool
    1.82    val generous_max_facts : int -> int
    1.83    val mepo_weight : real
    1.84    val mash_weight : real
    1.85 -  val relevant_facts :
    1.86 -    Proof.context -> params -> string -> int -> fact_override -> term list
    1.87 -    -> term -> raw_fact list -> (string * fact list) list
    1.88 +  val relevant_facts : Proof.context -> params -> string -> int -> fact_override -> term list ->
    1.89 +    term -> raw_fact list -> (string * fact list) list
    1.90    val kill_learners : Proof.context -> params -> unit
    1.91    val running_learners : unit -> unit
    1.92  end;
    1.93 @@ -130,8 +117,7 @@
    1.94  val relearn_isarN = "relearn_isar"
    1.95  val relearn_proverN = "relearn_prover"
    1.96  
    1.97 -fun mash_model_dir () =
    1.98 -  Path.explode "$ISABELLE_HOME_USER/mash" |> tap Isabelle_System.mkdir
    1.99 +fun mash_model_dir () = Path.explode "$ISABELLE_HOME_USER/mash" |> tap Isabelle_System.mkdir
   1.100  val mash_state_dir = mash_model_dir
   1.101  fun mash_state_file () = Path.append (mash_state_dir ()) (Path.explode "state")
   1.102  
   1.103 @@ -176,9 +162,9 @@
   1.104      fun run_on () =
   1.105        (Isabelle_System.bash command
   1.106         |> tap (fn _ =>
   1.107 -            (case try File.read (Path.explode err_file) |> the_default "" of
   1.108 -              "" => trace_msg ctxt (K "Done")
   1.109 -            | s => warning ("MaSh error: " ^ elide_string 1000 s)));
   1.110 +         (case try File.read (Path.explode err_file) |> the_default "" of
   1.111 +           "" => trace_msg ctxt (K "Done")
   1.112 +         | s => warning ("MaSh error: " ^ elide_string 1000 s)));
   1.113         read_suggs (fn () => try File.read_lines sugg_path |> these))
   1.114      fun clean_up () =
   1.115        if overlord then () else List.app wipe_out_file [err_file, sugg_file, cmd_file]
   1.116 @@ -190,8 +176,8 @@
   1.117    end
   1.118  
   1.119  fun meta_char c =
   1.120 -  if Char.isAlphaNum c orelse c = #"_" orelse c = #"." orelse c = #"(" orelse
   1.121 -     c = #")" orelse c = #"," then
   1.122 +  if Char.isAlphaNum c orelse c = #"_" orelse c = #"." orelse c = #"(" orelse c = #")" orelse
   1.123 +     c = #"," then
   1.124      String.str c
   1.125    else
   1.126      (* fixed width, in case more digits follow *)
   1.127 @@ -221,7 +207,8 @@
   1.128  val decode_unweighted_feature = space_explode "|" #> map decode_str
   1.129  
   1.130  fun encode_feature (names, weight) =
   1.131 -  encode_unweighted_feature names ^ (if Real.== (weight, 1.0) then "" else "=" ^ safe_str_of_real weight)
   1.132 +  encode_unweighted_feature names ^
   1.133 +  (if Real.== (weight, 1.0) then "" else "=" ^ safe_str_of_real weight)
   1.134  
   1.135  val encode_unweighted_features = map encode_unweighted_feature #> space_implode " "
   1.136  val decode_unweighted_features = space_explode " " #> map decode_unweighted_feature
   1.137 @@ -266,27 +253,25 @@
   1.138    let val path = mash_model_dir () in
   1.139      trace_msg ctxt (K "MaSh unlearn");
   1.140      shutdown ctxt overlord;
   1.141 -    try (File.fold_dir (fn file => fn _ =>
   1.142 -                           try File.rm (Path.append path (Path.basic file)))
   1.143 -                       path) NONE;
   1.144 +    try (File.fold_dir (fn file => fn _ => try File.rm (Path.append path (Path.basic file))) path)
   1.145 +      NONE;
   1.146      ()
   1.147    end
   1.148  
   1.149  fun learn _ _ _ [] = ()
   1.150 -  | learn ctxt overlord save (learns : (string * string list * string list list * string list) list) (*##*)
   1.151 -   =
   1.152 +  | learn ctxt overlord save learns =
   1.153      let val names = elide_string 1000 (space_implode " " (map #1 learns)) in
   1.154        (trace_msg ctxt (fn () => "MaSh learn" ^ (if names = "" then "" else " " ^ names));
   1.155 -       run_mash_tool ctxt overlord ([] |> save ? cons save_models_arg) false
   1.156 -                     (learns, str_of_learn) (K ()))
   1.157 +       run_mash_tool ctxt overlord ([] |> save ? cons save_models_arg) false (learns, str_of_learn)
   1.158 +         (K ()))
   1.159      end
   1.160  
   1.161  fun relearn _ _ _ [] = ()
   1.162    | relearn ctxt overlord save relearns =
   1.163      (trace_msg ctxt (fn () => "MaSh relearn " ^
   1.164 -         elide_string 1000 (space_implode " " (map #1 relearns)));
   1.165 +       elide_string 1000 (space_implode " " (map #1 relearns)));
   1.166       run_mash_tool ctxt overlord ([] |> save ? cons save_models_arg) false
   1.167 -                   (relearns, str_of_relearn) (K ()))
   1.168 +       (relearns, str_of_relearn) (K ()))
   1.169  
   1.170  fun query ctxt overlord max_suggs (query as (_, _, _, feats)) =
   1.171    (trace_msg ctxt (fn () => "MaSh query " ^ encode_features feats);
   1.172 @@ -329,8 +314,7 @@
   1.173  
   1.174  fun graph_info G =
   1.175    string_of_int (length (Graph.keys G)) ^ " node(s), " ^
   1.176 -  string_of_int (fold (Integer.add o length o snd) (Graph.dest G) 0) ^
   1.177 -  " edge(s), " ^
   1.178 +  string_of_int (fold (Integer.add o length o snd) (Graph.dest G) 0) ^ " edge(s), " ^
   1.179    string_of_int (length (Graph.minimals G)) ^ " minimal, " ^
   1.180    string_of_int (length (Graph.maximals G)) ^ " maximal"
   1.181  
   1.182 @@ -442,8 +426,7 @@
   1.183  val local_prefix = "local" ^ Long_Name.separator
   1.184  
   1.185  fun elided_backquote_thm threshold th =
   1.186 -  elide_string threshold
   1.187 -    (backquote_thm (Proof_Context.init_global (Thm.theory_of_thm th)) th)
   1.188 +  elide_string threshold (backquote_thm (Proof_Context.init_global (Thm.theory_of_thm th)) th)
   1.189  
   1.190  val thy_name_of_thm = Context.theory_name o Thm.theory_of_thm
   1.191  
   1.192 @@ -466,41 +449,37 @@
   1.193      val tab = fold add facts Symtab.empty
   1.194      fun lookup nick =
   1.195        Symtab.lookup tab nick
   1.196 -      |> tap (fn NONE => trace_msg ctxt (fn () => "Cannot find " ^ quote nick)
   1.197 -               | _ => ())
   1.198 +      |> tap (fn NONE => trace_msg ctxt (fn () => "Cannot find " ^ quote nick) | _ => ())
   1.199    in map_filter lookup end
   1.200  
   1.201  fun scaled_avg [] = 0
   1.202 -  | scaled_avg xs =
   1.203 -    Real.ceil (100000000.0 * fold (curry (op +)) xs 0.0) div length xs
   1.204 +  | scaled_avg xs = Real.ceil (100000000.0 * fold (curry (op +)) xs 0.0) div length xs
   1.205  
   1.206  fun avg [] = 0.0
   1.207    | avg xs = fold (curry (op +)) xs 0.0 / Real.fromInt (length xs)
   1.208  
   1.209  fun normalize_scores _ [] = []
   1.210    | normalize_scores max_facts xs =
   1.211 -    let val avg = avg (map snd (take max_facts xs)) in
   1.212 -      map (apsnd (curry Real.* (1.0 / avg))) xs
   1.213 -    end
   1.214 +    map (apsnd (curry Real.* (1.0 / avg (map snd (take max_facts xs))))) xs
   1.215  
   1.216  fun mesh_facts _ max_facts [(_, (sels, unks))] =
   1.217      map fst (take max_facts sels) @ take (max_facts - length sels) unks
   1.218    | mesh_facts fact_eq max_facts mess =
   1.219      let
   1.220        val mess = mess |> map (apsnd (apfst (normalize_scores max_facts)))
   1.221 +
   1.222        fun score_in fact (global_weight, (sels, unks)) =
   1.223 -        let
   1.224 -          val score_at = try (nth sels) #> Option.map (fn (_, score) => global_weight * score)
   1.225 -        in
   1.226 +        let val score_at = try (nth sels) #> Option.map (fn (_, score) => global_weight * score) in
   1.227            (case find_index (curry fact_eq fact o fst) sels of
   1.228              ~1 => if member fact_eq unks fact then NONE else SOME 0.0
   1.229            | rank => score_at rank)
   1.230          end
   1.231 +
   1.232        fun weight_of fact = mess |> map_filter (score_in fact) |> scaled_avg
   1.233 -      val facts = fold (union fact_eq o map fst o take max_facts o fst o snd) mess []
   1.234      in
   1.235 -      facts |> map (`weight_of) |> sort (int_ord o swap o pairself fst)
   1.236 -            |> map snd |> take max_facts
   1.237 +      fold (union fact_eq o map fst o take max_facts o fst o snd) mess []
   1.238 +      |> map (`weight_of) |> sort (int_ord o swap o pairself fst)
   1.239 +      |> map snd |> take max_facts
   1.240      end
   1.241  
   1.242  val default_weight = 1.0
   1.243 @@ -563,12 +542,10 @@
   1.244  (* try "Long_Name.base_name" for shorter names *)
   1.245  fun massage_long_name s = if s = @{class type} then "T" else s
   1.246  
   1.247 -val crude_str_of_sort =
   1.248 -  space_implode ":" o map massage_long_name o subtract (op =) @{sort type}
   1.249 +val crude_str_of_sort = space_implode ":" o map massage_long_name o subtract (op =) @{sort type}
   1.250  
   1.251  fun crude_str_of_typ (Type (s, [])) = massage_long_name s
   1.252 -  | crude_str_of_typ (Type (s, Ts)) =
   1.253 -    massage_long_name s ^ implode (map crude_str_of_typ Ts)
   1.254 +  | crude_str_of_typ (Type (s, Ts)) = massage_long_name s ^ implode (map crude_str_of_typ Ts)
   1.255    | crude_str_of_typ (TFree (_, S)) = crude_str_of_sort S
   1.256    | crude_str_of_typ (TVar (_, S)) = crude_str_of_sort S
   1.257  
   1.258 @@ -585,6 +562,7 @@
   1.259  fun sort_of_type alg T =
   1.260    let
   1.261      val graph = Sorts.classes_of alg
   1.262 +
   1.263      fun cls_of S [] = S
   1.264        | cls_of S (cl :: cls) =
   1.265          if Sorts.of_sort alg (T, [cl]) then
   1.266 @@ -610,10 +588,10 @@
   1.267      fun add_classes @{sort type} = I
   1.268        | add_classes S =
   1.269          fold (`(Sorts.super_classes classes)
   1.270 -              #> swap #> op ::
   1.271 -              #> subtract (op =) @{sort type} #> map massage_long_name
   1.272 -              #> map class_feature_of
   1.273 -              #> union (eq_fst (op =))) S
   1.274 +          #> swap #> op ::
   1.275 +          #> subtract (op =) @{sort type} #> map massage_long_name
   1.276 +          #> map class_feature_of
   1.277 +          #> union (eq_fst (op =))) S
   1.278  
   1.279      fun pattify_type 0 _ = []
   1.280        | pattify_type _ (Type (s, [])) =
   1.281 @@ -623,19 +601,25 @@
   1.282            val T = Type (s, Ts)
   1.283            val ps = keep max_pat_breadth (pattify_type depth T)
   1.284            val qs = keep max_pat_breadth ("" :: pattify_type (depth - 1) U)
   1.285 -        in map_product (fn p => fn "" => p | q => p ^ "(" ^ q ^ ")") ps qs end
   1.286 +        in
   1.287 +          map_product (fn p => fn "" => p | q => p ^ "(" ^ q ^ ")") ps qs
   1.288 +        end
   1.289        | pattify_type _ (TFree (_, S)) =
   1.290          maybe_singleton_str pat_tvar_prefix (crude_str_of_sort S)
   1.291        | pattify_type _ (TVar (_, S)) =
   1.292          maybe_singleton_str pat_tvar_prefix (crude_str_of_sort S)
   1.293 +
   1.294      fun add_type_pat depth T =
   1.295        union (eq_fst (op =)) (map type_feature_of (pattify_type depth T))
   1.296 +
   1.297      fun add_type_pats 0 _ = I
   1.298        | add_type_pats depth t =
   1.299          add_type_pat depth t #> add_type_pats (depth - 1) t
   1.300 +
   1.301      fun add_type T =
   1.302        add_type_pats type_max_depth T
   1.303        #> fold_atyps_sorts (add_classes o snd) T
   1.304 +
   1.305      fun add_subtypes (T as Type (_, Ts)) = add_type T #> fold add_subtypes Ts
   1.306        | add_subtypes T = add_type T
   1.307  
   1.308 @@ -647,6 +631,7 @@
   1.309           let val count = Symtab.lookup const_tab s |> the_default 1 in
   1.310             Real.fromInt num_facts / Real.fromInt count (* FUDGE *)
   1.311           end)
   1.312 +
   1.313      fun pattify_term _ 0 _ = ([] : (string list * real) list)
   1.314        | pattify_term _ _ (Const (x as (s, _))) =
   1.315          if is_widely_irrelevant_const s then
   1.316 @@ -699,11 +684,15 @@
   1.317                 | (q :: _, qw) => ([p ^ "(" ^ q ^ ")"], pw + qw)) ps qs
   1.318          end
   1.319        | pattify_term _ _ _ = []
   1.320 +
   1.321      fun add_term_pat Ts = union (eq_fst (op =)) oo pattify_term Ts
   1.322 +
   1.323      fun add_term_pats _ 0 _ = I
   1.324        | add_term_pats Ts depth t =
   1.325          add_term_pat Ts depth t #> add_term_pats Ts (depth - 1) t
   1.326 +
   1.327      fun add_term Ts = add_term_pats Ts term_max_depth
   1.328 +
   1.329      fun add_subterms Ts t =
   1.330        (case strip_comb t of
   1.331          (Const (s, T), args) =>
   1.332 @@ -717,7 +706,9 @@
   1.333           | Abs (_, T, body) => add_subtypes T #> add_subterms (T :: Ts) body
   1.334           | _ => I)
   1.335          #> fold (add_subterms Ts) args)
   1.336 -  in [] |> fold (add_subterms []) ts end
   1.337 +  in
   1.338 +    fold (add_subterms []) ts []
   1.339 +  end
   1.340  
   1.341  val term_max_depth = 2
   1.342  val type_max_depth = 1
   1.343 @@ -730,40 +721,37 @@
   1.344      |> scope <> Global ? cons local_feature
   1.345    end
   1.346  
   1.347 -(* Too many dependencies is a sign that a decision procedure is at work. There
   1.348 -   is not much to learn from such proofs. *)
   1.349 +(* Too many dependencies is a sign that a decision procedure is at work. There is not much to learn
   1.350 +   from such proofs. *)
   1.351  val max_dependencies = 20
   1.352  
   1.353  val prover_default_max_facts = 25
   1.354  
   1.355  (* "type_definition_xxx" facts are characterized by their use of "CollectI". *)
   1.356  val typedef_dep = nickname_of_thm @{thm CollectI}
   1.357 -(* Mysterious parts of the class machinery create lots of proofs that refer
   1.358 -   exclusively to "someI_ex" (and to some internal constructions). *)
   1.359 +(* Mysterious parts of the class machinery create lots of proofs that refer exclusively to
   1.360 +   "someI_ex" (and to some internal constructions). *)
   1.361  val class_some_dep = nickname_of_thm @{thm someI_ex}
   1.362  
   1.363  val fundef_ths =
   1.364 -  @{thms fundef_ex1_existence fundef_ex1_uniqueness fundef_ex1_iff
   1.365 -         fundef_default_value}
   1.366 +  @{thms fundef_ex1_existence fundef_ex1_uniqueness fundef_ex1_iff fundef_default_value}
   1.367    |> map nickname_of_thm
   1.368  
   1.369  (* "Rep_xxx_inject", "Abs_xxx_inverse", etc., are derived using these facts. *)
   1.370  val typedef_ths =
   1.371 -  @{thms type_definition.Abs_inverse type_definition.Rep_inverse
   1.372 -         type_definition.Rep type_definition.Rep_inject
   1.373 -         type_definition.Abs_inject type_definition.Rep_cases
   1.374 -         type_definition.Abs_cases type_definition.Rep_induct
   1.375 -         type_definition.Abs_induct type_definition.Rep_range
   1.376 -         type_definition.Abs_image}
   1.377 +  @{thms type_definition.Abs_inverse type_definition.Rep_inverse type_definition.Rep
   1.378 +      type_definition.Rep_inject type_definition.Abs_inject type_definition.Rep_cases
   1.379 +      type_definition.Abs_cases type_definition.Rep_induct type_definition.Abs_induct
   1.380 +      type_definition.Rep_range type_definition.Abs_image}
   1.381    |> map nickname_of_thm
   1.382  
   1.383  fun is_size_def [dep] th =
   1.384      (case first_field ".rec" dep of
   1.385 -       SOME (pref, _) =>
   1.386 -       (case first_field ".size" (nickname_of_thm th) of
   1.387 -          SOME (pref', _) => pref = pref'
   1.388 -        | NONE => false)
   1.389 -     | NONE => false)
   1.390 +      SOME (pref, _) =>
   1.391 +      (case first_field ".size" (nickname_of_thm th) of
   1.392 +        SOME (pref', _) => pref = pref'
   1.393 +      | NONE => false)
   1.394 +    | NONE => false)
   1.395    | is_size_def _ _ = false
   1.396  
   1.397  fun no_dependencies_for_status status =
   1.398 @@ -774,18 +762,16 @@
   1.399  
   1.400  fun isar_dependencies_of name_tabs th =
   1.401    let val deps = thms_in_proof (SOME name_tabs) th in
   1.402 -    if deps = [typedef_dep] orelse
   1.403 -       deps = [class_some_dep] orelse
   1.404 -       exists (member (op =) fundef_ths) deps orelse
   1.405 -       exists (member (op =) typedef_ths) deps orelse
   1.406 +    if deps = [typedef_dep] orelse deps = [class_some_dep] orelse
   1.407 +       exists (member (op =) fundef_ths) deps orelse exists (member (op =) typedef_ths) deps orelse
   1.408         is_size_def deps th then
   1.409        []
   1.410      else
   1.411        deps
   1.412    end
   1.413  
   1.414 -fun prover_dependencies_of ctxt (params as {verbose, max_facts, ...}) prover
   1.415 -                           auto_level facts name_tabs th =
   1.416 +fun prover_dependencies_of ctxt (params as {verbose, max_facts, ...}) prover auto_level facts
   1.417 +    name_tabs th =
   1.418    (case isar_dependencies_of name_tabs th of
   1.419      [] => (false, [])
   1.420    | isar_deps =>
   1.421 @@ -795,8 +781,11 @@
   1.422        val name = nickname_of_thm th
   1.423        val (_, hyp_ts, concl_t) = ATP_Util.strip_subgoal goal 1 ctxt
   1.424        val facts = facts |> filter (fn (_, th') => thm_less (th', th))
   1.425 +
   1.426        fun nickify ((_, stature), th) = ((nickname_of_thm th, stature), th)
   1.427 +
   1.428        fun is_dep dep (_, th) = nickname_of_thm th = dep
   1.429 +
   1.430        fun add_isar_dep facts dep accum =
   1.431          if exists (is_dep dep) accum then
   1.432            accum
   1.433 @@ -804,6 +793,7 @@
   1.434            (case find_first (is_dep dep) facts of
   1.435              SOME ((_, status), th) => accum @ [(("", status), th)]
   1.436            | NONE => accum (* should not happen *))
   1.437 +
   1.438        val mepo_facts =
   1.439          facts
   1.440          |> mepo_suggested_facts ctxt params (max_facts |> the_default prover_default_max_facts) NONE
   1.441 @@ -846,9 +836,11 @@
   1.442          parents |> forall (fn p => not (thm_less_eq (new, p))) parents
   1.443                     ? cons new
   1.444        end
   1.445 +
   1.446      fun rechunk seen (rest as th' :: ths) =
   1.447        if thm_less_eq (th', th) then (rev seen, rest)
   1.448        else rechunk (th' :: seen) ths
   1.449 +
   1.450      fun do_chunk [] accum = accum
   1.451        | do_chunk (chunk as hd_chunk :: _) (chunks, parents) =
   1.452          if thm_less_eq (hd_chunk, th) then
   1.453 @@ -880,7 +872,9 @@
   1.454                  (chunks, [nickname_of_thm th])
   1.455                else
   1.456                  chunks_and_parents_for chunks th'
   1.457 -          in (parents, fact) :: do_facts chunks_and_parents' facts end
   1.458 +          in
   1.459 +            (parents, fact) :: do_facts chunks_and_parents' facts
   1.460 +          end
   1.461      in
   1.462        old_facts @ facts
   1.463        |> do_facts (chunks_and_parents_for [[]] th)
   1.464 @@ -890,9 +884,12 @@
   1.465  fun maximal_wrt_graph G keys =
   1.466    let
   1.467      val tab = Symtab.empty |> fold (fn name => Symtab.default (name, ())) keys
   1.468 +
   1.469      fun insert_new seen name =
   1.470        not (Symtab.defined seen name) ? insert (op =) name
   1.471 +
   1.472      fun num_keys keys = Graph.Keys.fold (K (Integer.add 1)) keys 0
   1.473 +
   1.474      fun find_maxes _ (maxs, []) = map snd maxs
   1.475        | find_maxes seen (maxs, new :: news) =
   1.476          find_maxes
   1.477 @@ -915,7 +912,9 @@
   1.478               else
   1.479                 (maxs, Graph.Keys.fold (insert_new seen)
   1.480                                        (Graph.imm_preds G new) news))
   1.481 -  in find_maxes Symtab.empty ([], Graph.maximals G) end
   1.482 +  in
   1.483 +    find_maxes Symtab.empty ([], Graph.maximals G)
   1.484 +  end
   1.485  
   1.486  fun maximal_wrt_access_graph access_G =
   1.487    map (nickname_of_thm o snd)
   1.488 @@ -958,11 +957,12 @@
   1.489        raw_unknown
   1.490        |> fold (subtract (eq_snd Thm.eq_thm_prop))
   1.491                [unknown_chained, unknown_proximate]
   1.492 -  in (mesh_facts (eq_snd Thm.eq_thm_prop) max_facts mess, unknown) end
   1.493 +  in
   1.494 +    (mesh_facts (eq_snd Thm.eq_thm_prop) max_facts mess, unknown)
   1.495 +  end
   1.496  
   1.497  fun add_const_counts t =
   1.498 -  fold (fn s => Symtab.map_default (s, 0) (Integer.add 1))
   1.499 -       (Term.add_const_names t [])
   1.500 +  fold (fn s => Symtab.map_default (s, 0) (Integer.add 1)) (Term.add_const_names t [])
   1.501  
   1.502  fun mash_suggested_facts ctxt ({debug, overlord, ...} : params) max_facts hyp_ts concl_t facts =
   1.503    let
   1.504 @@ -1000,8 +1000,7 @@
   1.505                  |> weight_facts_steeply
   1.506                  |> map (chained_or_extra_features_of extra_feature_factor)
   1.507                  |> rpair [] |-> fold (union (eq_fst (op =)))
   1.508 -              val feats =
   1.509 -                fold (union (eq_fst (op =))) [chained_feats, extra_feats] goal_feats
   1.510 +              val feats = fold (union (eq_fst (op =))) [chained_feats, extra_feats] goal_feats
   1.511                  |> debug ? sort (Real.compare o swap o pairself snd)
   1.512                val hints = chained
   1.513                  |> filter (is_fact_in_graph access_G o snd)
   1.514 @@ -1023,7 +1022,9 @@
   1.515      val graph = graph |> Graph.default_node (name, (Isar_Proof, feats, deps))
   1.516      val (parents, graph) = ([], graph) |> fold maybe_learn_from parents
   1.517      val (deps, _) = ([], graph) |> fold maybe_learn_from deps
   1.518 -  in ((name, parents, feats, deps) :: learns, graph) end
   1.519 +  in
   1.520 +    ((name, parents, feats, deps) :: learns, graph)
   1.521 +  end
   1.522  
   1.523  fun relearn_wrt_access_graph ctxt (name, deps) (relearns, graph) =
   1.524    let
   1.525 @@ -1032,7 +1033,9 @@
   1.526          (from :: parents, Graph.add_edge_acyclic (from, name) graph))
   1.527      val graph = graph |> Graph.map_node name (fn (_, feats, _) => (Automatic_Proof, feats, deps))
   1.528      val (deps, _) = ([], graph) |> fold maybe_relearn_from deps
   1.529 -  in ((name, deps) :: relearns, graph) end
   1.530 +  in
   1.531 +    ((name, deps) :: relearns, graph)
   1.532 +  end
   1.533  
   1.534  fun flop_wrt_access_graph name =
   1.535    Graph.map_node name (fn (_, feats, deps) => (Isar_Proof_wegen_Prover_Flop, feats, deps))
   1.536 @@ -1045,26 +1048,28 @@
   1.537      val birth_time = Time.now ()
   1.538      val death_time = Time.+ (birth_time, hard_timeout)
   1.539      val desc = ("Machine learner for Sledgehammer", "")
   1.540 -  in Async_Manager.thread MaShN birth_time death_time desc task end
   1.541 +  in
   1.542 +    Async_Manager.thread MaShN birth_time death_time desc task
   1.543 +  end
   1.544  
   1.545  fun mash_learn_proof ctxt ({overlord, timeout, ...} : params) t facts used_ths =
   1.546    if is_mash_enabled () then
   1.547      launch_thread timeout (fn () =>
   1.548 -        let
   1.549 -          val thy = Proof_Context.theory_of ctxt
   1.550 -          val feats = features_of ctxt thy 0 Symtab.empty (Local, General) false [t] |> map fst
   1.551 -        in
   1.552 -          peek_state ctxt overlord (fn {access_G, ...} =>
   1.553 -              let
   1.554 -                val parents = maximal_wrt_access_graph access_G facts
   1.555 -                val deps =
   1.556 -                  used_ths |> filter (is_fact_in_graph access_G)
   1.557 -                           |> map nickname_of_thm
   1.558 -              in
   1.559 -                MaSh.learn ctxt overlord true [("", parents, feats, deps)]
   1.560 -              end);
   1.561 -          (true, "")
   1.562 -        end)
   1.563 +      let
   1.564 +        val thy = Proof_Context.theory_of ctxt
   1.565 +        val feats = features_of ctxt thy 0 Symtab.empty (Local, General) false [t] |> map fst
   1.566 +      in
   1.567 +        peek_state ctxt overlord (fn {access_G, ...} =>
   1.568 +            let
   1.569 +              val parents = maximal_wrt_access_graph access_G facts
   1.570 +              val deps =
   1.571 +                used_ths |> filter (is_fact_in_graph access_G)
   1.572 +                         |> map nickname_of_thm
   1.573 +            in
   1.574 +              MaSh.learn ctxt overlord true [("", parents, feats, deps)]
   1.575 +            end);
   1.576 +        (true, "")
   1.577 +      end)
   1.578    else
   1.579      ()
   1.580  
   1.581 @@ -1231,8 +1236,7 @@
   1.582          if verbose orelse auto_level < 2 then
   1.583            "Learned " ^ string_of_int n ^ " nontrivial " ^
   1.584            (if run_prover then "automatic and " else "") ^ "Isar proof" ^ plural_s n ^
   1.585 -          (if verbose then " in " ^ string_of_time (Timer.checkRealTimer timer)
   1.586 -           else "") ^ "."
   1.587 +          (if verbose then " in " ^ string_of_time (Timer.checkRealTimer timer) else "") ^ "."
   1.588          else
   1.589            ""
   1.590        end
   1.591 @@ -1242,12 +1246,11 @@
   1.592    let
   1.593      val css = Sledgehammer_Fact.clasimpset_rule_table_of ctxt
   1.594      val ctxt = ctxt |> Config.put instantiate_inducts false
   1.595 -    val facts =
   1.596 -      nearly_all_facts ctxt false fact_override Symtab.empty css chained []
   1.597 -                       @{prop True}
   1.598 +    val facts = nearly_all_facts ctxt false fact_override Symtab.empty css chained [] @{prop True}
   1.599        |> sort (crude_thm_ord o pairself snd o swap)
   1.600      val num_facts = length facts
   1.601      val prover = hd provers
   1.602 +
   1.603      fun learn auto_level run_prover =
   1.604        mash_learn_facts ctxt params prover true auto_level run_prover one_year facts
   1.605        |> Output.urgent_message
   1.606 @@ -1258,14 +1261,13 @@
   1.607         ").\n\nCollecting Isar proofs first..."
   1.608         |> Output.urgent_message;
   1.609         learn 1 false;
   1.610 -       "Now collecting automatic proofs. This may take several hours. You can \
   1.611 -       \safely stop the learning process at any point."
   1.612 +       "Now collecting automatic proofs. This may take several hours. You can safely stop the \
   1.613 +       \learning process at any point."
   1.614         |> Output.urgent_message;
   1.615         learn 0 true)
   1.616      else
   1.617 -      ("MaShing through " ^ string_of_int num_facts ^ " fact" ^
   1.618 -       plural_s num_facts ^ " for Isar proofs..."
   1.619 -       |> Output.urgent_message;
   1.620 +      (Output.urgent_message ("MaShing through " ^ string_of_int num_facts ^ " fact" ^
   1.621 +         plural_s num_facts ^ " for Isar proofs...");
   1.622         learn 0 false)
   1.623    end
   1.624