src/HOL/Tools/Sledgehammer/sledgehammer_provers.ML
changeset 50557 31313171deb5
parent 50494 06b199a042ff
child 50558 a719106124d8
equal deleted inserted replaced
50556:6209bc89faa3 50557:31313171deb5
    35      max_new_mono_instances : int option,
    35      max_new_mono_instances : int option,
    36      isar_proofs : bool,
    36      isar_proofs : bool,
    37      isar_shrink : real,
    37      isar_shrink : real,
    38      slice : bool,
    38      slice : bool,
    39      minimize : bool option,
    39      minimize : bool option,
    40      timeout : Time.time,
    40      timeout : Time.time option,
    41      preplay_timeout : Time.time,
    41      preplay_timeout : Time.time option,
    42      expect : string}
    42      expect : string}
    43 
    43 
    44   type relevance_fudge =
    44   type relevance_fudge =
    45     {local_const_multiplier : real,
    45     {local_const_multiplier : real,
    46      worse_irrel_freq : real,
    46      worse_irrel_freq : real,
   328    max_new_mono_instances : int option,
   328    max_new_mono_instances : int option,
   329    isar_proofs : bool,
   329    isar_proofs : bool,
   330    isar_shrink : real,
   330    isar_shrink : real,
   331    slice : bool,
   331    slice : bool,
   332    minimize : bool option,
   332    minimize : bool option,
   333    timeout : Time.time,
   333    timeout : Time.time option,
   334    preplay_timeout : Time.time,
   334    preplay_timeout : Time.time option,
   335    expect : string}
   335    expect : string}
   336 
   336 
   337 type relevance_fudge =
   337 type relevance_fudge =
   338   {local_const_multiplier : real,
   338   {local_const_multiplier : real,
   339    worse_irrel_freq : real,
   339    worse_irrel_freq : real,
   477 (* based on "Mirabelle.can_apply" and generalized *)
   477 (* based on "Mirabelle.can_apply" and generalized *)
   478 fun timed_apply timeout tac state i =
   478 fun timed_apply timeout tac state i =
   479   let
   479   let
   480     val {context = ctxt, facts, goal} = Proof.goal state
   480     val {context = ctxt, facts, goal} = Proof.goal state
   481     val full_tac = Method.insert_tac facts i THEN tac ctxt i
   481     val full_tac = Method.insert_tac facts i THEN tac ctxt i
   482   in TimeLimit.timeLimit timeout (try (Seq.pull o full_tac)) goal end
   482   in time_limit timeout (try (Seq.pull o full_tac)) goal end
   483 
   483 
   484 fun tac_for_reconstructor (Metis (type_enc, lam_trans)) =
   484 fun tac_for_reconstructor (Metis (type_enc, lam_trans)) =
   485     metis_tac [type_enc] lam_trans
   485     metis_tac [type_enc] lam_trans
   486   | tac_for_reconstructor SMT = SMT_Solver.smt_tac
   486   | tac_for_reconstructor SMT = SMT_Solver.smt_tac
   487 
   487 
   498           (if keep_chained then is_fact_chained else K false))
   498           (if keep_chained then is_fact_chained else K false))
   499 
   499 
   500 fun play_one_line_proof mode debug verbose timeout pairs state i preferred
   500 fun play_one_line_proof mode debug verbose timeout pairs state i preferred
   501                         reconstrs =
   501                         reconstrs =
   502   let
   502   let
   503     val _ =
       
   504       if mode = Minimize andalso Time.> (timeout, Time.zeroTime) then
       
   505         Output.urgent_message "Preplaying proof..."
       
   506       else
       
   507         ()
       
   508     val ths = pairs |> sort_wrt (fst o fst) |> map snd
       
   509     fun get_preferred reconstrs =
   503     fun get_preferred reconstrs =
   510       if member (op =) reconstrs preferred then preferred
   504       if member (op =) reconstrs preferred then preferred
   511       else List.last reconstrs
   505       else List.last reconstrs
   512     fun play [] [] = Failed_to_Play (get_preferred reconstrs)
       
   513       | play timed_outs [] =
       
   514         Trust_Playable (get_preferred timed_outs, SOME timeout)
       
   515       | play timed_out (reconstr :: reconstrs) =
       
   516         let
       
   517           val _ =
       
   518             if verbose then
       
   519               "Trying \"" ^ string_for_reconstructor reconstr ^ "\" for " ^
       
   520               string_from_time timeout ^ "..."
       
   521               |> Output.urgent_message
       
   522             else
       
   523               ()
       
   524           val timer = Timer.startRealTimer ()
       
   525         in
       
   526           case timed_reconstructor reconstr debug timeout ths state i of
       
   527             SOME (SOME _) => Played (reconstr, Timer.checkRealTimer timer)
       
   528           | _ => play timed_out reconstrs
       
   529         end
       
   530         handle TimeLimit.TimeOut => play (reconstr :: timed_out) reconstrs
       
   531   in
   506   in
   532     if timeout = Time.zeroTime then
   507     if timeout = SOME Time.zeroTime then
   533       Trust_Playable (get_preferred reconstrs, NONE)
   508       Trust_Playable (get_preferred reconstrs, NONE)
   534     else
   509     else
   535       play [] reconstrs
   510       let
       
   511         val _ =
       
   512           if mode = Minimize then Output.urgent_message "Preplaying proof..."
       
   513           else ()
       
   514         val ths = pairs |> sort_wrt (fst o fst) |> map snd
       
   515         fun play [] [] = Failed_to_Play (get_preferred reconstrs)
       
   516           | play timed_outs [] =
       
   517             Trust_Playable (get_preferred timed_outs, timeout)
       
   518           | play timed_out (reconstr :: reconstrs) =
       
   519             let
       
   520               val _ =
       
   521                 if verbose then
       
   522                   "Trying \"" ^ string_for_reconstructor reconstr ^ "\"" ^
       
   523                   (case timeout of
       
   524                      SOME timeout => " for " ^ string_from_time timeout
       
   525                    | NONE => "") ^ "..."
       
   526                   |> Output.urgent_message
       
   527                 else
       
   528                   ()
       
   529               val timer = Timer.startRealTimer ()
       
   530             in
       
   531               case timed_reconstructor reconstr debug timeout ths state i of
       
   532                 SOME (SOME _) => Played (reconstr, Timer.checkRealTimer timer)
       
   533               | _ => play timed_out reconstrs
       
   534             end
       
   535             handle TimeLimit.TimeOut => play (reconstr :: timed_out) reconstrs
       
   536       in play [] reconstrs end
   536   end
   537   end
   537 
   538 
   538 
   539 
   539 (* generic TPTP-based ATPs *)
   540 (* generic TPTP-based ATPs *)
   540 
   541 
   732             val type_enc =
   733             val type_enc =
   733               type_enc |> choose_type_enc soundness best_type_enc format
   734               type_enc |> choose_type_enc soundness best_type_enc format
   734             val sound = is_type_enc_sound type_enc
   735             val sound = is_type_enc_sound type_enc
   735             val real_ms = Real.fromInt o Time.toMilliseconds
   736             val real_ms = Real.fromInt o Time.toMilliseconds
   736             val slice_timeout =
   737             val slice_timeout =
   737               ((real_ms time_left
   738               case time_left of
   738                 |> (if slice < num_actual_slices - 1 then
   739                 SOME time_left =>
   739                       curry Real.min (time_frac * real_ms timeout)
   740                 ((real_ms time_left
   740                     else
   741                   |> (if slice < num_actual_slices - 1 then
   741                       I))
   742                         curry Real.min (time_frac * real_ms (the timeout))
   742                * 0.001) |> seconds
   743                       else
       
   744                         I))
       
   745                  * 0.001)
       
   746                 |> seconds |> SOME
       
   747               | NONE => NONE
   743             val generous_slice_timeout =
   748             val generous_slice_timeout =
   744               Time.+ (slice_timeout, atp_timeout_slack)
   749               Option.map (curry Time.+ atp_timeout_slack) slice_timeout
   745             val _ =
   750             val _ =
   746               if debug then
   751               if debug then
   747                 quote name ^ " slice #" ^ string_of_int (slice + 1) ^
   752                 quote name ^ " slice #" ^ string_of_int (slice + 1) ^
   748                 " with " ^ string_of_int num_facts ^ " fact" ^
   753                 " with " ^ string_of_int num_facts ^ " fact" ^
   749                 plural_s num_facts ^ " for " ^
   754                 plural_s num_facts ^
   750                 string_from_time slice_timeout ^ "..."
   755                 (case slice_timeout of
       
   756                    SOME timeout => " for " ^ string_from_time timeout
       
   757                  | NONE => "") ^ "..."
   751                 |> Output.urgent_message
   758                 |> Output.urgent_message
   752               else
   759               else
   753                 ()
   760                 ()
   754             val readable_names = not (Config.get ctxt atp_full_names)
   761             val readable_names = not (Config.get ctxt atp_full_names)
   755             val lam_trans =
   762             val lam_trans =
   776                                        readable_names true hyp_ts concl_t
   783                                        readable_names true hyp_ts concl_t
   777             fun sel_weights () = atp_problem_selection_weights atp_problem
   784             fun sel_weights () = atp_problem_selection_weights atp_problem
   778             fun ord_info () = atp_problem_term_order_info atp_problem
   785             fun ord_info () = atp_problem_term_order_info atp_problem
   779             val ord = effective_term_order ctxt name
   786             val ord = effective_term_order ctxt name
   780             val full_proof = debug orelse isar_proofs
   787             val full_proof = debug orelse isar_proofs
   781             val args = arguments ctxt full_proof extra slice_timeout
   788             val args = arguments ctxt full_proof extra
       
   789                                  (slice_timeout |> the_default one_day)
   782                                  (ord, ord_info, sel_weights)
   790                                  (ord, ord_info, sel_weights)
   783             val command =
   791             val command =
   784               "(exec 2>&1; " ^ File.shell_path command0 ^ " " ^ args ^ " " ^
   792               "(exec 2>&1; " ^ File.shell_path command0 ^ " " ^ args ^ " " ^
   785               File.shell_path prob_path ^ ")"
   793               File.shell_path prob_path ^ ")"
   786               |> enclose "TIMEFORMAT='%3R'; { time " " ; }"
   794               |> enclose "TIMEFORMAT='%3R'; { time " " ; }"
   788               atp_problem
   796               atp_problem
   789               |> lines_for_atp_problem format ord ord_info
   797               |> lines_for_atp_problem format ord ord_info
   790               |> cons ("% " ^ command ^ "\n")
   798               |> cons ("% " ^ command ^ "\n")
   791               |> File.write_list prob_path
   799               |> File.write_list prob_path
   792             val ((output, run_time), (atp_proof, outcome)) =
   800             val ((output, run_time), (atp_proof, outcome)) =
   793               TimeLimit.timeLimit generous_slice_timeout
   801               time_limit generous_slice_timeout Isabelle_System.bash_output
   794                                   Isabelle_System.bash_output command
   802                          command
   795               |>> (if overlord then
   803               |>> (if overlord then
   796                      prefix ("% " ^ command ^ "\n% " ^ timestamp () ^ "\n")
   804                      prefix ("% " ^ command ^ "\n% " ^ timestamp () ^ "\n")
   797                    else
   805                    else
   798                      I)
   806                      I)
   799               |> fst |> split_time
   807               |> fst |> split_time
   803                                                          known_failures output
   811                                                          known_failures output
   804                       |>> atp_proof_from_tstplike_proof atp_problem
   812                       |>> atp_proof_from_tstplike_proof atp_problem
   805                       handle UNRECOGNIZED_ATP_PROOF () =>
   813                       handle UNRECOGNIZED_ATP_PROOF () =>
   806                              ([], SOME ProofIncomplete)))
   814                              ([], SOME ProofIncomplete)))
   807               handle TimeLimit.TimeOut =>
   815               handle TimeLimit.TimeOut =>
   808                      (("", slice_timeout), ([], SOME TimedOut))
   816                      (("", the slice_timeout), ([], SOME TimedOut))
   809             val outcome =
   817             val outcome =
   810               case outcome of
   818               case outcome of
   811                 NONE =>
   819                 NONE =>
   812                 (case used_facts_in_unsound_atp_proof ctxt fact_names atp_proof
   820                 (case used_facts_in_unsound_atp_proof ctxt fact_names atp_proof
   813                       |> Option.map (sort string_ord) of
   821                       |> Option.map (sort string_ord) of
   824           in ((SOME key, value), (output, run_time, atp_proof, outcome)) end
   832           in ((SOME key, value), (output, run_time, atp_proof, outcome)) end
   825         val timer = Timer.startRealTimer ()
   833         val timer = Timer.startRealTimer ()
   826         fun maybe_run_slice slice
   834         fun maybe_run_slice slice
   827                 (result as (cache, (_, run_time0, _, SOME _))) =
   835                 (result as (cache, (_, run_time0, _, SOME _))) =
   828             let
   836             let
   829               val time_left = Time.- (timeout, Timer.checkRealTimer timer)
   837               val time_left =
       
   838                 Option.map
       
   839                     (fn timeout => Time.- (timeout, Timer.checkRealTimer timer))
       
   840                     timeout
   830             in
   841             in
   831               if Time.<= (time_left, Time.zeroTime) then
   842               if time_left <> NONE andalso
       
   843                  Time.<= (the time_left, Time.zeroTime) then
   832                 result
   844                 result
   833               else
   845               else
   834                 run_slice time_left cache slice
   846                 run_slice time_left cache slice
   835                 |> (fn (cache, (output, run_time, atp_proof, outcome)) =>
   847                 |> (fn (cache, (output, run_time, atp_proof, outcome)) =>
   836                        (cache, (output, Time.+ (run_time0, run_time),
   848                        (cache, (output, Time.+ (run_time0, run_time),
   977         val state =
   989         val state =
   978           state |> Proof.map_context
   990           state |> Proof.map_context
   979                        (repair_monomorph_context max_mono_iters
   991                        (repair_monomorph_context max_mono_iters
   980                             default_max_mono_iters max_new_mono_instances
   992                             default_max_mono_iters max_new_mono_instances
   981                             default_max_new_mono_instances)
   993                             default_max_new_mono_instances)
   982         val ms = timeout |> Time.toMilliseconds
       
   983         val slice_timeout =
   994         val slice_timeout =
   984           if slice < max_slices then
   995           if slice < max_slices andalso timeout <> NONE then
   985             Int.min (ms,
   996             let val ms = timeout |> the |> Time.toMilliseconds in
   986                 Int.max (1000 * Config.get ctxt smt_slice_min_secs,
   997               Int.min (ms,
   987                     Real.ceil (Config.get ctxt smt_slice_time_frac
   998                   Int.max (1000 * Config.get ctxt smt_slice_min_secs,
   988                                * Real.fromInt ms)))
   999                       Real.ceil (Config.get ctxt smt_slice_time_frac
   989             |> Time.fromMilliseconds
  1000                                  * Real.fromInt ms)))
       
  1001               |> Time.fromMilliseconds |> SOME
       
  1002             end
   990           else
  1003           else
   991             timeout
  1004             timeout
   992         val num_facts = length facts
  1005         val num_facts = length facts
   993         val _ =
  1006         val _ =
   994           if debug then
  1007           if debug then
   995             quote name ^ " slice " ^ string_of_int slice ^ " with " ^
  1008             quote name ^ " slice " ^ string_of_int slice ^ " with " ^
   996             string_of_int num_facts ^ " fact" ^ plural_s num_facts ^ " for " ^
  1009             string_of_int num_facts ^ " fact" ^ plural_s num_facts ^
   997             string_from_time slice_timeout ^ "..."
  1010             (case slice_timeout of
       
  1011                SOME timeout => " for " ^ string_from_time timeout
       
  1012              | NONE => "") ^ "..."
   998             |> Output.urgent_message
  1013             |> Output.urgent_message
   999           else
  1014           else
  1000             ()
  1015             ()
  1001         val birth = Timer.checkRealTimer timer
  1016         val birth = Timer.checkRealTimer timer
  1002         val _ =
  1017         val _ =
  1003           if debug then Output.urgent_message "Invoking SMT solver..." else ()
  1018           if debug then Output.urgent_message "Invoking SMT solver..." else ()
  1004         val state_facts = these (try (#facts o Proof.goal) state)
  1019         val state_facts = these (try (#facts o Proof.goal) state)
  1005         val (outcome, used_facts) =
  1020         val (outcome, used_facts) =
  1006           SMT_Solver.smt_filter_preprocess ctxt state_facts goal facts i
  1021           SMT_Solver.smt_filter_preprocess ctxt state_facts goal facts i
  1007           |> SMT_Solver.smt_filter_apply slice_timeout
  1022           |> SMT_Solver.smt_filter_apply (slice_timeout |> the_default one_day)
  1008           |> (fn {outcome, used_facts} => (outcome, used_facts))
  1023           |> (fn {outcome, used_facts} => (outcome, used_facts))
  1009           handle exn => if Exn.is_interrupt exn then
  1024           handle exn => if Exn.is_interrupt exn then
  1010                           reraise exn
  1025                           reraise exn
  1011                         else
  1026                         else
  1012                           (ML_Compiler.exn_message exn
  1027                           (ML_Compiler.exn_message exn
  1020           | SOME (SMT_Failure.Counterexample _) => false
  1035           | SOME (SMT_Failure.Counterexample _) => false
  1021           | SOME SMT_Failure.Time_Out => slice_timeout <> timeout
  1036           | SOME SMT_Failure.Time_Out => slice_timeout <> timeout
  1022           | SOME (SMT_Failure.Abnormal_Termination _) => true (* kind of *)
  1037           | SOME (SMT_Failure.Abnormal_Termination _) => true (* kind of *)
  1023           | SOME SMT_Failure.Out_Of_Memory => true
  1038           | SOME SMT_Failure.Out_Of_Memory => true
  1024           | SOME (SMT_Failure.Other_Failure _) => true
  1039           | SOME (SMT_Failure.Other_Failure _) => true
  1025         val timeout = Time.- (timeout, Timer.checkRealTimer timer)
  1040         val timeout =
       
  1041           Option.map
       
  1042               (fn timeout => Time.- (timeout, Timer.checkRealTimer timer))
       
  1043               timeout
  1026       in
  1044       in
  1027         if too_many_facts_perhaps andalso slice < max_slices andalso
  1045         if too_many_facts_perhaps andalso slice < max_slices andalso
  1028            num_facts > 0 andalso Time.> (timeout, Time.zeroTime) then
  1046            num_facts > 0 andalso
       
  1047            (timeout = NONE orelse Time.> (the timeout, Time.zeroTime)) then
  1029           let
  1048           let
  1030             val new_num_facts =
  1049             val new_num_facts =
  1031               Real.ceil (Config.get ctxt smt_slice_fact_frac
  1050               Real.ceil (Config.get ctxt smt_slice_fact_frac
  1032                          * Real.fromInt num_facts)
  1051                          * Real.fromInt num_facts)
  1033             val _ =
  1052             val _ =