src/HOL/Tools/Sledgehammer/sledgehammer_run.ML
changeset 41242 8edeb1dbbc76
parent 41208 1b28c43a7074
child 41245 cddc7db22bc9
equal deleted inserted replaced
41241:7d07736aaaf6 41242:8edeb1dbbc76
    41 
    41 
    42 val implicit_minimization_threshold = 50
    42 val implicit_minimization_threshold = 50
    43 
    43 
    44 fun run_prover (params as {debug, blocking, max_relevant, timeout, expect, ...})
    44 fun run_prover (params as {debug, blocking, max_relevant, timeout, expect, ...})
    45                auto minimize_command only
    45                auto minimize_command only
    46                {state, goal, subgoal, subgoal_count, facts} name =
    46                {state, goal, subgoal, subgoal_count, facts, smt_head} name =
    47   let
    47   let
    48     val ctxt = Proof.context_of state
    48     val ctxt = Proof.context_of state
    49     val birth_time = Time.now ()
    49     val birth_time = Time.now ()
    50     val death_time = Time.+ (birth_time, timeout)
    50     val death_time = Time.+ (birth_time, timeout)
    51     val max_relevant =
    51     val max_relevant =
    54     val desc =
    54     val desc =
    55       prover_description ctxt params name num_facts subgoal subgoal_count goal
    55       prover_description ctxt params name num_facts subgoal subgoal_count goal
    56     val prover = get_prover ctxt auto name
    56     val prover = get_prover ctxt auto name
    57     val problem =
    57     val problem =
    58       {state = state, goal = goal, subgoal = subgoal,
    58       {state = state, goal = goal, subgoal = subgoal,
    59        subgoal_count = subgoal_count, facts = take num_facts facts}
    59        subgoal_count = subgoal_count, facts = take num_facts facts,
       
    60        smt_head = smt_head}
    60     fun go () =
    61     fun go () =
    61       let
    62       let
    62         fun really_go () =
    63         fun really_go () =
    63           prover params (minimize_command name) problem
    64           prover params (minimize_command name) problem
    64           |> (fn {outcome, used_facts, message, ...} =>
    65           |> (fn {outcome, used_facts, message, ...} =>
   113     else
   114     else
   114       (Async_Manager.launch das_Tool birth_time death_time desc (snd o go);
   115       (Async_Manager.launch das_Tool birth_time death_time desc (snd o go);
   115        (false, state))
   116        (false, state))
   116   end
   117   end
   117 
   118 
       
   119 val smt_weights = Unsynchronized.ref true
       
   120 val smt_weight_min_facts = 20
       
   121 
       
   122 (* FUDGE *)
       
   123 val smt_min_weight = Unsynchronized.ref 0
       
   124 val smt_max_weight = Unsynchronized.ref 10
       
   125 val smt_max_index = Unsynchronized.ref 200
       
   126 val smt_weight_curve = Unsynchronized.ref (fn x : int => x * x)
       
   127 
       
   128 fun smt_fact_weight j num_facts =
       
   129   if !smt_weights andalso num_facts >= smt_weight_min_facts then
       
   130     SOME (!smt_max_weight
       
   131           - (!smt_max_weight - !smt_min_weight + 1)
       
   132             * !smt_weight_curve (Int.max (0, !smt_max_index - j - 1))
       
   133             div !smt_weight_curve (!smt_max_index))
       
   134   else
       
   135     NONE
       
   136 
       
   137 fun weight_smt_fact thy num_facts (fact, j) =
       
   138   fact |> apsnd (pair (smt_fact_weight j num_facts) o Thm.transfer thy)
       
   139 
       
   140 fun class_of_smt_solver ctxt name =
       
   141   ctxt |> select_smt_solver name
       
   142        |> SMT_Config.solver_class_of |> SMT_Utils.string_of_class
       
   143 
       
   144 (* Makes backtraces more transparent and might be more efficient as well. *)
       
   145 fun smart_par_list_map _ [] = []
       
   146   | smart_par_list_map f [x] = [f x]
       
   147   | smart_par_list_map f xs = Par_List.map f xs
       
   148 
   118 (* FUDGE *)
   149 (* FUDGE *)
   119 val auto_max_relevant_divisor = 2
   150 val auto_max_relevant_divisor = 2
   120 
   151 
   121 fun run_sledgehammer (params as {debug, blocking, provers, type_sys,
   152 fun run_sledgehammer (params as {debug, blocking, provers, type_sys,
   122                                  relevance_thresholds, max_relevant, ...})
   153                                  relevance_thresholds, max_relevant, ...})
   127   else case subgoal_count state of
   158   else case subgoal_count state of
   128     0 => (Output.urgent_message "No subgoal!"; (false, state))
   159     0 => (Output.urgent_message "No subgoal!"; (false, state))
   129   | n =>
   160   | n =>
   130     let
   161     let
   131       val _ = Proof.assert_backward state
   162       val _ = Proof.assert_backward state
       
   163       val state =
       
   164         state |> Proof.map_context (Config.put SMT_Config.verbose debug)
   132       val ctxt = Proof.context_of state
   165       val ctxt = Proof.context_of state
       
   166       val thy = ProofContext.theory_of ctxt
   133       val {facts = chained_ths, goal, ...} = Proof.goal state
   167       val {facts = chained_ths, goal, ...} = Proof.goal state
   134       val (_, hyp_ts, concl_t) = strip_subgoal goal i
   168       val (_, hyp_ts, concl_t) = strip_subgoal goal i
   135       val no_dangerous_types = types_dangerous_types type_sys
   169       val no_dangerous_types = types_dangerous_types type_sys
   136       val _ = () |> not blocking ? kill_provers
   170       val _ = () |> not blocking ? kill_provers
   137       val _ = case find_first (not o is_prover_available ctxt) provers of
   171       val _ = case find_first (not o is_prover_available ctxt) provers of
   138                 SOME name => error ("No such prover: " ^ name ^ ".")
   172                 SOME name => error ("No such prover: " ^ name ^ ".")
   139               | NONE => ()
   173               | NONE => ()
   140       val _ = if auto then () else Output.urgent_message "Sledgehammering..."
   174       val _ = if auto then () else Output.urgent_message "Sledgehammering..."
   141       val (smts, atps) = provers |> List.partition (is_smt_prover ctxt)
   175       val (smts, atps) = provers |> List.partition (is_smt_prover ctxt)
   142       fun run_provers label no_dangerous_types relevance_fudge maybe_translate
   176       fun run_provers get_facts translate maybe_smt_head provers
   143                       provers (res as (success, state)) =
   177                       (res as (success, state)) =
   144         if success orelse null provers then
   178         if success orelse null provers then
   145           res
   179           res
   146         else
   180         else
   147           let
   181           let
   148             val max_max_relevant =
   182             val facts = get_facts ()
   149               case max_relevant of
   183             val num_facts = length facts
   150                 SOME n => n
   184             val facts = facts ~~ (0 upto num_facts - 1)
   151               | NONE =>
   185                         |> map (translate num_facts)
   152                 0 |> fold (Integer.max o default_max_relevant_for_prover ctxt)
       
   153                           provers
       
   154                   |> auto ? (fn n => n div auto_max_relevant_divisor)
       
   155             val is_built_in_const =
       
   156               is_built_in_const_for_prover ctxt (hd provers)
       
   157             val facts =
       
   158               relevant_facts ctxt no_dangerous_types relevance_thresholds
       
   159                              max_max_relevant is_built_in_const relevance_fudge
       
   160                              relevance_override chained_ths hyp_ts concl_t
       
   161               |> map maybe_translate
       
   162             val problem =
   186             val problem =
   163               {state = state, goal = goal, subgoal = i, subgoal_count = n,
   187               {state = state, goal = goal, subgoal = i, subgoal_count = n,
   164                facts = facts}
   188                facts = facts,
       
   189                smt_head = maybe_smt_head (map smt_weighted_fact facts) i}
   165             val run_prover = run_prover params auto minimize_command only
   190             val run_prover = run_prover params auto minimize_command only
   166           in
   191           in
   167             if debug then
       
   168               Output.urgent_message (label ^ plural_s (length provers) ^ ": " ^
       
   169                   (if null facts then
       
   170                      "Found no relevant facts."
       
   171                    else
       
   172                      "Including (up to) " ^ string_of_int (length facts) ^
       
   173                      " relevant fact" ^ plural_s (length facts) ^ ":\n" ^
       
   174                      (facts |> map (fst o fst o untranslated_fact)
       
   175                             |> space_implode " ") ^ "."))
       
   176             else
       
   177               ();
       
   178             if auto then
   192             if auto then
   179               fold (fn prover => fn (true, state) => (true, state)
   193               fold (fn prover => fn (true, state) => (true, state)
   180                                   | (false, _) => run_prover problem prover)
   194                                   | (false, _) => run_prover problem prover)
   181                    provers (false, state)
   195                    provers (false, state)
   182             else
   196             else
   183               provers
   197               provers
   184               |> (if blocking andalso length provers > 1 then Par_List.map
   198               |> (if blocking then smart_par_list_map else map)
   185                   else map)
       
   186                      (run_prover problem)
   199                      (run_prover problem)
   187               |> exists fst |> rpair state
   200               |> exists fst |> rpair state
   188           end
   201           end
       
   202       fun get_facts label no_dangerous_types relevance_fudge provers =
       
   203         let
       
   204           val max_max_relevant =
       
   205             case max_relevant of
       
   206               SOME n => n
       
   207             | NONE =>
       
   208               0 |> fold (Integer.max o default_max_relevant_for_prover ctxt)
       
   209                         provers
       
   210                 |> auto ? (fn n => n div auto_max_relevant_divisor)
       
   211           val is_built_in_const =
       
   212             is_built_in_const_for_prover ctxt (hd provers)
       
   213         in
       
   214           relevant_facts ctxt no_dangerous_types relevance_thresholds
       
   215                          max_max_relevant is_built_in_const relevance_fudge
       
   216                          relevance_override chained_ths hyp_ts concl_t
       
   217           |> tap (fn facts =>
       
   218                      if debug then
       
   219                        label ^ plural_s (length provers) ^ ": " ^
       
   220                        (if null facts then
       
   221                           "Found no relevant facts."
       
   222                         else
       
   223                           "Including (up to) " ^ string_of_int (length facts) ^
       
   224                           " relevant fact" ^ plural_s (length facts) ^ ":\n" ^
       
   225                           (facts |> map (fst o fst) |> space_implode " ") ^ ".")
       
   226                        |> Output.urgent_message
       
   227                      else
       
   228                        ())
       
   229         end
   189       val run_atps =
   230       val run_atps =
   190         run_provers "ATP" no_dangerous_types atp_relevance_fudge
   231         run_provers
   191                     (ATP_Translated_Fact o translate_atp_fact ctxt) atps
   232             (get_facts "ATP" no_dangerous_types atp_relevance_fudge o K atps)
   192       val run_smts =
   233             (ATP_Translated_Fact oo K (translate_atp_fact ctxt o fst))
   193         run_provers "SMT solver" true smt_relevance_fudge Untranslated_Fact smts
   234             (K (K NONE)) atps
       
   235       fun run_smts (accum as (success, _)) =
       
   236         if success orelse null smts then
       
   237           accum
       
   238         else
       
   239           let
       
   240             val facts = get_facts "SMT solver" true smt_relevance_fudge smts
       
   241             val translate = SMT_Weighted_Fact oo weight_smt_fact thy
       
   242             val maybe_smt_head = try o SMT_Solver.smt_filter_head state
       
   243           in
       
   244             smts |> map (`(class_of_smt_solver ctxt))
       
   245                  |> AList.group (op =)
       
   246                  |> map (fn (_, smts) => run_provers (K facts) translate
       
   247                                                      maybe_smt_head smts accum)
       
   248                  |> exists fst |> rpair state
       
   249           end
   194       fun run_atps_and_smt_solvers () =
   250       fun run_atps_and_smt_solvers () =
   195         [run_atps, run_smts] |> Par_List.map (fn f => f (false, state) |> K ())
   251         [run_atps, run_smts]
       
   252         |> smart_par_list_map (fn f => f (false, state) |> K ())
   196         handle ERROR msg => (Output.urgent_message ("Error: " ^ msg); error msg)
   253         handle ERROR msg => (Output.urgent_message ("Error: " ^ msg); error msg)
   197     in
   254     in
   198       (false, state)
   255       (false, state)
   199       |> (if blocking then run_atps #> not auto ? run_smts
   256       |> (if blocking then run_atps #> not auto ? run_smts
   200           else (fn p => Future.fork (tap run_atps_and_smt_solvers) |> K p))
   257           else (fn p => Future.fork (tap run_atps_and_smt_solvers) |> K p))