src/HOL/Tools/Nitpick/kodkod_sat.ML
author blanchet
Tue, 09 Feb 2010 16:07:51 +0100
changeset 35075 6fd1052fe463
parent 34985 5e492a862b34
child 35177 168041f24f80
permissions -rw-r--r--
optimization to quantifiers in Nitpick's handling of simp rules + renamed some SAT solvers
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;