| author | wenzelm | 
| Sat, 11 Jul 2020 17:15:28 +0200 | |
| changeset 72021 | 664e90313a54 | 
| parent 70327 | c04d4951a155 | 
| child 72278 | 199dc903131b | 
| permissions | -rw-r--r-- | 
| 58061 | 1  | 
(* Title: HOL/Tools/SMT/smt_solver.ML  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
2  | 
Author: Sascha Boehme, TU Muenchen  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
3  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
4  | 
SMT solvers registry and SMT tactic.  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
5  | 
*)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
6  | 
|
| 58061 | 7  | 
signature SMT_SOLVER =  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
8  | 
sig  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
9  | 
(*configuration*)  | 
| 
70327
 
c04d4951a155
handle timeouts gracefully in 'smt' proof method (patch due to Mathias Fleury)
 
blanchet 
parents: 
70293 
diff
changeset
 | 
10  | 
datatype outcome = Unsat | Sat | Unknown | Time_Out  | 
| 57163 | 11  | 
|
12  | 
type parsed_proof =  | 
|
| 58061 | 13  | 
    {outcome: SMT_Failure.failure option,
 | 
| 60201 | 14  | 
fact_ids: (int * ((string * ATP_Problem_Generate.stature) * thm)) list option,  | 
| 57163 | 15  | 
atp_proof: unit -> (term, string) ATP_Proof.atp_step list}  | 
16  | 
||
17  | 
type solver_config =  | 
|
18  | 
    {name: string,
 | 
|
| 58061 | 19  | 
class: Proof.context -> SMT_Util.class,  | 
| 57163 | 20  | 
avail: unit -> bool,  | 
21  | 
command: unit -> string list,  | 
|
22  | 
options: Proof.context -> string list,  | 
|
| 57239 | 23  | 
smt_options: (string * string) list,  | 
| 57163 | 24  | 
default_max_relevant: int,  | 
25  | 
outcome: string -> string list -> outcome * string list,  | 
|
| 58061 | 26  | 
parse_proof: (Proof.context -> SMT_Translate.replay_data ->  | 
| 57164 | 27  | 
((string * ATP_Problem_Generate.stature) * thm) list -> term list -> term -> string list ->  | 
28  | 
parsed_proof) option,  | 
|
| 58061 | 29  | 
replay: (Proof.context -> SMT_Translate.replay_data -> string list -> thm) option}  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
30  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
31  | 
(*registry*)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
32  | 
val add_solver: solver_config -> theory -> theory  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
33  | 
val default_max_relevant: Proof.context -> string -> int  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
34  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
35  | 
(*filter*)  | 
| 58061 | 36  | 
val smt_filter: Proof.context -> thm -> ((string * ATP_Problem_Generate.stature) * thm) list ->  | 
| 
57165
 
7b1bf424ec5f
removed SMT weights -- their impact was very inconclusive anyway
 
blanchet 
parents: 
57164 
diff
changeset
 | 
37  | 
int -> Time.time -> parsed_proof  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
38  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
39  | 
(*tactic*)  | 
| 58061 | 40  | 
val smt_tac: Proof.context -> thm list -> int -> tactic  | 
41  | 
val smt_tac': Proof.context -> thm list -> int -> tactic  | 
|
| 57229 | 42  | 
end;  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
43  | 
|
| 58061 | 44  | 
structure SMT_Solver: SMT_SOLVER =  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
45  | 
struct  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
46  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
47  | 
(* interface to external solvers *)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
48  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
49  | 
local  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
50  | 
|
| 
56132
 
64eeda68e693
delayed construction of command (and of noncommercial check) + tuning
 
blanchet 
parents: 
56131 
diff
changeset
 | 
51  | 
fun make_command command options problem_path proof_path =  | 
| 
70293
 
c7e9d3a0a681
more direct invocation of Windows exe: avoid extra bash, cygpath, exec;
 
wenzelm 
parents: 
70288 
diff
changeset
 | 
52  | 
Bash.strings (command () @ options) ^ " " ^  | 
| 
 
c7e9d3a0a681
more direct invocation of Windows exe: avoid extra bash, cygpath, exec;
 
wenzelm 
parents: 
70288 
diff
changeset
 | 
53  | 
Bash.string (File.platform_path problem_path) ^  | 
| 
70288
 
2e101846ad8f
avoid extra subprocess -- potentially more robust on Cygwin;
 
