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;
|