33192
|
1 |
(* Title: HOL/Nitpick/Tools/kodkod_sat.ML
|
|
2 |
Author: Jasmin Blanchette, TU Muenchen
|
|
3 |
Copyright 2009
|
|
4 |
|
|
5 |
Kodkod SAT solver integration.
|
|
6 |
*)
|
|
7 |
|
|
8 |
signature KODKOD_SAT =
|
|
9 |
sig
|
|
10 |
val configured_sat_solvers : bool -> string list
|
|
11 |
val smart_sat_solver_name : bool -> string
|
|
12 |
val sat_solver_spec : string -> string * string list
|
|
13 |
end;
|
|
14 |
|
|
15 |
structure KodkodSAT : KODKOD_SAT =
|
|
16 |
struct
|
|
17 |
|
|
18 |
datatype sink = ToStdout | ToFile
|
|
19 |
|
|
20 |
datatype sat_solver_info =
|
|
21 |
Internal of bool * string list |
|
|
22 |
External of sink * string * string * string list |
|
|
23 |
ExternalV2 of sink * string * string * string list * string * string * string
|
|
24 |
|
|
25 |
val berkmin_exec = getenv "BERKMIN_EXE"
|
|
26 |
|
|
27 |
(* (string * sat_solver_info) list *)
|
|
28 |
val static_list =
|
|
29 |
[("MiniSat", ExternalV2 (ToFile, "MINISAT_HOME", "minisat", [], "SAT", "",
|
|
30 |
"UNSAT")),
|
|
31 |
("PicoSAT", External (ToStdout, "PICOSAT_HOME", "picosat", [])),
|
|
32 |
("zChaff", ExternalV2 (ToStdout, "ZCHAFF_HOME", "zchaff", [],
|
|
33 |
"Instance Satisfiable", "",
|
|
34 |
"Instance Unsatisfiable")),
|
|
35 |
("RSat", ExternalV2 (ToStdout, "RSAT_HOME", "rsat", ["-s"],
|
|
36 |
"s SATISFIABLE", "v ", "s UNSATISFIABLE")),
|
|
37 |
("BerkMin", ExternalV2 (ToStdout, "BERKMIN_HOME",
|
|
38 |
if berkmin_exec = "" then "BerkMin561"
|
|
39 |
else berkmin_exec, [], "Satisfiable !!",
|
|
40 |
"solution =", "UNSATISFIABLE !!")),
|
|
41 |
("BerkMinAlloy", External (ToStdout, "BERKMINALLOY_HOME", "berkmin", [])),
|
|
42 |
("Jerusat", External (ToStdout, "JERUSAT_HOME", "Jerusat1.3", [])),
|
|
43 |
("SAT4J", Internal (true, ["DefaultSAT4J"])),
|
|
44 |
("MiniSatJNI", Internal (true, ["MiniSat"])),
|
|
45 |
("zChaffJNI", Internal (false, ["zChaff"])),
|
|
46 |
("SAT4JLight", Internal (true, ["LightSAT4J"])),
|
|
47 |
("HaifaSat", ExternalV2 (ToStdout, "HAIFASAT_HOME", "HaifaSat", ["-p", "1"],
|
|
48 |
"s SATISFIABLE", "v ", "s UNSATISFIABLE"))]
|
|
49 |
|
|
50 |
val created_temp_dir = Unsynchronized.ref false
|
|
51 |
|
|
52 |
(* string -> sink -> string -> string -> string list -> string list
|
|
53 |
-> (string * (unit -> string list)) option *)
|
|
54 |
fun dynamic_entry_for_external name dev home exec args markers =
|
|
55 |
case getenv home of
|
|
56 |
"" => NONE
|
|
57 |
| dir => SOME (name, fn () =>
|
|
58 |
let
|
|
59 |
val temp_dir = getenv "ISABELLE_TMP"
|
|
60 |
val _ = if !created_temp_dir then
|
|
61 |
()
|
|
62 |
else
|
|
63 |
(created_temp_dir := true;
|
|
64 |
File.mkdir (Path.explode temp_dir))
|
|
65 |
val temp = temp_dir ^ "/" ^ name ^ serial_string ()
|
|
66 |
val out_file = temp ^ ".out"
|
|
67 |
in
|
|
68 |
[if null markers then "External" else "ExternalV2",
|
|
69 |
dir ^ "/" ^ exec, temp ^ ".cnf",
|
|
70 |
if dev = ToFile then out_file else ""] @ markers @
|
|
71 |
(if dev = ToFile then [out_file] else []) @ args
|
|
72 |
end)
|
|
73 |
(* bool -> string * sat_solver_info
|
|
74 |
-> (string * (unit -> string list)) option *)
|
|
75 |
fun dynamic_entry_for_info false (name, Internal (_, ss)) = SOME (name, K ss)
|
|
76 |
| dynamic_entry_for_info false (name, External (dev, home, exec, args)) =
|
|
77 |
dynamic_entry_for_external name dev home exec args []
|
|
78 |
| dynamic_entry_for_info false (name, ExternalV2 (dev, home, exec, args,
|
|
79 |
m1, m2, m3)) =
|
|
80 |
dynamic_entry_for_external name dev home exec args [m1, m2, m3]
|
|
81 |
| dynamic_entry_for_info true (name, Internal (true, ss)) = SOME (name, K ss)
|
|
82 |
| dynamic_entry_for_info true _ = NONE
|
|
83 |
(* bool -> (string * (unit -> string list)) list *)
|
|
84 |
fun dynamic_list incremental =
|
|
85 |
map_filter (dynamic_entry_for_info incremental) static_list
|
|
86 |
|
|
87 |
(* bool -> string list *)
|
|
88 |
val configured_sat_solvers = map fst o dynamic_list
|
|
89 |
|
|
90 |
(* bool -> string *)
|
|
91 |
val smart_sat_solver_name = dynamic_list #> hd #> fst
|
|
92 |
|
|
93 |
(* (string * 'a) list -> string *)
|
|
94 |
fun enum_solvers xs = commas (map (quote o fst) xs |> distinct (op =))
|
|
95 |
(* string -> string * string list *)
|
|
96 |
fun sat_solver_spec name =
|
|
97 |
let val dynamic_list = dynamic_list false in
|
|
98 |
(name, the (AList.lookup (op =) dynamic_list name) ())
|
|
99 |
handle Option.Option =>
|
|
100 |
error (if AList.defined (op =) static_list name then
|
|
101 |
"The SAT solver " ^ quote name ^ " is not configured. The \
|
|
102 |
\following solvers are configured:\n" ^
|
|
103 |
enum_solvers dynamic_list ^ "."
|
|
104 |
else
|
|
105 |
"Unknown SAT solver " ^ quote name ^ ". The following \
|
|
106 |
\solvers are supported:\n" ^ enum_solvers static_list ^ ".")
|
|
107 |
end
|
|
108 |
|
|
109 |
end;
|