wenzelm 
parents: 
69593 
diff
changeset
 | 
54  | 
" > " ^ File.bash_path proof_path ^ " 2>&1"  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
55  | 
|
| 
56132
 
64eeda68e693
delayed construction of command (and of noncommercial check) + tuning
 
blanchet 
parents: 
56131 
diff
changeset
 | 
56  | 
fun with_trace ctxt msg f x =  | 
| 58061 | 57  | 
let val _ = SMT_Config.trace_msg ctxt (fn () => msg) ()  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
58  | 
in f x end  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
59  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
60  | 
fun run ctxt name mk_cmd input =  | 
| 58061 | 61  | 
(case SMT_Config.certificates_of ctxt of  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
62  | 
NONE =>  | 
| 58061 | 63  | 
if not (SMT_Config.is_available ctxt name) then  | 
| 56131 | 64  | 
        error ("The SMT solver " ^ quote name ^ " is not installed")
 | 
| 58061 | 65  | 
else if Config.get ctxt SMT_Config.debug_files = "" then  | 
| 
56132
 
64eeda68e693
delayed construction of command (and of noncommercial check) + tuning
 
blanchet 
parents: 
56131 
diff
changeset
 | 
66  | 
        with_trace ctxt ("Invoking SMT solver " ^ quote name ^ " ...") (Cache_IO.run mk_cmd) input
 | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
67  | 
else  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
68  | 
let  | 
| 58061 | 69  | 
val base_path = Path.explode (Config.get ctxt SMT_Config.debug_files)  | 
70  | 
val in_path = Path.ext "smt_in" base_path  | 
|
71  | 
val out_path = Path.ext "smt_out" base_path  | 
|
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
72  | 
in Cache_IO.raw_run mk_cmd input in_path out_path end  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
73  | 
| SOME certs =>  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
74  | 
(case Cache_IO.lookup certs input of  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
75  | 
(NONE, key) =>  | 
| 58061 | 76  | 
if Config.get ctxt SMT_Config.read_only_certificates then  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
77  | 
            error ("Bad certificate cache: missing certificate")
 | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
78  | 
else  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
79  | 
Cache_IO.run_and_cache certs key mk_cmd input  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
80  | 
| (SOME output, _) =>  | 
| 
56132
 
64eeda68e693
delayed construction of command (and of noncommercial check) + tuning
 
blanchet 
parents: 
56131 
diff
changeset
 | 
81  | 
          with_trace ctxt ("Using cached certificate from " ^
 | 
| 
62549
 
9498623b27f0
File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
 
wenzelm 
parents: 
61268 
diff
changeset
 | 
82  | 
Path.print (Cache_IO.cache_path_of certs) ^ " ...") I output))  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
83  | 
|
| 
63102
 
71059cf60658
better handling of veriT's 'unknown' status
 
fleury <Mathias.Fleury@mpi-inf.mpg.de> 
parents: 
62549 
diff
changeset
 | 
84  | 
(* Z3 returns 1 if "get-proof" or "get-model" fails. veriT returns 255. *)  | 
| 
 
71059cf60658
better handling of veriT's 'unknown' status
 
fleury <Mathias.Fleury@mpi-inf.mpg.de> 
parents: 
62549 
diff
changeset
 | 
85  | 
val normal_return_codes = [0, 1, 255]  | 
| 56087 | 86  | 
|
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
87  | 
fun run_solver ctxt name mk_cmd input =  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
88  | 
let  | 
| 57164 | 89  | 
fun pretty tag lines = Pretty.string_of (Pretty.big_list tag (map Pretty.str lines))  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
90  | 
|
| 58061 | 91  | 
val _ = SMT_Config.trace_msg ctxt (pretty "Problem:" o split_lines) input  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
92  | 
|
| 
69205
 
8050734eee3e
add reconstruction by veriT in method smt
 
fleury <Mathias.Fleury@mpi-inf.mpg.de> 
parents: 
67522 
diff
changeset
 | 
93  | 
    val ({elapsed, ...}, {redirected_output = res, output = err, return_code}) =
 | 
| 
 
8050734eee3e
add reconstruction by veriT in method smt
 
fleury <Mathias.Fleury@mpi-inf.mpg.de> 
parents: 
67522 
diff
changeset
 | 
