src/HOL/Tools/Sledgehammer/sledgehammer_minimize.ML
author blanchet
Fri, 22 Oct 2010 13:48:21 +0200
changeset 40246 1e4c7185f3f9
parent 40244 d086e3699e78
child 40249 ed2869dd9bfa
permissions -rw-r--r--
remove more needless code ("run_smt_solvers");
tuning
blanchet@39232
     1
(*  Title:      HOL/Tools/Sledgehammer/sledgehammer_minimize.ML
immler@31037
     2
    Author:     Philipp Meyer, TU Muenchen
blanchet@36370
     3
    Author:     Jasmin Blanchette, TU Muenchen
immler@31037
     4
blanchet@40242
     5
Minimization of fact list for Metis using ATPs.
immler@31037
     6
*)
immler@31037
     7
blanchet@39232
     8
signature SLEDGEHAMMER_MINIMIZE =
boehmes@32525
     9
sig
blanchet@39232
    10
  type locality = Sledgehammer_Filter.locality
blanchet@38255
    11
  type params = Sledgehammer.params
blanchet@35867
    12
blanchet@40242
    13
  val minimize_facts :
blanchet@38991
    14
    params -> int -> int -> Proof.state -> ((string * locality) * thm list) list
blanchet@38991
    15
    -> ((string * locality) * thm list) list option * string
blanchet@39240
    16
  val run_minimize :
blanchet@39240
    17
    params -> int -> (Facts.ref * Attrib.src list) list -> Proof.state -> unit
blanchet@35866
    18
end;
boehmes@32525
    19
blanchet@39232
    20
structure Sledgehammer_Minimize : SLEDGEHAMMER_MINIMIZE =
immler@31037
    21
struct
immler@31037
    22
blanchet@39736
    23
open ATP_Proof
blanchet@36140
    24
open Sledgehammer_Util
blanchet@39232
    25
open Sledgehammer_Filter
blanchet@39248
    26
open Sledgehammer_Translate
blanchet@38255
    27
open Sledgehammer
nipkow@33492
    28
blanchet@36370
    29
(* wrapper for calling external prover *)
wenzelm@31236
    30
blanchet@39736
    31
fun string_for_failure Unprovable = "Unprovable."
blanchet@39736
    32
  | string_for_failure TimedOut = "Timed out."
blanchet@39736
    33
  | string_for_failure Interrupted = "Interrupted."
blanchet@38338
    34
  | string_for_failure _ = "Unknown error."
wenzelm@31236
    35
blanchet@40242
    36
fun n_facts names =
blanchet@38937
    37
  let val n = length names in
blanchet@40242
    38
    string_of_int n ^ " fact" ^ plural_s n ^
blanchet@38338
    39
    (if n > 0 then
blanchet@38937
    40
       ": " ^ (names |> map fst
blanchet@38937
    41
                     |> sort_distinct string_ord |> space_implode " ")
blanchet@38338
    42
     else
blanchet@38338
    43
       "")
blanchet@38338
    44
  end
blanchet@38338
    45
blanchet@40242
    46
fun test_facts ({debug, verbose, overlord, provers, full_types, isar_proof,
blanchet@40242
    47
                 isar_shrink_factor, ...} : params) (prover : prover)
blanchet@40246
    48
               explicit_apply timeout i n state axioms =
wenzelm@31236
    49
  let
blanchet@38249
    50
    val _ =
blanchet@40242
    51
      priority ("Testing " ^ n_facts (map fst axioms) ^ "...")
blanchet@38346
    52
    val params =
blanchet@39226
    53
      {blocking = true, debug = debug, verbose = verbose, overlord = overlord,
blanchet@40240
    54
       provers = provers, full_types = full_types,
blanchet@40240
    55
       explicit_apply = explicit_apply, relevance_thresholds = (1.01, 1.01),
blanchet@40242
    56
       max_relevant = NONE, isar_proof = isar_proof,
blanchet@39242
    57
       isar_shrink_factor = isar_shrink_factor, timeout = timeout, expect = ""}
blanchet@40242
    58
    val axioms =
blanchet@40242
    59
      axioms |> maps (fn (n, ths) => ths |> map (Unprepared o pair n))
blanchet@39242
    60
    val {context = ctxt, goal, ...} = Proof.goal state
blanchet@40246
    61
    val problem =
blanchet@40246
    62
      {state = state, goal = goal, subgoal = i, subgoal_count = n,
blanchet@40246
    63
       axioms = axioms, only = true}
blanchet@40246
    64
    val result as {outcome, used_axioms, ...} = prover params (K "") problem
blanchet@36223
    65
  in
blanchet@38338
    66
    priority (case outcome of
blanchet@40242
    67
                SOME failure => string_for_failure failure
blanchet@40242
    68
              | NONE =>
blanchet@40242
    69
                if length used_axioms = length axioms then "Found proof."
blanchet@40242
    70
                else "Found proof with " ^ n_facts used_axioms ^ ".");
blanchet@38338
    71
    result
blanchet@36223
    72
  end
wenzelm@31236
    73
wenzelm@31236
    74
(* minimalization of thms *)
wenzelm@31236
    75
blanchet@40242
    76
fun filter_used_axioms used = filter (member (op =) used o fst)
blanchet@38249
    77
blanchet@38249
    78
fun sublinear_minimize _ [] p = p
blanchet@38249
    79
  | sublinear_minimize test (x :: xs) (seen, result) =
