src/HOL/Tools/Sledgehammer/sledgehammer_mash.ML
changeset 61321 c982a4cc8dc4
parent 61318 6a5a188ab3e7
child 61322 44f4ffe2b210
equal deleted inserted replaced
61320:69022bbcd012 61321:c982a4cc8dc4
    43   val is_mash_enabled : unit -> bool
    43   val is_mash_enabled : unit -> bool
    44   val the_mash_algorithm : unit -> mash_algorithm
    44   val the_mash_algorithm : unit -> mash_algorithm
    45   val str_of_mash_algorithm : mash_algorithm -> string
    45   val str_of_mash_algorithm : mash_algorithm -> string
    46 
    46 
    47   val mesh_facts : ('a * 'a -> bool) -> int -> (real * (('a * real) list * 'a list)) list -> 'a list
    47   val mesh_facts : ('a * 'a -> bool) -> int -> (real * (('a * real) list * 'a list)) list -> 'a list
    48   val nickname_of_thm : Proof.context -> thm -> string
    48   val nickname_of_thm : thm -> string
    49   val find_suggested_facts : Proof.context -> ('b * thm) list -> string list -> ('b * thm) list
    49   val find_suggested_facts : Proof.context -> ('b * thm) list -> string list -> ('b * thm) list
    50   val crude_thm_ord : Proof.context -> thm * thm -> order
    50   val crude_thm_ord : Proof.context -> thm * thm -> order
    51   val thm_less : thm * thm -> bool
    51   val thm_less : thm * thm -> bool
    52   val goal_of_thm : theory -> thm -> thm
    52   val goal_of_thm : theory -> thm -> thm
    53   val run_prover_for_mash : Proof.context -> params -> string -> string -> fact list -> thm ->
    53   val run_prover_for_mash : Proof.context -> params -> string -> string -> fact list -> thm ->
    54     prover_result
    54     prover_result
    55   val features_of : Proof.context -> string -> stature -> term list -> string list
    55   val features_of : Proof.context -> string -> stature -> term list -> string list
    56   val trim_dependencies : string list -> string list option
    56   val trim_dependencies : string list -> string list option
    57   val isar_dependencies_of : Proof.context -> string Symtab.table * string Symtab.table ->
    57   val isar_dependencies_of : string Symtab.table * string Symtab.table -> thm -> string list option
    58     thm -> string list option
       
    59   val prover_dependencies_of : Proof.context -> params -> string -> int -> raw_fact list ->
    58   val prover_dependencies_of : Proof.context -> params -> string -> int -> raw_fact list ->
    60     string Symtab.table * string Symtab.table -> thm -> bool * string list
    59     string Symtab.table * string Symtab.table -> thm -> bool * string list
    61   val attach_parents_to_facts : Proof.context -> ('a * thm) list -> ('a * thm) list ->
    60   val attach_parents_to_facts : ('a * thm) list -> ('a * thm) list ->
    62     (string list * ('a * thm)) list
    61     (string list * ('a * thm)) list
    63   val num_extra_feature_facts : int
    62   val num_extra_feature_facts : int
    64   val extra_feature_factor : real
    63   val extra_feature_factor : real
    65   val weight_facts_smoothly : 'a list -> ('a * real) list
    64   val weight_facts_smoothly : 'a list -> ('a * real) list
    66   val weight_facts_steeply : 'a list -> ('a * real) list
    65   val weight_facts_steeply : 'a list -> ('a * real) list
   633     recompute_ffds_freqs_from_learns learns xtabs 0 empty_ffds empty_freqs
   632     recompute_ffds_freqs_from_learns learns xtabs 0 empty_ffds empty_freqs
   634   end
   633   end
   635 
   634 
   636 local
   635 local
   637 
   636 
   638 val version = "*** MaSh version 20140625 ***"
   637 val version = "*** MaSh version 20151004 ***"
   639 
   638 
   640 exception FILE_VERSION_TOO_NEW of unit
   639 exception FILE_VERSION_TOO_NEW of unit
   641 
   640 
   642 fun extract_node line =
   641 fun extract_node line =
   643   (case space_explode ":" line of
   642   (case space_explode ":" line of
   734 end
   733 end
   735 
   734 
   736 
   735 
   737 (*** Isabelle helpers ***)
   736 (*** Isabelle helpers ***)
   738 
   737 
   739 fun elided_backquote_thm ctxt threshold th =
   738 fun crude_printed_term depth t =
   740   elide_string threshold (backquote_thm ctxt th)
   739   let
   741 
   740     fun term _ (res, 0) = (res, 0)
   742 fun nickname_of_thm ctxt th =
   741       | term (t $ u) (res, depth) =
       
   742         let
       
   743           val (res, depth) = term t (res ^ "(", depth)
       
   744           val (res, depth) = term u (res ^ " ", depth)
       
   745         in
       
   746           (res ^ ")", depth)
       
   747         end
       
   748       | term (Abs (s, _, t)) (res, depth) = term t (res ^ "%" ^ s ^ ".", depth - 1)
       
   749       | term (Bound n) (res, depth) = (res ^ "#" ^ string_of_int n, depth - 1)
       
   750       | term (Const (s, _)) (res, depth) = (res ^ Long_Name.base_name s, depth - 1)
       
   751       | term (Free (s, _)) (res, depth) = (res ^ s, depth - 1)
       
   752       | term (Var ((s, _), _)) (res, depth) = (res ^ s, depth - 1)
       
   753   in
       
   754     fst (term t ("", depth))
       
   755   end
       
   756 
       
   757 fun nickname_of_thm th =
   743   if Thm.has_name_hint th then
   758   if Thm.has_name_hint th then
   744     let val hint = Thm.get_name_hint th in
   759     let val hint = Thm.get_name_hint th in
   745       (* There must be a better way to detect local facts. *)
   760       (* There must be a better way to detect local facts. *)
   746       (case Long_Name.dest_local hint of
   761       (case Long_Name.dest_local hint of
   747         SOME suf =>
   762         SOME suf =>
   748           Long_Name.implode [Thm.theory_name_of_thm th, suf, elided_backquote_thm ctxt 50 th]
   763         Long_Name.implode [Thm.theory_name_of_thm th, suf, crude_printed_term 50 (Thm.prop_of th)]
   749       | NONE => hint)
   764       | NONE => hint)
   750     end
   765     end
   751   else
   766   else
   752     elided_backquote_thm ctxt 200 th
   767     crude_printed_term 100 (Thm.prop_of th)
   753 
   768 
   754 fun find_suggested_facts ctxt facts =
   769 fun find_suggested_facts ctxt facts =
   755   let
   770   let
   756     fun add (fact as (_, th)) = Symtab.default (nickname_of_thm ctxt th, fact)
   771     fun add (fact as (_, th)) = Symtab.default (nickname_of_thm th, fact)
   757     val tab = fold add facts Symtab.empty
   772     val tab = fold add facts Symtab.empty
   758     fun lookup nick =
   773     fun lookup nick =
   759       Symtab.lookup tab nick
   774       Symtab.lookup tab nick
   760       |> tap (fn NONE => trace_msg ctxt (fn () => "Cannot find " ^ quote nick) | _ => ())
   775       |> tap (fn NONE => trace_msg ctxt (fn () => "Cannot find " ^ quote nick) | _ => ())
   761   in map_filter lookup end
   776   in map_filter lookup end
   770   let
   785   let
   771     val ancestor_lengths =
   786     val ancestor_lengths =
   772       fold (fn thy => Symtab.update (Context.theory_name thy, length (Context.ancestors_of thy)))
   787       fold (fn thy => Symtab.update (Context.theory_name thy, length (Context.ancestors_of thy)))
   773         (Theory.nodes_of (Proof_Context.theory_of ctxt)) Symtab.empty
   788         (Theory.nodes_of (Proof_Context.theory_of ctxt)) Symtab.empty
   774     val ancestor_length = Symtab.lookup ancestor_lengths o Context.theory_id_name
   789     val ancestor_length = Symtab.lookup ancestor_lengths o Context.theory_id_name
       
   790 
   775     fun crude_theory_ord p =
   791     fun crude_theory_ord p =
   776       if Context.eq_thy_id p then EQUAL
   792       if Context.eq_thy_id p then EQUAL
   777       else if Context.proper_subthy_id p then LESS
   793       else if Context.proper_subthy_id p then LESS
   778       else if Context.proper_subthy_id (swap p) then GREATER
   794       else if Context.proper_subthy_id (swap p) then GREATER
   779       else
   795       else
   787     fn p =>
   803     fn p =>
   788       (case crude_theory_ord (apply2 Thm.theory_id_of_thm p) of
   804       (case crude_theory_ord (apply2 Thm.theory_id_of_thm p) of
   789         EQUAL =>
   805         EQUAL =>
   790         (* The hack below is necessary because of odd dependencies that are not reflected in the theory
   806         (* The hack below is necessary because of odd dependencies that are not reflected in the theory
   791            comparison. *)
   807            comparison. *)
   792         let val q = apply2 (nickname_of_thm ctxt) p in
   808         let val q = apply2 nickname_of_thm p in
   793           (* Hack to put "xxx_def" before "xxxI" and "xxxE" *)
   809           (* Hack to put "xxx_def" before "xxxI" and "xxxE" *)
   794           (case bool_ord (apply2 (String.isSuffix "_def") (swap q)) of
   810           (case bool_ord (apply2 (String.isSuffix "_def") (swap q)) of
   795             EQUAL => string_ord q
   811             EQUAL => string_ord q
   796           | ord => ord)
   812           | ord => ord)
   797         end
   813         end
   941 val max_dependencies = 20
   957 val max_dependencies = 20
   942 
   958 
   943 val prover_default_max_facts = 25
   959 val prover_default_max_facts = 25
   944 
   960 
   945 (* "type_definition_xxx" facts are characterized by their use of "CollectI". *)
   961 (* "type_definition_xxx" facts are characterized by their use of "CollectI". *)
   946 val typedef_dep = nickname_of_thm @{context} @{thm CollectI}
   962 val typedef_dep = nickname_of_thm @{thm CollectI}
   947 (* Mysterious parts of the class machinery create lots of proofs that refer exclusively to
   963 (* Mysterious parts of the class machinery create lots of proofs that refer exclusively to
   948    "someI_ex" (and to some internal constructions). *)
   964    "someI_ex" (and to some internal constructions). *)
   949 val class_some_dep = nickname_of_thm @{context} @{thm someI_ex}
   965 val class_some_dep = nickname_of_thm @{thm someI_ex}
   950 
   966 
   951 val fundef_ths =
   967 val fundef_ths =
   952   @{thms fundef_ex1_existence fundef_ex1_uniqueness fundef_ex1_iff fundef_default_value}
   968   @{thms fundef_ex1_existence fundef_ex1_uniqueness fundef_ex1_iff fundef_default_value}
   953   |> map (nickname_of_thm @{context})
   969   |> map nickname_of_thm
   954 
   970 
   955 (* "Rep_xxx_inject", "Abs_xxx_inverse", etc., are derived using these facts. *)
   971 (* "Rep_xxx_inject", "Abs_xxx_inverse", etc., are derived using these facts. *)
   956 val typedef_ths =
   972 val typedef_ths =
   957   @{thms type_definition.Abs_inverse type_definition.Rep_inverse type_definition.Rep
   973   @{thms type_definition.Abs_inverse type_definition.Rep_inverse type_definition.Rep
   958       type_definition.Rep_inject type_definition.Abs_inject type_definition.Rep_cases
   974       type_definition.Rep_inject type_definition.Abs_inject type_definition.Rep_cases
   959       type_definition.Abs_cases type_definition.Rep_induct type_definition.Abs_induct
   975       type_definition.Abs_cases type_definition.Rep_induct type_definition.Abs_induct
   960       type_definition.Rep_range type_definition.Abs_image}
   976       type_definition.Rep_range type_definition.Abs_image}
   961   |> map (nickname_of_thm @{context})
   977   |> map nickname_of_thm
   962 
   978 
   963 fun is_size_def ctxt [dep] th =
   979 fun is_size_def [dep] th =
   964     (case first_field ".rec" dep of
   980     (case first_field ".rec" dep of
   965       SOME (pref, _) =>
   981       SOME (pref, _) =>
   966       (case first_field ".size" (nickname_of_thm ctxt th) of
   982       (case first_field ".size" (nickname_of_thm th) of
   967         SOME (pref', _) => pref = pref'
   983         SOME (pref', _) => pref = pref'
   968       | NONE => false)
   984       | NONE => false)
   969     | NONE => false)
   985     | NONE => false)
   970   | is_size_def _ _ _ = false
   986   | is_size_def _ _ = false
   971 
   987 
   972 fun trim_dependencies deps =
   988 fun trim_dependencies deps =
   973   if length deps > max_dependencies then NONE else SOME deps
   989   if length deps > max_dependencies then NONE else SOME deps
   974 
   990 
   975 fun isar_dependencies_of ctxt name_tabs th =
   991 fun isar_dependencies_of name_tabs th =
   976   thms_in_proof max_dependencies (SOME name_tabs) th
   992   thms_in_proof max_dependencies (SOME name_tabs) th
   977   |> Option.map (fn deps =>
   993   |> Option.map (fn deps =>
   978     if deps = [typedef_dep] orelse deps = [class_some_dep] orelse
   994     if deps = [typedef_dep] orelse deps = [class_some_dep] orelse
   979         exists (member (op =) fundef_ths) deps orelse exists (member (op =) typedef_ths) deps orelse
   995         exists (member (op =) fundef_ths) deps orelse exists (member (op =) typedef_ths) deps orelse
   980         is_size_def ctxt deps th then
   996         is_size_def deps th then
   981       []
   997       []
   982     else
   998     else
   983       deps)
   999       deps)
   984 
  1000 
   985 fun prover_dependencies_of ctxt (params as {verbose, max_facts, ...}) prover auto_level facts
  1001 fun prover_dependencies_of ctxt (params as {verbose, max_facts, ...}) prover auto_level facts
   986     name_tabs th =
  1002     name_tabs th =
   987   (case isar_dependencies_of ctxt name_tabs th of
  1003   (case isar_dependencies_of name_tabs th of
   988     SOME [] => (false, [])
  1004     SOME [] => (false, [])
   989   | isar_deps0 =>
  1005   | isar_deps0 =>
   990     let
  1006     let
   991       val isar_deps = these isar_deps0
  1007       val isar_deps = these isar_deps0
   992       val thy = Proof_Context.theory_of ctxt
  1008       val thy = Proof_Context.theory_of ctxt
   993       val goal = goal_of_thm thy th
  1009       val goal = goal_of_thm thy th
   994       val name = nickname_of_thm ctxt th
  1010       val name = nickname_of_thm th
   995       val (_, hyp_ts, concl_t) = ATP_Util.strip_subgoal goal 1 ctxt
  1011       val (_, hyp_ts, concl_t) = ATP_Util.strip_subgoal goal 1 ctxt
   996       val facts = facts |> filter (fn (_, th') => thm_less (th', th))
  1012       val facts = facts |> filter (fn (_, th') => thm_less (th', th))
   997 
  1013 
   998       fun nickify ((_, stature), th) = ((nickname_of_thm ctxt th, stature), th)
  1014       fun nickify ((_, stature), th) = ((nickname_of_thm th, stature), th)
   999 
  1015 
  1000       fun is_dep dep (_, th) = nickname_of_thm ctxt th = dep
  1016       fun is_dep dep (_, th) = (nickname_of_thm th = dep)
  1001 
  1017 
  1002       fun add_isar_dep facts dep accum =
  1018       fun add_isar_dep facts dep accum =
  1003         if exists (is_dep dep) accum then
  1019         if exists (is_dep dep) accum then
  1004           accum
  1020           accum
  1005         else
  1021         else
  1039 
  1055 
  1040 (*** High-level communication with MaSh ***)
  1056 (*** High-level communication with MaSh ***)
  1041 
  1057 
  1042 (* In the following functions, chunks are risers w.r.t. "thm_less_eq". *)
  1058 (* In the following functions, chunks are risers w.r.t. "thm_less_eq". *)
  1043 
  1059 
  1044 fun chunks_and_parents_for ctxt chunks th =
  1060 fun chunks_and_parents_for chunks th =
  1045   let
  1061   let
  1046     fun insert_parent new parents =
  1062     fun insert_parent new parents =
  1047       let val parents = parents |> filter_out (fn p => thm_less_eq (p, new)) in
  1063       let val parents = parents |> filter_out (fn p => thm_less_eq (p, new)) in
  1048         parents |> forall (fn p => not (thm_less_eq (new, p))) parents ? cons new
  1064         parents |> forall (fn p => not (thm_less_eq (new, p))) parents ? cons new
  1049       end
  1065       end
  1063         else
  1079         else
  1064           (chunk :: chunks, parents)
  1080           (chunk :: chunks, parents)
  1065   in
  1081   in
  1066     fold_rev do_chunk chunks ([], [])
  1082     fold_rev do_chunk chunks ([], [])
  1067     |>> cons []
  1083     |>> cons []
  1068     ||> map (nickname_of_thm ctxt)
  1084     ||> map nickname_of_thm
  1069   end
  1085   end
  1070 
  1086 
  1071 fun attach_parents_to_facts _ _ [] = []
  1087 fun attach_parents_to_facts _ [] = []
  1072   | attach_parents_to_facts ctxt old_facts (facts as (_, th) :: _) =
  1088   | attach_parents_to_facts old_facts (facts as (_, th) :: _) =
  1073     let
  1089     let
  1074       fun do_facts _ [] = []
  1090       fun do_facts _ [] = []
  1075         | do_facts (_, parents) [fact] = [(parents, fact)]
  1091         | do_facts (_, parents) [fact] = [(parents, fact)]
  1076         | do_facts (chunks, parents)
  1092         | do_facts (chunks, parents)
  1077                    ((fact as (_, th)) :: (facts as (_, th') :: _)) =
  1093                    ((fact as (_, th)) :: (facts as (_, th') :: _)) =
  1078           let
  1094           let
  1079             val chunks = app_hd (cons th) chunks
  1095             val chunks = app_hd (cons th) chunks
  1080             val chunks_and_parents' =
  1096             val chunks_and_parents' =
  1081               if thm_less_eq (th, th') andalso
  1097               if thm_less_eq (th, th') andalso
  1082                 Thm.theory_name_of_thm th = Thm.theory_name_of_thm th'
  1098                 Thm.theory_name_of_thm th = Thm.theory_name_of_thm th'
  1083               then (chunks, [nickname_of_thm ctxt th])
  1099               then (chunks, [nickname_of_thm th])
  1084               else chunks_and_parents_for ctxt chunks th'
  1100               else chunks_and_parents_for chunks th'
  1085           in
  1101           in
  1086             (parents, fact) :: do_facts chunks_and_parents' facts
  1102             (parents, fact) :: do_facts chunks_and_parents' facts
  1087           end
  1103           end
  1088     in
  1104     in
  1089       old_facts @ facts
  1105       old_facts @ facts
  1090       |> do_facts (chunks_and_parents_for ctxt [[]] th)
  1106       |> do_facts (chunks_and_parents_for [[]] th)
  1091       |> drop (length old_facts)
  1107       |> drop (length old_facts)
  1092     end
  1108     end
  1093 
  1109 
  1094 fun maximal_wrt_graph _ [] = []
  1110 fun maximal_wrt_graph _ [] = []
  1095   | maximal_wrt_graph G keys =
  1111   | maximal_wrt_graph G keys =
  1120       in
  1136       in
  1121         find_maxes Symtab.empty ([],
  1137         find_maxes Symtab.empty ([],
  1122           G |> Graph.restrict (not o String.isPrefix anonymous_proof_prefix) |> Graph.maximals)
  1138           G |> Graph.restrict (not o String.isPrefix anonymous_proof_prefix) |> Graph.maximals)
  1123       end
  1139       end
  1124 
  1140 
  1125 fun maximal_wrt_access_graph _ _ [] = []
  1141 fun maximal_wrt_access_graph _ [] = []
  1126   | maximal_wrt_access_graph ctxt access_G ((fact as (_, th)) :: facts) =
  1142   | maximal_wrt_access_graph access_G ((fact as (_, th)) :: facts) =
  1127     let val thy_id = Thm.theory_id_of_thm th in
  1143     let val thy_id = Thm.theory_id_of_thm th in
  1128       fact :: filter_out (fn (_, th') =>
  1144       fact :: filter_out (fn (_, th') =>
  1129         Context.proper_subthy_id (Thm.theory_id_of_thm th', thy_id)) facts
  1145         Context.proper_subthy_id (Thm.theory_id_of_thm th', thy_id)) facts
  1130       |> map (nickname_of_thm ctxt o snd)
  1146       |> map (nickname_of_thm o snd)
  1131       |> maximal_wrt_graph access_G
  1147       |> maximal_wrt_graph access_G
  1132     end
  1148     end
  1133 
  1149 
  1134 fun is_fact_in_graph ctxt access_G = can (Graph.get_node access_G) o nickname_of_thm ctxt
  1150 fun is_fact_in_graph access_G = can (Graph.get_node access_G) o nickname_of_thm
  1135 
  1151 
  1136 val chained_feature_factor = 0.5 (* FUDGE *)
  1152 val chained_feature_factor = 0.5 (* FUDGE *)
  1137 val extra_feature_factor = 0.1 (* FUDGE *)
  1153 val extra_feature_factor = 0.1 (* FUDGE *)
  1138 val num_extra_feature_facts = 10 (* FUDGE *)
  1154 val num_extra_feature_facts = 10 (* FUDGE *)
  1139 
  1155 
  1191 
  1207 
  1192     val goal_feats =
  1208     val goal_feats =
  1193       fold (union (eq_fst (op =))) [chained_feats, extra_feats] (map (rpair 1.0) goal_feats0)
  1209       fold (union (eq_fst (op =))) [chained_feats, extra_feats] (map (rpair 1.0) goal_feats0)
  1194       |> debug ? sort (Real.compare o swap o apply2 snd)
  1210       |> debug ? sort (Real.compare o swap o apply2 snd)
  1195 
  1211 
  1196     val parents = maximal_wrt_access_graph ctxt access_G facts
  1212     val parents = maximal_wrt_access_graph access_G facts
  1197     val visible_facts = map_filter (Symtab.lookup fact_tab) (Graph.all_preds access_G parents)
  1213     val visible_facts = map_filter (Symtab.lookup fact_tab) (Graph.all_preds access_G parents)
  1198 
  1214 
  1199     val suggs =
  1215     val suggs =
  1200       if algorithm = MaSh_NB_Ext orelse algorithm = MaSh_kNN_Ext then
  1216       if algorithm = MaSh_NB_Ext orelse algorithm = MaSh_kNN_Ext then
  1201         let
  1217         let
  1211         in
  1227         in
  1212           MaSh.query_internal ctxt algorithm num_facts num_feats ffds freqs visible_facts max_suggs
  1228           MaSh.query_internal ctxt algorithm num_facts num_feats ffds freqs visible_facts max_suggs
  1213             goal_feats int_goal_feats
  1229             goal_feats int_goal_feats
  1214         end
  1230         end
  1215 
  1231 
  1216     val unknown = filter_out (is_fact_in_graph ctxt access_G o snd) facts
  1232     val unknown = filter_out (is_fact_in_graph access_G o snd) facts
  1217   in
  1233   in
  1218     find_mash_suggestions ctxt max_suggs suggs facts chained unknown
  1234     find_mash_suggestions ctxt max_suggs suggs facts chained unknown
  1219     |> apply2 (map fact_of_raw_fact)
  1235     |> apply2 (map fact_of_raw_fact)
  1220   end
  1236   end
  1221 
  1237 
  1279         val facts = rev_sort_list_prefix (crude_thm_ord ctxt o apply2 snd) 1 facts
  1295         val facts = rev_sort_list_prefix (crude_thm_ord ctxt o apply2 snd) 1 facts
  1280       in
  1296       in
  1281         map_state ctxt
  1297         map_state ctxt
  1282           (fn {access_G, xtabs as ((num_facts0, _), _), ffds, freqs, dirty_facts} =>
  1298           (fn {access_G, xtabs as ((num_facts0, _), _), ffds, freqs, dirty_facts} =>
  1283              let
  1299              let
  1284                val parents = maximal_wrt_access_graph ctxt access_G facts
  1300                val parents = maximal_wrt_access_graph access_G facts
  1285                val deps = used_ths
  1301                val deps = used_ths
  1286                  |> filter (is_fact_in_graph ctxt access_G)
  1302                  |> filter (is_fact_in_graph access_G)
  1287                  |> map (nickname_of_thm ctxt)
  1303                  |> map nickname_of_thm
  1288 
  1304 
  1289                val name = anonymous_proof_name ()
  1305                val name = anonymous_proof_name ()
  1290                val (access_G', xtabs', rev_learns) =
  1306                val (access_G', xtabs', rev_learns) =
  1291                  add_node Automatic_Proof name parents feats deps (access_G, xtabs, [])
  1307                  add_node Automatic_Proof name parents feats deps (access_G, xtabs, [])
  1292 
  1308 
  1311   let
  1327   let
  1312     val timer = Timer.startRealTimer ()
  1328     val timer = Timer.startRealTimer ()
  1313     fun next_commit_time () = Time.+ (Timer.checkRealTimer timer, commit_timeout)
  1329     fun next_commit_time () = Time.+ (Timer.checkRealTimer timer, commit_timeout)
  1314 
  1330 
  1315     val {access_G, ...} = peek_state ctxt
  1331     val {access_G, ...} = peek_state ctxt
  1316     val is_in_access_G = is_fact_in_graph ctxt access_G o snd
  1332     val is_in_access_G = is_fact_in_graph access_G o snd
  1317     val no_new_facts = forall is_in_access_G facts
  1333     val no_new_facts = forall is_in_access_G facts
  1318   in
  1334   in
  1319     if no_new_facts andalso not run_prover then
  1335     if no_new_facts andalso not run_prover then
  1320       if auto_level < 2 then
  1336       if auto_level < 2 then
  1321         "No new " ^ (if run_prover then "automatic" else "Isar") ^ " proofs to learn." ^
  1337         "No new " ^ (if run_prover then "automatic" else "Isar") ^ " proofs to learn." ^
  1325            "")
  1341            "")
  1326       else
  1342       else
  1327         ""
  1343         ""
  1328     else
  1344     else
  1329       let
  1345       let
  1330         val name_tabs = build_name_tables (nickname_of_thm ctxt) facts
  1346         val name_tabs = build_name_tables nickname_of_thm facts
  1331 
  1347 
  1332         fun deps_of status th =
  1348         fun deps_of status th =
  1333           if status = Non_Rec_Def orelse status = Rec_Def then
  1349           if status = Non_Rec_Def orelse status = Rec_Def then
  1334             SOME []
  1350             SOME []
  1335           else if run_prover then
  1351           else if run_prover then
  1336             prover_dependencies_of ctxt params prover auto_level facts name_tabs th
  1352             prover_dependencies_of ctxt params prover auto_level facts name_tabs th
  1337             |> (fn (false, _) => NONE | (true, deps) => trim_dependencies deps)
  1353             |> (fn (false, _) => NONE | (true, deps) => trim_dependencies deps)
  1338           else
  1354           else
  1339             isar_dependencies_of ctxt name_tabs th
  1355             isar_dependencies_of name_tabs th
  1340 
  1356 
  1341         fun do_commit [] [] [] state = state
  1357         fun do_commit [] [] [] state = state
  1342           | do_commit learns relearns flops
  1358           | do_commit learns relearns flops
  1343               {access_G, xtabs as ((num_facts0, _), _), ffds, freqs, dirty_facts} =
  1359               {access_G, xtabs as ((num_facts0, _), _), ffds, freqs, dirty_facts} =
  1344             let
  1360             let
  1382 
  1398 
  1383         fun learn_new_fact _ (accum as (_, (_, _, true))) = accum
  1399         fun learn_new_fact _ (accum as (_, (_, _, true))) = accum
  1384           | learn_new_fact (parents, ((_, stature as (_, status)), th))
  1400           | learn_new_fact (parents, ((_, stature as (_, status)), th))
  1385               (learns, (num_nontrivial, next_commit, _)) =
  1401               (learns, (num_nontrivial, next_commit, _)) =
  1386             let
  1402             let
  1387               val name = nickname_of_thm ctxt th
  1403               val name = nickname_of_thm th
  1388               val feats = features_of ctxt (Thm.theory_name_of_thm th) stature [Thm.prop_of th]
  1404               val feats = features_of ctxt (Thm.theory_name_of_thm th) stature [Thm.prop_of th]
  1389               val deps = these (deps_of status th)
  1405               val deps = these (deps_of status th)
  1390               val num_nontrivial = num_nontrivial |> not (null deps) ? Integer.add 1
  1406               val num_nontrivial = num_nontrivial |> not (null deps) ? Integer.add 1
  1391               val learns = (name, parents, feats, deps) :: learns
  1407               val learns = (name, parents, feats, deps) :: learns
  1392               val (learns, next_commit) =
  1408               val (learns, next_commit) =
  1404             (0, 0)
  1420             (0, 0)
  1405           else
  1421           else
  1406             let
  1422             let
  1407               val new_facts = facts
  1423               val new_facts = facts
  1408                 |> sort (crude_thm_ord ctxt o apply2 snd)
  1424                 |> sort (crude_thm_ord ctxt o apply2 snd)
  1409                 |> attach_parents_to_facts ctxt []
  1425                 |> attach_parents_to_facts []
  1410                 |> filter_out (is_in_access_G o snd)
  1426                 |> filter_out (is_in_access_G o snd)
  1411               val (learns, (num_nontrivial, _, _)) =
  1427               val (learns, (num_nontrivial, _, _)) =
  1412                 ([], (0, next_commit_time (), false))
  1428                 ([], (0, next_commit_time (), false))
  1413                 |> fold learn_new_fact new_facts
  1429                 |> fold learn_new_fact new_facts
  1414             in
  1430             in
  1417 
  1433 
  1418         fun relearn_old_fact _ (accum as (_, (_, _, true))) = accum
  1434         fun relearn_old_fact _ (accum as (_, (_, _, true))) = accum
  1419           | relearn_old_fact ((_, (_, status)), th)
  1435           | relearn_old_fact ((_, (_, status)), th)
  1420               ((relearns, flops), (num_nontrivial, next_commit, _)) =
  1436               ((relearns, flops), (num_nontrivial, next_commit, _)) =
  1421             let
  1437             let
  1422               val name = nickname_of_thm ctxt th
  1438               val name = nickname_of_thm th
  1423               val (num_nontrivial, relearns, flops) =
  1439               val (num_nontrivial, relearns, flops) =
  1424                 (case deps_of status th of
  1440                 (case deps_of status th of
  1425                   SOME deps => (num_nontrivial + 1, (name, deps) :: relearns, flops)
  1441                   SOME deps => (num_nontrivial + 1, (name, deps) :: relearns, flops)
  1426                 | NONE => (num_nontrivial, relearns, name :: flops))
  1442                 | NONE => (num_nontrivial, relearns, name :: flops))
  1427               val (relearns, flops, next_commit) =
  1443               val (relearns, flops, next_commit) =
  1441             let
  1457             let
  1442               val max_isar = 1000 * max_dependencies
  1458               val max_isar = 1000 * max_dependencies
  1443 
  1459 
  1444               fun priority_of th =
  1460               fun priority_of th =
  1445                 Random.random_range 0 max_isar +
  1461                 Random.random_range 0 max_isar +
  1446                 (case try (Graph.get_node access_G) (nickname_of_thm ctxt th) of
  1462                 (case try (Graph.get_node access_G) (nickname_of_thm th) of
  1447                   SOME (Isar_Proof, _, deps) => ~100 * length deps
  1463                   SOME (Isar_Proof, _, deps) => ~100 * length deps
  1448                 | SOME (Automatic_Proof, _, _) => 2 * max_isar
  1464                 | SOME (Automatic_Proof, _, _) => 2 * max_isar
  1449                 | SOME (Isar_Proof_wegen_Prover_Flop, _, _) => max_isar
  1465                 | SOME (Isar_Proof_wegen_Prover_Flop, _, _) => max_isar
  1450                 | NONE => 0)
  1466                 | NONE => 0)
  1451 
  1467 
  1543           ()
  1559           ()
  1544 
  1560 
  1545       fun please_learn () =
  1561       fun please_learn () =
  1546         let
  1562         let
  1547           val {access_G, xtabs = ((num_facts0, _), _), ...} = peek_state ctxt
  1563           val {access_G, xtabs = ((num_facts0, _), _), ...} = peek_state ctxt
  1548           val is_in_access_G = is_fact_in_graph ctxt access_G o snd
  1564           val is_in_access_G = is_fact_in_graph access_G o snd
  1549           val min_num_facts_to_learn = length facts - num_facts0
  1565           val min_num_facts_to_learn = length facts - num_facts0
  1550         in
  1566         in
  1551           if min_num_facts_to_learn <= max_facts_to_learn_before_query then
  1567           if min_num_facts_to_learn <= max_facts_to_learn_before_query then
  1552             (case length (filter_out is_in_access_G facts) of
  1568             (case length (filter_out is_in_access_G facts) of
  1553               0 => ()
  1569               0 => ()