src/HOL/Tools/Nitpick/kodkod_sat.ML
author blanchet
Thu, 28 Nov 2013 15:14:00 +0100
changeset 55981 48dadf69c44d
parent 51504 0b7288aee751
child 57231 6bfbec3dff62
permissions -rw-r--r--
added Riss3g
     1 (*  Title:      HOL/Tools/Nitpick/kodkod_sat.ML
     2     Author:     Jasmin Blanchette, TU Muenchen
     3     Copyright   2009, 2010
     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 Kodkod_SAT : KODKOD_SAT =
    16 struct
    17 
    18 open Kodkod
    19 
    20 datatype sink = ToStdout | ToFile
    21 datatype availability =
    22   Java |
    23   JNI of int list
    24 datatype mode = Batch | Incremental
    25 
    26 datatype sat_solver_info =
    27   Internal of availability * mode * string list |
    28   External of string * string * string list |
    29   ExternalV2 of sink * string * string * string list * string * string * string
    30 
    31 (* for compatibility with "SatSolver" *)
    32 val berkmin_exec = getenv "BERKMIN_EXE"
    33 
    34 val static_list =
    35   [("Lingeling_JNI", Internal (JNI [1, 5], Batch, ["Lingeling"])),
    36    ("CryptoMiniSat", External ("CRYPTOMINISAT_HOME", "cryptominisat", [])),
    37    ("CryptoMiniSat_JNI", Internal (JNI [1, 5], Batch, ["CryptoMiniSat"])),
    38    ("MiniSat", ExternalV2 (ToFile, "MINISAT_HOME", "minisat", [], "SAT", "",
    39                            "UNSAT")),
    40    ("MiniSat_JNI", Internal (JNI [], Incremental, ["MiniSat"])),
    41    ("zChaff", ExternalV2 (ToStdout, "ZCHAFF_HOME", "zchaff", [],
    42                           "Instance Satisfiable", "",
    43                           "Instance Unsatisfiable")),
    44    ("RSat", ExternalV2 (ToStdout, "RSAT_HOME", "rsat", ["-s"],
    45                         "s SATISFIABLE", "v ", "s UNSATISFIABLE")),
    46    ("Riss3g", External ("RISS3G_HOME", "riss3g", [])),
    47    ("BerkMin", ExternalV2 (ToStdout, "BERKMIN_HOME",
    48                            if berkmin_exec = "" then "BerkMin561"
    49                            else berkmin_exec, [], "Satisfiable          !!",
    50                            "solution =", "UNSATISFIABLE          !!")),
    51    ("BerkMin_Alloy", External ("BERKMINALLOY_HOME", "berkmin", [])),
    52    ("SAT4J", Internal (Java, Incremental, ["DefaultSAT4J"])),
    53    ("SAT4J_Light", Internal (Java, Incremental, ["LightSAT4J"]))]
    54 
    55 fun dynamic_entry_for_external name dev home exec args markers =
    56   case getenv home of
    57     "" => NONE
    58   | dir =>
    59     SOME (name, fn () =>
    60                    let
    61                      val serial_str = serial_string ()
    62                      val base = name ^ serial_str
    63                      val out_file = base ^ ".out"
    64                      val dir_sep =
    65                        if String.isSubstring "\\" dir andalso
    66                           not (String.isSubstring "/" dir) then
    67                          "\\"
    68                        else
    69                          "/"
    70                    in
    71                      [if null markers then "External" else "ExternalV2",
    72                       dir ^ dir_sep ^ exec, base ^ ".cnf"] @
    73                       (if null markers then []
    74                        else [if dev = ToFile then out_file else ""]) @ markers @
    75                      (if dev = ToFile then [out_file] else []) @ args
    76                    end)
    77 fun dynamic_entry_for_info incremental (name, Internal (Java, mode, ss)) =
    78     if incremental andalso mode = Batch then NONE else SOME (name, K ss)
    79   | dynamic_entry_for_info incremental
    80         (name, Internal (JNI from_version, mode, ss)) =
    81     if (incremental andalso mode = Batch) orelse
    82        dict_ord int_ord (kodkodi_version (), from_version) = LESS then
    83       NONE
    84     else
    85       let
    86         val lib_paths = getenv "KODKODI_JAVA_LIBRARY_PATH"
    87                         |> space_explode ":"
    88       in
    89         if exists (fn path => File.exists (Path.explode (path ^ "/")))
    90                   lib_paths then
    91           SOME (name, K ss)
    92         else
    93           NONE
    94       end
    95   | dynamic_entry_for_info false (name, External (home, exec, args)) =
    96     dynamic_entry_for_external name ToStdout home exec args []
    97   | dynamic_entry_for_info false
    98         (name, ExternalV2 (dev, home, exec, args, m1, m2, m3)) =
    99     dynamic_entry_for_external name dev home exec args [m1, m2, m3]
   100   | dynamic_entry_for_info true _ = NONE
   101 fun dynamic_list incremental =
   102   map_filter (dynamic_entry_for_info incremental) static_list
   103 
   104 val configured_sat_solvers = map fst o dynamic_list
   105 val smart_sat_solver_name = fst o hd o dynamic_list
   106 
   107 fun sat_solver_spec name =
   108   let
   109     val dyns = dynamic_list false
   110     fun enum_solvers solvers =
   111       commas (distinct (op =) (map (quote o fst) solvers))
   112   in
   113     (name, the (AList.lookup (op =) dyns name) ())
   114     handle Option.Option =>
   115            error (if AList.defined (op =) static_list name then
   116                     "The SAT solver " ^ quote name ^ " is not configured. The \
   117                     \following solvers are configured:\n" ^
   118                     enum_solvers dyns ^ "."
   119                   else
   120                     "Unknown SAT solver " ^ quote name ^ ". The following \
   121                     \solvers are supported:\n" ^ enum_solvers static_list ^ ".")
   122   end
   123 
   124 end;