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 |
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 |
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 |
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 |
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 |
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) = |
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) = |