src/HOL/Tools/Sledgehammer/sledgehammer_mash.ML
changeset 57365 d2090a01e920
parent 57364 c1060d10089f
child 57366 d01d1befe4a3
equal deleted inserted replaced
57364:c1060d10089f 57365:d2090a01e920
   747   string_of_int (length (Graph.maximals G)) ^ " maximal"
   747   string_of_int (length (Graph.maximals G)) ^ " maximal"
   748 
   748 
   749 type mash_state =
   749 type mash_state =
   750   {access_G : (proof_kind * string list * string list) Graph.T,
   750   {access_G : (proof_kind * string list * string list) Graph.T,
   751    num_known_facts : int,
   751    num_known_facts : int,
   752    dirty : string list option}
   752    dirty_facts : string list option}
   753 
   753 
   754 val empty_state = {access_G = Graph.empty, num_known_facts = 0, dirty = SOME []} : mash_state
   754 val empty_state = {access_G = Graph.empty, num_known_facts = 0, dirty_facts = SOME []} : mash_state
   755 
   755 
   756 local
   756 local
   757 
   757 
   758 val version = "*** MaSh version 20140625 ***"
   758 val version = "*** MaSh version 20140625 ***"
   759 
   759 
   798                   else wipe_out_mash_state_dir ();
   798                   else wipe_out_mash_state_dir ();
   799                   (Graph.empty, 0))
   799                   (Graph.empty, 0))
   800                | GREATER => raise FILE_VERSION_TOO_NEW ())
   800                | GREATER => raise FILE_VERSION_TOO_NEW ())
   801            in
   801            in
   802              trace_msg ctxt (fn () => "Loaded fact graph (" ^ graph_info access_G ^ ")");
   802              trace_msg ctxt (fn () => "Loaded fact graph (" ^ graph_info access_G ^ ")");
   803              {access_G = access_G, num_known_facts = num_known_facts, dirty = SOME []}
   803              {access_G = access_G, num_known_facts = num_known_facts, dirty_facts = SOME []}
   804            end
   804            end
   805          | _ => empty_state)))
   805          | _ => empty_state)))
   806   end
   806   end
   807 
   807 
   808 fun str_of_entry (kind, name, parents, feats, deps) =
   808 fun str_of_entry (kind, name, parents, feats, deps) =
   809   str_of_proof_kind kind ^ " " ^ encode_str name ^ ": " ^ encode_strs parents ^ "; " ^
   809   str_of_proof_kind kind ^ " " ^ encode_str name ^ ": " ^ encode_strs parents ^ "; " ^
   810   encode_strs feats ^ "; " ^ encode_strs deps ^ "\n"
   810   encode_strs feats ^ "; " ^ encode_strs deps ^ "\n"
   811 
   811 
   812 fun save_state _ (time_state as (_, {dirty = SOME [], ...})) = time_state
   812 fun save_state _ (time_state as (_, {dirty_facts = SOME [], ...})) = time_state
   813   | save_state ctxt (memory_time, {access_G, num_known_facts, dirty}) =
   813   | save_state ctxt (memory_time, {access_G, num_known_facts, dirty_facts}) =
   814     let
   814     let
   815       fun append_entry (name, ((kind, feats, deps), (parents, _))) =
   815       fun append_entry (name, ((kind, feats, deps), (parents, _))) =
   816         cons (kind, name, Graph.Keys.dest parents, feats, deps)
   816         cons (kind, name, Graph.Keys.dest parents, feats, deps)
   817 
   817 
   818       val path = mash_state_file ()
   818       val path = mash_state_file ()
   819       val dirty' =
   819       val dirty_facts' =
   820         (case try OS.FileSys.modTime (Path.implode path) of
   820         (case try OS.FileSys.modTime (Path.implode path) of
   821           NONE => NONE
   821           NONE => NONE
   822         | SOME disk_time => if Time.< (disk_time, memory_time) then dirty else NONE)
   822         | SOME disk_time => if Time.< (disk_time, memory_time) then dirty_facts else NONE)
   823       val (banner, entries) =
   823       val (banner, entries) =
   824         (case dirty' of
   824         (case dirty_facts' of
   825           SOME names => (NONE, fold (append_entry o Graph.get_entry access_G) names [])
   825           SOME names => (NONE, fold (append_entry o Graph.get_entry access_G) names [])
   826         | NONE => (SOME (version ^ "\n"), Graph.fold append_entry access_G []))
   826         | NONE => (SOME (version ^ "\n"), Graph.fold append_entry access_G []))
   827     in
   827     in
   828       write_file banner (entries, str_of_entry) path;
   828       write_file banner (entries, str_of_entry) path;
   829       trace_msg ctxt (fn () =>
   829       trace_msg ctxt (fn () =>
   830         "Saved fact graph (" ^ graph_info access_G ^
   830         "Saved fact graph (" ^ graph_info access_G ^
   831         (case dirty of
   831         (case dirty_facts of
   832           SOME dirty => "; " ^ string_of_int (length dirty) ^ " dirty fact(s)"
   832           SOME dirty_facts => "; " ^ string_of_int (length dirty_facts) ^ " dirty fact(s)"
   833         | _ => "") ^  ")");
   833         | _ => "") ^  ")");
   834       (Time.now (), {access_G = access_G, num_known_facts = num_known_facts, dirty = SOME []})
   834       (Time.now (), {access_G = access_G, num_known_facts = num_known_facts, dirty_facts = SOME []})
   835     end
   835     end
   836 
   836 
   837 val global_state =
   837 val global_state = Synchronized.var "Sledgehammer_MaSh.global_state" (Time.zeroTime, empty_state)
   838   Synchronized.var "Sledgehammer_MaSh.global_state" (Time.zeroTime, empty_state)
       
   839 
   838 
   840 in
   839 in
   841 
   840 
   842 fun map_state ctxt overlord f =
   841 fun map_state ctxt overlord f =
   843   Synchronized.change global_state (load_state ctxt overlord ##> f #> save_state ctxt)
   842   Synchronized.change global_state (load_state ctxt overlord ##> f #> save_state ctxt)
  1465     launch_thread timeout (fn () =>
  1464     launch_thread timeout (fn () =>
  1466       let
  1465       let
  1467         val thy = Proof_Context.theory_of ctxt
  1466         val thy = Proof_Context.theory_of ctxt
  1468         val feats = map fst (features_of ctxt thy 0 Symtab.empty (Local, General) [t])
  1467         val feats = map fst (features_of ctxt thy 0 Symtab.empty (Local, General) [t])
  1469       in
  1468       in
  1470         map_state ctxt overlord (fn state as {access_G, num_known_facts, dirty} =>
  1469         map_state ctxt overlord (fn state as {access_G, num_known_facts, dirty_facts} =>
  1471           let
  1470           let
  1472             val parents = maximal_wrt_access_graph access_G facts
  1471             val parents = maximal_wrt_access_graph access_G facts
  1473             val deps = used_ths
  1472             val deps = used_ths
  1474               |> filter (is_fact_in_graph access_G)
  1473               |> filter (is_fact_in_graph access_G)
  1475               |> map nickname_of_thm
  1474               |> map nickname_of_thm
  1480               let
  1479               let
  1481                 val name = learned_proof_name ()
  1480                 val name = learned_proof_name ()
  1482                 val access_G = access_G |> add_node Automatic_Proof name parents feats deps
  1481                 val access_G = access_G |> add_node Automatic_Proof name parents feats deps
  1483               in
  1482               in
  1484                 {access_G = access_G, num_known_facts = num_known_facts + 1,
  1483                 {access_G = access_G, num_known_facts = num_known_facts + 1,
  1485                  dirty = Option.map (cons name) dirty}
  1484                  dirty_facts = Option.map (cons name) dirty_facts}
  1486               end
  1485               end
  1487           end);
  1486           end);
  1488         (true, "")
  1487         (true, "")
  1489       end)
  1488       end)
  1490   else
  1489   else
  1527             |> (fn (false, _) => NONE | (true, deps) => trim_dependencies deps)
  1526             |> (fn (false, _) => NONE | (true, deps) => trim_dependencies deps)
  1528           else
  1527           else
  1529             isar_dependencies_of name_tabs th
  1528             isar_dependencies_of name_tabs th
  1530 
  1529 
  1531         fun do_commit [] [] [] state = state
  1530         fun do_commit [] [] [] state = state
  1532           | do_commit learns relearns flops {access_G, num_known_facts, dirty} =
  1531           | do_commit learns relearns flops {access_G, num_known_facts, dirty_facts} =
  1533             let
  1532             let
  1534               val was_empty = Graph.is_empty access_G
  1533               val was_empty = Graph.is_empty access_G
  1535               val (learns, access_G) = ([], access_G) |> fold (learn_wrt_access_graph ctxt) learns
  1534               val (learns, access_G) = ([], access_G) |> fold (learn_wrt_access_graph ctxt) learns
  1536               val (relearns, access_G) =
  1535               val (relearns, access_G) =
  1537                 ([], access_G) |> fold (relearn_wrt_access_graph ctxt) relearns
  1536                 ([], access_G) |> fold (relearn_wrt_access_graph ctxt) relearns
  1538               val access_G = access_G |> fold flop_wrt_access_graph flops
  1537               val access_G = access_G |> fold flop_wrt_access_graph flops
  1539               val num_known_facts = num_known_facts + length learns
  1538               val num_known_facts = num_known_facts + length learns
  1540               val dirty =
  1539               val dirty_facts =
  1541                 (case (was_empty, dirty) of
  1540                 (case (was_empty, dirty_facts) of
  1542                   (false, SOME names) => SOME (map #1 learns @ map #1 relearns @ names)
  1541                   (false, SOME names) => SOME (map #1 learns @ map #1 relearns @ names)
  1543                 | _ => NONE)
  1542                 | _ => NONE)
  1544             in
  1543             in
  1545               if engine = MaSh_Py then
  1544               if engine = MaSh_Py then
  1546                 (MaSh_Py.learn ctxt overlord (save andalso null relearns) (rev learns);
  1545                 (MaSh_Py.learn ctxt overlord (save andalso null relearns) (rev learns);
  1547                  MaSh_Py.relearn ctxt overlord save relearns)
  1546                  MaSh_Py.relearn ctxt overlord save relearns)
  1548               else
  1547               else
  1549                 ();
  1548                 ();
  1550               {access_G = access_G, num_known_facts = num_known_facts, dirty = dirty}
  1549               {access_G = access_G, num_known_facts = num_known_facts, dirty_facts = dirty_facts}
  1551             end
  1550             end
  1552 
  1551 
  1553         fun commit last learns relearns flops =
  1552         fun commit last learns relearns flops =
  1554           (if debug andalso auto_level = 0 then Output.urgent_message "Committing..." else ();
  1553           (if debug andalso auto_level = 0 then Output.urgent_message "Committing..." else ();
  1555            map_state ctxt overlord (do_commit (rev learns) relearns flops);
  1554            map_state ctxt overlord (do_commit (rev learns) relearns flops);