40 axioms: axiom list, |
40 axioms: axiom list, |
41 only: bool} |
41 only: bool} |
42 |
42 |
43 type prover_result = |
43 type prover_result = |
44 {outcome: failure option, |
44 {outcome: failure option, |
45 message: string, |
|
46 used_axioms: (string * locality) list, |
45 used_axioms: (string * locality) list, |
47 run_time_in_msecs: int} |
46 run_time_in_msecs: int option, |
|
47 message: string} |
48 |
48 |
49 type prover = params -> minimize_command -> prover_problem -> prover_result |
49 type prover = params -> minimize_command -> prover_problem -> prover_result |
50 |
50 |
51 val smtN : string |
51 val smtN : string |
|
52 val smt_prover_names : string list |
|
53 val smt_default_max_relevant : int |
52 val dest_dir : string Config.T |
54 val dest_dir : string Config.T |
53 val problem_prefix : string Config.T |
55 val problem_prefix : string Config.T |
54 val measure_run_time : bool Config.T |
56 val measure_run_time : bool Config.T |
55 val available_provers : theory -> unit |
57 val available_provers : theory -> unit |
56 val kill_provers : unit -> unit |
58 val kill_provers : unit -> unit |
57 val running_provers : unit -> unit |
59 val running_provers : unit -> unit |
58 val messages : int option -> unit |
60 val messages : int option -> unit |
59 val run_atp : theory -> string -> prover |
61 val get_prover : theory -> string -> prover |
60 val is_smt_solver_installed : unit -> bool |
|
61 val run_smt_solver : |
|
62 bool -> params -> minimize_command -> prover_problem |
|
63 -> string * (string * locality) list |
|
64 val run_sledgehammer : |
62 val run_sledgehammer : |
65 params -> bool -> int -> relevance_override -> (string -> minimize_command) |
63 params -> bool -> int -> relevance_override -> (string -> minimize_command) |
66 -> Proof.state -> bool * Proof.state |
64 -> Proof.state -> bool * Proof.state |
67 val setup : theory -> theory |
65 val setup : theory -> theory |
68 end; |
66 end; |
85 (* Identifier to distinguish Sledgehammer from other tools using |
83 (* Identifier to distinguish Sledgehammer from other tools using |
86 "Async_Manager". *) |
84 "Async_Manager". *) |
87 val das_Tool = "Sledgehammer" |
85 val das_Tool = "Sledgehammer" |
88 |
86 |
89 val smtN = "smt" |
87 val smtN = "smt" |
90 val smt_names = [smtN, remote_prefix ^ smtN] |
88 val smt_prover_names = [smtN, remote_prefix ^ smtN] |
|
89 |
|
90 val smt_default_max_relevant = 300 (* FUDGE *) |
|
91 val auto_max_relevant_divisor = 2 (* FUDGE *) |
91 |
92 |
92 fun available_provers thy = |
93 fun available_provers thy = |
93 let |
94 let |
94 val (remote_provers, local_provers) = |
95 val (remote_provers, local_provers) = |
95 sort_strings (available_atps thy) @ smt_names |
96 sort_strings (available_atps thy) @ smt_prover_names |
96 |> List.partition (String.isPrefix remote_prefix) |
97 |> List.partition (String.isPrefix remote_prefix) |
97 in |
98 in |
98 priority ("Available provers: " ^ commas (local_provers @ remote_provers) ^ |
99 priority ("Available provers: " ^ commas (local_provers @ remote_provers) ^ |
99 ".") |
100 ".") |
100 end |
101 end |
230 fun as_num f = f >> (fst o read_int); |
234 fun as_num f = f >> (fst o read_int); |
231 val num = as_num (Scan.many1 Symbol.is_ascii_digit); |
235 val num = as_num (Scan.many1 Symbol.is_ascii_digit); |
232 val digit = Scan.one Symbol.is_ascii_digit; |
236 val digit = Scan.one Symbol.is_ascii_digit; |
233 val num3 = as_num (digit ::: digit ::: (digit >> single)); |
237 val num3 = as_num (digit ::: digit ::: (digit >> single)); |
234 val time = num --| Scan.$$ "." -- num3 >> (fn (a, b) => a * 1000 + b); |
238 val time = num --| Scan.$$ "." -- num3 >> (fn (a, b) => a * 1000 + b); |
235 val as_time = the_default 0 o Scan.read Symbol.stopper time o explode; |
239 val as_time = Scan.read Symbol.stopper time o explode |
236 in (output, as_time t) end; |
240 in (output, as_time t) end; |
237 fun run_on probfile = |
241 fun run_on probfile = |
238 case filter (curry (op =) "" o getenv o fst) (exec :: required_execs) of |
242 case filter (curry (op =) "" o getenv o fst) (exec :: required_execs) of |
239 (home_var, _) :: _ => |
243 (home_var, _) :: _ => |
240 error ("The environment variable " ^ quote home_var ^ " is not set.") |
244 error ("The environment variable " ^ quote home_var ^ " is not set.") |
248 bash_output command |
252 bash_output command |
249 |>> (if overlord then |
253 |>> (if overlord then |
250 prefix ("% " ^ command ^ "\n% " ^ timestamp () ^ "\n") |
254 prefix ("% " ^ command ^ "\n% " ^ timestamp () ^ "\n") |
251 else |
255 else |
252 I) |
256 I) |
253 |>> (if measure_run_time then split_time else rpair 0) |
257 |>> (if measure_run_time then split_time else rpair NONE) |
254 val (tstplike_proof, outcome) = |
258 val (tstplike_proof, outcome) = |
255 extract_tstplike_proof_and_outcome complete res_code |
259 extract_tstplike_proof_and_outcome complete res_code |
256 proof_delims known_failures output |
260 proof_delims known_failures output |
257 in (output, msecs, tstplike_proof, outcome) end |
261 in (output, msecs, tstplike_proof, outcome) end |
258 val readable_names = debug andalso overlord |
262 val readable_names = debug andalso overlord |
275 timeout) |
279 timeout) |
276 |> run_twice |
280 |> run_twice |
277 ? (fn (_, msecs0, _, SOME _) => |
281 ? (fn (_, msecs0, _, SOME _) => |
278 run true (Time.- (timeout, Timer.checkRealTimer timer)) |
282 run true (Time.- (timeout, Timer.checkRealTimer timer)) |
279 |> (fn (output, msecs, tstplike_proof, outcome) => |
283 |> (fn (output, msecs, tstplike_proof, outcome) => |
280 (output, msecs0 + msecs, tstplike_proof, outcome)) |
284 (output, int_option_add msecs0 msecs, |
|
285 tstplike_proof, outcome)) |
281 | result => result) |
286 | result => result) |
282 in ((pool, conjecture_shape, axiom_names), result) end |
287 in ((pool, conjecture_shape, axiom_names), result) end |
283 else |
288 else |
284 error ("Bad executable: " ^ Path.implode command ^ ".") |
289 error ("Bad executable: " ^ Path.implode command ^ ".") |
285 |
290 |
310 (pool, debug, isar_shrink_factor, ctxt, conjecture_shape) |
315 (pool, debug, isar_shrink_factor, ctxt, conjecture_shape) |
311 (proof_banner auto, full_types, minimize_command, tstplike_proof, |
316 (proof_banner auto, full_types, minimize_command, tstplike_proof, |
312 axiom_names, goal, subgoal) |
317 axiom_names, goal, subgoal) |
313 |>> (fn message => |
318 |>> (fn message => |
314 message ^ (if verbose then |
319 message ^ (if verbose then |
315 "\nATP real CPU time: " ^ string_of_int msecs ^ |
320 "\nATP real CPU time: " ^ |
316 " ms." |
321 string_of_int (the msecs) ^ " ms." |
317 else |
322 else |
318 "") ^ |
323 "") ^ |
319 (if important_message <> "" then |
324 (if important_message <> "" then |
320 "\n\nImportant message from Dr. Geoff Sutcliffe:\n" ^ |
325 "\n\nImportant message from Dr. Geoff Sutcliffe:\n" ^ |
321 important_message |
326 important_message |
325 in |
330 in |
326 {outcome = outcome, message = message, used_axioms = used_axioms, |
331 {outcome = outcome, message = message, used_axioms = used_axioms, |
327 run_time_in_msecs = msecs} |
332 run_time_in_msecs = msecs} |
328 end |
333 end |
329 |
334 |
330 fun run_atp thy name = atp_fun false name (get_atp thy name) |
335 fun get_atp_as_prover thy name = atp_fun false name (get_atp thy name) |
331 |
336 |
332 fun run_atp_somehow (params as {blocking, debug, max_relevant, timeout, |
337 fun run_atp_somehow (params as {blocking, debug, max_relevant, timeout, |
333 expect, ...}) |
338 expect, ...}) |
334 auto i n minimize_command |
339 auto i n minimize_command |
335 (prover_problem as {state, goal, axioms, ...}) |
340 (problem as {state, goal, axioms, ...}) |
336 (prover as {default_max_relevant, ...}, atp_name) = |
341 (prover as {default_max_relevant, ...}, atp_name) = |
337 let |
342 let |
338 val ctxt = Proof.context_of state |
343 val ctxt = Proof.context_of state |
339 val birth_time = Time.now () |
344 val birth_time = Time.now () |
340 val death_time = Time.+ (birth_time, timeout) |
345 val death_time = Time.+ (birth_time, timeout) |
381 (Async_Manager.launch das_Tool birth_time death_time desc (snd o go); |
386 (Async_Manager.launch das_Tool birth_time death_time desc (snd o go); |
382 (false, state)) |
387 (false, state)) |
383 end |
388 end |
384 |
389 |
385 (* FIXME: dummy *) |
390 (* FIXME: dummy *) |
386 fun is_smt_solver_installed () = true |
391 fun run_smt_solver remote timeout state axioms i = |
387 |
392 {outcome = NONE, used_axioms = axioms |> take 5 |> map fst, |
388 (* FIXME: dummy *) |
393 run_time_in_msecs = NONE} |
389 fun raw_run_smt_solver remote timeout state axioms i = |
394 |
390 ("", axioms |> take 5 |> map fst) |
395 fun get_smt_solver_as_prover remote ({timeout, ...} : params) minimize_command |
391 |
396 ({state, subgoal, axioms, ...} : prover_problem) = |
392 fun run_smt_solver remote ({timeout, ...} : params) minimize_command |
397 let |
393 ({state, subgoal, axioms, ...} : prover_problem) = |
398 val {outcome, used_axioms, run_time_in_msecs} = |
394 raw_run_smt_solver remote timeout state |
399 run_smt_solver remote timeout state |
395 (map_filter (try dest_Unprepared) axioms) subgoal |
400 (map_filter (try dest_Unprepared) axioms) subgoal |
396 |
401 val message = |
397 fun run_smt_solver_somehow state (params as {timeout, ...}) i n goal axioms |
402 if outcome = NONE then |
|
403 sendback_line (proof_banner false) |
|
404 (apply_on_subgoal subgoal (subgoal_count state) ^ |
|
405 command_call smtN (map fst used_axioms)) |
|
406 else |
|
407 "" |
|
408 in |
|
409 {outcome = outcome, used_axioms = used_axioms, |
|
410 run_time_in_msecs = run_time_in_msecs, message = message} |
|
411 end |
|
412 |
|
413 fun get_prover thy name = |
|
414 if member (op =) smt_prover_names name then |
|
415 get_smt_solver_as_prover (String.isPrefix remote_prefix) |
|
416 else |
|
417 get_atp_as_prover thy name |
|
418 |
|
419 fun run_smt_solver_somehow state params minimize_command i n goal axioms |
398 (remote, name) = |
420 (remote, name) = |
399 let |
421 let |
400 val ctxt = Proof.context_of state |
422 val ctxt = Proof.context_of state |
401 val desc = prover_description ctxt params name (length axioms) i n goal |
423 val desc = prover_description ctxt params name (length axioms) i n goal |
402 val (failure, used_axioms) = |
424 val problem = |
403 raw_run_smt_solver remote timeout state axioms i |
425 {state = state, goal = goal, subgoal = i, |
404 val success = (failure = "") |
426 axioms = axioms |> map Unprepared, only = true} |
405 val message = |
427 val {outcome, used_axioms, message, ...} = |
406 das_Tool ^ ": " ^ desc ^ "\n" ^ |
428 get_smt_solver_as_prover remote params minimize_command problem |
407 (if success then |
429 val _ = |
408 sendback_line (proof_banner false) |
430 priority (das_Tool ^ ": " ^ desc ^ "\n" ^ |
409 (apply_on_subgoal i n ^ |
431 (if outcome = NONE then message |
410 command_call "smt" (map fst used_axioms)) |
432 else "An unknown error occurred.")) |
411 else |
433 in outcome = NONE end |
412 "Error: " ^ failure) |
|
413 in priority message; success end |
|
414 |
|
415 val smt_default_max_relevant = 300 (* FUDGE *) |
|
416 val auto_max_relevant_divisor = 2 (* FUDGE *) |
|
417 |
434 |
418 fun run_sledgehammer (params as {blocking, provers, full_types, |
435 fun run_sledgehammer (params as {blocking, provers, full_types, |
419 relevance_thresholds, max_relevant, timeout, |
436 relevance_thresholds, max_relevant, timeout, |
420 ...}) |
437 ...}) |
421 auto i (relevance_override as {only, ...}) minimize_command |
438 auto i (relevance_override as {only, ...}) minimize_command |
431 val {context = ctxt, facts = chained_ths, goal} = Proof.goal state |
448 val {context = ctxt, facts = chained_ths, goal} = Proof.goal state |
432 val (_, hyp_ts, concl_t) = strip_subgoal goal i |
449 val (_, hyp_ts, concl_t) = strip_subgoal goal i |
433 val _ = () |> not blocking ? kill_provers |
450 val _ = () |> not blocking ? kill_provers |
434 val _ = if auto then () else priority "Sledgehammering..." |
451 val _ = if auto then () else priority "Sledgehammering..." |
435 val (smts, atps) = |
452 val (smts, atps) = |
436 provers |> List.partition (member (op =) smt_names) |
453 provers |> List.partition (member (op =) smt_prover_names) |
437 |>> (take 1 #> map (`(String.isPrefix remote_prefix))) |
454 |>> (take 1 #> map (`(String.isPrefix remote_prefix))) |
438 ||> map (`(get_atp thy)) |
455 ||> map (`(get_atp thy)) |
439 fun run_atps (res as (success, state)) = |
456 fun run_atps (res as (success, state)) = |
440 if success orelse null atps then |
457 if success orelse null atps then |
441 res |
458 res |
449 |> auto ? (fn n => n div auto_max_relevant_divisor) |
466 |> auto ? (fn n => n div auto_max_relevant_divisor) |
450 val axioms = |
467 val axioms = |
451 relevant_facts ctxt full_types relevance_thresholds |
468 relevant_facts ctxt full_types relevance_thresholds |
452 max_max_relevant relevance_override chained_ths |
469 max_max_relevant relevance_override chained_ths |
453 hyp_ts concl_t |
470 hyp_ts concl_t |
454 val prover_problem = |
471 val problem = |
455 {state = state, goal = goal, subgoal = i, |
472 {state = state, goal = goal, subgoal = i, |
456 axioms = axioms |> map (Prepared o prepare_axiom ctxt), |
473 axioms = axioms |> map (Prepared o prepare_axiom ctxt), |
457 only = only} |
474 only = only} |
458 val run_atp_somehow = |
475 val run_atp_somehow = |
459 run_atp_somehow params auto i n minimize_command prover_problem |
476 run_atp_somehow params auto i n minimize_command problem |
460 in |
477 in |
461 if auto then |
478 if auto then |
462 fold (fn prover => fn (true, state) => (true, state) |
479 fold (fn prover => fn (true, state) => (true, state) |
463 | (false, _) => run_atp_somehow prover) |
480 | (false, _) => run_atp_somehow prover) |
464 atps (false, state) |
481 atps (false, state) |
476 val axioms = |
493 val axioms = |
477 relevant_facts ctxt full_types relevance_thresholds |
494 relevant_facts ctxt full_types relevance_thresholds |
478 max_relevant relevance_override chained_ths |
495 max_relevant relevance_override chained_ths |
479 hyp_ts concl_t |
496 hyp_ts concl_t |
480 in |
497 in |
481 smts |> map (run_smt_solver_somehow state params i n goal axioms) |
498 smts |> map (run_smt_solver_somehow state params minimize_command i |
|
499 n goal axioms) |
482 |> exists I |> rpair state |
500 |> exists I |> rpair state |
483 end |
501 end |
484 fun run_atps_and_smt_solvers () = |
502 fun run_atps_and_smt_solvers () = |
485 [run_atps, run_smt_solvers] |
503 [run_atps, run_smt_solvers] |
486 |> Par_List.map (fn f => f (false, state) |> K ()) |
504 |> Par_List.map (fn f => f (false, state) |> K ()) |