blanchet@38249
    80
    case test (xs @ seen) of
blanchet@40242
    81
      result as {outcome = NONE, used_axioms, ...} : prover_result =>
blanchet@40242
    82
      sublinear_minimize test (filter_used_axioms used_axioms xs)
blanchet@40242
    83
                         (filter_used_axioms used_axioms seen, result)
blanchet@38249
    84
    | _ => sublinear_minimize test xs (x :: seen, result)
blanchet@38249
    85
blanchet@38338
    86
(* Give the ATP some slack. The ATP gets further slack because the Sledgehammer
blanchet@38338
    87
   preprocessing time is included in the estimate below but isn't part of the
blanchet@38338
    88
   timeout. *)
blanchet@38813
    89
val fudge_msecs = 1000
blanchet@38338
    90
blanchet@40242
    91
fun minimize_facts {provers = [], ...} _ _ _ _ = error "No prover is set."
blanchet@40246
    92
  | minimize_facts (params as {provers = prover_name :: _, timeout, ...}) i n
blanchet@40246
    93
                   state axioms =
wenzelm@31236
    94
  let
blanchet@36378
    95
    val thy = Proof.theory_of state
blanchet@40244
    96
    val prover = get_prover thy false prover_name
blanchet@38813
    97
    val msecs = Time.toMilliseconds timeout
blanchet@40242
    98
    val _ = priority ("Sledgehammer minimize: " ^ quote prover_name ^ ".")
blanchet@40242
    99
    val {goal, ...} = Proof.goal state
blanchet@38346
   100
    val (_, hyp_ts, concl_t) = strip_subgoal goal i
blanchet@38346
   101
    val explicit_apply =
blanchet@38346
   102
      not (forall (Meson.is_fol_term thy)
blanchet@38983
   103
                  (concl_t :: hyp_ts @ maps (map prop_of o snd) axioms))
blanchet@38346
   104
    fun do_test timeout =
blanchet@40246
   105
      test_facts params prover explicit_apply timeout i n state
blanchet@38338
   106
    val timer = Timer.startRealTimer ()
wenzelm@31236
   107
  in
blanchet@38983
   108
    (case do_test timeout axioms of
blanchet@40242
   109
       result as {outcome = NONE, used_axioms, ...} =>
blanchet@38249
   110
       let
blanchet@38338
   111
         val time = Timer.checkRealTimer timer
blanchet@38338
   112
         val new_timeout =
blanchet@38338
   113
           Int.min (msecs, Time.toMilliseconds time + fudge_msecs)
blanchet@38338
   114
           |> Time.fromMilliseconds
blanchet@40242
   115
         val (min_thms, {message, ...}) =
blanchet@38346
   116
           sublinear_minimize (do_test new_timeout)
blanchet@40242
   117
               (filter_used_axioms used_axioms axioms) ([], result)
blanchet@38340
   118
         val n = length min_thms
blanchet@38249
   119
         val _ = priority (cat_lines
blanchet@40242
   120
           ["Minimized: " ^ string_of_int n ^ " fact" ^ plural_s n] ^
blanchet@38991
   121
            (case length (filter (curry (op =) Chained o snd o fst) min_thms) of
blanchet@38937
   122
               0 => ""
blanchet@38937
   123
             | n => " (including " ^ Int.toString n ^ " chained)") ^ ".")
blanchet@40242
   124
       in (SOME min_thms, message) end
blanchet@38249
   125
     | {outcome = SOME TimedOut, ...} =>
blanchet@38249
   126
       (NONE, "Timeout: You can increase the time limit using the \"timeout\" \
blanchet@38249
   127
              \option (e.g., \"timeout = " ^
blanchet@38249
   128
              string_of_int (10 + msecs div 1000) ^ " s\").")
blanchet@38249
   129
     | {outcome = SOME UnknownError, ...} =>
blanchet@38249
   130
       (* Failure sometimes mean timeout, unfortunately. *)
blanchet@38249
   131
       (NONE, "Failure: No proof was found with the current time limit. You \
blanchet@38249
   132
              \can increase the time limit using the \"timeout\" \
blanchet@38249
   133
              \option (e.g., \"timeout = " ^
blanchet@38249
   134
              string_of_int (10 + msecs div 1000) ^ " s\").")
blanchet@38249
   135
     | {message, ...} => (NONE, "ATP error: " ^ message))
blanchet@38228
   136
    handle ERROR msg => (NONE, "Error: " ^ msg)
immler@31037
   137
  end
immler@31037
   138
blanchet@38506
   139
fun run_minimize params i refs state =
blanchet@38291
   140
  let
blanchet@38291
   141
    val ctxt = Proof.context_of state
blanchet@38935
   142
    val reserved = reserved_isar_keyword_table ()
blanchet@38291
   143
    val chained_ths = #facts (Proof.goal state)
blanchet@38983
   144
    val axioms =
blanchet@38991
   145
      maps (map (apsnd single)
blanchet@38983
   146
            o name_thm_pairs_from_ref ctxt reserved chained_ths) refs
blanchet@38291
   147
  in
blanchet@38291
   148
    case subgoal_count state of
blanchet@38291
   149
      0 => priority "No subgoal!"
blanchet@38291
   150
    | n =>
blanchet@40240
   151
      (kill_provers ();
blanchet@40242
   152
       priority (#2 (minimize_facts params i n state axioms)))
blanchet@38291
   153
  end
blanchet@38291
   154
blanchet@35866
   155
end;