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