author | blanchet |
Fri, 08 Sep 2017 00:02:52 +0200 | |
changeset 66632 | 6950d3da13f8 |
parent 66627 | 4145169ae609 |
child 66637 | 809d40cfa4de |
permissions | -rw-r--r-- |
64389 | 1 |
(* Title: HOL/Nunchaku/Tools/nunchaku_tool.ML |
66614
1f1c5d85d232
moved Nunchaku to Main; the goal is to move Nitpick out in the next 1-2 years
blanchet
parents:
66163
diff
changeset
|
2 |
Author: Jasmin Blanchette, VU Amsterdam |
1f1c5d85d232
moved Nunchaku to Main; the goal is to move Nitpick out in the next 1-2 years
blanchet
parents:
66163
diff
changeset
|
3 |
Copyright 2015, 2016, 2017 |
64389 | 4 |
|
5 |
Interface to the external "nunchaku" tool. |
|
6 |
*) |
|
7 |
||
8 |
signature NUNCHAKU_TOOL = |
|
9 |
sig |
|
10 |
type ty = Nunchaku_Problem.ty |
|
11 |
type tm = Nunchaku_Problem.tm |
|
12 |
type nun_problem = Nunchaku_Problem.nun_problem |
|
13 |
||
14 |
type tool_params = |
|
66163 | 15 |
{solvers: string list, |
16 |
overlord: bool, |
|
66627 | 17 |
min_bound: int, |
18 |
max_bound: int option, |
|
66625 | 19 |
bound_increment: int, |
64389 | 20 |
debug: bool, |
21 |
specialize: bool, |
|
22 |
timeout: Time.time} |
|
23 |
||
24 |
type nun_solution = |
|
25 |
{tys: (ty * tm list) list, |
|
26 |
tms: (tm * tm) list} |
|
27 |
||
28 |
datatype nun_outcome = |
|
66620 | 29 |
Unsat of string |
30 |
| Sat of string * string * nun_solution |
|
31 |
| Unknown of (string * string * nun_solution) option |
|
64389 | 32 |
| Timeout |
33 |
| Nunchaku_Var_Not_Set |
|
34 |
| Nunchaku_Cannot_Execute |
|
35 |
| Nunchaku_Not_Found |
|
36 |
| CVC4_Cannot_Execute |
|
37 |
| CVC4_Not_Found |
|
38 |
| Unknown_Error of int * string |
|
39 |
||
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
40 |
val nunchaku_home_env_var: string |
64389 | 41 |
|
42 |
val solve_nun_problem: tool_params -> nun_problem -> nun_outcome |
|
43 |
end; |
|
44 |
||
45 |
structure Nunchaku_Tool : NUNCHAKU_TOOL = |
|
46 |
struct |
|
47 |
||
48 |
open Nunchaku_Util; |
|
49 |
open Nunchaku_Problem; |
|
50 |
||
51 |
type tool_params = |
|
66163 | 52 |
{solvers: string list, |
53 |
overlord: bool, |
|
66627 | 54 |
min_bound: int, |
55 |
max_bound: int option, |
|
66625 | 56 |
bound_increment: int, |
64389 | 57 |
debug: bool, |
58 |
specialize: bool, |
|
59 |
timeout: Time.time}; |
|
60 |
||
61 |
type nun_solution = |
|
62 |
{tys: (ty * tm list) list, |
|
63 |
tms: (tm * tm) list}; |
|
64 |
||
65 |
datatype nun_outcome = |
|
66620 | 66 |
Unsat of string |
67 |
| Sat of string * string * nun_solution |
|
68 |
| Unknown of (string * string * nun_solution) option |
|
64389 | 69 |
| Timeout |
70 |
| Nunchaku_Var_Not_Set |
|
71 |
| Nunchaku_Cannot_Execute |
|
72 |
| Nunchaku_Not_Found |
|
73 |
| CVC4_Cannot_Execute |
|
74 |
| CVC4_Not_Found |
|
75 |
| Unknown_Error of int * string; |
|
76 |
||
77 |
fun bash_output_error s = |
|
78 |
let val {out, err, rc, ...} = Bash.process s in |
|
79 |
((out, err), rc) |
|
80 |
end; |
|
81 |
||
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
82 |
val nunchaku_home_env_var = "NUNCHAKU_HOME"; |
64389 | 83 |
|
66620 | 84 |
val unknown_solver = "unknown"; |
85 |
||
66163 | 86 |
val cached_outcome = Synchronized.var "Nunchaku_Tool.cached_outcome" |
66626 | 87 |
(NONE : ((tool_params * nun_problem) * nun_outcome) option); |
64389 | 88 |
|
66627 | 89 |
fun uncached_solve_nun_problem ({solvers, overlord, min_bound, max_bound, bound_increment, |
90 |
specialize, timeout, ...} : tool_params) |
|
64389 | 91 |
(problem as {sound, complete, ...}) = |
92 |
with_tmp_or_overlord_file overlord "nunchaku" "nun" (fn prob_path => |
|
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
93 |
if getenv nunchaku_home_env_var = "" then |
64389 | 94 |
Nunchaku_Var_Not_Set |
95 |
else |
|
96 |
let |
|
97 |
val bash_cmd = |
|
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
98 |
"PATH=\"$CVC4_HOME:$KODKODI/bin:$PATH\" \"$" ^ |
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
99 |
nunchaku_home_env_var ^ "\"/nunchaku --skolems-in-model --no-color " ^ |
64389 | 100 |
(if specialize then "" else "--no-specialize ") ^ |
66621 | 101 |
"--solvers \"" ^ space_implode "," (map Bash_Syntax.string solvers) ^ "\" " ^ |
64389 | 102 |
"--timeout " ^ string_of_int (Time.toSeconds timeout) ^ " " ^ |
66627 | 103 |
"--kodkod-min-bound " ^ string_of_int min_bound ^ " " ^ |
104 |
(case max_bound of NONE => "" | SOME n => "--kodkod-max-bound " ^ string_of_int n ^ " ") ^ |
|
105 |
"--kodkod-bound-increment " ^ string_of_int bound_increment ^ " " ^ |
|
64389 | 106 |
File.bash_path prob_path; |
107 |
val comments = |
|
108 |
[bash_cmd, "This file was generated by Isabelle (most likely Nunchaku)", timestamp ()]; |
|
109 |
val prob_str = cat_lines (map (prefix "# ") comments) ^ "\n\n" ^ str_of_nun_problem problem; |
|
110 |
val _ = File.write prob_path prob_str; |
|
111 |
val ((output, error), code) = bash_output_error bash_cmd; |
|
66620 | 112 |
|
113 |
val backend = |
|
114 |
(case filter_out (curry (op =) "") (split_lines output) of |
|
115 |
[] => unknown_solver |
|
116 |
| lines => |
|
117 |
(case try (unprefix "{backend:") (List.last lines) of |
|
118 |
NONE => unknown_solver |
|
119 |
| SOME "" => unknown_solver |
|
120 |
| SOME s => hd (space_explode "," s))); |
|
64389 | 121 |
in |
122 |
if String.isPrefix "SAT" output then |
|
66620 | 123 |
(if sound then Sat else Unknown o SOME) (backend, output, {tys = [], tms = []}) |
64389 | 124 |
else if String.isPrefix "UNSAT" output then |
66620 | 125 |
if complete then Unsat backend else Unknown NONE |
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
126 |
else if String.isSubstring "TIMEOUT" output |
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
127 |
(* FIXME: temporary *) |
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
128 |
orelse String.isSubstring "kodkod failed (errcode 152)" error then |
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
129 |
Timeout |
64389 | 130 |
else if String.isPrefix "UNKNOWN" output then |
131 |
Unknown NONE |
|
132 |
else if code = 126 then |
|
133 |
Nunchaku_Cannot_Execute |
|
134 |
else if code = 127 then |
|
135 |
Nunchaku_Not_Found |
|
136 |
else |
|
137 |
Unknown_Error (code, |
|
138 |
simplify_spaces (elide_string 1000 (if error <> "" then error else output))) |
|
139 |
end); |
|
140 |
||
66163 | 141 |
fun solve_nun_problem (params as {solvers, overlord, debug, ...}) problem = |
66626 | 142 |
let val key = (params, problem) in |
66163 | 143 |
(case (overlord orelse debug, |
144 |
AList.lookup (op =) (the_list (Synchronized.value cached_outcome)) key) of |
|
145 |
(false, SOME outcome) => outcome |
|
146 |
| _ => |
|
147 |
let |
|
148 |
val outcome = uncached_solve_nun_problem params problem; |
|
64389 | 149 |
|
66163 | 150 |
fun update_cache () = |
151 |
Synchronized.change cached_outcome (K (SOME (key, outcome))); |
|
152 |
in |
|
153 |
(case outcome of |
|
66620 | 154 |
Unsat _ => update_cache () |
66163 | 155 |
| Sat _ => update_cache () |
156 |
| Unknown _ => update_cache () |
|
157 |
| _ => ()); |
|
158 |
outcome |
|
159 |
end) |
|
160 |
end; |
|
64389 | 161 |
|
162 |
end; |