src/HOL/Tools/Sledgehammer/sledgehammer_provers.ML
changeset 54816 10d48c2a3e32
parent 54815 4f6ec8754bf5
child 54818 a80bd631e573
equal deleted inserted replaced
54815:4f6ec8754bf5 54816:10d48c2a3e32
    38      isar_proofs : bool option,
    38      isar_proofs : bool option,
    39      isar_compress : real,
    39      isar_compress : real,
    40      isar_try0 : bool,
    40      isar_try0 : bool,
    41      slice : bool,
    41      slice : bool,
    42      minimize : bool option,
    42      minimize : bool option,
    43      timeout : Time.time option,
    43      timeout : Time.time,
    44      preplay_timeout : Time.time option,
    44      preplay_timeout : Time.time,
    45      expect : string}
    45      expect : string}
    46 
    46 
    47   type prover_problem =
    47   type prover_problem =
    48     {comment : string,
    48     {comment : string,
    49      state : Proof.state,
    49      state : Proof.state,
   279    isar_proofs : bool option,
   279    isar_proofs : bool option,
   280    isar_compress : real,
   280    isar_compress : real,
   281    isar_try0 : bool,
   281    isar_try0 : bool,
   282    slice : bool,
   282    slice : bool,
   283    minimize : bool option,
   283    minimize : bool option,
   284    timeout : Time.time option,
   284    timeout : Time.time,
   285    preplay_timeout : Time.time option,
   285    preplay_timeout : Time.time,
   286    expect : string}
   286    expect : string}
   287 
   287 
   288 type prover_problem =
   288 type prover_problem =
   289   {comment : string,
   289   {comment : string,
   290    state : Proof.state,
   290    state : Proof.state,
   376 (* based on "Mirabelle.can_apply" and generalized *)
   376 (* based on "Mirabelle.can_apply" and generalized *)
   377 fun timed_apply timeout tac state i =
   377 fun timed_apply timeout tac state i =
   378   let
   378   let
   379     val {context = ctxt, facts, goal} = Proof.goal state
   379     val {context = ctxt, facts, goal} = Proof.goal state
   380     val full_tac = Method.insert_tac facts i THEN tac ctxt i
   380     val full_tac = Method.insert_tac facts i THEN tac ctxt i
   381   in time_limit timeout (try (Seq.pull o full_tac)) goal end
   381   in
       
   382     TimeLimit.timeLimit timeout (try (Seq.pull o full_tac)) goal
       
   383   end
   382 
   384 
   383 fun tac_of_reconstructor (Metis (type_enc, lam_trans)) =
   385 fun tac_of_reconstructor (Metis (type_enc, lam_trans)) =
   384     metis_tac [type_enc] lam_trans
   386     metis_tac [type_enc] lam_trans
   385   | tac_of_reconstructor SMT = SMT_Solver.smt_tac
   387   | tac_of_reconstructor SMT = SMT_Solver.smt_tac
   386 
   388 
   399   let
   401   let
   400     fun get_preferred reconstrs =
   402     fun get_preferred reconstrs =
   401       if member (op =) reconstrs preferred then preferred
   403       if member (op =) reconstrs preferred then preferred
   402       else List.last reconstrs
   404       else List.last reconstrs
   403   in
   405   in
   404     if timeout = SOME Time.zeroTime then
   406     if timeout = Time.zeroTime then
   405       Play_Timed_Out (get_preferred reconstrs, Time.zeroTime)
   407       Play_Timed_Out (get_preferred reconstrs, Time.zeroTime)
   406     else
   408     else
   407       let
   409       let
   408         val _ = if mode = Minimize then Output.urgent_message "Preplaying proof..." else ()
   410         val _ = if mode = Minimize then Output.urgent_message "Preplaying proof..." else ()
   409         val ths = pairs |> sort_wrt (fst o fst) |> map snd
   411         val ths = pairs |> sort_wrt (fst o fst) |> map snd
   410         fun play [] [] = Play_Failed (get_preferred reconstrs)
   412         fun play [] [] = Play_Failed (get_preferred reconstrs)
   411           | play timed_outs [] =
   413           | play timed_outs [] = Play_Timed_Out (get_preferred timed_outs, timeout)
   412             Play_Timed_Out (get_preferred timed_outs, timeout |> the_default Time.zeroTime (* wrong *))
       
   413           | play timed_out (reconstr :: reconstrs) =
   414           | play timed_out (reconstr :: reconstrs) =
   414             let
   415             let
   415               val _ =
   416               val _ =
   416                 if verbose then
   417                 if verbose then
   417                   "Trying \"" ^ string_of_reconstructor reconstr ^ "\"" ^
   418                   Output.urgent_message ("Trying \"" ^ string_of_reconstructor reconstr ^
   418                   (case timeout of
   419                     "\" for " ^ string_of_time timeout ^ "...")
   419                      SOME timeout => " for " ^ string_of_time timeout
       
   420                    | NONE => "") ^ "..."
       
   421                   |> Output.urgent_message
       
   422                 else
   420                 else
   423                   ()
   421                   ()
   424               val timer = Timer.startRealTimer ()
   422               val timer = Timer.startRealTimer ()
   425             in
   423             in
   426               case timed_reconstructor reconstr debug timeout ths state i of
   424               case timed_reconstructor reconstr debug timeout ths state i of
   662             val type_enc =
   660             val type_enc =
   663               type_enc |> choose_type_enc strictness best_type_enc format
   661               type_enc |> choose_type_enc strictness best_type_enc format
   664             val sound = is_type_enc_sound type_enc
   662             val sound = is_type_enc_sound type_enc
   665             val real_ms = Real.fromInt o Time.toMilliseconds
   663             val real_ms = Real.fromInt o Time.toMilliseconds
   666             val slice_timeout =
   664             val slice_timeout =
   667               case time_left of
   665               (real_ms time_left
   668                 SOME time_left =>
   666                |> (if slice < num_actual_slices - 1 then
   669                 ((real_ms time_left
   667                      curry Real.min (time_frac * real_ms timeout)
   670                   |> (if slice < num_actual_slices - 1 then
   668                    else
   671                         curry Real.min (time_frac * real_ms (the timeout))
   669                      I))
   672                       else
   670               * 0.001
   673                         I))
   671               |> seconds
   674                  * 0.001)
       
   675                 |> seconds |> SOME
       
   676               | NONE => NONE
       
   677             val generous_slice_timeout =
   672             val generous_slice_timeout =
   678               if mode = MaSh then NONE
   673               if mode = MaSh then one_day else Time.+ (slice_timeout, atp_timeout_slack)
   679               else Option.map (curry Time.+ atp_timeout_slack) slice_timeout
       
   680             val _ =
   674             val _ =
   681               if debug then
   675               if debug then
   682                 quote name ^ " slice #" ^ string_of_int (slice + 1) ^
   676                 quote name ^ " slice #" ^ string_of_int (slice + 1) ^
   683                 " with " ^ string_of_int num_facts ^ " fact" ^
   677                 " with " ^ string_of_int num_facts ^ " fact" ^
   684                 plural_s num_facts ^
   678                 plural_s num_facts ^ " for " ^ string_of_time slice_timeout ^ "..."
   685                 (case slice_timeout of
       
   686                    SOME timeout => " for " ^ string_of_time timeout
       
   687                  | NONE => "") ^ "..."
       
   688                 |> Output.urgent_message
   679                 |> Output.urgent_message
   689               else
   680               else
   690                 ()
   681                 ()
   691             val readable_names = not (Config.get ctxt atp_full_names)
   682             val readable_names = not (Config.get ctxt atp_full_names)
   692             val lam_trans =
   683             val lam_trans =
   713             fun sel_weights () = atp_problem_selection_weights atp_problem
   704             fun sel_weights () = atp_problem_selection_weights atp_problem
   714             fun ord_info () = atp_problem_term_order_info atp_problem
   705             fun ord_info () = atp_problem_term_order_info atp_problem
   715             val ord = effective_term_order ctxt name
   706             val ord = effective_term_order ctxt name
   716             val full_proof = isar_proofs |> the_default (mode = Minimize)
   707             val full_proof = isar_proofs |> the_default (mode = Minimize)
   717             val args =
   708             val args =
   718               arguments ctxt full_proof extra (slice_timeout |> the_default one_day)
   709               arguments ctxt full_proof extra slice_timeout (File.shell_path prob_path)
   719                         (File.shell_path prob_path) (ord, ord_info, sel_weights)
   710                 (ord, ord_info, sel_weights)
   720             val command =
   711             val command =
   721               "(exec 2>&1; " ^ File.shell_path command0 ^ " " ^ args ^ " " ^ ")"
   712               "(exec 2>&1; " ^ File.shell_path command0 ^ " " ^ args ^ " " ^ ")"
   722               |> enclose "TIMEFORMAT='%3R'; { time " " ; }"
   713               |> enclose "TIMEFORMAT='%3R'; { time " " ; }"
   723             val _ =
   714             val _ =
   724               atp_problem
   715               atp_problem
   725               |> lines_of_atp_problem format ord ord_info
   716               |> lines_of_atp_problem format ord ord_info
   726               |> cons ("% " ^ command ^ "\n" ^ (if comment = "" then "" else "% " ^ comment ^ "\n"))
   717               |> cons ("% " ^ command ^ "\n" ^ (if comment = "" then "" else "% " ^ comment ^ "\n"))
   727               |> File.write_list prob_path
   718               |> File.write_list prob_path
   728             val ((output, run_time), (atp_proof, outcome)) =
   719             val ((output, run_time), (atp_proof, outcome)) =
   729               time_limit generous_slice_timeout Isabelle_System.bash_output command
   720               TimeLimit.timeLimit generous_slice_timeout Isabelle_System.bash_output command
   730               |>> (if overlord then prefix ("% " ^ command ^ "\n% " ^ timestamp () ^ "\n") else I)
   721               |>> (if overlord then prefix ("% " ^ command ^ "\n% " ^ timestamp () ^ "\n") else I)
   731               |> fst |> split_time
   722               |> fst |> split_time
   732               |> (fn accum as (output, _) =>
   723               |> (fn accum as (output, _) =>
   733                      (accum,
   724                      (accum,
   734                       extract_tstplike_proof_and_outcome verbose proof_delims known_failures output
   725                       extract_tstplike_proof_and_outcome verbose proof_delims known_failures output
   735                       |>> atp_proof_of_tstplike_proof atp_problem
   726                       |>> atp_proof_of_tstplike_proof atp_problem
   736                       handle UNRECOGNIZED_ATP_PROOF () => ([], SOME ProofIncomplete)))
   727                       handle UNRECOGNIZED_ATP_PROOF () => ([], SOME ProofIncomplete)))
   737               handle TimeLimit.TimeOut => (("", the slice_timeout), ([], SOME TimedOut))
   728               handle TimeLimit.TimeOut => (("", slice_timeout), ([], SOME TimedOut))
   738             val outcome =
   729             val outcome =
   739               case outcome of
   730               case outcome of
   740                 NONE =>
   731                 NONE =>
   741                 (case used_facts_in_unsound_atp_proof ctxt fact_names atp_proof
   732                 (case used_facts_in_unsound_atp_proof ctxt fact_names atp_proof
   742                       |> Option.map (sort string_ord) of
   733                       |> Option.map (sort string_ord) of
   757           end
   748           end
   758         val timer = Timer.startRealTimer ()
   749         val timer = Timer.startRealTimer ()
   759         fun maybe_run_slice slice
   750         fun maybe_run_slice slice
   760                 (result as (cache, (_, run_time0, _, _, SOME _))) =
   751                 (result as (cache, (_, run_time0, _, _, SOME _))) =
   761             let
   752             let
   762               val time_left =
   753               val time_left = Time.- (timeout, Timer.checkRealTimer timer)
   763                 Option.map
       
   764                     (fn timeout => Time.- (timeout, Timer.checkRealTimer timer))
       
   765                     timeout
       
   766             in
   754             in
   767               if time_left <> NONE andalso
   755               if Time.<= (time_left, Time.zeroTime) then
   768                  Time.<= (the time_left, Time.zeroTime) then
       
   769                 result
   756                 result
   770               else
   757               else
   771                 run_slice time_left cache slice
   758                 run_slice time_left cache slice
   772                 |> (fn (cache, (output, run_time, used_from, atp_proof,
   759                 |> (fn (cache, (output, run_time, used_from, atp_proof,
   773                                 outcome)) =>
   760                                 outcome)) =>
   933     fun do_slice timeout slice outcome0 time_so_far
   920     fun do_slice timeout slice outcome0 time_so_far
   934                  (weighted_factss as (fact_filter, weighted_facts) :: _) =
   921                  (weighted_factss as (fact_filter, weighted_facts) :: _) =
   935       let
   922       let
   936         val timer = Timer.startRealTimer ()
   923         val timer = Timer.startRealTimer ()
   937         val slice_timeout =
   924         val slice_timeout =
   938           if slice < max_slices andalso timeout <> NONE then
   925           if slice < max_slices then
   939             let val ms = timeout |> the |> Time.toMilliseconds in
   926             let val ms = Time.toMilliseconds timeout in
   940               Int.min (ms,
   927               Int.min (ms,
   941                   Int.max (1000 * Config.get ctxt smt_slice_min_secs,
   928                   Int.max (1000 * Config.get ctxt smt_slice_min_secs,
   942                       Real.ceil (Config.get ctxt smt_slice_time_frac
   929                       Real.ceil (Config.get ctxt smt_slice_time_frac
   943                                  * Real.fromInt ms)))
   930                                  * Real.fromInt ms)))
   944               |> Time.fromMilliseconds |> SOME
   931               |> Time.fromMilliseconds
   945             end
   932             end
   946           else
   933           else
   947             timeout
   934             timeout
   948         val num_facts = length weighted_facts
   935         val num_facts = length weighted_facts
   949         val _ =
   936         val _ =
   950           if debug then
   937           if debug then
   951             quote name ^ " slice " ^ string_of_int slice ^ " with " ^
   938             quote name ^ " slice " ^ string_of_int slice ^ " with " ^ string_of_int num_facts ^
   952             string_of_int num_facts ^ " fact" ^ plural_s num_facts ^
   939             " fact" ^ plural_s num_facts ^ " for " ^ string_of_time slice_timeout
   953             (case slice_timeout of
       
   954                SOME timeout => " for " ^ string_of_time timeout
       
   955              | NONE => "") ^ "..."
       
   956             |> Output.urgent_message
   940             |> Output.urgent_message
   957           else
   941           else
   958             ()
   942             ()
   959         val birth = Timer.checkRealTimer timer
   943         val birth = Timer.checkRealTimer timer
   960         val _ =
   944         val _ =
   961           if debug then Output.urgent_message "Invoking SMT solver..." else ()
   945           if debug then Output.urgent_message "Invoking SMT solver..." else ()
   962         val (outcome, used_facts) =
   946         val (outcome, used_facts) =
   963           SMT_Solver.smt_filter_preprocess ctxt [] goal weighted_facts i
   947           SMT_Solver.smt_filter_preprocess ctxt [] goal weighted_facts i
   964           |> SMT_Solver.smt_filter_apply (slice_timeout |> the_default one_day)
   948           |> SMT_Solver.smt_filter_apply slice_timeout
   965           |> (fn {outcome, used_facts} => (outcome, used_facts))
   949           |> (fn {outcome, used_facts} => (outcome, used_facts))
   966           handle exn => if Exn.is_interrupt exn then
   950           handle exn => if Exn.is_interrupt exn then
   967                           reraise exn
   951                           reraise exn
   968                         else
   952                         else
   969                           (ML_Compiler.exn_message exn
   953                           (ML_Compiler.exn_message exn
   977           | SOME (SMT_Failure.Counterexample _) => false
   961           | SOME (SMT_Failure.Counterexample _) => false
   978           | SOME SMT_Failure.Time_Out => slice_timeout <> timeout
   962           | SOME SMT_Failure.Time_Out => slice_timeout <> timeout
   979           | SOME (SMT_Failure.Abnormal_Termination _) => true (* kind of *)
   963           | SOME (SMT_Failure.Abnormal_Termination _) => true (* kind of *)
   980           | SOME SMT_Failure.Out_Of_Memory => true
   964           | SOME SMT_Failure.Out_Of_Memory => true
   981           | SOME (SMT_Failure.Other_Failure _) => true
   965           | SOME (SMT_Failure.Other_Failure _) => true
   982         val timeout =
   966         val timeout = Time.- (timeout, Timer.checkRealTimer timer)
   983           Option.map
       
   984               (fn timeout => Time.- (timeout, Timer.checkRealTimer timer))
       
   985               timeout
       
   986       in
   967       in
   987         if too_many_facts_perhaps andalso slice < max_slices andalso
   968         if too_many_facts_perhaps andalso slice < max_slices andalso num_facts > 0 andalso
   988            num_facts > 0 andalso
   969            Time.> (timeout, Time.zeroTime) then
   989            (timeout = NONE orelse Time.> (the timeout, Time.zeroTime)) then
       
   990           let
   970           let
   991             val new_num_facts =
   971             val new_num_facts =
   992               Real.ceil (Config.get ctxt smt_slice_fact_frac
   972               Real.ceil (Config.get ctxt smt_slice_fact_frac * Real.fromInt num_facts)
   993                          * Real.fromInt num_facts)
       
   994             val weighted_factss as (new_fact_filter, _) :: _ =
   973             val weighted_factss as (new_fact_filter, _) :: _ =
   995               weighted_factss
   974               weighted_factss
   996               |> rotate_one
   975               |> rotate_one
   997               |> app_hd (apsnd (take new_num_facts))
   976               |> app_hd (apsnd (take new_num_facts))
   998             val show_filter = fact_filter <> new_fact_filter
   977             val show_filter = fact_filter <> new_fact_filter