blanchet@33982
|
1 |
(* Title: HOL/Tools/Nitpick/kodkod_sat.ML
|
blanchet@33192
|
2 |
Author: Jasmin Blanchette, TU Muenchen
|
blanchet@34969
|
3 |
Copyright 2009, 2010
|
blanchet@33192
|
4 |
|
blanchet@33192
|
5 |
Kodkod SAT solver integration.
|
blanchet@33192
|
6 |
*)
|
blanchet@33192
|
7 |
|
blanchet@33192
|
8 |
signature KODKOD_SAT =
|
blanchet@33192
|
9 |
sig
|
blanchet@33192
|
10 |
val configured_sat_solvers : bool -> string list
|
blanchet@33192
|
11 |
val smart_sat_solver_name : bool -> string
|
blanchet@34985
|
12 |
val sat_solver_spec : bool -> string -> string * string list
|
blanchet@33192
|
13 |
end;
|
blanchet@33192
|
14 |
|
blanchet@33224
|
15 |
structure Kodkod_SAT : KODKOD_SAT =
|
blanchet@33192
|
16 |
struct
|
blanchet@33192
|
17 |
|
blanchet@34985
|
18 |
open Kodkod
|
blanchet@34985
|
19 |
|
blanchet@33192
|
20 |
datatype sink = ToStdout | ToFile
|
blanchet@33221
|
21 |
datatype availability = Java | JNI
|
blanchet@33221
|
22 |
datatype mode = Batch | Incremental
|
blanchet@33192
|
23 |
|
blanchet@33192
|
24 |
datatype sat_solver_info =
|
blanchet@33221
|
25 |
Internal of availability * mode * string list |
|
blanchet@33192
|
26 |
External of sink * string * string * string list |
|
blanchet@33192
|
27 |
ExternalV2 of sink * string * string * string list * string * string * string
|
blanchet@33192
|
28 |
|
blanchet@33192
|
29 |
val berkmin_exec = getenv "BERKMIN_EXE"
|
blanchet@33192
|
30 |
|
blanchet@33192
|
31 |
(* (string * sat_solver_info) list *)
|
blanchet@33192
|
32 |
val static_list =
|
blanchet@33726
|
33 |
[("MiniSat", ExternalV2 (ToFile, "MINISAT_HOME", "minisat", [], "SAT", "",
|
blanchet@33192
|
34 |
"UNSAT")),
|
blanchet@33192
|
35 |
("PicoSAT", External (ToStdout, "PICOSAT_HOME", "picosat", [])),
|
blanchet@33192
|
36 |
("zChaff", ExternalV2 (ToStdout, "ZCHAFF_HOME", "zchaff", [],
|
blanchet@33192
|
37 |
"Instance Satisfiable", "",
|
blanchet@33192
|
38 |
"Instance Unsatisfiable")),
|
blanchet@33192
|
39 |
("RSat", ExternalV2 (ToStdout, "RSAT_HOME", "rsat", ["-s"],
|
blanchet@33192
|
40 |
"s SATISFIABLE", "v ", "s UNSATISFIABLE")),
|
blanchet@33192
|
41 |
("BerkMin", ExternalV2 (ToStdout, "BERKMIN_HOME",
|
blanchet@33192
|
42 |
if berkmin_exec = "" then "BerkMin561"
|
blanchet@33192
|
43 |
else berkmin_exec, [], "Satisfiable !!",
|
blanchet@33192
|
44 |
"solution =", "UNSATISFIABLE !!")),
|
blanchet@35075
|
45 |
("BerkMin_Alloy", External (ToStdout, "BERKMINALLOY_HOME", "berkmin", [])),
|
blanchet@33192
|
46 |
("Jerusat", External (ToStdout, "JERUSAT_HOME", "Jerusat1.3", [])),
|
blanchet@35075
|
47 |
("MiniSat_JNI", Internal (JNI, Incremental, ["MiniSat"])),
|
blanchet@35075
|
48 |
("zChaff_JNI", Internal (JNI, Batch, ["zChaff"])),
|
blanchet@33221
|
49 |
("SAT4J", Internal (Java, Incremental, ["DefaultSAT4J"])),
|
blanchet@35075
|
50 |
("SAT4J_Light", Internal (Java, Incremental, ["LightSAT4J"])),
|
blanchet@33192
|
51 |
("HaifaSat", ExternalV2 (ToStdout, "HAIFASAT_HOME", "HaifaSat", ["-p", "1"],
|
blanchet@33192
|
52 |
"s SATISFIABLE", "v ", "s UNSATISFIABLE"))]
|
blanchet@33192
|
53 |
|
blanchet@34985
|
54 |
(* bool -> string -> sink -> string -> string -> string list -> string list
|
blanchet@33192
|
55 |
-> (string * (unit -> string list)) option *)
|
blanchet@34985
|
56 |
fun dynamic_entry_for_external overlord name dev home exec args markers =
|
blanchet@33192
|
57 |
case getenv home of
|
blanchet@33192
|
58 |
"" => NONE
|
blanchet@34985
|
59 |
| dir =>
|
blanchet@34985
|
60 |
SOME (name, fn () =>
|
blanchet@34985
|
61 |
let
|
blanchet@34985
|
62 |
val serial_str = if overlord then "" else serial_string ()
|
blanchet@34985
|
63 |
val base = name ^ serial_str
|
blanchet@34985
|
64 |
val out_file = base ^ ".out"
|
blanchet@34985
|
65 |
val dir_sep =
|
blanchet@34985
|
66 |
if String.isSubstring "\\" dir andalso
|
blanchet@34985
|
67 |
not (String.isSubstring "/" dir) then
|
blanchet@34985
|
68 |
"\\"
|
blanchet@34985
|
69 |
else
|
blanchet@34985
|
70 |
"/"
|
blanchet@34985
|
71 |
in
|
blanchet@34985
|
72 |
[if null markers then "External" else "ExternalV2",
|
blanchet@34985
|
73 |
dir ^ dir_sep ^ exec, base ^ ".cnf",
|
blanchet@34985
|
74 |
if dev = ToFile then out_file else ""] @ markers @
|
blanchet@34985
|
75 |
(if dev = ToFile then [out_file] else []) @ args
|
blanchet@34985
|
76 |
end)
|
blanchet@34985
|
77 |
(* bool -> bool -> string * sat_solver_info
|
blanchet@33192
|
78 |
-> (string * (unit -> string list)) option *)
|
blanchet@34985
|
79 |
fun dynamic_entry_for_info _ incremental (name, Internal (Java, mode, ss)) =
|
blanchet@33221
|
80 |
if incremental andalso mode = Batch then NONE else SOME (name, K ss)
|
blanchet@34985
|
81 |
| dynamic_entry_for_info _ incremental (name, Internal (JNI, mode, ss)) =
|
blanchet@33221
|
82 |
if incremental andalso mode = Batch then
|
blanchet@33221
|
83 |
NONE
|
blanchet@33221
|
84 |
else
|
blanchet@33221
|
85 |
let
|
blanchet@33221
|
86 |
val lib_paths = getenv "KODKODI_JAVA_LIBRARY_PATH"
|
blanchet@33221
|
87 |
|> space_explode ":"
|
blanchet@33221
|
88 |
in
|
blanchet@33221
|
89 |
if exists (fn path => File.exists (Path.explode (path ^ "/")))
|
blanchet@33221
|
90 |
lib_paths then
|
blanchet@33221
|
91 |
SOME (name, K ss)
|
blanchet@33221
|
92 |
else
|
blanchet@33221
|
93 |
NONE
|
blanchet@33221
|
94 |
end
|
blanchet@34985
|
95 |
| dynamic_entry_for_info overlord false
|
blanchet@34985
|
96 |
(name, External (dev, home, exec, args)) =
|
blanchet@34985
|
97 |
dynamic_entry_for_external overlord name dev home exec args []
|
blanchet@34985
|
98 |
| dynamic_entry_for_info overlord false
|
blanchet@34985
|
99 |
(name, ExternalV2 (dev, home, exec, args, m1, m2, m3)) =
|
blanchet@34985
|
100 |
dynamic_entry_for_external overlord name dev home exec args [m1, m2, m3]
|
blanchet@34985
|
101 |
| dynamic_entry_for_info _ true _ = NONE
|
blanchet@34985
|
102 |
(* bool -> bool -> (string * (unit -> string list)) list *)
|
blanchet@34985
|
103 |
fun dynamic_list overlord incremental =
|
blanchet@34985
|
104 |
map_filter (dynamic_entry_for_info overlord incremental) static_list
|
blanchet@33192
|
105 |
|
blanchet@33192
|
106 |
(* bool -> string list *)
|
blanchet@34985
|
107 |
val configured_sat_solvers = map fst o dynamic_list false
|
blanchet@34985
|
108 |
(* bool -> string *)
|
blanchet@34985
|
109 |
val smart_sat_solver_name = fst o hd o dynamic_list false
|
blanchet@33192
|
110 |
|
blanchet@34985
|
111 |
(* bool -> string -> string * string list *)
|
blanchet@34985
|
112 |
fun sat_solver_spec overlord name =
|
blanchet@34985
|
113 |
let
|
blanchet@34985
|
114 |
val dyn_list = dynamic_list overlord false
|
blanchet@34985
|
115 |
(* (string * 'a) list -> string *)
|
blanchet@34985
|
116 |
fun enum_solvers solvers =
|
blanchet@34985
|
117 |
commas (distinct (op =) (map (quote o fst) solvers))
|
blanchet@34985
|
118 |
in
|
blanchet@34985
|
119 |
(name, the (AList.lookup (op =) dyn_list name) ())
|
blanchet@33192
|
120 |
handle Option.Option =>
|
blanchet@33192
|
121 |
error (if AList.defined (op =) static_list name then
|
blanchet@33192
|
122 |
"The SAT solver " ^ quote name ^ " is not configured. The \
|
blanchet@33192
|
123 |
\following solvers are configured:\n" ^
|
blanchet@34985
|
124 |
enum_solvers dyn_list ^ "."
|
blanchet@33192
|
125 |
else
|
blanchet@33192
|
126 |
"Unknown SAT solver " ^ quote name ^ ". The following \
|
blanchet@33192
|
127 |
\solvers are supported:\n" ^ enum_solvers static_list ^ ".")
|
blanchet@33192
|
128 |
end
|
blanchet@33192
|
129 |
|
blanchet@33192
|
130 |
end;
|