author | haftmann |
Sat, 19 Jul 2025 18:41:55 +0200 | |
changeset 82886 | 8d1e295aab70 |
parent 82024 | bbda3b4f3c99 |
permissions | -rw-r--r-- |
66646 | 1 |
(* Title: HOL/Tools/Nunchaku/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 |
| Unknown_Error of int * string |
|
37 |
||
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
38 |
val nunchaku_home_env_var: string |
64389 | 39 |
|
40 |
val solve_nun_problem: tool_params -> nun_problem -> nun_outcome |
|
41 |
end; |
|
42 |
||
43 |
structure Nunchaku_Tool : NUNCHAKU_TOOL = |
|
44 |
struct |
|
45 |
||
46 |
open Nunchaku_Util; |
|
47 |
open Nunchaku_Problem; |
|
48 |
||
49 |
type tool_params = |
|
66163 | 50 |
{solvers: string list, |
51 |
overlord: bool, |
|
66627 | 52 |
min_bound: int, |
53 |
max_bound: int option, |
|
66625 | 54 |
bound_increment: int, |
64389 | 55 |
debug: bool, |
56 |
specialize: bool, |
|
57 |
timeout: Time.time}; |
|
58 |
||
59 |
type nun_solution = |
|
60 |
{tys: (ty * tm list) list, |
|
61 |
tms: (tm * tm) list}; |
|
62 |
||
63 |
datatype nun_outcome = |
|
66620 | 64 |
Unsat of string |
65 |
| Sat of string * string * nun_solution |
|
66 |
| Unknown of (string * string * nun_solution) option |
|
64389 | 67 |
| Timeout |
68 |
| Nunchaku_Var_Not_Set |
|
69 |
| Nunchaku_Cannot_Execute |
|
70 |
| Nunchaku_Not_Found |
|
71 |
| Unknown_Error of int * string; |
|
72 |
||
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
73 |
val nunchaku_home_env_var = "NUNCHAKU_HOME"; |
64389 | 74 |
|
66620 | 75 |
val unknown_solver = "unknown"; |
76 |
||
66163 | 77 |
val cached_outcome = Synchronized.var "Nunchaku_Tool.cached_outcome" |
66626 | 78 |
(NONE : ((tool_params * nun_problem) * nun_outcome) option); |
64389 | 79 |
|
66627 | 80 |
fun uncached_solve_nun_problem ({solvers, overlord, min_bound, max_bound, bound_increment, |
81 |
specialize, timeout, ...} : tool_params) |
|
64389 | 82 |
(problem as {sound, complete, ...}) = |
83 |
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
|
84 |
if getenv nunchaku_home_env_var = "" then |
64389 | 85 |
Nunchaku_Var_Not_Set |
86 |
else |
|
87 |
let |
|
88 |
val bash_cmd = |
|
82024
bbda3b4f3c99
switch from CVC5 to cvc5, including updates of internal tool references;
wenzelm
parents:
81751
diff
changeset
|
89 |
"PATH=\"$CVC5_HOME:$KODKODI/bin:$SMBC_HOME:$PATH\" \"$" ^ |
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
90 |
nunchaku_home_env_var ^ "\"/nunchaku --skolems-in-model --no-color " ^ |
64389 | 91 |
(if specialize then "" else "--no-specialize ") ^ |
67106 | 92 |
"--solvers \"" ^ space_implode "," (map Bash.string solvers) ^ "\" " ^ |
64389 | 93 |
"--timeout " ^ string_of_int (Time.toSeconds timeout) ^ " " ^ |
66627 | 94 |
"--kodkod-min-bound " ^ string_of_int min_bound ^ " " ^ |
95 |
(case max_bound of NONE => "" | SOME n => "--kodkod-max-bound " ^ string_of_int n ^ " ") ^ |
|
96 |
"--kodkod-bound-increment " ^ string_of_int bound_increment ^ " " ^ |
|
64389 | 97 |
File.bash_path prob_path; |
98 |
val comments = |
|
99 |
[bash_cmd, "This file was generated by Isabelle (most likely Nunchaku)", timestamp ()]; |
|
100 |
val prob_str = cat_lines (map (prefix "# ") comments) ^ "\n\n" ^ str_of_nun_problem problem; |
|
101 |
val _ = File.write prob_path prob_str; |
|
74147
d030b988d470
provide bash_process server for Isabelle/ML and other external programs;
wenzelm
parents:
74142
diff
changeset
|
102 |
val res = Isabelle_System.bash_process (Bash.script bash_cmd); |
73275 | 103 |
val rc = Process_Result.rc res; |
104 |
val out = Process_Result.out res; |
|
105 |
val err = Process_Result.err res; |
|
66620 | 106 |
|
107 |
val backend = |
|
73274 | 108 |
(case map_filter (try (unprefix "{backend:")) (split_lines out) of |
66638 | 109 |
[s] => hd (space_explode "," s) |
110 |
| _ => unknown_solver); |
|
64389 | 111 |
in |
73274 | 112 |
if String.isPrefix "SAT" out then |
113 |
(if sound then Sat else Unknown o SOME) (backend, out, {tys = [], tms = []}) |
|
114 |
else if String.isPrefix "UNSAT" out then |
|
66620 | 115 |
if complete then Unsat backend else Unknown NONE |
73274 | 116 |
else if String.isSubstring "TIMEOUT" out |
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
117 |
(* FIXME: temporary *) |
73274 | 118 |
orelse String.isSubstring "kodkod failed (errcode 152)" err then |
64469
488d4e627238
added Nunchaku component and tuned Nunchaku integration accordingly
blanchet
parents:
64407
diff
changeset
|
119 |
Timeout |
73274 | 120 |
else if String.isPrefix "UNKNOWN" out then |
64389 | 121 |
Unknown NONE |
73274 | 122 |
else if rc = 126 then |
64389 | 123 |
Nunchaku_Cannot_Execute |
73274 | 124 |
else if rc = 127 then |
64389 | 125 |
Nunchaku_Not_Found |
126 |
else |
|
73274 | 127 |
Unknown_Error (rc, |
128 |
simplify_spaces (elide_string 1000 (if err <> "" then err else out))) |
|
64389 | 129 |
end); |
130 |
||
66163 | 131 |
fun solve_nun_problem (params as {solvers, overlord, debug, ...}) problem = |
66626 | 132 |
let val key = (params, problem) in |
66163 | 133 |
(case (overlord orelse debug, |
134 |
AList.lookup (op =) (the_list (Synchronized.value cached_outcome)) key) of |
|
135 |
(false, SOME outcome) => outcome |
|
136 |
| _ => |
|
137 |
let |
|
138 |
val outcome = uncached_solve_nun_problem params problem; |
|
64389 | 139 |
|
66163 | 140 |
fun update_cache () = |
141 |
Synchronized.change cached_outcome (K (SOME (key, outcome))); |
|
142 |
in |
|
143 |
(case outcome of |
|
66620 | 144 |
Unsat _ => update_cache () |
66163 | 145 |
| Sat _ => update_cache () |
146 |
| Unknown _ => update_cache () |
|
147 |
| _ => ()); |
|
148 |
outcome |
|
149 |
end) |
|
150 |
end; |
|
64389 | 151 |
|
152 |
end; |