94  | 
Timing.timing (SMT_Config.with_timeout ctxt (run ctxt name mk_cmd)) input  | 
| 58061 | 95  | 
val _ = SMT_Config.trace_msg ctxt (pretty "Solver:") err  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
96  | 
|
| 67522 | 97  | 
val output = drop_suffix (equal "") res  | 
| 58061 | 98  | 
val _ = SMT_Config.trace_msg ctxt (pretty "Result:") output  | 
| 69593 | 99  | 
val _ = SMT_Config.trace_msg ctxt (pretty "Time (ms):") [\<^make_string> (Time.toMilliseconds elapsed)]  | 
100  | 
val _ = SMT_Config.statistics_msg ctxt (pretty "Time (ms):") [\<^make_string> (Time.toMilliseconds elapsed)]  | 
|
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
101  | 
|
| 56087 | 102  | 
val _ = member (op =) normal_return_codes return_code orelse  | 
| 58061 | 103  | 
raise SMT_Failure.SMT (SMT_Failure.Abnormal_Termination return_code)  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
104  | 
in output end  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
105  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
106  | 
fun trace_assms ctxt =  | 
| 58061 | 107  | 
SMT_Config.trace_msg ctxt (Pretty.string_of o  | 
| 61268 | 108  | 
Pretty.big_list "Assertions:" o map (Thm.pretty_thm ctxt o snd))  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
109  | 
|
| 58061 | 110  | 
fun trace_replay_data ({context = ctxt, typs, terms, ...} : SMT_Translate.replay_data) =
 | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
111  | 
let  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
112  | 
fun pretty_eq n p = Pretty.block [Pretty.str n, Pretty.str " = ", p]  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
113  | 
fun p_typ (n, T) = pretty_eq n (Syntax.pretty_typ ctxt T)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
114  | 
fun p_term (n, t) = pretty_eq n (Syntax.pretty_term ctxt t)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
115  | 
in  | 
| 58061 | 116  | 
SMT_Config.trace_msg ctxt (fn () =>  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
117  | 
Pretty.string_of (Pretty.big_list "Names:" [  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
118  | 
Pretty.big_list "sorts:" (map p_typ (Symtab.dest typs)),  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
119  | 
Pretty.big_list "functions:" (map p_term (Symtab.dest terms))])) ()  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
120  | 
end  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
121  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
122  | 
in  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
123  | 
|
| 57239 | 124  | 
fun invoke name command smt_options ithms ctxt =  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
125  | 
let  | 
| 58061 | 126  | 
val options = SMT_Config.solver_options_of ctxt  | 
| 56112 | 127  | 
val comments = [space_implode " " options]  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
128  | 
|
| 
56132
 
64eeda68e693
delayed construction of command (and of noncommercial check) + tuning
 
blanchet 
parents: 
56131 
diff
changeset
 | 
