15 type solver_config = { |
15 type solver_config = { |
16 command: {env_var: string, remote_name: string option}, |
16 command: {env_var: string, remote_name: string option}, |
17 arguments: string list, |
17 arguments: string list, |
18 interface: interface, |
18 interface: interface, |
19 reconstruct: (string list * SMT_Translate.recon) -> Proof.context -> |
19 reconstruct: (string list * SMT_Translate.recon) -> Proof.context -> |
20 thm * Proof.context } |
20 (int list * thm) * Proof.context } |
21 |
21 |
22 (*options*) |
22 (*options*) |
23 val timeout: int Config.T |
23 val timeout: int Config.T |
24 val with_timeout: Proof.context -> ('a -> 'b) -> 'a -> 'b |
24 val with_timeout: Proof.context -> ('a -> 'b) -> 'a -> 'b |
25 val trace: bool Config.T |
25 val trace: bool Config.T |
28 (*certificates*) |
28 (*certificates*) |
29 val fixed_certificates: bool Config.T |
29 val fixed_certificates: bool Config.T |
30 val select_certificates: string -> Context.generic -> Context.generic |
30 val select_certificates: string -> Context.generic -> Context.generic |
31 |
31 |
32 (*solvers*) |
32 (*solvers*) |
33 type solver = Proof.context -> thm list -> thm |
33 type solver = Proof.context -> (int * thm) list -> int list * thm |
34 type solver_info = Context.generic -> Pretty.T list |
34 type solver_info = Context.generic -> Pretty.T list |
35 val add_solver: string * (Proof.context -> solver_config) -> |
35 val add_solver: string * (Proof.context -> solver_config) -> |
36 Context.generic -> Context.generic |
36 Context.generic -> Context.generic |
37 val all_solver_names_of: Context.generic -> string list |
37 val all_solver_names_of: Context.generic -> string list |
38 val add_solver_info: string * solver_info -> Context.generic -> |
38 val add_solver_info: string * solver_info -> Context.generic -> |
39 Context.generic |
39 Context.generic |
40 val solver_name_of: Context.generic -> string |
40 val solver_name_of: Context.generic -> string |
41 val select_solver: string -> Context.generic -> Context.generic |
41 val select_solver: string -> Context.generic -> Context.generic |
42 val solver_of: Context.generic -> solver |
42 val solver_of: Context.generic -> solver |
43 |
43 |
|
44 (*solver*) |
|
45 val smt_solver: Proof.context -> ('a * thm) list -> 'a list * thm |
|
46 val smt_filter: Proof.context -> ('a * thm) list -> 'a list * string |
|
47 |
44 (*tactic*) |
48 (*tactic*) |
45 val smt_tac': bool -> Proof.context -> thm list -> int -> Tactical.tactic |
49 val smt_tac': bool -> Proof.context -> thm list -> int -> Tactical.tactic |
46 val smt_tac: Proof.context -> thm list -> int -> Tactical.tactic |
50 val smt_tac: Proof.context -> thm list -> int -> Tactical.tactic |
47 |
51 |
48 (*setup*) |
52 (*setup*) |
64 type solver_config = { |
68 type solver_config = { |
65 command: {env_var: string, remote_name: string option}, |
69 command: {env_var: string, remote_name: string option}, |
66 arguments: string list, |
70 arguments: string list, |
67 interface: interface, |
71 interface: interface, |
68 reconstruct: (string list * SMT_Translate.recon) -> Proof.context -> |
72 reconstruct: (string list * SMT_Translate.recon) -> Proof.context -> |
69 thm * Proof.context } |
73 (int list * thm) * Proof.context } |
70 |
74 |
71 |
75 |
72 |
76 |
73 (* SMT options *) |
77 (* SMT options *) |
74 |
78 |
175 trace_msg ctxt (fn () => Pretty.string_of (Pretty.big_list "SMT names:" [ |
179 trace_msg ctxt (fn () => Pretty.string_of (Pretty.big_list "SMT names:" [ |
176 Pretty.big_list "sorts:" (map pretty_typ (Symtab.dest typs)), |
180 Pretty.big_list "sorts:" (map pretty_typ (Symtab.dest typs)), |
177 Pretty.big_list "functions:" (map pretty_term (Symtab.dest terms))])) () |
181 Pretty.big_list "functions:" (map pretty_term (Symtab.dest terms))])) () |
178 end |
182 end |
179 |
183 |
180 fun invoke translate_config comments command arguments thms ctxt = |
184 fun invoke translate_config comments command arguments irules ctxt = |
181 thms |
185 irules |
182 |> SMT_Translate.translate translate_config ctxt comments |
186 |> SMT_Translate.translate translate_config ctxt comments |
183 ||> tap (trace_recon_data ctxt) |
187 ||> tap (trace_recon_data ctxt) |
184 |>> run_solver ctxt command arguments |
188 |>> run_solver ctxt command arguments |
185 |> rpair ctxt |
189 |> rpair ctxt |
186 |
190 |
200 in |
204 in |
201 (prems, ctxt) |
205 (prems, ctxt) |
202 |-> SMT_Normalize.normalize extra_norm has_datatypes |
206 |-> SMT_Normalize.normalize extra_norm has_datatypes |
203 |-> invoke translate comments command arguments |
207 |-> invoke translate comments command arguments |
204 |-> reconstruct |
208 |-> reconstruct |
205 |-> (fn thm => fn ctxt' => thm |
209 |-> (fn (idxs, thm) => fn ctxt' => thm |
206 |> singleton (ProofContext.export ctxt' ctxt) |
210 |> singleton (ProofContext.export ctxt' ctxt) |
207 |> discharge_definitions) |
211 |> discharge_definitions |
|
212 |> pair idxs) |
208 end |
213 end |
209 |
214 |
210 |
215 |
211 |
216 |
212 (* solver store *) |
217 (* solver store *) |
213 |
218 |
214 type solver = Proof.context -> thm list -> thm |
219 type solver = Proof.context -> (int * thm) list -> int list * thm |
215 type solver_info = Context.generic -> Pretty.T list |
220 type solver_info = Context.generic -> Pretty.T list |
216 |
221 |
217 structure Solvers = Generic_Data |
222 structure Solvers = Generic_Data |
218 ( |
223 ( |
219 type T = ((Proof.context -> solver_config) * solver_info) Symtab.table |
224 type T = ((Proof.context -> solver_config) * solver_info) Symtab.table |
254 | SOME (s, _) => s) |
259 | SOME (s, _) => s) |
255 |
260 |
256 fun solver_of context = |
261 fun solver_of context = |
257 let val name = solver_name_of context |
262 let val name = solver_name_of context |
258 in gen_solver name (raw_solver_of context name) end |
263 in gen_solver name (raw_solver_of context name) end |
|
264 |
|
265 |
|
266 |
|
267 (* SMT solver *) |
|
268 |
|
269 val has_topsort = Term.exists_type (Term.exists_subtype (fn |
|
270 TFree (_, []) => true |
|
271 | TVar (_, []) => true |
|
272 | _ => false)) |
|
273 |
|
274 fun smt_solver ctxt xrules = |
|
275 (* without this test, we would run into problems when atomizing the rules: *) |
|
276 if exists (has_topsort o Thm.prop_of o snd) xrules |
|
277 then raise SMT "proof state contains the universal sort {}" |
|
278 else |
|
279 split_list xrules |
|
280 ||>> solver_of (Context.Proof ctxt) ctxt o map_index I |
|
281 |>> uncurry (map_filter o try o nth) o apsnd (distinct (op =)) |
|
282 |
|
283 fun smt_filter ctxt xrules = |
|
284 (fst (smt_solver ctxt xrules), "") |
|
285 handle SMT msg => ([], "SMT: " ^ msg) |
|
286 | SMT_COUNTEREXAMPLE _ => ([], "SMT: potential counterexample") |
259 |
287 |
260 |
288 |
261 |
289 |
262 (* SMT tactic *) |
290 (* SMT tactic *) |
263 |
291 |
277 fun SAFE pass_exns tac ctxt i st = |
305 fun SAFE pass_exns tac ctxt i st = |
278 if pass_exns then tac ctxt i st |
306 if pass_exns then tac ctxt i st |
279 else (tac ctxt i st |
307 else (tac ctxt i st |
280 handle SMT msg => fail_tac (trace_msg ctxt (prefix "SMT: ")) msg st |
308 handle SMT msg => fail_tac (trace_msg ctxt (prefix "SMT: ")) msg st |
281 | SMT_COUNTEREXAMPLE ce => fail_tac tracing (pretty_cex ctxt ce) st) |
309 | SMT_COUNTEREXAMPLE ce => fail_tac tracing (pretty_cex ctxt ce) st) |
282 |
|
283 fun smt_solver rules ctxt = solver_of (Context.Proof ctxt) ctxt rules |
|
284 |
|
285 val has_topsort = Term.exists_type (Term.exists_subtype (fn |
|
286 TFree (_, []) => true |
|
287 | TVar (_, []) => true |
|
288 | _ => false)) |
|
289 in |
310 in |
290 fun smt_tac' pass_exns ctxt rules = |
311 fun smt_tac' pass_exns ctxt rules = |
291 CONVERSION (SMT_Normalize.atomize_conv ctxt) |
312 CONVERSION (SMT_Normalize.atomize_conv ctxt) |
292 THEN' Tactic.rtac @{thm ccontr} |
313 THEN' Tactic.rtac @{thm ccontr} |
293 THEN' SUBPROOF (fn {context, prems, ...} => |
314 THEN' SUBPROOF (fn {context, prems, ...} => |
294 let val thms = rules @ prems |
315 let fun solve cx = snd (smt_solver cx (map (pair ()) (rules @ prems))) |
295 in |
316 in SAFE pass_exns (Tactic.rtac o solve) context 1 end) ctxt |
296 if exists (has_topsort o Thm.prop_of) thms |
|
297 then fail_tac (trace_msg context I) |
|
298 "SMT: proof state contains the universal sort {}" |
|
299 else SAFE pass_exns (Tactic.rtac o smt_solver thms) context 1 |
|
300 end) ctxt |
|
301 |
317 |
302 val smt_tac = smt_tac' false |
318 val smt_tac = smt_tac' false |
303 end |
319 end |
304 |
320 |
305 val smt_method = |
321 val smt_method = |
355 Pretty.big_list "Solver-specific settings:" infos]) |
371 Pretty.big_list "Solver-specific settings:" infos]) |
356 end |
372 end |
357 |
373 |
358 val _ = |
374 val _ = |
359 Outer_Syntax.improper_command "smt_status" |
375 Outer_Syntax.improper_command "smt_status" |
360 "show the available SMT solvers and the currently selected solver" Keyword.diag |
376 "show the available SMT solvers and the currently selected solver" |
|
377 Keyword.diag |
361 (Scan.succeed (Toplevel.no_timing o Toplevel.keep (fn state => |
378 (Scan.succeed (Toplevel.no_timing o Toplevel.keep (fn state => |
362 print_setup (Context.Proof (Toplevel.context_of state))))) |
379 print_setup (Context.Proof (Toplevel.context_of state))))) |
363 |
380 |
364 end |
381 end |