129  | 
    val (str, replay_data as {context = ctxt', ...}) =
 | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
130  | 
ithms  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
131  | 
|> tap (trace_assms ctxt)  | 
| 58061 | 132  | 
|> SMT_Translate.translate ctxt smt_options comments  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
133  | 
||> tap trace_replay_data  | 
| 
56132
 
64eeda68e693
delayed construction of command (and of noncommercial check) + tuning
 
blanchet 
parents: 
56131 
diff
changeset
 | 
134  | 
in (run_solver ctxt' name (make_command command options) str, replay_data) end  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
135  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
136  | 
end  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
137  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
138  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
139  | 
(* configuration *)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
140  | 
|
| 
70327
 
c04d4951a155
handle timeouts gracefully in 'smt' proof method (patch due to Mathias Fleury)
 
blanchet 
parents: 
70293 
diff
changeset
 | 
141  | 
datatype outcome = Unsat | Sat | Unknown | Time_Out  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
142  | 
|
| 57163 | 143  | 
type parsed_proof =  | 
| 58061 | 144  | 
  {outcome: SMT_Failure.failure option,
 | 
| 60201 | 145  | 
fact_ids: (int * ((string * ATP_Problem_Generate.stature) * thm)) list option,  | 
| 57163 | 146  | 
atp_proof: unit -> (term, string) ATP_Proof.atp_step list}  | 
147  | 
||
148  | 
type solver_config =  | 
|
149  | 
  {name: string,
 | 
|
| 58061 | 150  | 
class: Proof.context -> SMT_Util.class,  | 
| 57163 | 151  | 
avail: unit -> bool,  | 
152  | 
command: unit -> string list,  | 
|
153  | 
options: Proof.context -> string list,  | 
|
| 57239 | 154  | 
smt_options: (string * string) list,  | 
| 57163 | 155  | 
default_max_relevant: int,  | 
156  | 
outcome: string -> string list -> outcome * string list,  | 
|
| 58061 | 157  | 
parse_proof: (Proof.context -> SMT_Translate.replay_data ->  | 
| 57164 | 158  | 
((string * ATP_Problem_Generate.stature) * thm) list -> term list -> term -> string list ->  | 
159  | 
parsed_proof) option,  | 
|
| 58061 | 160  | 
replay: (Proof.context -> SMT_Translate.replay_data -> string list -> thm) option}  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
161  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
162  | 
|
| 56106 | 163  | 
(* check well-sortedness *)  | 
164  | 
||
165  | 
val has_topsort = Term.exists_type (Term.exists_subtype (fn  | 
|
166  | 
TFree (_, []) => true  | 
|
167  | 
| TVar (_, []) => true  | 
|
168  | 
| _ => false))  | 
|
169  | 
||
170  | 
(* top sorts cause problems with atomization *)  | 
|
171  | 
fun check_topsort ctxt thm =  | 
|
| 58061 | 172  | 
if has_topsort (Thm.prop_of thm) then (SMT_Normalize.drop_fact_warning ctxt thm; TrueI) else thm  | 
| 56106 | 173  | 
|
174  | 
||
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
175  | 
(* registry *)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
176  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
177  | 
type solver_info = {
 | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
178  | 
command: unit -> string list,  | 
| 57239 | 179  | 
smt_options: (string * string) list,  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
180  | 
default_max_relevant: int,  | 
| 58061 | 181  | 
parse_proof: Proof.context -> SMT_Translate.replay_data ->  | 
| 57164 | 182  | 
((string * ATP_Problem_Generate.stature) * thm) list -> term list -> term -> string list ->  | 
183  | 
parsed_proof,  | 
|
| 58061 | 184  | 
replay: Proof.context -> SMT_Translate.replay_data -> string list -> thm}  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
185  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
186  | 
structure Solvers = Generic_Data  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
187  | 
(  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
188  | 
type T = solver_info Symtab.table  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
189  | 
val empty = Symtab.empty  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
190  | 
val extend = I  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
191  | 
fun merge data = Symtab.merge (K true) data  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
192  | 
)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
193  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
194  | 
local  | 
| 57164 | 195  | 
fun parse_proof outcome parse_proof0 outer_ctxt replay_data xfacts prems concl output =  | 
| 57157 | 196  | 
(case outcome output of  | 
| 57164 | 197  | 
(Unsat, lines) =>  | 
198  | 
(case parse_proof0 of  | 
|
199  | 
SOME pp => pp outer_ctxt replay_data xfacts prems concl lines  | 
|
| 60201 | 200  | 
        | NONE => {outcome = NONE, fact_ids = NONE, atp_proof = K []})
 | 
| 
70327
 
c04d4951a155
handle timeouts gracefully in 'smt' proof method (patch due to Mathias Fleury)
 
blanchet 
parents: 
70293 
diff
changeset
 | 
201  | 
| (Time_Out, _) => raise SMT_Failure.SMT (SMT_Failure.Time_Out)  | 
| 58061 | 202  | 
| (result, _) => raise SMT_Failure.SMT (SMT_Failure.Counterexample (result = Sat)))  | 
| 57157 | 203  | 
|
204  | 
fun replay outcome replay0 oracle outer_ctxt  | 
|
| 58061 | 205  | 
      (replay_data as {context = ctxt, ...} : SMT_Translate.replay_data) output =
 | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
206  | 
(case outcome output of  | 
| 57164 | 207  | 
(Unsat, lines) =>  | 
| 66661 | 208  | 
if Config.get ctxt SMT_Config.oracle then  | 
209  | 
oracle ()  | 
|
210  | 
else  | 
|
211  | 
(case replay0 of  | 
|
212  | 
SOME replay => replay outer_ctxt replay_data lines  | 
|
213  | 
| NONE => error "No proof reconstruction for solver -- \  | 
|
214  | 
\declare [[smt_oracle]] to allow oracle")  | 
|
| 
70327
 
c04d4951a155
handle timeouts gracefully in 'smt' proof method (patch due to Mathias Fleury)
 
blanchet 
parents: 
70293 
diff
changeset
 | 
215  | 
| (Time_Out, _) => raise SMT_Failure.SMT (SMT_Failure.Time_Out)  | 
| 58061 | 216  | 
| (result, _) => raise SMT_Failure.SMT (SMT_Failure.Counterexample (result = Sat)))  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
217  | 
|
| 69593 | 218  | 
val cfalse = Thm.cterm_of \<^context> \<^prop>\<open>False\<close>  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
219  | 
in  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
220  | 
|
| 57239 | 221  | 
fun add_solver ({name, class, avail, command, options, smt_options, default_max_relevant, outcome,
 | 
| 57164 | 222  | 
parse_proof = parse_proof0, replay = replay0} : solver_config) =  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
223  | 
let  | 
| 57157 | 224  | 
    fun solver oracle = {
 | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
225  | 
command = command,  | 
| 57239 | 226  | 
smt_options = smt_options,  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
227  | 
default_max_relevant = default_max_relevant,  | 
| 57157 | 228  | 
parse_proof = parse_proof (outcome name) parse_proof0,  | 
229  | 
replay = replay (outcome name) replay0 oracle}  | 
|
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
230  | 
|
| 
56132
 
64eeda68e693
delayed construction of command (and of noncommercial check) + tuning
 
blanchet 
parents: 
56131 
diff
changeset
 | 
231  | 
    val info = {name = name, class = class, avail = avail, options = options}
 | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
232  | 
in  | 
| 57157 | 233  | 
Thm.add_oracle (Binding.name name, K cfalse) #-> (fn (_, oracle) =>  | 
234  | 
Context.theory_map (Solvers.map (Symtab.update_new (name, solver oracle)))) #>  | 
|
| 58061 | 235  | 
Context.theory_map (SMT_Config.add_solver info)  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
236  | 
end  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
237  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
238  | 
end  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
239  | 
|
| 56125 | 240  | 
fun get_info ctxt name = the (Symtab.lookup (Solvers.get (Context.Proof ctxt)) name)  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
241  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
242  | 
fun name_and_info_of ctxt =  | 
| 58061 | 243  | 
let val name = SMT_Config.solver_of ctxt  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
244  | 
in (name, get_info ctxt name) end  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
245  | 
|
| 57163 | 246  | 
val default_max_relevant = #default_max_relevant oo get_info  | 
| 57157 | 247  | 
|
| 
57165
 
7b1bf424ec5f
removed SMT weights -- their impact was very inconclusive anyway
 
blanchet 
parents: 
57164 
diff
changeset
 | 
248  | 
fun apply_solver_and_replay ctxt thms0 =  | 
| 57157 | 249  | 
let  | 
| 
57165
 
7b1bf424ec5f
removed SMT weights -- their impact was very inconclusive anyway
 
blanchet 
parents: 
57164 
diff
changeset
 | 
250  | 
val thms = map (check_topsort ctxt) thms0  | 
| 57239 | 251  | 
    val (name, {command, smt_options, replay, ...}) = name_and_info_of ctxt
 | 
252  | 
val (output, replay_data) =  | 
|
| 58061 | 253  | 
invoke name command smt_options (SMT_Normalize.normalize ctxt thms) ctxt  | 
| 57157 | 254  | 
in replay ctxt replay_data output end  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
255  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
256  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
257  | 
(* filter *)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
258  | 
|
| 58061 | 259  | 
fun smt_filter ctxt0 goal xfacts i time_limit =  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
260  | 
let  | 
| 58061 | 261  | 
val ctxt = ctxt0 |> Config.put SMT_Config.timeout (Time.toReal time_limit)  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
262  | 
|
| 
60695
 
757549b4bbe6
Variable.focus etc.: optional bindings provided by user;
 
wenzelm 
parents: 
60201 
diff
changeset
 | 
263  | 
    val ({context = ctxt, prems, concl, ...}, _) = Subgoal.focus ctxt i NONE goal
 | 
| 69593 | 264  | 
fun negate ct = Thm.dest_comb ct ||> Thm.apply \<^cterm>\<open>Not\<close> |-> Thm.apply  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
265  | 
val cprop =  | 
| 58061 | 266  | 
(case try negate (Thm.rhs_of (SMT_Normalize.atomize_conv ctxt concl)) of  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
267  | 
SOME ct => ct  | 
| 
61033
 
fd7fe96ca7b9
generate proper error instead of exception if goal cannot be atomized
 
blanchet 
parents: 
60752 
diff
changeset
 | 
268  | 
| NONE => raise SMT_Failure.SMT (SMT_Failure.Other_Failure "cannot atomize goal"))  | 
| 56082 | 269  | 
|
| 
57165
 
7b1bf424ec5f
removed SMT weights -- their impact was very inconclusive anyway
 
blanchet 
parents: 
57164 
diff
changeset
 | 
270  | 
val conjecture = Thm.assume cprop  | 
| 
 
7b1bf424ec5f
removed SMT weights -- their impact was very inconclusive anyway
 
blanchet 
parents: 
57164 
diff
changeset
 | 
271  | 
val facts = map snd xfacts  | 
| 
 
7b1bf424ec5f
removed SMT weights -- their impact was very inconclusive anyway
 
blanchet 
parents: 
57164 
diff
changeset
 | 
272  | 
val thms = conjecture :: prems @ facts  | 
| 
 
7b1bf424ec5f
removed SMT weights -- their impact was very inconclusive anyway
 
blanchet 
parents: 
57164 
diff
changeset
 | 
273  | 
val thms' = map (check_topsort ctxt) thms  | 
| 57159 | 274  | 
|
| 57239 | 275  | 
    val (name, {command, smt_options, parse_proof, ...}) = name_and_info_of ctxt
 | 
276  | 
val (output, replay_data) =  | 
|
| 58061 | 277  | 
invoke name command smt_options (SMT_Normalize.normalize ctxt thms') ctxt  | 
| 57164 | 278  | 
in  | 
279  | 
parse_proof ctxt replay_data xfacts (map Thm.prop_of prems) (Thm.term_of concl) output  | 
|
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
280  | 
end  | 
| 60201 | 281  | 
  handle SMT_Failure.SMT fail => {outcome = SOME fail, fact_ids = NONE, atp_proof = K []}
 | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
282  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
283  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
284  | 
(* SMT tactic *)  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
285  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
286  | 
local  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
287  | 
fun str_of ctxt fail =  | 
| 58061 | 288  | 
"Solver " ^ SMT_Config.solver_of ctxt ^ ": " ^ SMT_Failure.string_of_failure fail  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
289  | 
|
| 
57165
 
7b1bf424ec5f
removed SMT weights -- their impact was very inconclusive anyway
 
blanchet 
parents: 
57164 
diff
changeset
 | 
290  | 
fun safe_solve ctxt facts = SOME (apply_solver_and_replay ctxt facts)  | 
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
291  | 
handle  | 
| 58061 | 292  | 
SMT_Failure.SMT (fail as SMT_Failure.Counterexample _) =>  | 
293  | 
(SMT_Config.verbose_msg ctxt (str_of ctxt) fail; NONE)  | 
|
294  | 
| SMT_Failure.SMT (fail as SMT_Failure.Time_Out) =>  | 
|
295  | 
        error ("SMT: Solver " ^ quote (SMT_Config.solver_of ctxt) ^ ": " ^
 | 
|
296  | 
SMT_Failure.string_of_failure fail ^ " (setting the " ^  | 
|
297  | 
"configuration option " ^ quote (Config.name_of SMT_Config.timeout) ^ " might help)")  | 
|
298  | 
| SMT_Failure.SMT fail => error (str_of ctxt fail)  | 
|
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
299  | 
|
| 60752 | 300  | 
fun resolve ctxt (SOME thm) = resolve_tac ctxt [thm] 1  | 
301  | 
| resolve _ NONE = no_tac  | 
|
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
302  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
303  | 
fun tac prove ctxt rules =  | 
| 58061 | 304  | 
CONVERSION (SMT_Normalize.atomize_conv ctxt)  | 
| 60752 | 305  | 
    THEN' resolve_tac ctxt @{thms ccontr}
 | 
306  | 
    THEN' SUBPROOF (fn {context = ctxt', prems, ...} =>
 | 
|
307  | 
resolve ctxt' (prove ctxt' (rules @ prems))) ctxt  | 
|
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
308  | 
in  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
309  | 
|
| 58061 | 310  | 
val smt_tac = tac safe_solve  | 
311  | 
val smt_tac' = tac (SOME oo apply_solver_and_replay)  | 
|
| 
56078
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
312  | 
|
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
313  | 
end  | 
| 
 
624faeda77b5
moved 'SMT2' (SMT-LIB-2-based SMT module) into Isabelle
 
blanchet 
parents:  
diff
changeset
 | 
314  | 
|
| 57229 | 315  | 
end;  |